Defending against Injections

Web Security Products, Consulting & Training Company
Oct. 26, 2015

More Related Content


Defending against Injections

  1. Defending Application against Injections
  2. Defending – Input & SQLi
  3. Input Validation • Design Strategy • Assume all input is malicious. • Centralize validation approach. • Client-side validation doesn’t help. • Be careful with canonicalization issues. • Constrain, reject, and sanitize your input.
  4. Input Validation • Design Strategy • Validate for type, length, format and range. • Prepare Whitelist of characters instead of Blacklist.
  5. Input Validation • Options for constraining data, Requirement Options Type checks • .NET Framework type system. Parse string data, convert to a strong type, and then handle FormatExceptions. Regular expressions. •Use ASP.NET RegularExpressionValidator control or Regex class. Length checks Regular expressions String.Length property Format checks Regular expressions for pattern matching .NET Framework type system Range checks ASP.NET RangeValidator control (supports currency, date, integer, double, and string data) Typed data comparisons
  6. Input Validation • Validation Controls, Validation Server Control Description CompareValidator Compares the value of one input control to the value of another input control or to a fixed value CustomValidator Allows you to write a method to handle the validation of the value entered RangeValidator Checks that the user enters a value that falls between two values RegularExpressionValidator Ensures that the value of an input control matches a specified pattern RequiredFieldValidator Makes an input control a required field ValidationSummary Displays a report of all validation errors occurred in a Web page
  7. Input Validation • RegulareExpressionValidator <script  runat="server"> sub submit(sender As Object, e As EventArgs)  if Page.IsValid then     lbl.Text="The page is valid!" else     lbl.Text="The page is not valid!" end if end sub </script> <html> <body> <form runat="server"> Enter a US zip code: <asp:TextBox id="txtbox1" runat="server" /> <br /><br /> <asp:Button text="Submit" OnClick="submit" runat="server" /> <br /><br /> <asp:Label id="lbl" runat="server" /> <br /> <asp:RegularExpressionValidator  ControlToValidate="txtbox1" ValidationExpression="d{5}" EnableClientScript="false" ErrorMessage="The zip code must be 5 numeric digits!" runat="server" /> </form> </body> </html>
  8. Input Validation • Regex (System.Text.RegularExpressions) Regular expressions are much easier to understand if you use the  following syntax and comment each component of the expression  using #. To enable comments, you must also specify  RegexOptions.IgnorePatternWhitespace, which means that non-escaped  white space is ignored. Regex regex = new Regex(@"                         ^          # anchor at the start                        (?=.*d)    # must contain at least one  digit                        (?=.*[a-z])  # must contain one lowercase                        (?=.*[A-Z])  # must contain one uppercase                        .{8,10}      # From 8 to 10 characters in  length                        $            # anchor at the end",                         RegexOptions.IgnorePatternWhitespace);
  9. Input Validation • String Fields (Name, Address..) • For Social Security Number the expression would be "d{3}-d{2}-d{4}" <form id="WebForm" method="post" runat="server">   <asp:TextBox id="txtName" runat="server"></asp:TextBox>   <asp:RegularExpressionValidator id="nameRegex "runat="server"          ControlToValidate="txtName"          ValidationExpression="[a-zA-Z'.'-'s]{1,40}"          ErrorMessage="Invalid name">   </asp:regularexpressionvalidator> </form>
  10. Input Validation • Date/Time Field Validation try { DateTime dt = DateTime.Parse(txtDate.Text).Date; } // If the type conversion fails, a FormatException is thrown catch(FormatException ex) { // Return invalid date message to caller } //range check on a date field // Exception handling is omitted for brevity DateTime dt = DateTime.Parse(txtDate.Text).Date; // The date must be today or earlier if(dt > DateTime.Now.Date) throw new ArgumentException("Date must be in the past");
  11. Input Validation • Numeric Field Validation • Convert input to integer type and return the error if exception raised. try { int i = Int32.Parse(txtAge.Text); . . . } catch( FormatException) { . . . }
  12. Input Validation • Range Validation • Use RangeValidator control with RequiredFieldValidator control so it can't accept blank input. • Convert into Integer with FormatException handling and check the integer range.
  13. Input Validation • Range Validation <form id="WebForm3" method="post" runat="server"> <asp:TextBox id="txtNumber" runat="server"></asp:TextBox> <asp:RequiredFieldValidator id="rangeRegex" runat="server" ErrorMessage="Please enter a number between 0 and 255" ControlToValidate="txtNumber" style="LEFT: 10px; POSITION: absolute; TOP: 47px" > </asp:RequiredFieldValidator> <asp:RangeValidator id="RangeValidator1" runat="server" ErrorMessage="Please enter a number between 0 and 255" ControlToValidate="TextBox1" Type="Integer" MinimumValue="0" MaximumValue="255" style="LEFT: 10px; POSITION: absolute; TOP: 47px" > </asp:RangeValidator> <asp:Button id="Button1" style="LEFT: 10px; POSITION: absolute; TOP: 100px" runat="server" Text="Button"></asp:Button> </form>
  14. Input Validation • Sanitizing Inputs • Strips out a range of potentially unsafe characters, including < > " ' % ; ( ) &. private string SanitizeInput(string input) { Regex badCharReplace = new Regex(@"([<>""'%;()&])"); string goodChars = badCharReplace.Replace(input, ""); return goodChars; }
  15. Input Validation • Validating HTML controls private void Page_Load(object sender, System.EventArgs e) { // Note that IsPostBack applies only for // server forms (with runat="server") if ( Request.RequestType == "POST" ) // non-server forms { // Validate the supplied email address if( !Regex.Match(Request.Form["email"], @"w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*", RegexOptions.None).Success) { // Invalid email address } // Validate the supplied name if ( !RegEx.Match(Request.Form["name"], @"[A-Za-z'- ]", RegexOptions.None).Success) { // Invalid name } } }
  16. Input Validation • File/Path Input • Avoid code which accepts file input or path input from the caller. • Use fixed file names and locations • Canonicalize path names before validating by System.IO.Path.GetFullPath or Request.MapPath to check that the file path is valid in the context of your application. • Use .NET code access security to grant the precise FileIOPermission to your code
  17. Input Validation • MapPath API try { string mappedPath = Request.MapPath( inputPath.Text, Request.ApplicationPath, false); //Is path is what supposed to be if(!validateFilepath(mappedPath)) { return null; } if(mappedPath.exist()) { return abspath; } } catch (HttpException) { // Cross-application mapping attempted }
  18. For XML Input • Create and use xml schema definition (XSD) or DTD file for xml validation • Don’t just check XML for certain tags. • Pay special attention to XPATH query inputs.
  19. Input Validation • ESAPI (The OWASP Enterprise Security API) • Open source free library • Set of security control interfaces. • Reference implementation for each security control. The logic is not organization or application-specific. An example: string-based input validation.
  20. OWASP ESAPI Namespace ESAPI { AccessController Encoder Encryptor HttpUtilities IntrusionDetector Logger Randomizer SecurityConfiguration Validator }
  21. Input Validation • ESAPI Sample public void Test_IsValidDouble() { IValidator validator = Esapi.Validator; //testing negative range Assert.IsTrue(validator.IsValid(BuiltinValidationRules.Double, "-4")); //testing empty string Assert.IsFalse(validator.IsValid(BuiltinValidationRules.Double, "")); Assert.IsFalse(validator.IsValid(BuiltinValidationRules.Double, "alsdkf")); } public void Test_GetValidDate() { IValidator validator = Esapi.Validator; Assert.IsTrue(validator.IsValid(BuiltinValidationRules.Date, "June 23, 1967")); Assert.IsTrue(validator.IsValid(BuiltinValidationRules.Date, "Jun 23, 1967")); Assert.IsFalse(validator.IsValid(BuiltinValidationRules.Date, "June 32, 1967")); Assert.IsFalse(validator.IsValid(BuiltinValidationRules.Date, string.Empty)); Assert.IsFalse(validator.IsValid(BuiltinValidationRules.Date, null)); }
  22. Input Validation • ESAPI Sample public void Test_StringRule() { IValidator validator = Esapi.Validator; string id = Guid.NewGuid().ToString(); StringValidationRule rule = new StringValidationRule(); validator.AddRule(id, rule); // Test valid Assert.IsTrue(validator.IsValid(id, Guid.NewGuid().ToString())); // Test allow null or empty Assert.IsFalse(validator.IsValid(id, string.Empty)); Assert.IsFalse(validator.IsValid(id, null)); rule.AllowNullOrEmpty = true; // Test whitelist Assert.IsTrue(validator.IsValid(id, "abc")); rule.AddWhitelistPattern("d+"); Assert.IsFalse(validator.IsValid(id, "abc")); Assert.IsTrue(validator.IsValid(id, "123")); // Test blacklist rule.AddBlacklistPattern("1"); Assert.IsFalse(validator.IsValid(id, "123")); Assert.IsTrue(validator.IsValid(id, "23")); }
  23. Input Validation • ESAPI Sample public void Test_StringRuleRange() { IValidator validator = Esapi.Validator; // Test range string id = Guid.NewGuid().ToString(); StringValidationRule rule = new StringValidationRule() { MinLength = 1, MaxLength = 10 }; validator.AddRule(id, rule); Assert.IsTrue(validator.IsValid(id, "a")); Assert.IsFalse(validator.IsValid(id, "")); Assert.IsFalse(validator.IsValid(id, "12345678901")); } public void Test_IsValidPrintable() { IValidator validator = Esapi.Validator; Assert.IsTrue(validator.IsValid(BuiltinValidationRules.Printable, "abcDEF")); Assert.IsTrue(validator.IsValid(BuiltinValidationRules.Printable, "! @#R()*$;><()")); char[] bytes = new char[] { (char)(0x60), (char)(0xFF), (char)(0x10), (char) (0x25) }; Assert.IsFalse(validator.IsValid(BuiltinValidationRules.Printable, new String(bytes))); }
  24. Prevent SQL Injection • Design Strategy • Constrain Input • Use Type Safe SQL parameters for data access. • SQL parameters can be used with stored procedures or dynamically constructed SQL command strings. Parameters perform type and length checks and also ensure that injected code is treated as literal data, not executable statements in the database.
  25. Prevent SQL Injection • Design Strategy • Use least privilege account that has restricted permissions in the database. • Only grant execute permissions to selected stored procedures in the database and provide no direct table access. • Protect sensitive data in storage. • Use separate data access assemblies. • Use Windows authentication
  26. Prevent SQL Injection • Use Separate Data Access Assemblies
  27. Prevent SQL Injection • Type Safe SQL Parameters • Input is treated as a literal value and SQL does not treat it as executable code. • Enforce type and length checks. • Stored Procedure without SQL parameters do not protect against SQL Injection.
  28. Prevent SQL Injection • Stored Procedure Example //the good example SqlDataAdapter myCommand = new SqlDataAdapter("AuthorLogin", conn); myCommand.SelectCommand.CommandType = CommandType.StoredProcedure; SqlParameter parm = myCommand.SelectCommand.Parameters.Add( "@au_id", SqlDbType.VarChar, 11); parm.Value = Login.Text; //the bad example SqlDataAdapter myCommand = new SqlDataAdapter("LoginStoredProcedure '" + Login.Text + "'", conn);
  29. Prevent SQL Injection • Dynamic SQL With Parameters • Escape routine (can’t rely completely) SqlDataAdapter myCommand = new SqlDataAdapter( "SELECT au_lname, au_fname FROM Authors WHERE au_id = @au_id", conn); SqlParameter parm = myCommand.SelectCommand.Parameters.Add("@au_id", SqlDbType.VarChar, 11); parm.Value = Login.Text; private string SafeSqlLiteral(string inputSQL) { return inputSQL.Replace("'", "''"); }
  30. Prevent SQL Injection
  31. Prevent SQL Injection • Default error page revels • Database information • Tables and Stored Procedure information • Internal file structure • Configure Generic Error Page (5xx page) <customErrors mode="On" defaultRedirect="YourErrorPage.htm" />
  32. Prevent SQL Injection • Use Microsoft Enterprise Library
  33. Conclusion