Thursday, April 24, 2014
Text Size

Basic Tests for SQL-Injection Vulnerabilities

I'm putting this article here so that I can run through a checklist when I am adding an input field to an interface.

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.

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".

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.


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":
  1. Random SQL
    Type some random SQL for the input value and see if the server returns a message

    1.  Username:     SELECT Username FROM Users WHERE ID=1 
    2.  Password:     SELECT MD5(Password) FROM Users WHERE ID=1 
    » Result should be "invalid username/password".

  2. Wildcards
    Type an asterisk (*) as the input value and observe

    1.  Username:     * 
    2.  Password:     <Leave Blank> 
    » Result should be "invalid username/password".

  3. The Classic
    Type the following: ' or 1=1-- as the input value. Replace "aValidUsername" with a username you know exists (eg. admin).

    1.  Username:     aValidUsername 
    2.  Password:     ' or 1=1-- 
    » Result should be "invalid username/password".

  4. Variations of the Classic: Comments
    Depending on your system, try inputting comment syntax. Replace "aValidUsername" with a username you know exists (eg. admin).

    1.  Username:     aValidUsername 
    2.  Password:     ' or 1=1 /*IamJOE 
    » Result should be "invalid username/password".

  5. 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.

    1.  Username:     aValidUsername 
    2.  Password:      ' or ''=' 
    » Result should be "invalid username/password".

  6. 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.

    1.  Username:     aValidUsername 
    2.  Password:     ' 
    3.                OR 1=1-- 
    » Result should be "invalid username/password". New lines in SQL should be understood as \r\n.

  7. 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.

    1.  Username:     aValidUsername 
    2.  Password:     %27%20or%20%27%27%3D%27 
    » Result should be "invalid username/password".

  8. DataType Conversions
    Type a conversion:

    1.  Username:     CAST('username' AS SIGNED INTEGER) 
    2.  Password:     <Leave Blank> 
    » Result should be "invalid username/password". Any other response should be addressed.

  9. Login and Login
    Login as a standard user, and then try to login again without logging out in between.

    1.  Fix: Hide Login link once logged in. 
    » Result should fail if system is set up properly and advise you you are already logged in.

  10. Login/Logout/Login
    Do the following: Login, Logout, Login, Logout, Login, Login

    1.  Do this in as little time as possible. 
    » Result should be the same as the previous test but we are testing session caching here.

  11. Correct ID
    Enter a valid value and note the number of rows and what messages are returned.

    1.  Also: ${Test Request: Login#Response#//sam:loginResponse[1]/sessionid[1]} 
    » Result should work as per usual.

  12. Expired Session
    Login while logged out on the same day or when sessions are suspected for not changing.

    1.  Also test closing the browser and re-opening, then login. 
    » Result should show new session and nothing conflicting.

  13. Expired Multiple Sessions
    Try logging into the application with two instances of the viewer (eg. same user using 2 browsers looking at same site).

    1.  Open two browser instances. 
    » 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?

  14. Guest Password
    If you know of a valid username/password, check that your scripts do not validate on password alone.

    1.  Username:     Guest 
    2.  Password:     <Password you know exists in system> 
    » Result should be "invalid username/password".

  15. Lost users
    Type a random input value that the system is not expecting or that could not exist in the database.

    1.  Username:     '@#=6453kfe" 
    2.  Password:     <Leave Blank> 
    » 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.

  16. 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.

    1.  Copy & Paste Values and hit "Submit" button as many times as possible in under a minute. 
    » Result is you should be locked out of the system or be unable to execute further processes.

  17. Element Duplication
    If you can modify the URL, try submitting the same input field twice in one url (specify the parameter twice)

    1.  eg.  /Login.php?username=myUsername&password=MyPassword&username=admin 
    » Result should demonstrate that the system can still understand the input and ignore the additional elements.

  18. Element Ommission
    Again if you can modify the URL, submit less than the expected input values (so if username&password required just send username).

    1.  eg.  /Login.php?username=myUsername 
    » Result should demonstrate that the system will advise on missing elements.

  19. 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

    1.  <login><username>joe&joe</username></login> 
    » Results should have no messages. Any error/validation messages should be suppressed in this case.

  20. 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.

    1.  y?2`Fg0y1&&qiJH`Gl<p5hRZp<g(ICZ{3<)(..:e|<xgWI9V,k4s<.[L-6p}WgZ]~h 
    2.      or copy & paste a Lorem Ipsum text ( 
    » 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.

  21. 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.

    1.  eg. <login>string(//user[username/text()='' or '1' = '1' and password/text()='' or '1' = '1'])</login> 
    » Result should be no messages or errors.

  22. 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

    1.  <script>alert("XSS");</script> 
    » 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!



Steve Moyer
# Steve Mon, 3rd September 2012
I'm using MediaWiki and someone managed to inject 11 gigabytes of data into our MySQL databases through the site. Is there a fix for this problem?
Like | Dislike | 0 Reply | Reply with quote | Quote
# Webmaster Tue, 11th September 2012
Hi Steve,

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).
Like | Dislike | 0 Reply | Reply with quote | Quote
# MohammadReza Sun, 1st September 2013
nice :-*
Like | Dislike | -1 Reply | Reply with quote | Quote
kumar prakash
# kumar Thu, 17th October 2013
Thanks for sharing this information.

Like | Dislike | +1 Reply | Reply with quote | Quote
Add Comment





Latest Posts

  • 301 Redirect using htaccess file

    • Tue 15-Apr-14
      Further suggestion:
      RewriteRule ^(.*/)?assets/s 2dmain.html\?/( .*/)? $2 [R=301,L]
    • Thu 10-Apr-14
      Playing with some RegEx testers
      RewriteRule ^(.*\?/)?(?:$|( .+?)(?:(\.[^.]$ )|$)) $2 [R=301,L] ...
    • Wed 09-Apr-14
      I tried to redirect links from my old site to my new site, based on what I read in this thread. The old ...
  • Joes Revolver Map (JRM)

    • Tue 22-Apr-14
      Hi Manfred, Some downloaders have reported that the version of this module intended for Joomla 2.5.x ...
    • Sun 20-Apr-14
      Hello, is it possible to use this module also in joomla 3.2? Thanks Manfred
      Manfred V.