Last Updated on Tuesday, 13 November 2012
I'm putting this article here so that I can run through a checklist when I am adding an input field to an interface.
Why?
There is a strange complacency in many applications released for public use which are vulnerable to SQL Injection. According to the industry over 60% of attacks on websites is through SQL-Injection alone.
How?
SQL-Injection is not as complicated as it is made out. An input field in a website form is where the hacker can add code that can drastically affect a database-driven website. Take a search engine for instance, this is a field which the end-user can freely enter any text they want, especially any code. But a search engine is just one example, you need to test EVERY input field the end-user can access. For more information on SQL-Injection, please read my article "Anti-SQL Injection Basics".
Tips
Avoid informative errors! For example: "error in script /mypath/myfile.php on line 81" are system errors which should NOT be displayed to the end-user as this can allow the hacker to examine the results and adapt their attack -> See "Blind SQL-Injection".
If you're expecting a number, then multiply by 1 My easiest fix but by no means a silver bullet, if your form submits a number and your receiving file expects a number, then multiply the submitted value by 1. In most cases, a string multiplied by 1 equals -1 (minus 1). Note: If a username is a number (eg. CustomerID=1234567890), test without apostrophes, eg. 1 or 1=1
Search-Engine apostrophes and quotes! End-users will want to use these in free-text so always check you account for this. (eg. Name=O'Reilly, SearchQuery="two words") I usually encode these temporarily between scripts to HTML or Numerical entities and then the results script would decode these.
Checklist
Advise the administrators of the server/service you will be testing SQL-injection. Advise them that your account will need to be unlocked or for your IP addressed to be un-banned. I would not recommend being added to the whitelist in case this permission is accidentally replicated on a production environment!
The first input fields I like to test are the "Search Engine" and the "Login Form" of a website, the below examples are testing a "Login Form":
- Random SQL
Type some random SQL for the input value and see if the server returns a message» Result should be "invalid username/password".- Username: SELECT Username FROM Users WHERE ID=1
- Password: SELECT MD5(Password) FROM Users WHERE ID=1
- Wildcards
Type an asterisk (*) as the input value and observe» Result should be "invalid username/password".- Username: *
- Password: <Leave Blank>
- The Classic
Type the following: ' or 1=1-- as the input value. Replace "aValidUsername" with a username you know exists (eg. admin).» Result should be "invalid username/password".- Username: aValidUsername
- Password: ' or 1=1--
- Variations of the Classic: Comments
Depending on your system, try inputting comment syntax. Replace "aValidUsername" with a username you know exists (eg. admin).» Result should be "invalid username/password".- Username: aValidUsername
- Password: ' or 1=1 /*IamJOE
- Variations of the Classic: Empty
Type the following: ' or ''=' as the input value (note that there is a space in front of the first apostrophe here). Replace "aValidUsername" with a username you know exists.» Result should be "invalid username/password".- Username: aValidUsername
- Password: ' or ''='
- Variations of the Classic: NewLines
Some scripts cannot interpret a newline, is it another query or does the script trim the last line submitted? Replace "aValidUsername" with a username you know exists.» Result should be "invalid username/password". New lines in SQL should be understood as \r\n.- Username: aValidUsername
- Password: '
- OR 1=1--
- Variations of the Classic: URL Encoded
Type the following: %27%20or%20%27%27%3D%27 as the input value. Replace "aValidUsername" with a username you know exists.» Result should be "invalid username/password".- Username: aValidUsername
- Password: %27%20or%20%27%27%3D%27
- DataType Conversions
Type a conversion:» Result should be "invalid username/password". Any other response should be addressed.- Username: CAST('username' AS SIGNED INTEGER)
- Password: <Leave Blank>
- Login and Login
Login as a standard user, and then try to login again without logging out in between.» Result should fail if system is set up properly and advise you you are already logged in.- Fix: Hide Login link once logged in.
- Login/Logout/Login
Do the following: Login, Logout, Login, Logout, Login, Login» Result should be the same as the previous test but we are testing session caching here.- Do this in as little time as possible.
- Correct ID
Enter a valid value and note the number of rows and what messages are returned.» Result should work as per usual.- Also: ${Test Request: Login#Response#//sam:loginResponse[1]/sessionid[1]}
- Expired Session
Login while logged out on the same day or when sessions are suspected for not changing.» Result should show new session and nothing conflicting.- Also test closing the browser and re-opening, then login.
- Expired Multiple Sessions
Try logging into the application with two instances of the viewer (eg. same user using 2 browsers looking at same site).» Result should error or deal appropriately with two sessions by the same user. Why does this matter? If your web-application only has 10 licenses for example, and an end-user can create more than one instance, if they create more than 10 then does your web-application stop working?- Open two browser instances.
- Guest Password
If you know of a valid username/password, check that your scripts do not validate on password alone.» Result should be "invalid username/password".- Username: Guest
- Password: <Password you know exists in system>
- Lost users
Type a random input value that the system is not expecting or that could not exist in the database.» Result should not give information as to how to validate your input (eg. "The specified username does not exist" or "Your username must consist of only letters and numbers"). Why does this matter? Here's a little game, try determining the username of the system administrator, the correct guess will more than often return "invalid password". The onus is on the web-developer to always return "invalid username/password" if there is any user/pass mismatch.- Username: '@#=6453kfe"
- Password: <Leave Blank>
- Lockout
If this is a login input, then test how many times you can try incorrect logins without getting locked out. If this is merely a websystem, test how many queries you can input before being locked out.» Result is you should be locked out of the system or be unable to execute further processes.- Copy & Paste Values and hit "Submit" button as many times as possible in under a minute.
- Element Duplication
If you can modify the URL, try submitting the same input field twice in one url (specify the parameter twice)» Result should demonstrate that the system can still understand the input and ignore the additional elements.- eg. /Login.php?username=myUsername&password=MyPassword&username=admin
- Element Ommission
Again if you can modify the URL, submit less than the expected input values (so if username&password required just send username).» Result should demonstrate that the system will advise on missing elements.- eg. /Login.php?username=myUsername
- Malformed XML
Need to create a posting form on a server that can communicate with the service you are testing. Create some XML file with invalid XML» Results should have no messages. Any error/validation messages should be suppressed in this case.- <login><username>joe&joe</username></login>
- The weirdest things happen with the weirdest content
If username is expected to be 25 characters, enter 26. If free-text field, then enter text of about 1000 lines.» Result should have no error messages or possibly a notification of a size limit. Lookout for timeouts and size limits as a giveaway for hackers.- y?2`Fg0y1&&qiJH`Gl<p5hRZp<g(ICZ{3<)(..:e|<xgWI9V,k4s<.[L-6p}WgZ]~h
- or copy & paste a Lorem Ipsum text (http://www.lipsum.com/)
- Xpath Injection variants
This is similar to SQL injection but the SQL is parsed and escaped among XML code which is used between many of our applications.» Result should be no messages or errors.- eg. <login>string(//user[username/text()='' or '1' = '1' and password/text()='' or '1' = '1'])</login>
- While we're here: Cross-Site Scripting (XSS)
The same fields you are testing can be vulnerable to XSS-Injection as well: Go to a field and type the following» If vulnerable: Will popup a message saying "XSS". Warning If not vulnerable, will submit a command that the system admins will know is an attempt of XSS-Injection!- <script>alert("XSS");</script>
Source(s):
- The Open Web Application Security Project (OWASP) - Prevention Cheat Sheet
- SQL-Injection Tests
- SQLDumper - Automated SQL-Injection - Reminder: advise monitoring admins that you will be running this or you may face legal action.
Latest Posts
-
Joes Revolver Map (JRM)
-
Fri 17-May-13
Hmmm... Sounds like a problem with the identifier. Was it working before and has there been a change ...
-
Fri 17-May-13
Hello Joel: Yes, I do have it published on all pages of the site. I just went back to Revolver maps to ...
-
Fri 17-May-13
Hi Bill, From the developers of RevolverMaps, "the module would need to be published on every page ...
-
Fri 17-May-13
Hi Bill, I'll investigate further as you're not the first to say this happens. In the meantime, simply ...
-
Fri 17-May-13
Its a great extension. But when I set it up I only show my presence on the 3D map and no other visitors ...
-
Fri 17-May-13


Comments
We had some breakins but nothing like that. Was it 11Gb of ASCII files or something binary? It's surprising because MediaWiki has a default installation which blocks most uploads. Did you find where they got through? (Our case was that they got through using URL encoded entities).
RSS feed for comments to this post