Moving Off of Gmail? What About All Those Filter Rules?

So, for one reason or another, I decided that I was going to move away from gmail.  It’s easy to underestimate the massive pain that is running a mail server, especially if you expect anti-spam, ant-virus, and the thousand (seemingly so at least) other features that are offered for free from most web mail providers. There’s a good chance that people doing the same thing (abandoning gmail that is,) will eventually find that it has been decided that dovecot and sieve will feature heavily in whatever setup they decide upon.  And if they are anything like me, they filter a significant portion of their mail into gmail’s equivalent of IMAP folders (tags.) In my case, I didn’t want (despite the probability that most of the rules are stale) to recreate all of these rules by hand.  It’s fortunate that Google allows the rules to be exported as XML (though actual sieve rules would have been better!)  A quick search didn’t turn up any tools to convert from one to the other, so I threw together a (admittedly poorly written) PERL script.  And to think, I had promised to stop using PERL and move to Ruby for one-off little scripts like this, perhaps a decent new-years resolution?
(googleMailFilters.pl) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#!perl
use XML::Simple;
use Data::Dumper;
$xml = new XML::Simple;
$data = $xml->XMLin("mailFilters.xml");
# Build hashes of arrays one for each type (to, from, subject) with the destination as key, and search values as array values
%from = ();
foreach $filter (keys %{$data->{entry}}){
	push @{$from{$data->{entry}->{$filter}->{"apps:property"}->{"label"}->{"value"}}}, $data->{entry}->{$filter}->{"apps:property"}->{"from"}->{"value"}
	if ( length($data->{entry}->{$filter}->{"apps:property"}->{"from"}->{"value"}) > 0 && length($data->{entry}->{$filter}->{"apps:property"}->{"label"}->{"value"}) > 0);
}
%to = ();
foreach $filter (keys %{$data->{entry}}){
        push @{$to{$data->{entry}->{$filter}->{"apps:property"}->{"label"}->{"value"}}}, $data->{entry}->{$filter}->{"apps:property"}->{"to"}->{"value"}
           if ( length($data->{entry}->{$filter}->{"apps:property"}->{"to"}->{"value"}) > 0 && length($data->{entry}->{$filter}->{"apps:property"}->{"label"}->{"value"}) > 0);
}
%subject = ();
foreach $filter (keys %{$data->{entry}}){
        push @{$subject{$data->{entry}->{$filter}->{"apps:property"}->{"label"}->{"value"}}}, $data->{entry}->{$filter}->{"apps:property"}->{"subject"}->{"value"}
           if ( length($data->{entry}->{$filter}->{"apps:property"}->{"subject"}->{"value"}) > 0 && length($data->{entry}->{$filter}->{"apps:property"}->{"label"}->{"value"}) > 0);
}
# Print out sieve rules from our hashes:
print "require [\"fileinto\"];\n";
foreach $rule (keys %from){
	print "\n# rule:[from-$rule]\n";
	print "if any of (";
	$i=0;
	foreach $value (@{$from{$rule}}){
		print ",\n\t" if $i>0;
		print "header :contains \"From\" \"$value\"";
		$i++;
	}
	print " )\n\t{\n\t\tfileinto \"$rule\";\n\t}\n"
}
foreach $rule (keys %to){
        print "\n# rule:[to-$rule]\n";
        print "if any of (";
        $i=0;
        foreach $value (@{$to{$rule}}){
                print ",\n\t" if $i>0;
                print "header :contains \"To\" \"$value\"";
                $i++;
        }
        print " )\n\t{\n\t\tfileinto \"$rule\";\n\t}\n"
}
foreach $rule (keys %subject){
        print "\n# rule:[subject-$rule]\n";
        print "if any of (";
        $i=0;
        foreach $value (@{$subject{$rule}}){
                print ",\n\t" if $i>0;
                print "header :contains \"Subject\" \"$value\"";
                $i++;
        }
        print " )\n\t{\n\t\tfileinto \"$rule\";\n\t}\n"
}

Making Java (Slightly) Safer on Windows

