Blogger Widgets

Tuesday, 10 September 2013

SQL Injection Attack #WebSecurity #Infosec #Hacking #SQL



What are SQL Injection attacks?
 

SQL(Structured Query Language) injection attacks is a type of attack against websites where special constructed  web request are used to control the site database. Web-servers and application  servers interact with database servers anytime they need to store data or retrieve  data, or change some data, or delete data; and most database have a variant of a  language called SQL that is used to do this. So if an attacker is creating a SQL Injection attack they will actually build malicious SQL statements that are designed  to be executed along with the SQL statements that the site will be performing  normally, and this malicious statement will be included with otherwise be normal  request to the website
 

Why are they so prevalent?
SQL Injections attacks are increasingly prevalent as there's been a change in focus  where attacks are no longer focusing only on web-servers,operating system or  web-server software but also targeting the application layer and the custom code  that runs the site. Of this application level attack, SQL injection is particular  interesting because it's potentially very powerful if it's successful

What damage can be caused by a successful SQL injection attack?
A successful SQL injection attack could have a number of different outcomes:
A SQL Injection attack could be used to bypass the site authentication or  authorization; so this will let the attacker view the records on the database which  could be anything associated with that site, it could be customer data, credit card  numbers, account credentials and be through the entire data-set could be taken.

SQL Injection attack could also be used to modify the application database;so this  will be adding records, altering records or deleting records, adding a new account to  the database, adding a transaction, removing a transaction and it could be not just to  one part of the site, it could naturally be the site's entire database meaning that the  entire database of that site could be destroyed. Even worse if the database with the  database server is hosting content from multiple websites, the entire database with the data across all websites could potentially be infected either access, modify or  delete completely. 
In others circumstances SQL Injection attack could even potentially lead to a full  compromise of the database server allowing operating system level access and total  control of the server.





How do I know if my application are vulnerable to SQL Injection attacks?

Any of your applications that accept user input and store data in a back-end  database are vulnerable to SQL injection attack.Across the web this is a very large  class of applications if you think of banking sites,retail sites they all have those  common characteristics of interacting with users, letting users provide information,  but they also have databases in the back-end where they're working with that data  as well.
To detect SQL Injection attacks you can test for it in a number of different  ways:
You can use penetration testing or you can use static or binary analysis to detect.  It's important also to have security as a part of your development life cycle so that  new applications that are being build today already have the protection build in to  prevent SQL injection from the start
 



How do you prevent SQL Injection Attacks?
So you can prevent SQL Injection attacks through a number of best practices:

  1. First of all you can use prioritized or prepared statements those limit the amount  of influence that an attacker could possibly have against the queries run against the  database
  2.  Use input validation for the length,the type,the syntax or rather than the business  rules of the input coming form the user and it's important there to whenever  possible use known good validation versus known bad. It's alot easier to know that  US zip code has a specific format comprised of digits and possibly a dash versus  trying to eliminate all possible bad inputs such as trying to detect SQL statements  mixed in with an address or something.
  3. The third, use the lowest possible privilege for the database account. This doesn't  prevent SQL Injection attack but this will limit the possible damage as a result a  successful SQL injection attack. If an attack is successful the only damage that will be possible is whatever damage could be done with that account; for example if this  database hosts data for multiple websites and each website has it's specific user that  can only  access the data from that website, you don't have to worry about that  cross contamination where the attack against one site could affect data of the second  site.

Mozilla Recovery - crack master passwords #Passwords #Mozilla #Firefox



About the program
Requirements: Java 7 or a higher version

Posted Image

Once you start the program, it searches automatically for default locations of your key3.db in Firefox and, if not found, in the Thunderbird application directory. I prepared and tested this for Windows 7 and Linux. If it is not working for your OS, please tell me the default location for it. I just need the information to put that in. You can change the location by hand, of course.

