WordPress version 2.6 & ModSecurity

Today I updated my WordPress installation to version 2.6. The upgrade went smooth as usual. However afterwards I couldn’t login anymore because one of my ModSecurity rules was triggered at the login. Turns out the WordPress developers changed the use of the ‘redirect_to’ argument in wp-login.php. WordPress uses it to redirect the browser to some part of the weblog software after a successful login. Some time ago there used to be a vulnerability in WordPress as described here: http://www.securityfocus.com/archive/1/463291. To prevent exploitation on my box at the time I created the following rule:

SecRule REQUEST_FILENAME “/wp-login.php” “chain,msg:’WORDPRESS wp-login.php redirect_to credentials stealing attempt’,severity:2,t:normalisePath”
SecRule ARGS:/^s*redirect_to$/ “^(ht|f)tps?://”

This worked because WordPress only used relative paths as values for the ‘redirect_to’ argument. With 2.6 however, this has changed. WordPress now tries to redirect to a full URI. So the above rule needed an update. What I wanted is to adapt the rule so that it only allows the redirect to my own domain. So I created the following rule:

SecRule REQUEST_FILENAME “/wp-login.php” “chain,msg:’WORDPRESS wp-login.php redirect_to credentials stealing attempt’,severity:2,t:normalisePath”
SecRule ARGS:/^s*redirect_to$/ “^(?:ht|f)tps?://(.*)$” “chain,capture”
SecRule TX:1 “!@beginsWith %{SERVER_NAME}”

What it does is take the domain name from the ‘redirect_to’ variable and strip the leading http:// or https:// from it. Next, that is compared with Apache2’s SERVER_NAME variable. It is tested using ‘beginsWith’ so the rule can’t be bypassed using something like ‘redirect_to=http://evil.com/www.inliniac.net/’.

This way the logins work again and I still should be notified when someone tries this old (and patched) trick on me!

New WordPress issue + Snort and ModSecurity rules

I just read about a new issue with WordPress here at SecurityFocus. It’s a potential credential stealing vulnerability, so I quickly created these ModSecurity 2 rules:

SecDefaultAction “log,deny,status:403,phase:2,t:lowercase,t:escapeSeqDecode”
SecRule REQUEST_FILENAME “/wp-login.php$” “chain,msg:’WORDPRESS wp-login.php redirect_to credentials stealing attempt’,severity:2,t:normalisePath”
SecRule ARGS_NAMES “^redirect_to$” “chain”
SecRule ARGS:redirect_to “(ht|f)tps?://”

I can still login to my WordPress install, so it seems that the rule does no harm. Use at your own risk!

Update: I’ve created a Snort rule as well:

alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS $HTTP_PORTS (msg:”WORDPRESS wp-login.php redirect_to credentials stealing attempt”; flow:to_server,established; uricontent:”/wp-login.php”; nocase; uricontent:”redirect_to”; pcre:”/redirect_to=(ht|f)tps?://iU”; classtype:web-application-attack; sid:4000003; rev:1;)

Update 2: fixed the Snort rule, thanks to Shirkdog for pointing out that it had some broken pcre in it. The rule is now included in the BleedingThreats ruleset (check here), however that (slightly modified) rule doesn’t detect the attack for me.

Update 3: the Bleeding rule is now fixed. I’ve updated the above rule as well.

Update 4: updated the ModSecurity rule to prevent a possible evasion by prepending tab chars to the redirect url. Thanks to Ryan Barnett for pointing this out.