Contents tagged with Injection

  • Using client templates, part 1

    Last week, we shipped the first preview for the Ajax work we're doing in ASP.NET 4.0 under the simple form of a simple script file (release and debug versions). This should show how much emphasis this release puts on the client-side. As a matter of facts, I'll use a plain HTML file here instead of an ASPX file to make it perfectly clear that everything here (except for the web service that provides the data) runs on the client.

    One of the scenarios we're trying to improve is updating parts of the page with new data without a postback (in other words, Ajax). That's a scenario you could implement in a number of manners. First, you could put an UpdatePanel control around your server rendering of the data and be done with it. That works, but is a little more chatty than you'd wish. It's all the chattier if you're dealing with a relatively large page with a lot of ViewState (in which case your small partial update pays a tax for the rest of the page that won't get updated). Even without ViewState, HTML isn't necessarily the most compact representation of your data.

    It's usually more efficient, at least in terms of network traffic, to transmit pure JSON data and do the rendering on the client. Now doing that without a proper template engine is clearly not the best use of your time. You could do it either with DOM APIs and a hard to maintain mess of document.createElement and appendChild calls, or you could concatenate strings. The latter solution isn't much easier to maintain (how do you explain your HTML designer how to modify that stuff?) and is quite dangerous, in the same way that building a SQL query using string concatenation is. Nobody in their right mind does that anymore, right? I mean, ...right?

    A good template engine should be highly readable, as close to designable HTML as possible (bonus points if it *is* a version of HTML that can be validated), it must have a good expression language and should perform well.

    Our engine is using markup that can be (but doesn't *have* to be) valid XHTML, it uses JavaScript as the expression language (which means you don't have to learn yet another language), and we're quite pleased with how it performs. Let's have a look.

    The page we're building here is a very simple example of getting some data from a web service (names and photos) and rendering that on the client. Here's what the template looks like:

    <div id="peopleIKnow" class="sys-template">
        <fieldset>
            <legend>{{ FirstName }} {{ LastName }}</legend>
            <!--* if (Photo) { *-->
            <img sys:src="{{ 'Images/' + Photo }}"
    alt="{{ FirstName + ' ' + LastName }}" /> <!--* } *--> </fieldset> </div>

    And here's what it renders like:

    A few things to notice here.

    The syntax to insert data, be it into text nodes or attribute values, is {{ expression }}, where expression is any valid JavaScript expression. The most common case will be that you want to inject a column of the current data item. For that case, you won't have to use anything like the server-side's Eval("columnName") or anything like Container.DataItem.columnName or $T.row.columnName. You just use the column name and that's it: {{ FirstName }}. This will just inject the value of the FirstName column into the markup. And of course when you need something more complex, like a combination of columns or some additional formatting, you have all the power of JavaScript and the Ajax library at your disposal.

    The alt attribute of the image is one example of that: here, we're combining the first and last name. You could be tempted here to do something like alt="{{ FirstName }} {{ LastName }}". This won't work as the engine only accepts expressions for the full attribute and within text nodes (in the same way that on the server-side, <%# %> blocks have to be the full attribute).

    The src attribute is one of those attributes that you have to prefix with the system namespace sys if you want to bind them (together with id, checked and a few others). There are several reasons for that. First, the template is part of the initial markup of the page. If you used src as usual here, the browser would try to download an image named "{{ 'Images/' + Photo }}", which will of course result in an unnecessary network request, a 404 and some junk in your server logs. Second, an Internet Explorer bug prevents us from reading the binding expression from the DOM (the browser won't give you the actual value that you set, but will always give you what it thinks is the right value, in this case the server-resolved url, which is useless to us). Finally, it can help achieving XHTML compliance (for which, I know, there is a small violation in this template in that the imag tag is missing an actual src attribute, which you can fix -if you have to- by including a src="about:blank" attribute). Some attributes don't accept just any value in XHTML. To summarize, if binding an attribute directly doesn't work, chances are prefixing it with "sys:" just will.

    Last thing is this weird comment block, which we're using to mix JavaScript code into the markup. More precisely, we're doing conditional rendering of the image depending on the existence of the Photo field. There has been much debate over the use of a special comment-based syntax for this. We don't especially like using comments here as we agree that you should ideally be able to remove comments from markup without any impact. We decided to use them anyway because there wasn't a better solution that was still compatible with our XHTML constraint. We did consider admitting both <!--* *--> blocks and something like <script type="application/ms-template"> but that just seemed too verbose and it's rarely a good thing to have two solutions for exactly the same problem. It would be interesting to hear your comments on that, by the way...

    So how do you transform this template into markup? Depends whether you're a component developer, in which case you're going to use the template APIs directly from your component, or if you're an application developer. I'll focus on the latter in this post.

    To render the template with data, you simply instantiate a DataView control and feed it data:

    var peopleIKnowView = $create(Sys.Preview.UI.DataView, {}, {}, {},
    $get("peopleIKnow")); PeopleIKnow.GetPeople(function(results) { peopleIKnowView.set_data(results); });

    In this code, we're using $create to create and initialize an instance of DataView on the "peopleIKnow" div tag, then we invoke the web service, and set the data property on the Dataview control from the callback function of the web service call. That's it.

    Next time, I'll get into more details into what really happens when you instantiate a template, and I'll give some debugging tips.

    The full code for this can be downloaded here: http://weblogs.asp.net/bleroy/attachment/6461783.ashx. Included script files are subject to the licenses for the Ajax Library and ASP.NET Ajax 4.0 CodePlex Preview 1.

    Part 2 can be found here: http://weblogs.asp.net/bleroy/archive/2008/09/02/using-client-templates-part-2-live-bindings.aspx.

    Read more...

  • New tools to prevent SQL injection attacks

    I've blogged in the past about injection attacks. Microsoft publishes additional new tools to detect and protect against injection attacks. The first tool, developed by HP, crawls web sites to automatically detect possible attacks, the second blocks dangerous requests from being executed, and the last one analyzes code to look for dangerous practice.

    http://www.microsoft.com/technet/security/advisory/954462.mspx

    Read more...

  • Please, please, please, learn about injection attacks!

    I answer a lot of posts on the forums of the ASP.NET site. And more often than I would like to, I answer a different question than the one the poster asked, because I happened to easily spot a potential injection attack in the posted code.
     
    Now, what is an injection attack? If you don't know and you're a web developer, you're in trouble. Read on.
     
    There are mainly two types of injection attacks, but both use the same vector of penetration: unvalidated user input.
     
    Rule #1: User input is EVIL (pronounced eyveel, like the doctor of the same name) and should never be trusted. Validate all user input. In the case of a web application, user input is form fields, headers, cookies, query strings, or any thing that was input or sent by users (that may include some database data, or other sometimes more exotic input like mail or ftp).
     
    The first type of injection attack, and the most deadly for most web sites are SQL Injection Attacks. It happens most of the time when the developer injects user input into a SQL query using string concatenation. For example:

    SqlCommand cmd = new SqlCommand(
      "SELECT ID, FullName FROM User WHERE Login='"
      +
    Login.Text
      + "' AND Password='"
      +
    Password.Text
      + "'");
     
    This is C#, but I'm sure our VB programmer friends will get the idea (+ means &). This code is simply frightening, but I've seen it or a variation on it so often I just can't count. OK, why is it frigtening? Well, try to enter these strings into the login and password textboxes:
    ' OR ''='
     
    There, you're authenticated! What happens is simple. Instead of being the simple text that you expected, the user input some evil text that contains the string delimiter and some SQL code that you're very generously executing.
     
    Of course, this is not the worse that could happen. Any SQL command could be executed, especially if you've been careless enough not to restrict the rights of the ASP.NET user on your database. For example, the user could very well steal all the information in your database, completely obliterate it or even take complete control of the server. This leads us to rule #2, our fisrt counter measure:
     
    Rule #2: Secure your database: don't use the sa user to connect to the database from your application, have a strong password on the sa user (and on any user), preferably use integrated authentication to keep all secrets out of your connection string and config file, and restrict the authorizations on your database objects to what's absolutely necessary (don't give writing rights to internet users except on log tables or forum tables, for example). This way, even if you accidentally write injectable code, the database will refuse to execute anything harmful beyond information disclosure (which could still be pretty bad). Please note that the above injection example will still work even if the database is secured.
     
    So it may seem at first that the quotes are the usual suspects in this case. Actually, if you use this kind of code, you may have noticed a few glitches for example if people have legitimate quotes in their names. So what many people have been doing for a long time is to double the quotes in the input strings, something like Login.Text.Replace("'", "''"), or replace them with another harmless character (you can recognize these sites usually because they use the ` character instead of quotes). This gives a false sense of security, which is sometimes worse than no security at all. Consider this request:

    "SELECT FullName FROM User WHERE ID=" + Identity
    .Text
     
    Here, no need for quotes to inject code, all you need is space and letters. Enter 0 DELETE * FROM User into the textbox, and there goes your User table. And I'm sure a hacker creative enough could come up with wicked injections that don't even need spaces. Escape sequences in particular are a usual way to pass characters that were thought to be invalid in many applications (including, yes, Microsoft products whose name have two letters, begin with I and end with E). This leads us to the third rule:
     
    Rule #3: Black lists are always incomplete (because hackers are many and potentially smarter than you). If you have to, rely on white lists, but never black lists.
     
    A black list is a list of all characters you consider evil (like the quote). There will always be something missing in it. Consider this as a fact (even though of course it can be complete, but you should act as if this was not the case).
     
    A white list is a list of authorized characters. What's great about it is that you know precisely what's permitted (what's in the list) and what's is forbidden (everything else). In the last example, restricting ID.Text to numeric characters is enough to secure the request.
     
    And now for the good news. While it is useful to know all this about SQL Injections, the .NET framework (and all modern development frameworks, like Java) provide an excellent way to prevent injections: parametrized queries. Parametrized queries are safer, cleaner and make your code easier to read. Here are the two previous examples, rewritten as parametrized queries:

     

    SqlCommand cmd = new SqlCommand("SELECT ID, FullName FROM User WHERE Login=@Login AND Password=@Password");
    cmd.Parameters.Add("@Login",
    SqlDbType.NVarChar, 50).Value = Login
    .Text;
    cmd.Parameters.Add("@Password",
    SqlDbType.NVarChar, 50).Value = Password.Text;

    SqlCommand cmd = new SqlCommand("SELECT FullName FROM User WHERE ID=@ID");
    cmd.Parameters.Add("@ID",
    SqlDbType.Int).Value = int.Parse(Identity.Text);

    This way, there is no need to escape any characters because the parameter values are directly communicated in a strongly typed manner to the database.
     
    N.B. In the second example, you may also want to use validator controls on the Identity TextBox, and check the validity of the page server-side before you build and execute the SQL query using Page.IsValid.
     
    Rule #4: Use parametrized queries whenever possible.
     
    Whenever possible? Does that mean that it's not always possible? Well, here's a little problem I got from the ASP.NET forums: you have a list of checkboxes on a page that have numeric identifiers as their values. Let's say that you must extract all the database rows that have the checked values. You'd want to write something like that (pseudo-code here):

     

    SqlCommand cmd = new SqlCommand("SELECT FullName FROM User WHERE ID IN(@IdArray)");
    cmd.Parameters.Add("@IdArray",
    SqlDbType.IntArray).Value = Convert.ChangeType(Request.Form["Identities"], typeof(int[]));

    Unfortunately, there is no such thing as an array type for Sql. So in this case, unfortunately, unless someone comes up with something better, you have to rely on concatenation:

     

    string idList = Request.Form["Identities"];
    if (IntListValidate(idList)) {
     
    SqlCommand cmd = new SqlCommand("SELECT FullName FROM User WHERE ID IN(" + idList + ")");
    }
    else {
     
    throw new InvalidDataException("The posted data contains illegal characters.");
    }
    ...
    private bool IntListValidate(string input) {
      for (int i = 0; i < input.Length; i++) {
       
    if (!Char.IsDigit(input, i) && input[i] != ',') return false;
      }
     
    return true;
    }

    Of course, here, you have to use a white list, digits and comma in this case. Not even space is allowed. That's pretty safe, but I wish you could do that with parameters.

    Update 8/19/2004: Kyle Heon just pointed me to this great Sql article that explains just how to do that with a parameter. Thanks for the link, Kyle! So now, there's one less reason not to use parameters everywhere.
    http://msdn.microsoft.com/en-us/library/aa496058.aspx

    The second common type of injection attack is Cross-Site Scripting, or X-Site Scripting. Consider this simple piece of asp page:

    Bonjour, <%= Request.Form("Name") %>.

    What if the user enters <script>alert("5tUp1dH4k3R ownz you");</script> in the Name form field? Well, he successfully displayed an alert on his browser using your page. Nothing to be afraid about for the moment, as he'll be the only one to see it. But what if instead of directly displaying the user input we store it in a database for other users to see, in a forum application, for example? What if the parameter is passed in the querystring parameters of a hyperlink in a mail that seems to come from your bank?

    Well, then a lot of nasty things can happen (by the way, these are real scenarios, stuff that happened and continues to happen every day). For example, the attacker can inject script that will post all your cookies or some confidential information that's displayed on the page to some remote site that he owns. This can include your social security number, your authentication cookies, your credit card number, or any sensitive information that may be displayed on the page.

    It is usually relatively harmless for many sites because they just don't have any information that's confidential or that could allow for other, more dangerous attacks.

    Once again, ASP.NET gives a first line of defense out of the box. Since v1.1, all form and querystring data is validated on the server before the page is executed. So the above example does not work on ASP.NET 1.1, it will just throw an exception. Now, this feature is sometimes deactivated by controls such as rich text editors.

    The second thing we're doing, which is what you should do in your own pages and controls, is to HtmlEncode any property that comes from user input. That includes the value of an input tag that's rendered from a TextBox. It protects this particular textbox from script injections and also makes it robust against legitimate characters in the contents, such as quotes.

    Rule #5: Encode all rendered properties that come from user input when rendering them.

    The above example would then become:

    Bonjour, <%= Server.HtmlEncode(Request.Form("Name")) %>.

    There's another often overlooked rule:

    Rule #6: Don't display any secrets in error messages.

    ASP.NET limits by default the complete error messages to calls from the local machine. A complete error message sent to any machine can reveal table names or other secrets that could give clues for some attacker to use. And usually, an error message gives an indication as to how to make this application fail, which can be repeated and improved on the basis of all the information the error message contains.

    And of course, probably the most important rule:

    Rule #7: Encrypt any page that contains sensitive data.

    Of course, these rules are all important and the order in which they are presented here is irrelevant. Did I forget something?

    If you need more information, here's some more reading:

    On Sql Injections: http://www.governmentsecurity.org/articles/SQLInjectionModesofAttackDefenceandWhyItMatters.php

    On Cross-Site Scripting: http://www.net-security.org/dl/articles/xss_anatomy.pdf

    And of course, Google is your friend.

    UPDATE: I've used the word "quote" in this article for both the apostrophe (or single quote) and double quote. Todd pointed out in the comments that was somehow ambiguous. The point is that anything that can be used as a string delimiter, or as a delimiter in general, should be considered suspicious. Double-quotes are more frequent, but some languages such as JavaScript use both single and double quotes. SQL uses single quotes. Bottom line: beware of delimiters, and remember you may not even know the list of possible delimiters.

    UPDATE: we just released new tools that aim at helping developers scan their code for potential injection attacks.
    http://www.microsoft.com/technet/security/advisory/954462.mspx

    Read more...