Here’s a suggestion that can make it a little safer to run the Java plugin in your web browser on Windows (Vista, Win 7, and Win 8–but not XP.)  This doesn’t stop exploits, and is probably not entirely effective, but it can stop some bad things from happening.  Don’t be fooled into feeling safe by doing this, it’s just one additional layer, but could stop your system from being fully-compromised. Windows includes a feature called mandatory integrity controls that imposes an extra layer of protection on top of the discretionary access controls provided by the operating system.  It is a (very) simple method of preventing write access to items with a higher security level label.  There are several levels defined: Anonymous, Low, Medium, High, and System.  Mandatory integrity controls are one of the many features that makes Google Chrome’s sandbox possible. One of the first thing that many Java exploits perform is to grab a dropper, save it to the filesystem, and execute it.  In most cases by running Java running with low integrity (this is easy for malware authors to work around though,) will short circuit the download.  Also important is that child processes will inherit the integrity label, so if the malware was smart enough to drop the bot or whatever it grabbed into a location with a “low” label, the bot will execute with low permissions.  This will stop it from being persistent, writing to browser settings, copying itself to system folders and so on. The downsides?  the “Low” label still allows reading of files and information labeled as “Medium” or higher, relying on discretionary access controls.  Another downside, is this will probably break any complex Java applet.  I was still able to run most of the stuff I came across, it’s just when trying to write files that things get denied.  Another thing is that you probably don’t want to change the java.exe program itself if you use any Java applications, but this isn’t really a problem because Internet Explorer uses a helper executable to launch the program “jp2launcher.exe”, and as mentioned before it will inherit the “Low” label on execution. Here’s how to run the Java browser plugin as Low integrity: Read full post →

Even Easier Brute-force Login Protection for Wordpress

Here’s another *easy* way to help with those pesky wordpress brute-force logins we have been hearing about.  Most automated attacks make a lot of assumptions.  Like where your blog’s login page is located, and what information is needed to login via that page.  It’s really easy to take those assumptions and make them wrong.  The trick is doing it in a way that doesn’t mess up your real users, and can be done without modifying source code. I am writing this for the much-outdated Apache 2.2, since that’s what my server is running.  The 2.4 version can easily (and more elegantly I might add) do the same thing, but uses different modules.  This example uses only mod_rewrite and mod_usertrack, which should make the scope a little wider, since it’s something that many users will be able to implement in a .htaccess file. So, this is so laughably simple to setup (only 7 lines in the config file!) that you might think it’s useless (and in a week or two it could be,) but the simple truth is most brute-force hacking tools can’t do a lot of things that a real web-browser does all the time.  Like follow 302 redirects, and use session cookies.  It’s very easy to do this with Apache in a way that doesn’t break the login process for normal users, but will trip up many automated attack tools. So the premise is this, if requests are being generated by a real user that user will likely visit via a link (or maybe even a saved bookmark) to the login page, they will fill out a form, and then submit it.  If it’s an attack script, it’s likely got the POST target hard-coded.  So here’s an easy way to deal with that.
  1. When a request comes into the login page, check if there is a session setup for it.
  2. If the session is valid, process the request.
  3. If it isn’t, perform a 302 redirect to a (rewritten) version of the login page that will set the session.  (Discarding, and ignoring the POST form data in the case of a login attempt!)
It’s really that simple.  Of course there are some gotchas … the session data (either name or value) should be hard to guess without following the 302, and setting the actual cookie, and the URL that sets the session should also be unique to the site.  Unfortunately, mod_usertrack wasn’t built for this, and the session payload is a fixed value (mod_session in 2.4 offers much better options.)  So to do this without any external components to Apache 2.2, I decided that a unique cookie name is good enough.
(session-redirect.apacheconf) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  RewriteEngine On
   # This can be placed within your conf file for apache or possible a .htaccess
   #	It performs some very rudimentary session-based redirection that breaks 
   #	automated login attack scripts that don't handle redirects and session tracking.
   #
   # If this cookie isn't set, then redirect to a (rewritten) version of the login page that sets the cookie.
   #   This will short-circuit automated posts, and force an attacker to perform session tracking.
   #   It's also possible to use mod_security to track these values.
   #
   # Sorry, I used to generate random values as I served this from my server, but I moving away from
   # 	a static site :(
   #
   RewriteCond %{HTTP_COOKIE} !ac8bf83d1adc0471b7d4c593
   #         Change this value ^^^^^^^^^^^^^^^^^^^^^^^^
   RewriteRule /wp-login.php /wordpress-login-63e40526.php [R,L]
   #                        Change this value ^^^^^^^^
   <Location /wordpress-login-63e40526.php>
   #  Change to same as above ^^^^^^^^
	   CookieTracking on
	   CookieExpires 30
	   CookieName ac8bf83d1adc0471b7d4c593
   #    same as first ^^^^^^^^^^^^^^^^^^^^^^^^
   </Location>
   RewriteRule /wordpress-login-63e40526.php /wp-login.php [NE]
   #  yes, one more time        ^^^^^^^^
I can already hear your thoughts … but that doesn’t validate anything!  True, but if you really want you can do that through by adding on mod_security’s session tracking on top of the above measures.  See here and here for more on that.

