Download as pdf or txt
Download as pdf or txt
You are on page 1of 58

Adam Getchell (acgetchell@ucdavis.edu) Scott Kirkland (srkirkland@ucdavis.edu) Alan Lai (anlai@ucdavis.

edu) College of Agricultural & Environmental Sciences Deans Office


IT Security Symposium June 20-22, 2007

Introductions
Not experts, just offering experience gained from .NET

programs weve done Goal is practical advice, based on principles and code smells1, rather than exact code one is supposed to apply to every programs (though reusable code is good) This (mostly) works for us it may not work for you. Use what works for your team, but remember:

Good Software = Secure Software

OWASP Top 10
1. 2. 3. 4. 5. 6. 7. 8. 9. 10.

2 2007

Cross Site Scripting (XSS) SQL Injection Malicious File Execution (via Remote File Inclusion) Insecure Direct Object Reference Cross Site Request Forgery (CSRF) Information Leakage and Improper Error Handling Broken Authentication and Session Management Insecure Cryptographic Storage Insecure Communications Failure to Restrict URL Access

XSS
Cross site scripting is the most prevalent/pernicious web

application security issue. XSS flaws occur whenever an application takes data that originated from a user and sends it to a web browser without first validating or encoding that content. XSS types:
1. 2. 3.

Reflected displaying user supplied (hostile) data directly Stored storing user supplied (hostile) data and displaying (e.g. CMS, blogs, forums) DOM Injection Manipulating JavaScript directly on the page, including using XmlHttpRequest (basis of AJAX) to get around same source origination policies to forward users to hostile sites, etc.

SQL Injection Attacks


SQL Injection Attacks: Easy, Common, Dangerous. Definition: Injection occurs when user-supplied data

is sent to an interpreter as part of a command or query. Attackers trick the interpreter into executing unintended commands via supplying specially crafted data.

SQL Injection Attacks


Vulnerability:

String query = "SELECT user_id FROM user_data WHERE user_name = '" + txtUserName.Text + "'";

SQL Injection Attacks


Protection:
Use Input Validation Check for length, type, sytax,

etc. Use Stored Procedures or at least strongly typed parameterized queries. Dont show detailed error messages.

SQL Injection Attacks


Parameterized Queries: SqlCommand command = new SqlCommand(); command.CommandText = "SELECT user_id FROM user_data WHERE user_name = @user_name"; command.Parameters.AddWithValue("@user_name", txtUserName.Text);

Input Validation
.NET makes it easy to validate input controls using the

<asp:xxxValidator> controls.
ASP.NET Validators (except for the customValidator)

validate controls once using client side JavaScript and again on the server side (protecting you from clients who turn off JavaScript).

.NET Validation Tips


An Empty Control will pass every validation test except for

the RequiredFieldValidator Ex: If you want to make sure a string is not empty and matches a regular expression (like an Email address), you must use both a RequiredFieldValidator and a RegularExpressionValidator. The CompareValidator can do much more than comparing two controls. Leave the ControlToValidate propery blank, use the Type, Operator and ValueToCompare properties. Operators: dataTypeCheck, Equal, NotEqual, GreaterThan, GreaterThanEqual, LessThan, LessThanEqual Types: Currency, Date, Double, Integer, String

.NET CompareValidator Examples


The value entered should convert to an integer greater

than one

<asp:CompareValidator ID="val" runat="server" Type="integer" ValueToCompare="1" Operator="greaterThan />

.NET CompareValidator Examples


The value entered should convert to a DateTime

<asp:CompareValidator ID="val" runat="server" Type="date" Operator="dataTypeCheck" />

