Professional ASP.NET Security - Jeff Ferguson
.pdfTreating the Client with Caution
1 3 SQL Injection - Microsoft Internet Explore! |
|
|
|
|
HilEIj |
|
||
File |
Edit View |
Favorites lools |
Help |
'. |
' J -3 |
$ |
|
|
Jj Ba |
|
|
|
|
|
|
||
Address ]*) htlp://loc*ost,'cn12/'SQLInji.Aspx |
|
|
|
J |
^Go |
|
SQL Injection |
|
3 |
||
I |
Customer ID: |
|
|
|
|
|
|
|
|
; |
[ALFKI |
|
|
|
Gel Customer Info |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CustomerlD CompanyName |
ContactName |
ntactTitle |
|
|
ALFKI |
Alfreds Futterkiste Maria |
es Representative |
|
|
|
|
|
.......... ___ .... _______ |
fej Done |
|
|
1J |
|
|
|
^ Local intranet |
A user might try to tamper with the SQL statement in order to receive an error message. If we don't handle the error properly, and if we expose the original error message to the user, they can gain more information about the SQL statement, and can start tampering with the SQL statement. For example, the user could enter:
ALFKI' or CustomerlD like '%
Since we don't perform any validation on the input provided by the user, the SQL string building statement will build the following SQL statement and execute it.
SELECT CustomerlD, CompanyName, ContactName, ContactTitle FROM Customers WHERE CustomerlD = 'ALFKI1 or CustomerlD like '%'
The result is that instead of seeing the specific information related to the current customer ID, all the information is exposed to the user. If the information shown on the screen is very sensitive, such as Social Security Numbers, date of birth, or credit card information, think of how much of an issue this could be!
41
Fte |
£dit |
View |
Favorites |
Joois |
H |
SQL Injection
Customer ID:
JALFKI' or customerid like '%
Get Cust
Cystornerl |
CompanyName |
ContactName |
ContactTitle |
|
|
|
|
|
|
ALFKI |
Alfreds Futterkiste |
Maria Anders |
Sales Representative |
|
ANATR |
Ana Trujillo |
Ana Trujillo |
Owner |
|
Emparedados y helados |
||||
ANTON |
Antonio Moreno |
Antonio Moreno |
Owner |
|
Taquen'a |
||||
|
|
|
||
AROUT |
Around the Horn |
Thomas Hardy |
Sales Representative |
|
|
|
|
|
|
BERGS |
Berglunds snabbkdp |
Christina Berglund |
Order Administrator |
|
BLAUS |
Blauer See Delikatessen |
Hanna Moos |
Sales Representative |
|
|
|
|
|
|
BLONP |
Blondesddsl pere et fils |
-rederique Citeaux |
Marketing Manager |
|
BOLID |
Bolido Comidas |
Martfn Sommer |
Owner |
|
|
|
|
|
i Done
The hacker can also enter ALKI' or 1 = 1 -- in the textbox. This will also have the same effect as above.
SELECT CustomerlD, CompanyName, ContactName, ContactTitle FROM Customers WHERE CustomerlD = 'ALFKI' or 1=1 --'
The two hyphens (--) is MS SQL Server's comment marker. The same technique can be used for My SQL with the hash (#) symbol, and with a semicolon (;) for oracle databases. The hacker can enter anything in the textbox, and if we don't validate it very well, then the database can come under attack.
SQL Union Attack
The attacker can also use SQL union statements to get more data. Even though the SQL union attack is very hard to carry out, it is certainly possible. For example, the main restrictions with the SQL UNION statement is that both queries should return the same number of columns, expressions, or aggregate functions, and the data types of the columns from the both queries should match. This makes the union attack a little harder to carry out, but after few tries the hacker can be successful. For example, the hacker can enter:
ALFKI' union select @@Servername
— This will generate a SQL statement like this.
SELECT CustomerlD, CompanyName, ContactName, ContactTitle FROM Customers WHERE CustomerlD = 'ALFKI' union select @@Servername --'
42
Treating the Client with Caution
-rhis will generate an error at the server and, based on your error handling mechanism, the error may or anv not be reflected to the hacker. After a few retries like this:
ALFKI' union select @@Servername, @@Servicename, @@Version --
ALFKI ' union select @@Servername , @@Servicename, @@Servicename, @@version --
the hacker will eventually be successful in their mission, and they find out how many rows are returned by the first SQL statement. This will give them more control over the second SQL statement that they are going to create using the union statement. For example, the above input will produce the following SQL Statement:
SELECT CustomerlD, CompanyName , ContactName, ContactTitle FROM Customers WHERE Customer ID = 'ALFKI' union select @@Servername, @@Servicename, @@Servicename, @@Version -- '
Since this is a valid SQL statement, SQL Server will execute the above statement and return the values back to the ASP.NET page.
'
SQL Injection
Customer ID:
'.'^Service
iria Anders
:i SQL Server 2000 - 8.00.194 (Intel X86) SQLSERV 4ug 6 2000 00:37:48 Copyright CO 1988-2000
Microsoft Corporation Personal Edition on Vlndows NT 5-0 (Build 2195: Service Pack 2)
ALR- I
SQL: SELECT CustomerlD, CompanyName, ContactName, ContactTitie FROM Customers WHERE CustomerfD = 'ALFKI1 union select @g>Servernarne, @@Servicename, ®)@>Ser»ioertame, ©©Version —'
..J
This output provides plenty of information about the server to the hacker including the server name, service name, version of the server including the service pack, and the OS version.
More Advanced Attacks
What we've seen so far is a simple SQL Injection, and all databases are vulnerable to this kind of attack. Let's look at a more advanced type of attack. Each and every database has its own strengths and weaknesses. For example, SQL Server lets us execute an external operating system command using the xp_cmdshell stored procedure.
The user can exploit this feature using the form field like this:
'exec master..xp_cmdshell 'net user HackUser MyPassword /ADD1--The
ASP.NET application will build the following SQL statement and send it to the SQL Server.
SELECT CustomerlD, CompanyName, ContactName, ContactTitle FROM Customers WHERE CustomerlD = ''exec master..xp_cmdshell 'net user HackUser MyPassword /ADD'--'
SQL Injection
Customer ID:
|_cmdshell 'net user HackUser MyPassword ^ADD'-- *
|g| Local intranet
When SQL Server receives this SQL statement, it will treat it as two separate statements in a batch, as follows:
SELECT CustomerlD, |
CompanyName, |
ContactName, ContactTitle |
FROM Customers |
|
WHERE CustomerlD = |
'' |
|
|
|
exec master..xp_cmdshell |
'net user |
HackUser MyPassword |
/ADD'--' |
First, SQL Server will execute the select query, and will then execute the OS command, which will add the HackUser with MyPassword to the local System Account Manager (SAM). The rest of the SQL statement will be ignored, since it starts with the comment statement (--). If the ASPNET account is running with the admin privilege such as the sa account using SQL Server authentication, then this will happen without any problems since the sa account has sufficient privileges.
gj^jjgpg^g^gg|§[^nffgTB»"7^^i^^^MMaaaaaaMMKga[
Tree
^ Computer Management (Local)
B-ti! System Tools
• E
El System Information
a Performance Logs and Alerts
b~3 Shared Folders
J|| Device Manager
B|g Local Users and Groups
^i f c a r s
eg C3 Groups
Storage
d Disk Management
|Q^ Disk Def ragmenter i^a Logical Drives
i? jjgjj^ Removable Storage i l^i Services and Applications
iPt
JSK HackUsei
Full name-
Description:
f~ User must change password at next fogon f" User cannot change password
1™ Password never expires
!~" Account is disabled
r
--------- |
r~ . |
|
|
|
|
| |
OK |
| |
Cancel |
||
— |
|
j |
|
:r> |
|
44
Treating the Client with Caution
Validating, Encoding, and Filtering User Input
All these attacks are preventable, provided that we validate all data from un-trusted sources. When it comes to validating un-trusted data, we have to use several methods to make the input usable, including validating, encoding, and filtering the content. In this section we'll see how to process content before using it.
Validating Content
'Validate the user input before processing' is the mantra we have to remember if we want to avoid the types of attacks we've just been looking at. The validation could be anything from simple validation such as checking whether the entered value for 'Job Applicant Age" is a number, and is 16 or over, or making sure the username column has only valid characters such as A to Z, a to z, 0 to 9, and a few special characters.
The ASP.NET validation controls are an excellent way to validate content. In particular, the RegularExpressionValidator control is handy when validating user input. With regular expressions and the RegularExpressionValidator control, we can pretty much validate all kinds of data.
The advantage of using the validation controls is that we're defining the rules for the controls to decide what to allow and what not to allow.
Let's look at a simple example that uses regular expressions to validate username, US social security number, telephone number, and e-mail address.
<td><asp:TextBox id=txtUser runat=server MaxLength="20" /></td>
<asp:ReguiredFieldValidator id="RFVUser" runat="server" ControlToValidate="txtUser" Displays"Dynamic"
Font-Name="Verdana" Font-Size="lOpt">*</asp:RequiredFieldValidator> <asp:RegularExpressionValidator id="REVUser" runat="server" ControlToValidate="txtUser"
ValidationExpression="[A-Za-zO-9]{1,32}" Display="Static"
Font-Name="verdana" Font-Size="10pt">
Enter a valid user name. Only A-Z, a-z and 0-9 are allowed. </asp:RegularExpressionValidator>
<tdxasp:TextBox id=txtSSN runat=server MaxLength=" 11" /></td>
<asp:RequiredFieldValidator id="RFVSSN" runat="server" ControlToValidate="txtSSN" Display="Dynamic"
Font-Name="Verdana" Font-Size="10pt">*</asp:RequiredFieldValidator> <asp:RegularExpressionValidator id="REVSSN" runat="server" ControlToValidate="txtSSN"
ValidationExpre.ssion="\d{3}-\d{2}-\d{4)" Display="Static"
Font-Name="verdana" Font-Size="1 Opt">
45
If you don't have Unix or Perl programming experience, regular expressions could drive you crazy. Fortunately, Visual Studio .NET includes a number of commonly used regular expressions that can be used with the RegularExpressionValidator control.
French Phone Number
French Postal Code
German Phone Number
German Postal Code
If we use the CustomValidator control, it gives us the option to call the server-side validation function as well as the client-side validation function.
<asp: CustomValidator id="CVPwd" runat= "server" OnServerValidate="ServerSideFunction( ) " ClientValidationFunction="ClientSideFunction()
Since any one with a little JavaScript knowledge can understand our validation logic it is really not a good idea to use this. Therefore, be cautious when using the client-side validation function.
Filtering Input
When you've received incorrect input from an un-trusted source, it's not always practicable to refuse that input. In this kind of scenario, filtering the input is the best way. For example, let's suppose we want to filter out special characters such as the following: [ ] { } ; &.
To achieve this functionality, we're going to use the Replace method of the String object.
String sSearch = txtSearch.Text;
sSearch = sSearch.Replace("[" sSearch = sSearch.Replace("]' sSearch = sSearch.Replace("{" sSearch = sSearch.Replace("}" sSearch = sSearch.Replace (",-" sSearch = sSearch.Replace("&"
This code will replace all the unwanted characters from the users input. When we display the stripped version of the user input, we should see:
48
Treating the Client with Caution
F_fc |
E* |
Wen |
Favorites |
Tools |
Help |
*>B«k • •* |
- (jjj Jj |
4( |
Jjsearch |
|
^Favorites A#ress |f!?)
http://localhost/chl2;F*erng_CS.Aspx
Filtering Example
Search: |[{ )]
Search Term: nbsp
l5 Local Intranet
We can create this cleaning routine as a reusable method, and can use it against all kinds of data. Consider the following example:
String CleanUpInput(String strlnput)
strlnput = sSearch. Replace ("[ = strlnput sSearch. Replace! "] = strlnput sSearch. Replace ("{ = strlnput sSearch. Replace ("} = strlnput sSearch. Replace ( "; = strlnput sSearch. Replace ( "& = strlnput sSearch. Replace ("< = strlnput sSearch. Replace ( ">
//Return the clean data return strlnput;
Once this reusable method is built, we can use it from anywhere.
Encoding Input
Sometimes, the validated input might contain some illegal characters, or it might not always be viable to validate all user input. For example, in a search field, the user could type anything that they are searching for, including script tags such as <script>, script commands, such as alert, or HTML tags, such as <B>. In these cases, we can't always enforce a validation pattern. Encoding is the best way to neutralize harmful data from user input, since encoding translates the harmful characters into their display equivalents. For example the < character will be translated into < character. The HtmlEncode method of the Server object can be used to encode the harmful characters. Encoding characters that form the tags will prevent the tags they might form from executing. For example, let's say you've written an Online Form for programmers to exchange code and support each other. In this scenario, we have to allow members to show the code that fixes each other's problem. If we encode the content of the posting, users will be able to see the code, and the code will not be executed.
Consider the following example, in which we display the encoded search string in an ASP.NET label control.
void SearchDataStore(Object Src, EventArgs E)
IblSearchString.Text = Server.HtmlEncode(txtSearch.Text);
Search: <asp:textbox id="txtSearch" width="300" runat=server />
<asp:button id="btnSearch" Text="Search" OnClick="SearchDataStore" runat=Server /> <HR>Search Term: <asp:label id="IblSearchString" Text="" Runat="server" />
Now, when we enter some script, it will not execute, but will be handled as an inert character string:
|
Encoding Example |
|
Search: [<script>alert('HiThere!);</script> |
|
Search Term: <script>alert('Hi |
|
There!');</script> |
Encoding the |
user input can prevent script injection attacks and preserves |
the entered text |
L.for display purposes. |
Avoiding Cross-Site Scripting Attacks
Again, the only way to avoid cross-site scripting attacks is to validate users' input thoroughly before processing it. The first step in the anti-cross-site scripting attack precautions is to set the character set of the HTML output with the meta tag. If the character set is not specified in the HTML output by the web server, it can't determine which are the special characters. This will help the hacker to set a different character set and make all our validation code obsolete. The following example shows the use of Latin character set encoding (ISO-8859-1).
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-l">
</head>
The next defense against cross-site scripting is to validate user input. The best way to beat the cross-site script attack is to replace the special characters "% < > [ ] { } ; & + - - " ' ( )" with spaces. This can be done with the Replace method of the string object, or we can use the regular expression validator to exclude these characters at the input server control level.
50
Treating the Client with Caution
Once the special characters have been excluded, we can use the Server .HtmlEncode and Server . HtmlDecode methods. Here is a fixed example:
3 Encoding Example - Microsoft Internet Explorer
FJe Eds |
View Favcrtes Tools |
Help |
* . B a c k - |
• * - ' d j | | 3 - ^S e a r c h |
Ajdress |
|^j http://localtTOt/chl2/Enroding_Cs,Asp
Encoding Example
Search: <script>alert(This is cross-site attack);</script>
Search Term: <script>alert('This is cross-site attack1); </script>
..i
• K LLii.ai intranet
The hacker could also enter the hex alternative of any character as input. For example, %3C and %3E are hex representations of the < and > characters. So the <Script> can be entered as %3Cscript%3E by the hacker. The Server .UrlEncode method can prevent his kind of attack. Unlike ASP, ASP.NET supports a Server .UrlDecode method that can be used to decode any encoded data.
For example, let's say the user enters something like:
%3Cscript%3Ealert('Hi');%3C/script%3E in
the textbox, which is equivalent to:
<script>alert('Hi');</script> We can use the UrlDecode and HtmlEncode methods of the
Server object to tackle this problem.
<HTML>
<HEAD>
<Title>Decoding Example</Title> <SCRIPT LANGUAGE="C#" runat=server>
void SearchDataStore(Object Src, EventArgs E)
{
IblSearchStr ing. Text = Server .HtmlEncode (Server .UrlDecode (txtSearch. Text) ) ; }
</SCRIPT>
</HEAD>
<BODY>
<h3>Decoding Example</h3> <FORM runat="server" Method="Post">
Search: <asp:textbox id="txtSearch" width="300" runat=server /> <asp:button id="btnSearch" Text="Search" OnClick="SearchDataStore" runat=Server /> <HR>Search Term: <asp:label id="IblSearchString" Text="" Runat="server" /> </FORM> </BODY> </HTML>
Here is what the output of the code will look like:
c-i
£cfc |
View |
Fawritec |
look- |
Help |
Jj |
Bacfc- » iMfeMfcitt) http //localhost/ch12yDecodinsLVB Aspx
Search: |%3Cscript%3Ealert('Hi}.%3C/scnpt%3E
Search Term: <script>alert('Hi');</script>
CjDone
Decoding Example
Disabling Active Scripting
As a consumer or user, we can disable the active scripting in Internet Explorer. Go to the Tools menu and select the Internet Options. Then go to the Security tab and select the Restricted Site option. Click the Custom Level button and scroll down to the Scripting section and select the Disable radio button for the Active Scripting option. Obviously, this means that no script will run, and relies on users to configure it.
J |
|
|
General Security j Privacy] Contentj Connectionsj Programs] |
|
|
|
|
|
|
|
|
||||
OO |
Advanced! Seiect a Web content zone to specify its security settings. |
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
O Enable |
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
O Disable |
|
|
|
|
|
|
|
|
|
Internet |
Local intianet |
Trusted sites |
Restricted siies |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
© Prompt €J |
|
|
|
|
|
|
|
|
|||||
Restricted sftet |
|
|
|
Userdata persistence |
|
|
|
|
|
|
|
|
|||
|
|
|
|
© Disable |
|
|
|
|
|
|
|
|
|||
'am Web ^ites tha' |
|
|
|
|
|
|
|
|
|
|
|
ia%> damage youf |
|||
|
|
|
O Enable [] |
|
|
|
|
|
|
|
|||||
""^ Lurnpu'er OF daia. |
No ^ |
|
|
|
|
|
|
|
|
|
|
||||
|
Scripting y^j Active |
|
|
|
|
|
|
|
|
||||||
SwuiSy level foMhts zone |
|
|
|
|
|
|
|
|
|
|
|||||
|
|
scripting |
|
|
|
|
|
|
|
|
|||||
|
|
Custom settings. |
|
|
|
|
|
|
|
J |
|
|
|||
|
|
|
|
|
|
© QQ^j |
|
|
|
|
|
|
|
||
|
|
To change rhe settings, click Custom level - To use the |
|
|
|
|
|
|
|
|
|
||||
|
|
recommended settings, cbck Default Level. |
|
|
O Enable O Prompt lj|} Allow |
|
|
|
|
|
|
|
|||
|
|
|
|
|
HP |
w* |
|
|
|
||||||
|
|
|
|
• |
|
paste operations via script © |
|
|
|
||||||
|
|
|
|
|
|
||||||||||
|
|
|
|
R |
|
Disable |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
e |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
et custom settings |
|
|
|
|
|
|
|
|
- Reset to: High
Preventing SQL Injection Attacks
So, how might we prevent a SQL injection attack? The first step that we can take is to make use of the MaxLength attribute of the Textbox controls, thus restricting the number of characters the hacker can type. For example, if the Firstname textbox should only accept 40 characters, then we can enforce the length in the MaxLength attribute. This will restrict the hacker to sending small set of commands back to the server.
<asp:Textbox id="txtFirstname" MaxLength="40" runat="server" /> or:
52