Kerberos Ticket Renewal on MacOS Mountain Lion

The active directory integration in Mountain Lion is getting pretty good, certainly much better than the early 10.7 days.  Several applications integrate quite well, offering kerberos single sign on, such as Safari, and the Microsoft Office apps.  One thing I do not like about kerberos on MacOS is that when my TGT expired it would not auto-renew. That means Safari wouldn’t perform SSO, and some tools like Lync or Communicator would start prompting for passwords.  The easiest way to deal with this is to open a terminal and type “kinit”.  This would prompt for your password and will issue a new ticket. As easy as it is, I don’t like it, so I went looking for a solution, and as luck would have it there is an easy solution.  If you set this up, each time you authenticate to the screensaver, or unlock the keychain the OS will get a new ticket granting ticket, which is much better … one downside is that it will not renew the ticket if you are logged in and the ticket expires.  But my screen lock timeout is short enough anyways, so it will reduce much of the pain. Here’s how to do it … (it’s super simple!) Open the “Keychain Access” application, and under the “Keychain Access” dropdown menu select “Ticket Viewer”.
Screen Shot 2013-01-30 at 12.59.09 PM
Once that opens, you should see some tickets … note the principle name (case matters, so it needs to match how your directory services are configured.)  Click on Add, type your principle name, password, and uncheck the remember password box (that setting might cause you to lock your domain account when you change your password–depending on lockout policy.)  Then click continue.  It takes a few seconds to work, so be patient.  Once it is added (all the other tickets will likely disappear) highlight the principle and click on the “Set as Default” button.  Now when you unlock the screensaver (or the keychain) it will request a new TGT, so it’s less likely that you will have timeouts.  I did find one bug … if the Ticket Viewer application is open and running when a new key is issued it will crash, and all your tickets will be deleted; so close the application before testing.

IPv6 on Comcast Using OpenWRT

I bought a new wireless router (TP-Link N750 TL-WDR4300) that had fantastic hardware specs. It was to replace what I had been using, an Airport extreme, that was having problems dealing with the number of DHCP leases on my network. I also didn’t like the lack of flexibility in firewalling, DHCP options, and on and on. Basically the Airport worked great, but sticks to Apple’s design philosophy: user’s don’t really know what they want, so we’ll tell them. One thing I really liked about the Airport, however, was that it worked great with IPv6. The new TP-Link router didn’t support IPv6, crashed a lot, would randomly stop routing bridged traffic between the wired and wireless interfaces, and did a pretty good job of pissing me off. It’s OS was based on an older version of either OpenWRT or dd-wrt; and this was the source of my problems. Since it wasn’t really working I decided to go ahead and drop OpenWRT’s latest snapshot on the router, I figured what do I have to lose.  (I am super happy with the results, what a great community project!) I’m not going to cover how to install it, that’s well-enough documented at the OpenWRT site.  I am going to give a couple of pointers to getting IPv6 working on Comcast’s network.  It’s actually pretty easy once you install the right packages.  There are  different ways to get IPv6 working in OpenWRT, and this is the combination I got to work, I tried a lot of things.  Other setups might work better or not at all, I don’t know–I stopped once it worked. opkgs you will want: Wide DHCP Client, and the route advertisement daemon. (You don’t need wide-dhcp-server.)
opkg install wide-dhcpv6-client radvd
First a couple of gotchas that tripped me up.
  • Comcast only delegates a /64 prefix (standard ISP practice is a /60,) which means a few things that at first tricked me …
    • You can’t subnet a /64, so at layer 3 you will talk to the upstream router using link local addresses.
    • The br-lan interface will get the delegated address.
    • The default config for wide dhcp6c assumes a /60 delegation, if you don’t change this you won’t get your lease.
  • By default the native IPv6 stack is configured to listen for route advertisements and send route solicitations.  This conflicts with what dhcp6c is doing. I’m not sure, but it might be possible to use the native IPv6 settings in /etc/config/network but I’m not sure if it works as expected with the /64 delegation; I was seeing the wan interface get the address assignment and not the internal layer-3 interface we would use as the default gateway.
    • If you are seeing strange behavior on your network this might be the cause … when I didn’t know better and had both native and dhcp6c enabled I would restart the network, or reboot the router and IPv6 would be working great.  A few hours later it would stop working.  I would also see that my clients had been assigned new network prefixes.  But they had not disabled the old ones (marked as deprecated but still listening.)  And I could’t route IPv6 anymore.
Here are some of my settings that got my OpenWRT routing IPv6 on Comcast (sorry, just config files I didn’t even install the web gui.) Read full post →