Parsing Objects
int age = 0; if (int.TryParse(textBoxAge.Text, out age)) { // Success in parsing string to int } else // Was not able to parse string { // Handle error }

Microsoft Enterprise Library [9]


What is it? Reusable source-code components implementing best practices and providing proven solutions to common problems. Can be integrated into applications and extended/customized
Caching Application Block Cryptography Application Block Data Access Application Block

Exception Handling Application Block


Logging Application Block Policy Injection Application Block Security Application Block

Validation Application Block

Validation Application Block


Ex: Nullable Phone Number
[IgnoreNulls()] [RegexValidator(@"((\(\d{3}\) ?)|(\d{3}))?\d{3}-\d{4}", MessageTemplate="Phone number must be properly formatted")] public virtual string HRPhone { get { return _HRPhone; } set { _HRPhone = value; } }

Validation Application Block


Ex: Non-Null Email Address between 7 and 150 chars.
[NotNullValidator()] [StringLengthValidator(7, RangeBoundaryType.Inclusive, 150, RangeBoundaryType.Inclusive, MessageTemplate = "Email address must be from 7 to 150 characters")] [RegexValidator(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([.]\w+)*", MessageTemplate = "Email must be properly formatted")] public virtual string HREmail { get { return _HREmail; } set { _HREmail = value; } }

Validation Application Block


Ex: Non-Null String between 1 and 100 chars.

[NotNullValidator()] [StringLengthValidator(1, 100)] public virtual string PositionTitle { get { return _PositionTitle; } set { _PositionTitle = value;} }

Validation Application Block


Ex: Nullable DateTime between now and next month. [IgnoreNulls()] [DateTimeRangeValidator(DateTime.Now, DateTime.Now.AddMonths(1))] public virtual DateTime? DatePosted { get { return _DatePosted; } set { _DatePosted = value; } }

Validation Application Block


public static class ValidateBO<T> { public static bool isValid(T obj) { return Validation.Validate<T>(obj).IsValid; } public static ValidationResults GetValidationResults(T obj) { return Validation.Validate<T>(obj); } public static string GetValidationResultsAsString(T obj) { StringBuilder ErrorString = new StringBuilder(); foreach (ValidationResult r in GetValidationResults(obj)) { ErrorString.AppendLine(string.Format("{0}, {1}", r.Key, r.Message)); } return ErrorString.ToString(); } }

Validation Application Block


if (ValidateBO<File>.isValid(jobDescription)) { newPosition.DescriptionFile = jobDescription; } else {

Trace.Warn(ValidateBO<File>.GetValidationResultsAsSt ring(jobDescription)); //Throw error }

File Upload/Download -- No direct file access


Dont allow direct URL access to stored (user supplied)

files.
Potential Issues: Remote Code Execution Unauthorized File Access

File Upload/Download -- No direct file access


Protection Obscure Filenames: Store files as a hash or partial reference Use a proxy class to retrieve files on behalf of a user

Check user permissions on retrieval Return the file as a binary stream (application/octet-stream)

File Upload/Download -- No direct file access


File fileToDownload = GetFile(); System.IO.FileInfo file = new System.IO.FileInfo(FilePath + fileToDownload.HashedFileName); if (file.Exists) { Response.Clear(); //Control the name that they see Response.ContentType = "application/octet-stream"; Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(fileToDownload.FileName)); Response.AddHeader("Content-Length", file.Length.ToString()); //Response.TransmitFile(path + FileID.ToString()); Response.TransmitFile(file.FullName); Response.End(); }

Insecure Direct Object Reference


A direct object reference occurs when a developer exposes a reference to an internal implementation object, such as a file, directory, database record, or key as a URL or form parameter Without access control checks such as authorization and parameter checking, very easy to abuse/manipulate systems. Ex: (can you spot the flaws)

<select name="language"><option value="fr">Franais</option></select> require_once ($_REQUEST['language]."lang.php"); And, assuming no SQL injection is possible, what is wrong with the following? int cartID = Integer.parseInt( request.getParameter( "cartID" ) ); String query = "SELECT * FROM table WHERE cartID=" + cartID;

Direct Object Reference countermeasures


Avoid use of object references whenever possible, such

as primary keys or filenames Validate any private object references extensively (e.g. RegExs) Verify authorization to all referenced objects
Its the web Assume a user will access any published

URL, dont assume theyll follow links to get there But see more on CSRF!

Code Access Security


Identify Permissions your application requires using

Permission Calculator (Permcalc.exe) Choose an appropriate trust level with required permissions, or better yet, create a custom trust level with only the permissions needed by the application Configure the ASP.NET application to use

Code Access Security


Declarative Code Security Checks Check by Role, User or Authenticated

In the System.Security.Permissions namespace. Throws a System.Security.SecurityException.

[PrincipalPermission( SecurityAction.Demand, Role="Admin")] private void secureOperation() { }

Custom Permissions
Copy the Medium trust policy file, web_MediumTrust.conf,

located in %windir%\Microsoft.NET\Framework\{version}\CONFIG\ to a file located in your application directory Add RegistryPermission to <SecurityClass> in Web_CustomTrust.config: <SecurityClass Name="RegistryPermission" Description="System.Security.Permissions.Regis tryPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

Custom Permissions

Add new <trustLevel> element to the <securityPolicy> section of the Web.config file to define new level called Custom associated with custom policy file

<location allowOverride="true"> <system.web> <securityPolicy> <trustLevel name="Full" policyFile="internal" /> <trustLevel name="High" policyFile="web_hightrust.config" /> <trustLevel name="Medium" policyFile="web_mediumtrust.config" /> <trustLevel name="Low" policyFile="web_lowtrust.config" /> <trustLevel name="Minimal" policyFile="web_minimaltrust.config" /> <trustLevel name="Custom" policyFile="web_CustomTrust.config" /> </securityPolicy> <trust level="Full" originUrl="" /> </system.web> </location>

Custom Permissions
Add RegistryPermission to <SecurityClass> in

Web_CustomTrust.config:

<SecurityClass Name="RegistryPermission"
Description="System.Security.Permissions.R egistryPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

Custom Permissions
Refer to web_CustomTrust.config in your applications web.config:

... <location allowOverride="true"> <system.web> <securityPolicy> <trustLevel name="Custom" policyFile="web_CustomTrust.config" /> </securityPolicy> <trust level="Custom" originUrl="" /> </system.web> </location> ...

Code Signing
Sign common necessary files with private key to

emplace in the Global Assembly Cache

Example of Signing Enterprise Library


Signing Enterprise Library 3.0 is easier than ever! Strong-Naming Guidance Package (included in

download)
Generates Key Pair files Places keys into each project (each application block has

its own project )

All you have to do is build

CSRF
Cross site request forger forces a logged-on browser to send a request to a vulnerable web app, which performs chosen actions on behalf of the victim. Example:
<img src="http://www.example.com/logout.php">

Changed to:
<img src="http://www.example.com/transfer.do?frmAcct=document.fo rm.frmAcct& toAcct=4345754&toSWIFTid=434343&amt=3434.43">

Note the use of Direct Object access, but done in the context of

the user! (Hence my own preference to not use URL-based object references)

Information Leakage and Improper Error Handling


In a production environment, always set customErrors

to On or RemoteOnly in the web.config file.


You can set a generic error page to be displayed when an

uncaught error is raised, and specific error pages when certain status codes appear (403/404/etc).

Information Leakage and Improper Error Handling


Using Global.asax to handle and log uncaught exceptions

globally

void Application_Error(object sender, EventArgs e) { Exception baseException = Server.GetLastError().GetBaseException();


//Handle Error: Log and Redirect to Error Page

Information Leakage and Improper Error Handling


Overriding System.UI.Web.Page to handle

and log uncaught exceptions globally

public class ApplicationPage : System.Web.UI.Page { public ApplicationPage() { } protected override void OnError(EventArgs e) { Exception baseException = Server.GetLastError().GetBaseException(); //Handle Error: Log and Redirect to Error Page base.OnError(e); } }

Error Handling / Logging


Logging of errors Writing errors to database Emailing errors Writing to the event log When reporting errors be sure to get any inner

exceptions, not just the outer most exception

Error Handling / Logging


ErrorReporting eReport = new ErrorReporting("ApplicationName", "EventLogName");

try {
// Execute Database call } catch (SqlException sqlEx) { eReport.ReportError(sqlEx, System.Reflection.MethodBase.GetCurrentMethod()); }

GridView DataKeys
Use DataKeys to store primary key fields without

displaying them to the user.


Note: The DataKeyNames property must be set for the

automatic updating and deleting features of the GridView control to work.

GridView DataKeys
<asp:GridView ID="CustomersGridView" DataSourceID="CustomersSqlDataSource" DataKeyNames="CustomerID" runat="server"> <Columns> <asp:BoundField DataField="CustomerName" HeaderText="Name" /> </Columns> </asp:GridView> //Access the datakey in your codefile gViewData.DataKeys[rowIndex].Value;

Broken Authentication/Session Management


Account credentials and session tokens are not often

properly protected. Attackers compromise passwords, keys, or authentication tokens to assume other users identities.

Role Provider
The fundamental job of a role provider is to interface

with data sources containing role data mapping users to roles, and to provide methods for creating roles, deleting roles, adding users to roles, and so on. Given a user name, the role manager relies on the role provider to determine whether what role or roles the user belongs to.

Role Provider
public abstract class RoleProvider : ProviderBase { // Abstract properties public abstract string ApplicationName { get; set; } // Abstract methods public abstract bool IsUserInRole(string username, string roleName); public abstract string[] GetRolesForUser(string username); public abstract void CreateRole(string roleName); public abstract bool DeleteRole(string roleName, bool throwOnPopulatedRole); public abstract bool RoleExists(string roleName); public abstract void AddUsersToRoles(string[] usernames, string[] roleNames); public abstract void RemoveUsersFromRoles(string[] usernames, string[] roleNames); public abstract string[] GetUsersInRole(string roleName); public abstract string[] GetAllRoles(); public abstract string[] FindUsersInRole(string roleName, string usernameToMatch);

Role Provider
<authentication mode="Forms"> <forms name="FormsAuthDB.AspxAuth" loginUrl="~/login.aspx" defaultUrl="~/Default.aspx" protection="All" timeout="120" path="/"> </forms> </authentication> <roleManager enabled="true" defaultProvider="CAESDORoleProvider" cacheRolesInCookie="true"> <providers> <add name="CAESDORoleProvider" type="CAESDO.Recruitment.Providers.CAESDORoleProvider" applicationName="Recruitment" description="CAESDO Authorization Test Program" connectionString="CATBERT"/> </providers> </roleManager>

Role Provider
<location path="members"> <system.web> <authorization> <allow roles="member, manager" /> <deny users="*" /> </authorization> </system.web> </location> <system.web> <authorization> <deny users="?" /> </authorization> </system.web>

Role Provider: Code Demo


Login.aspx.cs

Encrypting the Web.config


Why use the Web.Config? Centrally store sensitive information (passwords, connection strings, etc.) Why encrypt? Sensitive information in plain text is no good

Password

Encrypting the Web.Config


Methods Programmatic Encryption

Requires manual encryption and decryption in code Changes to legacy programs required Performs on the fly decryption No changes to code necessary

Encrypting using Machine Keys (RSA Keys)

Encrypting the Web.Config


Changes to make to the web.config :
<configProtectedData> <providers> <add keyContainerName="CustomKeys" useMachineContainer="true" description="Uses RsaCryptoServiceProvider to encrypt and decrypt" name="CustomProvider" type="System.Configuration.RsaProtectedConfigurationPr ovider, System.Configuration, Version=2.0.0.0, Cultural=neutral, PublicKeyToken=b03f5f7f11d50a3a"/> </providers> </configProtectedData>

Encrypting the Web.Config


How? (Using machine key method) Use tool called aspnet_regiis.exe

Add necessary lines to the web.config 2. Import / create machine key 3. Encrypt desired section (appSettings or connectionStrings)
1.

Insecure Communications
Use SSL Purchase Certs at IT Secuity site: http://security.ucdavis.edu/ Or you can use selfcert.exe or OpenSSH to create your

own certificates
No excuse!

Secure SQL server access


Use Windows Authentication Mixed mode uses trivially crackable encryption

Unicode password XORd with byte value 0xA5! [4]

Recommend local Windows password rather than

Domain account
Associate with Application Pool
Keep separate accounts for separate App Pools

Development vs. Production Sensitive vs. Non-sensitive

Other SQL Server practices


Strong password to sa account, even when not in mixed mode Prevent brute force attacks Yes, SQL Server 2005 has an sa account Use Firewall to only allow certain servers to talk to particular ports Dont give generic access to 1433 and 1434

Lots of attacks that do not require authentication

Check for backdoors Audit startup procedures (sp_MSRepl_startup) Audit commonly run procedures (sp_help, sp_password) Administrator Xstatus (2218 allows Admin login with no password) Use SQL Server 2005 if possible Reduced attack surface Table and column encryption [6]

But
All that can change next year. So what principles stay in common? Software Engineering - A systematic approach to the analysis, design, implementation and maintenance of software3
Software Development Life Cycle Security is a process Maintainable, auditable, provably correct code Architecture Separation of concerns into functional, independent, minimally coupled layers Service Oriented Architecture Infrastructure Separation of concerns into functional, independent, minimally coupled tiers Deployment, maintenance, upgrade, and retirement handled separately from programming/development

Software Engineering
Team Foundation Server with Visual Studio Team System Source control and code check-in policies

Require compilation(!) Require passing FxCop Require evaluation

Bug and project tracking Automated (nightly) builds with MSBuild Test-driven development Unit testing Database testing Setup & deployment projects

Use Design Patterns Singletons Factories Inversion of Control/Dependency Injection Consider using frameworks Microsoft Enterprise Library NHibernate (Object-relational mapping) [7] Castle (Object interceptors) [8]

References
1. 2. 3.

4. 5. 6.

7. 8. 9.

A Taxonomy for Bad Code Smells. http://www.soberit.hut.fi/mmantyla/BadCodeSmellsTaxonomy.htm The Open Web Application Security Project.<http://www.owasp.org/index.php/Top_10_2007>. "software engineering." The Free On-line Dictionary of Computing. Denis Howe. 13 Jun. 2007. <Dictionary.com http://dictionary.reference.com/browse/software engineering>. Threat Profiling Microsoft SQL Server (A Guide to Security Auditing), David Litchfield, 20 July 2002. http://www.nextgenss.com/papers/tp-SQL2000.pdf Security in SQL Server 2005 as seen by a programmer, Software Developers Journal, 21 March 2006. http://www.codeproject.com/database/sqlserver_secure.asp How To: Use Code Access Security in ASP.NET 2.0, Microsoft Patterns & Practices Developer Center, August 2005. http://msdn2.microsoft.com/enus/library/ms998326.aspx NHibernate for .NET, Sergey Koshcheyev, Ayende Rahien, and others. http://www.hibernate.org/343.html Castle Project, Castle Project. http://www.castleproject.org/ Enterprise Library, Microsoft Patterns & Practices Developer Center, May 2007. http://msdn2.microsoft.com/en-us/library/aa480453.aspx

Adam Getchell (acgetchell@ucdavis.edu) Scott Kirkland (srkirkland@ucdavis.edu) Alan Lai (anlai@ucdavis.edu) College of Agricultural & Environmental Sciences Deans Office
IT Security Symposium June 20-22, 2007

You might also like