开发者

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

开发者 https://www.devze.com 2023-01-10 03:48 出处:网络
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references,or expertise, but this question will likely solicit debate, a
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance. Closed 10 years ago.

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 w开发者_JS百科as 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


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.


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.


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


One answer, which is not really a language feature, is the concept of Domain Driven Security. Instead of passing strings up and down, wrap them in objects that capture the limitations of the domain. And then whenever you have an object, you know that data is valid and hopefully that means it can also be trusted.

A couple of resources:
http://erlend.oftedal.no/blog/?blogid=116
https://vimeo.com/28768994


Use Code Contracts ...(also in pdf format).

Basically, you're asking for an additional constraint on the CLR Control Flow Graph that prevents any function from using data that has not been cleaned.

Like others have said, sanitizing user input is trivial; it's ensuring that only the sanitized data is available is when programmer oversight introduces security vulnerabilities. Code contracts will effectively extend the compiler to limit methods to use only sanitized data (however you define that) with the same assurance that you can't add a String to an Int.

See also: Static Program Analysis:

0

精彩评论

暂无评论...
验证码 换一张
取 消