I searched all over google to see how it would be possible to bypass the following (it's from the high level of security from DVWA):


if (isset($_GET['Submit'])) {

// Retrieve data

$id = $_GET['id'];
$id = stripslashes($id);
$id = mysql_real_escape_string($id);

if (is_numeric($id)){

    $getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'";
    $result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );

    $num = mysql_numrows($result);


    while ($i < $num) {

        $first = mysql_result($result,$i,"first_name");
        $last = mysql_result($result,$i,"last_name");

        echo '<pre>';
        echo 'ID: ' . $id . '<br>First name: ' . $first . '<br>Surname: ' . $last;
        echo '</pre>';


Is it possible to crack that?

Also, my other concern is on Medium level. It does have the mysql_real_escape_string() working, but when you use the same SQL injection from Low level AND you remove the quotes, it bypasses the protection. Why is that? How come it was so easy to bypass mysql_real_escape string?

The code (concise version) of the Medium level is this:

   $id = $_GET['id']; 
   $id = mysql_real_escape_string($id); 
   $getid = "SELECT first_name, last_name FROM users WHERE user_id = $id";
  • You can look this: youtube.com/watch?v=I5nrCCL4LIc This video explain how you can succeed the sqli high with sqlmap.
    – user81420
    Jul 20, 2015 at 18:11
  • All they are doing is using the cached session files from their medium and low exploits. It doesn't work if --flush-session is specified. Jul 20, 2015 at 18:38

5 Answers 5


The ‘high’ example is not exploitable. It's not a good approach (in modern code you would use parameterisation instead of calling mysql_real_escape_string, and stripslashes is a relic of an era of magical quotes that is thankfully over), but it is designed not to be immediately vulnerable.

(To SQL injection anyway. It is vulnerable to HTML-injection leading to XSS issues, thanks to those horrible echos, but that's another story.)

How come it was so easy to bypass mysql_real_escape string? [in the Medium example]

Because mysql_real_escape_string is designed to escape characters for safety when included in an SQL string literal context. Without any surrounding single quotes in the query's injection point, you're not in a string literal context, you're in a raw SQL context.

  • 1
    The last part is very interesting. Could you expand on that string literal vs raw SQL context and how it changes things? Oct 4, 2013 at 11:01
  • @markus-tharkun because if you pass 3 OR 1=1 through mysql_real_escape string you still get 3 OR 1=1. If the query is built like $query = "$sql = select * from users where id = $id", then feeding 3 OR 1=1 will return all rows. whereas $query = "$sql = select * from users where id = '$id'" (note the quotes around $id) would prevent this type of injection.
    – longneck
    Oct 7, 2013 at 14:29

SQL Injection is not possible in this situation. This code is preventing SQLi properly and even if the platform is old or misconfigured, it should still be immune to SQLi.

... In a slightly different configuration it maybe vulnerable.

If is_numeric() was removed, mysql_real_escape_string() was replaced with addslashes(), and the server was configured to used the GBK language set, then there is the possibility of a multi-byte attack using the GBK language encoding.


Here's something interesting: The high level in DVWA is not meant to be exploitable. It's the "correct" and safe implementation of the concepts as the DVWA's author saw fit at the time. So, it's very natural that you're unable to perform SQL Injection at the high level. If you actually do, you would be discovering something new. A zero-day, maybe.

I've been playing with DVWA for years and I had to learn this the hard way.

  • 3
    It's still a silly implementation. Three different "sanitization" functions instead of converting to the appropriate type. Presumably it's an integer, so why not simply $id = intval($_GET['id'])? Oct 3, 2013 at 18:35
  • @CodesInChaos Hey, I agree with you. I wouldn't have done it that way either, but I've tried my best to make it clear in my answer that this is (apparently) what the DVWA's authors saw fit at the time. You're welcome to ask him/them.
    – Adi
    Oct 3, 2013 at 18:41
  • You have to be careful with intval and how it treats non numeric values. From the PHP documentation on intval: "Strings will most likely return 0 although this depends on the leftmost characters of the string". I don't see it causing an issue in this case, but it could though.
    – droope
    Oct 10, 2013 at 21:06

Prior to DVWA 1.9, DVWA was using 'high' as the highest security level while currently, they use 'impossible' security level. So in 'high', it is possible to do any other SQL injection for example input like: ' union select user, password from users; -- . Note that you should have space after -- else the command would be syntactically wrong.


The current code on dvwa for high level sql injection is vulnerable with the same approach.

if you just omit the Limit command from the sql query which you can do so by doing ex: a' or 1=1;#.

# mentioned over here will restrict the Limit command mentioned in the last of the query and bingo you get all the users and passwords.

  • I'm wondering if you've tested this with the current version of DVWA as the other answers all say that it is not exploitable. Dec 27, 2015 at 19:10
  • That is also claimed on this answer to another question. Dec 27, 2015 at 19:12
  • I've just tested it ... a' or 1=1;# didn't work on DVWA v1.8 SQLi high & medium. It only works for low level
    – Wolf
    Jun 21, 2020 at 7:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .