Security: Code Injection 101

One of the junior wizards on Astaria suggested yesterday that I should write an article about why the old housing system was removed, and what’s been done to fix it — always a hot topic.  I started to demur, since there’s a lot of complex technical issues involved that not a lot of people seem to be aware of, but then it occurred to me that some of these are fascinating topics in their own right.

So, courtesy of Clovis, today’s post is about security: specifically, basic fundamentals of code injection attacks.

Let us suppose that we have a login form on a bank website.  Upon providing valid credentials, this will return your bank balance.  It has not been secured against SQL injection.

We will have, likely, two input text boxes.  We’ll assume they’re called txtUsername and txtPassword, and that we can retrieve the contents of these in Visual Basic fashion by using the Text method.  Therefore, if you type in the username “guest”, then txtUsername.text will equal “guest”.

Underlying this login form we have a SQL database containing a table of usernames and their respective passwords.  Since we’re illustrating a very common security vulnerability on the web, we’ll assume we’ve failed utterly and have stored usernames and passwords both in plaintext, unencrypted.

Username | Password    | Balance
---------+-------------+----------
user1    | password    |    0.00
user2    | sex         |   19.41
user3    | FEm&gYfDP=R |  655.35
admin    | godlol      |  (null)

(user3 is much more secure than anyone else.)

Our website frontend contains a code statement which looks something very much like this:

string user, password, sql, balance;

username = txtUsername.text;
password = txtPassword.text;

sql_query = "select balance from table where username = '" + username + 
"' and password = '" + password + "'";

balance = SqlServer.execute(sql);

if (balance)

print "Your balance is " + balance;

else

print "Access is denied.";

...

So let’s walk through the logic.

  • User enters a username; we’ll pick “user1”, into txtUsername.
  • User enters their password, “password”, into txtPassword.
  • The value of txtUsername.text is stored to the variable “user”.
  • The value of txtPassword.text is stored into the variable “password”.
  • A string called “sql_query” is defined which will contain a line of SQL code.  After allowing for the username expansion, this string is defined as:
    select balance from login where username = 'user1' and password = 'password'
  • A connection is opened to SqlServer and the string sql_query is sent.
  • The SQL server returns the results of that SQL query, which in this case is “0.00” — the balance stored in the table — and that is saved to the variable “balance”.
  • If the balance is a valid value, then it’s assumed that authentication was successful, and that value is sent on to the user.  If not, then we assume that the user has failed authentication (because no valid row was found in the table with the correct username and the incorrect password), and the SQL server sent back a “null” response instead of a balance value.

So what is code injection?  Code injection is where an attacker can manipulate this process to execute code that the attacker specifies at some point in the process.

Suppose that a malicious user with knowledge of both the pseudo-language that we’re using for this front end, and SQL, gets ahold of this poorly secured system.  Being knowledgeable about code injection, instead of entering in a password, they enter this username:

' OR 1=1 //

Now, when they submit that along with any password imaginable, or none, step 5 builds the SQL statement:

select balance from login where username = '' OR 1=1 --' and password = ''

This modifies the behaviour: we’re returning a balance when there’s no username (the attacker doesn’t know anybody’s valid username) or when the number 1 equals the number 1… which is always.  The double-dash is a comment, which means “Disregard the rest of this line.”

So now the query returns a nicely formatted table of query results:

Balance
----------
  0.00
 19.41
655.35
(null)

This hasn’t gotten our malicious user the keys to the kingdom yet, but he’s definitely gained information which he’s not supposed to have; the balances of every user in the table.  From there, attacks can be refined with additional code and the information discovered in the previous queries.

What if they’re even more malicious than that?  After they’re done playing with the data, let’s put in the username:

' OR 1=1; drop table login --

Now our SQL query becomes:

select balance from login where username = '' OR 1=1; drop table login --' and password = ''

The semicolon tells the SQL server that it’s the end of the line of code, and the text afterward is treated as a separate statement:

select balance from login where username = '' OR 1=1
drop table login

The SQL drop table statement spits out all the data, and then deletes the entire login table.  Oops.

This is, obviously, a highly oversimplified example and takes into consideration none of the tricks which attackers can use to build information to more highly refine their queries.

SQL injection is one of the most common forms of code injection attack because SQL databases are ubiquitous online, especially for holding user credentials.  However, the basics of this attack can be applied to all manner of systems, languages, and platforms.

Her daughter is named Help I'm trapped in a driver's license factory.

4 responses to “Security: Code Injection 101

    • They were not secured against code injection attacks.

      Any time the mud (or any system at all, really) allows input to go directly from a user into an object, security needs to happen.

      In this case, somebody putting text into a room’s desc could use methods very similar to what I describe in this article to break out of the description string and insert arbitrary properties and function calls, if they knew enough about the lib to do so.

  1. It’s actually very simple. The new estate system does not actually directly produce code, but instead produces a series of data lists which are then applied to templates to produce the rooms you see. The system is referred to as “Virtualization” and the user at no time is allowed to directly interact with code. The old estate system however did not allow this. There are still ways to exploit code injection, but they’re very quickly being patched.

Leave a comment