Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending Type Safety to prevent dirty data coming from being used against functions that require "clean" data [closed]

Can .NET or one of it's many languages enforce the cleaning of untrusted data... or prevent accidental variable use in the wrong locations?

One example of this is when a user POST's data and the "raw" response is used within a SQL transaction. This could cause anything from a client-side scripting vulnerability to the entire server being compromised.

Another example is where I have to pass the data to a COM object for further processing.

What are my options as a C#, ASP.net, and SQL developer to make sure that my user's dirty bits don't touch anything internal before it's cleaned? Is there a feature of the runtime (or compiler) I could leverage?

Short of having the language actually enforce it, perhaps I could just add a suffix of _dirty to my incoming variables. Is this something you would recommend as a best practice?

How do the pros approach this problem?

Update

Here is the conceptual direction I was going

This is somewhat inspired based on the answers given so far (specifically SteveCzetty and Erlend)

For example:

public Interface ICleanForJavascript { bool IsCleanForJavascript(); }  

public Interface ICleanForXSS { bool IsCleanForJavascript(); }

public class DirtyData 
{
    string Name {get; set;}
}

public class CleanData
{
    private CleanData() {}
    string Name {get; private set;}


     // Perhaps use casting to support the conversion from Dirty to Clean data
     // Might use this in an option explicit DirtyData CleanData(object o); command 
    public static CleanData Validate(DirtyData d)
    {
        CleanData data = new CleanData();
        if (ValidateString(d.Name))
        { 
             data.Name = d.Name
        }
        else
        {
             throw new ValidationException();
        }
        return CleanData;
    }
}

[RequiresCleanedDataAttribute(ICleanForJavascript )]
public void DoSomething(CleanData data)
{
    //...
}

 Attribute RequiresCleanedDataAttribute(object arrayOfCleanings[])
 {
  // do some reflection on the method signature and see if the object supports the required interfaces
 }

With the above, then:

DoSomething(new DirtyData()); // Compiler Error, or runtime error if Attribute validation fails
DoSomething(CleanData.Validate(new DirtyData())); // Compiles
like image 289
makerofthings7 Avatar asked Jul 31 '10 02:07

makerofthings7


3 Answers

Can .NET or one of it's many languages enforce the cleaning of untrusted data

Yes it can, but not in the way you're asking about. Instead, you ensure clean sql by correctly parameterizing it. For example:

string sql = "SELECT * FROM [table] WHERE [column] = @value";
using (var cn = new SqlConnection("connection string here"))
using (var cmd = new SqlCommand(sql, cn)
{
    cmd.Parameters.Add("@value").Value = "'';DROP Table Users;--";
    cn.Open();
    SomeControl.DataSource = cmd.ExecuteReader();
    SomeControl.DataBind();
}

That code is perfectly safe to run, even though there's an obvious injection attempt. The reason is that the SqlCommand object's parameters collection is never substituted directly in the query. The data is sent to the server and handled completely separate from the code, and so everything is safe, no matter what the user enters.

Anything else you do that attempts to "sanitize" a request will always be an arms race with the crackers. This way, the right way, keeps data and code separate.

like image 191
Joel Coehoorn Avatar answered Sep 22 '22 18:09

Joel Coehoorn


You seem to be assuming that there can only be one way to sanitize() data. The problem is that a vulnerability is highly dependent on how the data is used and there for in practice this approach is very difficult. For instance sql injection and xss have very little in common and they should never use the same function. In fact there are very few similarities between any of the injection flaws.

That being said, the best implementation of Taint checking is ruby's safe mode. IronRuby lets you can use ruby on .net. This works by having a list of sanitation functions that will mark the variable as clean. But even this isn't going to stop everything, if you look at the owasp top 10, only A1-Injection and A2-XSS vulnerabilities are caused by tainted input, the rest do not, most notably CSRF.

like image 41
rook Avatar answered Sep 21 '22 18:09

rook


I suggest keeping different (parallel) types for the "clean" and "dirty" data. You should expose only the "dirty" types to your untrusted sources, and then have your cleaning/validation methods return the internal "clean" types. Many architectural models would consider the "dirty" types a "DTO", or Data Transmission Object, and the "clean" types part of the model, or domain.

With this separation, you can use simple type-safety to ensure that your sensitive methods only get clean data.

For example:

public class DirtyData
{
    string Name {get; set;}
}

public class CleanData
{
    private CleanData() {}
    string Name {get; private set;}

    public static CleanData Validate(DirtyData d)
    {
        CleanData data = new CleanData();
        if (ValidateString(d.Name))
        { 
             data.Name = d.Name
        }
        else
        {
             throw new ValidationException();
        }
        return CleanData;
    }
}

//...

public void DoSomething(CleanData data)
{
    //...
}

With the above, then:

DoSomething(new DirtyData()); // Compiler Error
DoSomething(CleanData.Validate(new DirtyData())); // Compiles
like image 41
Steve Czetty Avatar answered Sep 22 '22 18:09

Steve Czetty