Search code examples
pythondatabasesql-injectiontornado

Tornado: get_argument -- should I escape the input myself?


I'm running a Tornado web server for a single page application. The client is POSTing to the server and I'm using tornado.web.RequestHandler.get_argument() to get the input.

When testing, I can't seem to force an SQL injection bug. It looks like get_argument() somehow escapes the input. When doing a POST from a login-form (username + password) I've tried all sorts of tricks to force a simple SQL injection but to no avail.

EDIT2:

HAH! I managed to do an SQL injection at last :D I URL-escaped some of the input and I could see the injected SQL statement go all the way to the DB module. The query I generate from the login-form does not get committed, as it's just supposed to be a SELECT statement - so I couldn't actually alter the database.

If the query never gets committed and the output of the whole query (including the injected) is hidden, what kind of damage can be done ?

For instance if the query is supposed to be, say SELECT * FROM Users WHERE UserID='USERNAME' AND Password='PASSWORD'; but the input for username has an INSERT injected, so USERNAME becomes USERNAME'; INSERT INTO Users (UserID, Password) VALUES ('hacker', 'hacked'); -- we end up with:

SELECT * FROM Users WHERE UserID='USERNAME'; INSERT INTO Users (UserID, Password) VALUES ('hacker', 'hacked'); --' AND Password='PASSWORD';

I am aware of the dangers of SQL injections in general, I'm just curious regarding this detail. I'm also aware I should hash and salt passwords, the code above is a simplification for the sake of the example.


Solution

  • Tornado only escapes the strings in the templates to avoid HTML issues. If you're just doing something like print self.get_argument('ihack') you'll get the raw string that is sent.

    You should using MySQLdb with injection prevention:

     cursor.execute("SELECT * FROM user_info WHERE email = %s", email)
    

    Rather than:

     cursor.execute("SELECT * FROM user_info WHERE email = %s" % email)   # BAD!
    

    This will protected your SQL just like the templates protect your HTML.