Security: Code Injection Attacks

Lecture Notes for CS 142
Spring 2012
John Ousterhout

  • Additional reading for this topic: none.
  • The general problem:
    • Attacker tricks victim application into executing code designed by the attacker.
    • Happens in situations where code and the data are intermixed and victim fails to properly escape data values.

SQL Injection

  • Suppose your server code generates a SQL query directly, using input provided by the user from a form field:
    advisorName = params[:form][:advisor]
    students = Student.find_by_sql("SELECT students.* " +
        "FROM students, advisors " +
        "WHERE student.advisor_id = " +
        "AND = '" + advisorName + "'")
  • Under normal conditions the SQL query will look like this:
    SELECT students.* FROM students, advisors
        WHERE student.advisor_id =
        AND = 'Jones'
  • What if an attacker enters the following name in the form field:
    UPDATE grades
        SET g.grade = 4.0
        FROM grades g, students s
        WHERE g.student_id =
        AND = 'Jones
  • Then the actual query will be:
    SELECT students.* FROM students, advisors
        WHERE student.advisor_id =
        AND = 'Jones';
    UPDATE grades
        SET grades.grade = 4.0
        FROM students
        WHERE grades.student_id =
        AND = 'Jones';
  • Injection can also be used to extract sensitive information
    • Modify existing query to retrieve different information
    • Stolen information appears in "normal" Web output
  • Solution: must escape special characters in queries:
    UPDATE blog
    SET message = 'This message isn''t a problem.'
    WHERE ...
  • Unfortunately, the escaping rules are complex and different in each database system.
  • Solutions in Rails:
    • Avoid find_by_sql. Other methods automatically handle escaping:
    • Use the Rails substitution mechanism: it will automatically escape special characters:
      Student.find_by_sql("SELECT students.* " +
          "FROM students, advisors " +
          "WHERE student.advisor_id = " +
          "AND = ?", params[:form][:advisor]) 
  • In other frameworks, use parameterized SQL or prepared statements:
    • Specify a statement in advance, with placeholders for dynamic data
    • Execute statement later, providing values for placeholders
    • Database library takes care of escaping any special characters in the values.
    • Example (PHP):
      $statement = odbc_prepare($connection,
              "SELECT * FROM students WHERE advisor = ? AND gpa >= ?;");
      odbc_execute($statement, array($advisor, $gpa));
    • Example (Java):
      statement = connection.prepareStatement(
          "SELECT * FROM students WHERE advisor = ? AND gpa >= ?;");
      statement.setString(1, advisor);
      statement.setString(2, gpa);
      ResultSet rs = statement.executeQuery();

Stored XSS

  • Many injection attacks are in the category of cross-site scripting (XSS) attacks.
  • Stored XSS: attacker stores attacking code in a victim Web server, where it gets accessed by victim clients.
  • Enabled if the server fails to escape data in template substitution, e.g.:
    <div class="blogComment">
      <%= @comment.message.html_safe() %>
  • Attacker types in a blog comment like the following:
    I agree completely with Alice ...
    <script>"" + document.cookie)
  • Even better, create an invisible iframe for the evil URL so there is no sign of the attack.

Reflected XSS

  • Suppose server echoes user-supplied data (e.g. search term) and fails to escape special characters:
    <h1>Search Results</h1>
    Results for <%= params[:searchTerm].html_safe() %>
  • Suppose attacker can trick user into submitting a URL with the following value for the searchTerm query value:
    <script>"" + document.cookie);
  • Allows attacker to steal session info and impersonate user.
  • How to get user to submit that URL?
    • Step #1: lure user to attacker site:
      • Sponsored advertisement
      • Spam email
      • Facebook application
    • Step #2: HTML provided by attacker contains harmless-looking link.
    • Step #3: user clicks on link, unaware of the actual contents.
    • May not even need user's help: attacker HTML can automatically load the link in an invisible iframe.
  • Moral of the story:
    • Never ever display user-supplied data without escaping.
    • Crucial for frameworks to escape by default.