4

I want to do a demo for a login page that is vulnerable to SQL injection for training purposes. I already tried to build one using PHP and MySQL. I commented the code sanitation to make the page vulnerable.

The login page code is this:

//step 1a: sanitise and store data into vars (storing encrypted password)
//$usr = mysqli_real_escape_string($dbc, htmlentities($_POST['u_name']));
//$psw = SHA1($_POST['u_pass']) ; //using SHA1() to encrypt passwords  
$usr = $_POST['u_name'];
$psw = $_POST['u_pass'] ; 

//step2: create query to check if username and password match
$q = "SELECT * FROM users WHERE userName='$usr' AND password='$psw'  ";

//step3: run the query and store result
$res = mysqli_query($dbc, $q);

Then, I tried to enter this in the user name and password fields: ' or '1' = '1

However, the web page tells me the user name and password is wrong. How can I make SQL injection work?

schroeder
  • 123,438
  • 55
  • 284
  • 319
user2192774
  • 295
  • 4
  • 8
  • 6
    For training purposes, I would highly recommend Damn Vulnerable Web App. http://www.dvwa.co.uk/ – tlng05 Feb 26 '15 at 18:56
  • 1
    Are you inputting your SQLi string in both fields at the same time? – schroeder Feb 26 '15 at 19:03
  • 1
    You should note that using prepared statements is the preferred way to prevent SQL Injection. While it should be fine here, falling into the habit of using `mysqli_real_escape_string` could lead to vulnerabilities down the road. – Abe Miessler Feb 26 '15 at 21:00
  • Where is the part that evaluates whether username and password where correct? – Gumbo Feb 27 '15 at 00:34

3 Answers3

2

If you are injecting both fields at the same time:

Think about the SQL string with the replaced text:

"SELECT * FROM users WHERE userName='$usr' AND password='$psw' "

becomes

"SELECT * FROM users WHERE userName='' OR '1' = '1' AND password='' OR '1' = '1' "

Can you run that query from a SQL prompt and get a response? I think you might find that the logic flow with all those ANDs and ORs will trip you up.

schroeder
  • 123,438
  • 55
  • 284
  • 319
  • Any time your SQLi doesn't work - try the resulting query string in a SQL prompt. 99% of the time, it's a misunderstanding of the SQL. – schroeder Feb 26 '15 at 20:01
1

As others have commented, you need to pay attention to the resulting SQL statement. With a SQLi you're typically only needing/wanting to inject on one field. As @schroeder noted, your example input ends up essentially with

SELECT * FROM users WHERE userName='' OR '1' = '1' AND password='' OR '1' = '1'

being sent to the SQL server. The AND and OR statements are hard to get to a point where they result in a true statement. This would be especially hard if you did not have access to the source code.

The typical trick to SQLi is to cause an end to the SQL statement and comment out the remainder of the query the code will build. So, if you enter

' or 1=1;--  

for the username and whatever you wish for the password the SQL statement that gets built is:

SELECT * FROM users WHERE userName='' OR 1=1;-- ' AND password='whatever'

*Edit: @gumbo pointed out MySQL requires a space after the --, which has now been added. Removing the ; may be required. Part of the fun of SQL injection is dealing with how each engine interprets SQL!

This allows you to avoid having to worry about how the rest of the statement is built because the remainder is not run. Here the database will not see/execute the password comparison part because it is part of a comment now. In the case where you can't see the source code you would try it first on username and then on password since you don't know which parameter would come first in the SQL statement.

Alex Kuhl
  • 251
  • 1
  • 5
  • You aren’t allowed to execute multiple statements with `mysqli_query`. And without the `;`, you would still end up with a syntax error as the comment delimiter is `-- ` with a space after `--`. – Gumbo Feb 27 '15 at 00:38
  • My mistake, didn't notice that in the original. My answer applies generally to SQL. If @schroeder is looking to demonstrate SQL injection it is probably easier to use mysqli::multi_query. – Alex Kuhl Feb 28 '15 at 02:45
0

If you use

userName: ' OR 1=1 -- .
password: whatever

You this query

SELECT * FROM users WHERE userName='' OR 1=1 -- .' AND password='whatever'
  • ' closes the string
  • OR 1=1 makes it ignore that userName='' does not match anything
  • With -- . you create a comment so it does not matter what comes afterwords.
  • The . is just in case you use this not in a form but in a URL because some browser will cutoff the space.

The query basically will be this:

SELECT * FROM users WHERE 1=1

Note that this will return all users. Depending on what code follows you might need to have exactly one user returned. For this you could limit the results:

userName: ' OR 1=1 LIMIT 1 -- .

Or you guess the username:

userName: admin' OR 1=1 -- .

Last but not least have a look at Starting with sandbox development

PiTheNumber
  • 5,394
  • 4
  • 19
  • 36