views:

5431

answers:

10

Just looking at:

What does this SQL do:

Robert'); DROP
TABLE STUDENTS; --

I know both ' and -- are for comments, but doesn't the word DROP get commented as well since it is part of the same line?

+119  A: 

It drops the students table.

The original query in the school's program probably looks something like

var query = "SELECT * FROM Students WHERE (Name = '" + tbName.Text + "')";

This is the naive way to add user text to a query, and is evil. Since the student's name is "Robert'); DROP TABLE STUDENTS; --" the resulting query (after concatenation) is

SELECT * FROM Students WHERE (Name = 'Robert'); DROP TABLE STUDENTS; --')

which, in plain English, roughly translates to the two queries:

Get everything from the Students table where the student's name is Robert.

and

Delete the Students table and ignore everything else I say from this point on ') and any other query-breaking junk.

The ' in the student's name is not a comment, it's the string delimeter. Since the student's name is a string, it's needed to complete the hypothetical query (i.e., Name = ' ). Injection attacks only work when the SQL query they inject results in good SQL (good being very relative in this case).

Will
Good explanation, +1.
paxdiablo
Mmm, the WHERE with parentheses around the arguments is rather unusual, but at least it avoids a syntax error... :-)
PhiLho
Personally, I'd have named my son Robert'; drop table students;--, but then I'm not a cartoonist.
Will
Great explanation
Anoop
An example of someone with this very vulnerability: http://stackoverflow.com/questions/1608127/asp-net-how-to-edit-bit-data-type/1608270#1608270
Will
@PhiLho: If the original statement were an `INSERT`, then the parenthesis would make more sense. It would also explain why the database connection isn't in read-only mode.
dan04
Nice Explanation, +1
Azhar
+2  A: 

The '); ends the query, it doesn't start a comment. Then it drops the students table and comments the rest of the query that was supposed to be executed.

Jorn
+2  A: 

The ' character in SQL is used for string constants. In this case it is used for ending the string constant and not for comment.

Mr. Brownstone
+2  A: 

The writer of the database probably did a

sql = "SELECT * FROM STUDENTS WHERE (STUDENT_NAME = '" + student_name + "') AND other stuff";
execute(sql);

If student_name is the one given, that does the selection with the name "Robert" and then drops the table. The "-- " part changes the rest of the given query into a comment.

Paul Tomblin
It was my first thought, but you get a syntax error with the trailing closing parenthesis, no?
PhiLho
That's why there is a -- at the end, indicating the remaining text is a comment and should be ignored.
Will
+22  A: 

Let's say the name was used in a variable, $Name. You then run this query:

INSERT INTO Students VALUES ( '$Name' )

What you get is:

INSERT INTO Students VALUES ( 'Robert' );  DROP TABLE STUDENTS; --')

The -- only comments the remainder of the line.

sinoth
This is much better then the highest voted, because it explains the closing parenthesis.
Tim Büthe
+2  A: 

In this case, ' is not a comment character. It's used to delimit string literals. The comic artist is banking on the idea that the school in question has dynamic sql somewhere that looks something like this:

$sql = "INSERT INTO `Students` (FirstName, LastName) VALUES ('" + $fname + "', '" + $lname + "')";

So now the ' character ends the string literal before the programmer was expecting it. Combined with the ; character to end the statement, an attacker can now add whatever sql they want. The -- comment at the end is to make sure any remaining sql in the original statement does not prevent the query from compiling on the server.

Joel Coehoorn
+5  A: 

Say you naively wrote a student creation method like this:

void createStudent(String name) {
    database.execute("INSERT INTO students (name) VALUES ('" + name + "')");
}

And someone enters the name Robert'); DROP TABLE STUDENTS; --

What gets run on the database is this query:

INSERT INTO students (name) VALUES ('Robert'); DROP TABLE STUDENTS --')

The semicolon ends the insert command and starts another; the -- comments out the rest of the line. The DROP TABLE command is executed...

This is why bind parameters are a good thing.

Dan Vinton
+1  A: 

If you listen to the most recent blog.stackoverflow podcast, they actually discuss this.

EBGreen
Adding a link to the actual podcast would probably help, because *most recent* tends to change over time. Frequently.
Robert Koritnik
+9  A: 

No, ' isn't a comment in SQL, but a delimiter.

Mom supposed the database programmer made a request looking like:

INSERT INTO 'students' ('first_name', 'last_name') VALUES ('$firstName', '$lastName');

(for example) to add the new student, where the $xxx variable contents was taken directly out of an HTML form, without checking format nor escaping special characters.

So if $firstName contains Robert'); DROP TABLE students; -- the database program will execute directly on the DB the request:

INSERT INTO 'students' ('first_name', 'last_name') VALUES ('Robert'); DROP TABLE students; --', 'XKCD');

ie. it will terminate early the insert statement, execute whatever malicious code the cracker wants, then comment out whatever remainder of code there might be.

Mmm, I am too slow, I see already 8 answers before mine in the orange band... :-) A popular topic, it seems.

PhiLho
+3  A: 

A single quote is the start and end of a string. A semicolon is the end of a statement. So if they were doing a select like this:

Select * From Students Where (Name = '')

The SQL would become:

Select * From Students Where (Name = 'Robert'); DROP TABLE STUDENTS; --'

On some systems, the select would get ran first followed by the drop statement! The message is: DONT EMBED VALUES INTO YOUR SQL. Instead use parameters!

Ben Daniel