New malware with user-agent value: Parser::Template::Auto=CODE()

There is a new piece of malware attempting to guess WordPress account credentials. You can recognize it by its odd user-agent header. Here is the first one I saw:

Parser::Template::Auto=CODE(0xa1d5ff0)

All subsequent occurrences have been identical other than the hexadecimal value inside the parentheses.

The first incidence of this user-agent on my site occurred at 2015-09-02T07:35:06 UTC; that is, ten days ago. Since then I’ve seen at least 241 attacks with that signature (see note below). Googling for "Parser::Template::Auto=CODE" (including the quotes) returns a lot of hits from web log analysis tools. I didn’t see any predating the first instance I found in my logs. Which isn’t to say there aren’t any but it’s pretty clear this malware probably started attacking within a day or two of the first attack my system logged. Which is to say, around September 1st.

Of those 241 attacks the breakdown by country is

  46 NL
  43 FR
  34 US
  25 CH
  24 DE
  18 GB
  13 SE
  11 RO
   5 CZ
   3 LU
   3 CA
   2 UA
   2 RU
   2 PL
   2 MD
   2 FI
   2 BY
   1 SK
   1 HU
   1 ES
   1 AT

More interesting is that 218, 90%, of those 241 attacks originated from ToR exit nodes. The remaining 23, 10%, are probably ToR exit nodes since they originate from cloud hosting providers with known ToR exit nodes and whose reverse-DNS (rDNS) host names are generic (e.g., ovh.net addresses) or highly suggestive (e.g., privateinternetaccess.com).

Based on the double colons and CODE token I am confident this is from a Perl language module meant to convert templates into concrete text. Most likely the person using the module made a mistake in how they invoke the method thus causing the module to emit a diagnostic rather than the expected interpolated template. However, I did a bit of Googling and searching CPAN and could not find a published module with that signature. So another possibility is this is a module written by the malware author.

Note: I say “at least 241 attacks” because I installed the Mac OS X El Capitan “golden master” release during this period which resulted in my losing almost a full days worth of Apache logs.

P.S., The address 18.243.0.29 shows up in my logs with this attack signature. That address is owned by MiT and resolves to hostname zscore.mit.edu. That does not appear to be a known ToR exit node but MiT does have many known ToR exit nodes so I would not be surprised if this address was simply not yet classified as such.

Update 2015-09-15: Given that all the attacks appear to be originating from ToR exit nodes it occurs to me the strange user-agent header could be the result of ToR software anonymizing the request rather than a characteristic of the malware. In other words the odd HTTP user-agent header might be just an artifact of the malware using ToR to hide the origin of the attack and not a mistake on the part of the hacker.

Hosting provider ovh.net is incompetent at handling abuse reports

Hosting provider ovh.net has published WhoIs data that says they handle abuse reports at the email address abuse@ovh.net. So I dutifully reported a WordPress account credential guessing attack that began on 2015-03-18. I sent emails on 2015-03-25 and again on 2015-06-04. As of today, 2015-06-14, three months after the first attack I’m still seeing attacks from that server. This was my first email (I’ve clipped the log records I included to just the first one):

from:    Kurtis Rader 
to:      abuse@ovh.net
date:    Mon, May 25, 2015 at 5:56 PM
subject: HTTP attack from your network (188.165.61.65)

Timestamps UTC-7. My IP 75.101.21.75.

2015-05-24T17:53:47 1432515227.388128 403 address-blacklisted 4773 808 188.165.61.65 www.skepticism.us "POST /wp-login.php HTTP/1.1" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)"

So I called their support phone number. The support representative told me abuse emails are handled automatically. He implied that no human is ever involved in handling those emails but I couldn’t get him to say so directly. He said that the only sure way to get Ovh.net to pay attention was to use their abuse web form. Which is the most annoying such form I’ve ever encountered.

This is the type of behavior that makes the balkanization of the Internet more likely. ISPs and hosting providers need to take security far more seriously and ruthlessly disconnect systems that are infected by malware.

Updated 2015-06-18: I just noticed that web crawler [AhrefsBot](http://ahrefs.com/robot/) is hosted by ovh.net. Yet AhrefsBot is an example of a web crawler that is a good Internet citizen. It identifies itself, honors robots.txt, and has never done anything to trip my extremely aggressive blacklist rules. Not every ovh.com customer is an asshole. I simply wish ovh.com would be more aggressive about dealing with the idiots who let their servers be infected with malware.
Updated 2015-07-13: Someone emailed me asking why their computer was blocked by my server. They also complained that another site had blocked his OVH server. Which prompted me to check if 188.165.61.65 was still attacking my server. Yes, it is. It made fifteen WordPress credential guesses less than a week ago on 7/7. That server has been attacking my server for four months and continues to do so after I’ve reported the abuse to OVH three times. And there are another 30 OVH servers that have been attacking mine for as long as two months. So, yes, I stand by my assertion that OVH has an incompetent abuse department.

New WordPress attack: POST /wp-admin/maint/repair.php

Update: I received the following reply from Dion Hulse speaking on behalf of the WordPress project in response to my email to security@wordpress.org. He points out what should have been obvious to me: the malware is probably probing for details about the database schema in hopes of crafting SQL injection attacks.

The 'pass' and 'p2' parameters have never been used, nor have any effect, on the maint/repair.php script. It's possible that these could be used by a plugin though.

The script in question is a tool for when a database has become corrupt, and user-logins are no longer possible (for example, the user table has crashed), because of this, no user authentication is handled on the request.

The authentication which the script relies upon is the existence of the 'WP_ALLOW_REPAIR' constant, which a remote user cannot trigger, only someone with code-level access to the server can.

My assumption here is that they're searching for WordPress installs which have incorrectly left the script open and available, they could use this to discover the database table prefixes, which in itself doesn't give them much details, but could be used to get a more reliable SQL Injection through a vulnerability in a plugin. The chances of all these aligning is very small though.

The following trac ticket has a few improvements which could be made to this script:
https://core.trac.wordpress.org/ticket/11717 

Today I logged a new attack against my WordPress installation. Malware is now issuing POST /wp-admin/main/repair.php (and rrepair.php) requests. The data in all four requests is the following:

pass=asldkjsdfhoiuer3u98iuefghkjdbvmnbkjhas398&p2=ZWNobyAieHh4ISEheHh4Ijs=

WordPress quite unhelpfully returns a 200 (OK) HTTP status even though the request was rejected. This is something about WordPress that really irritates me. It frequently reports a OK HTTP status when in fact something went wrong; e.g., an authentication failure. In this particular case the failure is because I have not enabled the feature. How did I learn this? I created a file named wp-repair-post.req with the content of the request sent by the malware:

POST /wp-admin/maint/repair.php HTTP/1.1
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Content-Length: 74
Host: www.skepticism.us
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://www.skepticism.us/wp-admin/maint/repair.php
Cookie: wordpress_test_cookie=WP+Cookie+check

pass=asldkjsdfhoiuer3u98iuefghkjdbvmnbkjhas398&p2=ZWNobyAieHh4ISEheHh4Ijs=

I then manually sent that request to my web server:

nc localhost 80 < wp-repair-post.req

The output from WordPress helpfully told me:

To allow use of this page to automatically repair database problems, please add the following line to your wp-config.php file. Once this line is added to your config, reload this page.

define('WP_ALLOW_REPAIR', true);

I then enabled that feature and reissued the request. This time WordPress returned a HTML page that included a button with the link repair.php?repair=1. So I modified the request to include that query string.

Holy shit! Even though the passwords in the post are completely bogus WordPress reported that it did in fact perform a repair:

The <code>blog_users</code> table is okay.
The <code>blog_usermeta</code> table is okay.
The <code>blog_posts</code> table is okay.
The <code>blog_comments</code> table is okay.
The <code>blog_links</code> table is okay.
The <code>blog_options</code> table is okay.
The <code>blog_postmeta</code> table is okay.
The <code>blog_terms</code> table is okay.
The <code>blog_term_taxonomy</code> table is okay.
The <code>blog_term_relationships</code> table is okay.
The <code>blog_commentmeta</code> table is okay.
Repairs complete. Please remove the following line from wp-config.php to prevent this page from being used by unauthorized users.

<code>define('WP_ALLOW_REPAIR', true);</code>

The /wp-admin/maint/repair.php URI performs no authentication. WTF! Who in the hell thinks an unauthenticated administrative interface is acceptable in the year 2015?

What is unclear is why the malware is probing that URI. On the bleeding edge WordPress 4.2.3 release I’m running the “pass” and “p2” parameters appear to be ignored. Are they utilized on earlier versions? If so then these probes might be a way to verify whether a password is valid. Is the malware simply trying to overload the site with database repair activity? Whatever the case I’ve opened an enhancement request to make this interface authenticate the request and filed a security report with security@wordpress.org.

web passwords to avoid

I set this web server and WordPress blog up three weeks ago. Since then there have been eleven attempts to hack it via password guessing. Below is a table of the passwords the hackers tried for your amusement. The login names tried were admin, my user name (from my email address), and variations of the blogs host name. If any of your passwords look like these you should consider changing your password to something stronger.

password password password password
0 00 000 0000
00000 000000 0000000 00006666
00009999 010203 012345 0123456
012345678 0123456789 1 10031990
100483 100500 100656 100660
100789 10081976 10091965 101010
101165 101182 1011990 10121982
100789 10081976 10091965 101010
101165 101182 1011990 10121982
1031970 1031974 1031991 10387
1041987 1051957 1091983 11
11011977 1101988 1101990 111
1111 11111 111111 1111111
11111111 111222333 112112 112233
11223344 1122334455 12 12081964
121121 121212 12121212 123
123098 123123 123123123 123123a
123321 1234 12341234 1234321
12344321 12345 123454321 123456
1234565 1234567 12345678 123456789
1234567890 1234567890qwert 123456789qwerty 123456a
123456q 12345a 12345q 12345qwert
1234qwer 1234rewq 123654 123890
123qwe 123qwe123 12qwaszx 13
130175 13021984 13121965 131313
135 14 140361 140394
140578 14061986 14071959 140989
147258 147852 15 150493
159357 159753 159951 16
160383 160873 161095 17
17011977 170188 17031987 171095
180765 18121995 19011992 190466
19051966 19071983 190993 19101987
191085 1912 19121963 1928
1951 1976 1nternet 1q2w3e
1q2w3e4r 1q2w3e4r5t 1q2w3e4r5t6z 1q2w3e4r5t6z7u
1qaz2wsx 1qaz2wsx3edc 1qazxsw2 1qw23e
2 20 2002 200677
200687 2007 200886 201083
202020 2041987 20773 2081970
21 2101962 210384 210579
210580 210674 210693 2112
21 2101962 210384 210579
210580 210674 210693 2112
212121 220883 220890 220957
222111 22222 222222 223344
2243 230291 230486 232323
2345678 240286 246 249
250489 250664 252525 260296
260687 261073 261084 262546
270799 270882 270992 271165
280183 280186 280880 281186
281256 290569 290579 290670
291185 291268 3 300193
300584 300892 310385 310592
3121991 31295 321 321123
321321 33333 3333333 33333333
336699 343434 34521 345qwerty
369 369369 4011991 4031972
4041978 41078 4121989 41292
424242 4321 444 4444
44444 445566 456321 456789
45M2DO5BS 505050 50761 50780
50991 5111980 5252 531531531
555 5555 55555 555555
555666 5678 576823 6021980
60455 60678 60890 6091970
60994 6121998 654321 666
666666 66666666 6969 696969
69696969 7007 7071955 7081973
7654321 777 777777 7777777
789456 789789 789987 80163
8021995 80876 87654321 888
8888 88888 888888 8888888
88888888 9021957 9021989 9021996
90591 9081942 911911 9121976
91276 92072 98765 9876543
90591 9081942 911911 9121976
91276 92072 98765 9876543
987654321 9876543210 9988 999
9999 99999 999999999 a12345
aaa aaaa aaaaaa aaaaaaa
aaaaaaaa aaaaaxxxxx abc123 access
adgj adm admin admin1
admin12 admin123 admin1234 admin123456789
admin1234567890 admin1235 admin2011 admin2014
adminadmin adminadmins adminemail Administrator
administrator123 adminpass admin_password angle
asd123 asdasd asdf asdfgh
asdfghjkl asdfzxcv asdzxc cooladmin
david demo flvbybcnhfnjh fred
future garena gfhjkm ghbdtn
klaster krader linux ljgda
louis margaret mars mercury
mypass nokia orange P%40ssw0rd
pass pass1234 passw Passw0rd
passwd pAssword password1 passwords
piyrw q1w2e3 q1w2e3r4 q1w2e3r4t5
qazwsx qazwsxedc qazxsw qazxswedc
qazxswedcvfr qazzaq qetu qqq111
qqqq qqqqqq qwas qwaszx
qwe qwe123 qwe123asd qwe321
qweasd qweasdzxc qweqwe qwer1234
qwerasdf qwert qwert123 qwert12345
qwerty qwerty12 qwerty123 qwerty123456
qwerty7 qwertyu qwertyui qwertyuiop
root samsung secrecy secret
Sendit skepticism skepticism.us Soccer
support123 test test123 user
user123 xxx xxxx zxcv
zxcvbn zxcvbnm zxscvfbnh zzzzxxxx