key3.db is the file that is used to recover the master password. You can start a wordlist attack on that. The program ships with a default worldlist, but it is small (I didn't want to upload a wordlist file that adds several megabytes to the program). You can use your own list by changing the location.

Alternatively you can start a bruteforce attack by activating the "bruteforce" checkbox. Although I used threads, this is limited to a word length of five (a bruteforce attack with a wordlength of six would take several days, so I don't allow that) and the alphabet a-zA-Z by now. I got about 30000 password tests per second on my machine.

Once you got the master password, it is very easy to obtain saved login information from signons.sqlite, since both, Thunderbird and Firefox, will show usernames and passwords in plain text. (google if you don't know how)

Conclusion: Always set a master password if you save login information with Thunderbird or Firefox. Otherwise the login information can be obtained without any problems.

 

About the source

The only (non-standard) library I used is apache.log4j for logging purposes. You will see a properties file and a log folder. The standard logging level is WARN. If you change this level to INFO or DEBUG, the master passwords found with the program will be saved in there, so be careful with that option.

Lines of code without comments and empty lines: 914
Lines of code with everything else: 1141

The source is attached as Source.zip.

The code was tested for: Firefox 9.01 Thunderbird 9.01, Windows 7, Arch Linux
If you have a different setting, you can help me by telling me that it worked or that it didn't.
Edit: According to Kulverstukas and Superfly it works in Windows XP too. theellemist tested it on Windows Vista. Thanks to you.

Problems?

Please make sure that you have Java 7 or a higher version
* Mozilla Recovery.zip (471.23 kB -)
* Source.zip (452.76 kB -)

How Mozilla Saves Passwords #Programming #Passwords



This paper is written from the view of a programmer. It describes which algorithms are used by Mozilla to encrypt login data, i.e. saved passwords and usernames for websites in Firefox or the login data of your e-mail accounts in Thunderbird. I will provide some example code (Java) from this Mozilla Recovery program.


An information that you will find without problems is the location of your login data: It is the signons.sqlite (or signons.txt, signons3.txt in older versions), which can be found in the profile folder of your application.

First thing I did was researching about the sqlite format: http://www.sqlite.org/fileformat2.html
It is recommended to use a hex editor to compare the description with your own signons.sqlite file.
The format is well documented, so writing a program that obtains data from an sqlite file shouldn't be a problem.

Because I read that the data is encoded in Base64 and not encrypted if no master password is set, I copied a username entry and tried to decode. But it didn't work. I guess it worked with older versions. Now there is some kind of encryption too.

I searched for open-source programs that recover passwords from Firefox or Thunderbird and found this: http://securityxploded.com/thunderbirdpassdecryptor.php
Old website entries told me it was open-source, but I couldn't find any source to download. Old postings in the forum of securityxploded told me, that they changed this. Some people had used their code for writing maleware, so antivirus scanner recognized their program as a virus. It is pretty sad that the lazyness (not writing their own code, just grieving) and improvidence of some people forced the authors of ThunderbirdPassDecryptor to hide their knowledge. The further search for open-source programs was not fruitful.

In fact, signons.sqlite is useless without the key3.db file, which also resides in the profile folder of your application. This is where the trouble began. I couldn't find information about that file for a long time, so I downloaded the source code of Thunderbird, looked into it for several days and learned more about it's inner workings. I discovered that the login data in the signons.sqlite file is encrypted with TripleDES in CBC mode. The key used for the encryption is saved in key3.db and encrypted as well.

One day I stumbled on this website and it helped me a lot: http://www.drh-consultancy.demon.co.uk/key3.html
It describes how the keys in key3.db can be obtained. But not everything is correct anymore. Some changes are necessary.


First thing that made me think:
Quote
Initially you will need the database password

Where do I get that from?
I just guessed that this is the master password and was right.

I also got the idea that the entry values should follow right after the entry name (I am not sure if it is standard knowledge to do it in another way). I.e. looking at the key3.db in a hex editor you might get that picture on the plain text side:

...................password-check.Version..........

Which means the password-check entry would only have a one byte value. That couldn't be true. But the version entry which follows right after, only has a one byte value. So I tried it backwards, with the entry name following it's value (which lead to the problem to find out where the entries start). It was still not enough to get it working.

Since this website provides some test vectors (I am very grateful for that), I was able to implement and verify the decryption algorithm. Now I knew that it worked with the data on this website, but it still didn't work with my own key3.db file.
I can't really say how I got the idea, but I changed the length of the global salt entry from 16 bytes to 20 bytes. I guess it was just out of a hunch while looking at the hex values. Surprisingly this was the right thing. My test output decrypted the string "password-check" and I was happy. This is how I got the main algorithm for checking if a master password is the right one.

I still didn't implement a program for obtaining the login data out of signons.sqlite, once you got the key entries from key3.db. But my hunger for knowing how it works is satisfied and implementing it shouldn't be necessary at all. Reason: Thunderbird and Firefox show you the data (passwords included) in plaintext, if you know the master password. If no master password is given, the data is not secured at all, just encrypted with a hardcoded key: http://www.infond.fr/2010/04/firefox-passwords-management-leaks.html
(I didn't verify this yet, but I will)

How Mozilla saves login data:

Summary: login data is saved in signons.sqlite. It is encoded in Base64, encrypted with TripleDES in CBC mode and standard block padding. The key for the decryption is saved in key3.db. The entries in key3.db are encrypted with the master password. The decryption algorithm (of the key3.db entries) is not straight forward, but shown right after.

Sqlite Format: http://www.sqlite.org/fileformat2.html

Netscape Communicator Key Database Format: http://www.drh-consultancy.demon.co.uk/key3.html

Work through this description, but change the following:
  • the global salt value is 20 bytes (not 16 bytes) long (I think there may be a value indicating the length of the global salt somewhere)
  • the plain text entry names (i.e. Version, global salt) follow after their values
  • the database password is the master password
To verify the master password and your decryption algorithm, use the check-password entry. Its value is the encrypted string "check-password".

Java example code: extracted from MozillaRecovery

Key3.db key derivation algorithm:

The comments are in the notation of the website mentioned above.
Code: Java
  1. private static String decrypt(byte[] password, byte[] es, byte[] gs, byte[] text) {
  2.         try {
  3.             // HP = SHA1(global-salt||password)
  4.             byte[] hp = SHA.sha1(appendArray(gs, password));
  5.             byte[] pes = Arrays.copyOf(es, 20);
  6.             // CHP = SHA1(HP||ES)
  7.             byte[] chp = SHA.sha1(appendArray(hp, es));
  8.             // k1 = CHMAC(PES||ES)
  9.             byte[] k1 = SHA.sha1Hmac(appendArray(pes, es), chp);
  10.             // tk = CHMAC(PES)
  11.             byte[] tk = SHA.sha1Hmac(pes, chp);
  12.             // k2 = CHMAC(tk||ES)
  13.             byte[] k2 = SHA.sha1Hmac(appendArray(tk, es), chp);
  14.             // k = k1||k2
  15.             byte[] k = appendArray(k1, k2);
  16.             byte[] desKey = Arrays.copyOf(k, 24);
  17.             byte[] desIV = Arrays.copyOfRange(k, k.length - 8, k.length);
  18.             return new TripleDES(desKey, desIV).decrypt(text);
  19.         } catch (NoSuchAlgorithmException e) {
  20.             logger.fatal(e.getMessage());
  21.             e.printStackTrace();
  22.         } catch (BadPaddingException e) {
  23.             logger.debug(e.getMessage() + ". Probably wrong key.");
  24.         }
  25.         return null;
  26.     }


SHA-1 and HMAC-SHA1:
Code: Java
  1. import java.security.InvalidKeyException;
  2. import java.security.MessageDigest;
  3. import java.security.NoSuchAlgorithmException;
  4.  
  5. import javax.crypto.Mac;
  6. import javax.crypto.spec.SecretKeySpec;
  7.  
  8. public class SHA {
  9.  
  10.     private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
  11.     private static final String SHA1_ALGORITHM = "SHA-1";
  12.  
  13.     public static byte[] sha1Hmac(byte[] data, byte[] key) {
  14.         try {
  15.             SecretKeySpec signingKey = new SecretKeySpec(key,
  16.                     HMAC_SHA1_ALGORITHM);
  17.             Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
  18.             mac.init(signingKey);
  19.             return mac.doFinal(data);
  20.         } catch (NoSuchAlgorithmException | InvalidKeyException e) {
  21.             e.printStackTrace();
  22.         }
  23.         return null;
  24.  
  25.     }
  26.    
  27.     public static byte[] sha1(byte[] text) throws NoSuchAlgorithmException {
  28.         MessageDigest md = MessageDigest.getInstance(SHA1_ALGORITHM);
  29.         md.update(text, 0, text.length);
  30.         return md.digest();
  31.     }
  32. }}


TripleDES:
Code: Java
  1. import java.io.UnsupportedEncodingException;
  2. import java.security.InvalidAlgorithmParameterException;
  3. import java.security.InvalidKeyException;
  4. import java.security.NoSuchAlgorithmException;
  5. import java.security.NoSuchProviderException;
  6. import java.security.spec.InvalidKeySpecException;
  7. import java.security.spec.KeySpec;
  8.  
  9. import javax.crypto.BadPaddingException;
  10. import javax.crypto.Cipher;
  11. import javax.crypto.IllegalBlockSizeException;
  12. import javax.crypto.NoSuchPaddingException;
  13. import javax.crypto.SecretKey;
  14. import javax.crypto.SecretKeyFactory;
  15. import javax.crypto.spec.DESedeKeySpec;
  16. import javax.crypto.spec.IvParameterSpec;
  17.  
  18. public class TripleDES {
  19.     private KeySpec keySpec;
  20.     private SecretKey key;
  21.     private IvParameterSpec iv;
  22.  
  23.     public TripleDES(byte[] keyBytes, byte[] ivString) {
  24.         try {
  25.             keySpec = new DESedeKeySpec(keyBytes);
  26.             key = SecretKeyFactory.getInstance("DESede")
  27.                     .generateSecret(keySpec);
  28.             iv = new IvParameterSpec(ivString);
  29.         } catch (InvalidKeySpecException | NoSuchAlgorithmException
  30.                 | InvalidKeyException e) {
  31.             e.printStackTrace();
  32.         }
  33.  
  34.     }
  35.  
  36.     public byte[] encrypt(byte[] text) {
  37.         if (text != null) {
  38.             try {
  39.                 Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding",
  40.                         "SunJCE");
  41.                 cipher.init(Cipher.ENCRYPT_MODE, key, iv);
  42.                 return cipher.doFinal(text);
  43.             } catch (IllegalBlockSizeException | InvalidKeyException
  44.                     | InvalidAlgorithmParameterException
  45.                     | NoSuchAlgorithmException | NoSuchProviderException
  46.                     | NoSuchPaddingException | BadPaddingException e) {
  47.                 e.printStackTrace();
  48.             }
  49.         }
  50.  
  51.         return null;
  52.     }
  53.  
  54.     public String decrypt(byte[] text) throws BadPaddingException {
  55.         if (text != null) {
  56.             try {
  57.                 Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding",
  58.                         "SunJCE");
  59.                 cipher.init(Cipher.DECRYPT_MODE, key, iv);
  60.                 byte[] result = cipher.doFinal(text);
  61.                 return new String(result, "UTF8");
  62.             } catch (NoSuchAlgorithmException | NoSuchProviderException
  63.                     | NoSuchPaddingException | IllegalBlockSizeException
  64.                     | InvalidKeyException | InvalidAlgorithmParameterException
  65.                     | UnsupportedEncodingException e) {
  66.                 e.printStackTrace();
  67.             }
  68.         }
  69.         return null;
  70.     }
  71. }