Hacking the Code ASP.NET Web Application Security [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Hacking the Code ASP.NET Web Application Security [Electronic resources] - نسخه متنی

James C. Foster, Mark M. Burnett

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید








Using ASP.NET Tokens


After establishing a method for tracking and managing state, you can focus on the specifics of state management. Neither cookies nor URLs were designed to securely transport session or authentication tokens, but there are some techniques you can employ to protect them from attack.



Using Cookies














Summary:




Cookies were not designed to be secure, but with careful configuration you can help protect them




Threats:




Session hijacking, account hijacking, session fixation, information leakage




HTTP cookies are a mechanism to store user state to create the effect of a seamless connection with a Web server. Cookies were designed to handle user preferences and to track session variables, and they do that well. But when it comes to security, some problems do arise. Much of the specification depends on servers, client browsers, and any proxies in between following the rules. Unfortunately, that is not always the case. Furthermore, there is no requirement for the user agent to even accept cookies, although some Web sites will not grant users access if they don’t.


Normally, to save a cookie with ASP.NET, you use the Response.Cookies collection. However, ASP.NET automatically writes some cookies without you writing any code. If you enable session state, ASP.NET creates a session cookie with a unique token for each user who connects to the server. If you use forms authentication with cookies, ASP.NET also adds a forms authentication token to this cookie.


To access these cookies, you can use the Response.Cookies collection. For the forms authentication cookie, the FormsAuthenticationTicket object provides access to the cookie properties as well as other properties associated with forms authentication.


Cookies will always be somewhat vulnerable, but some settings limit that vulnerability. The properties that have security significance are:





Domain





Path





Expires





Secure





Value





Cookie Domain



The optional domain property of the cookie determines which servers can access the information in the cookie. If this property is left blank, the browser is supposed to allow access to only the host that issued the cookie. However, you might still want to specify this value.


The cookie domain allows access to all hosts that match the domain name, including all subdomains. In other words, it matches from right to left, so the cookie domain set to example.com would match *.example.com. The domain name must contain a minimum of two dots, to prevent a server from setting the domain to something like .com. Try to be specific as possible on the domain. For example, if you have a host named ro.cker.org and set the cookie domain to .cker.org, the hosts cra.cker.org, atta.cker.org, and just.about.any.script.kiddie._ha.cker.org can all access the cookie. This is important because an attacker might be able to find and exploit flaws on these systems to gain access to cookies from the target system. Figures 3.2 and 3.3 demonstrate how to set the domain on all cookies.


In addition to providing a specific host name, you might also want to check the cookie domain you receive. Say, for example, that the host ro.cker.org sets the domain property to ro.cker.org. However, the host ha.cker.org sets the domain property to .cker.org. Now suppose the user browses to ha.cker.org and the server sends a session cookie with this header:


Set-Cookie: ASP.NET_SessionId=nkih5piv3zdeuc55xj2np555; domain=.cker.org.


Now the user browses to ro.cker.org, and the browser sees that the host ro.cker.org matches the domain .cker.org, so it sends back the cookie it received from ha.cker.org:


Cookie:  ASP.NET_SessionId=nkih5piv3zdeuc55xj2np555;


The ro.cker.org server does not check the domain and simply accepts the cookie. This kind of flaw may expose the server to a number of attacks, including session fixation, account hopping, and token manipulation. To prevent this type of attack, always check the cookie’s domain, as shown in Figure 3.2 (C#) and Figure 3.3 (VB.NET). Note that you should always run the verification code in Figure 3.4 (C#) and Figure 3.5 (VB.NET) before you set the domain on all cookies, as shown in Figures 3.2 and 3.3.








private void settingTheDomainOnAllCookies() 
{
foreach (string key in Response.Cookies.Keys )
{
Request.Cookies[key].Domain = "te.st.ing";
}
}







Figure 3.2: Setting the Domain on All Cookies: C#








private void verifyingTheCookieDomain() 
{
foreach (string key in Response.Cookies.Keys )
{
HttpCookie cookie = Request.Cookies[key];
if (cookie.Domain != "te.st.ing")
{
cookie.Expires = DateTime.Now.AddYears(-1);
}
}
}







Figure 3.3: Setting the Domain on All Cookies: VB.NET








Private Function settingTheDomainOnAllCookies()
Dim key As String
For Each key In Response.Cookies.Keys
Request.Cookies(key).Domain = "te.st.ing"
Next
End Function







Figure 3.4: Verifying the Cookie Domain:










Private Function verifyingTheCookieDomain()
Dim key As String
For Each key In Response.Cookies.Keys
Dim cookie As HttpCookie = Request.Cookies(key)
If cookie.Domain <> "te.st.ing" Then
cookie.Expires = DateTime.Now.AddYears(-1)
End If
Next
End Function







Figure 3.5: Verifying the Cookie Domain: VB.NET


Cookie Path



Similar to the domain, cookies also have a path property to limit their scope. After passing the domain check, the server checks the cookie path. The path matches from left to right, matching any path and the paths below it. So if you set the path to / (slash), the cookie applies to all paths on the server. A path of /shopping limits the cookie to all items in the shopping directory and all its subdirectories.


It is helpful to set the path as specifically as possible because a browser will send the cookie to all URLs that match the path. By keeping the scope narrow, you can prevent the browser from sending the cookie when it shouldn’t do so, such as when browsing non-SSL pages. It also limits exposure to cross-site scripting attacks if an attacker finds a flaw in one part of the application. For instance, suppose that you have a Web application for members only at www.example.com/protected/ but provide a demo application that anyone can log in to at www.example.com/_demo/. Now suppose that someone plays around with the demo and finds a cross-site scripting flaw that allows him to use the demo application to steal all members’ authentication cookies. In this instance, setting a specific cookie path for the protected and demo directories would likely limit exposure to the attack, so someone would need access to the protected directory to exploit the flaw against actual members, whereas everyone has access to the demo directory. Although this is by no means a solution for the cross-site scripting problem, it does limit exposure to the attack.






Tip


Security strategies usually have varying levels of effectiveness. Some techniques are absolutely effective; other techniques mitigate attacks by limiting scope. Yet other techniques serve only to obscure things to slow an attack and discourage less dedicated hackers. Mitigating and obscuring techniques do not provide solid protection, but they do have the effect of improving overall exposure to attack, especially when you combine many techniques.




Always set a specific cookie path, and always check the path on cookies the client sends your application. For forms authentication, set the path attribute for the forms element in the web.config file.


Cookie Expiration



Cookie expiration in ASP.NET is sometimes confusing, but it is important to keep the lifetime of a cookie as short as possible, to limit exposure to cookie hijacking. Cookies have an Expires property that sets a limit on how long the browser should keep the cookie. If the expiration is left blank, the client browser is supposed to discard the cookie when it closes and not save it to disk. Although the expiration date tells a browser when it should stop using the cookie, there is no guarantee that it will remove expired cookies. So, even though this is not a reliable security measure, you should still take advantage of the feature.


When ASP.NET issues a session ID cookie, it does not set an expiration date, so the browser should discard the cookie when it closes. ASP.NET itself handles the expiring and reissuing of session tokens based on the session timeout setting in the sessionState element of the web.config file, as shown here:


<sessionState 
mode="InProc"
sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"
cookieless="false"
timeout="20"
/>


ASP.NET also handles the expiration of forms authentication tickets. The cookies for forms authentication tokens will not have an expiration date unless the Web application sets the cookie as persistent. The FormsAuthentication.RedirectFromLoginPage method has a parameter to indicate whether you want to use a persistent cookie or not, like this:


FormsAuthentication.RedirectFromLoginPage(UserName.Text, Persist.Checked)


Note that the FormsAuthenticationTicket class also has an IsPersistent property that you can set. Some Web applications provide users with a “Remember Me” feature so they don’t have to enter their credentials with each visit. This is an unsafe security practice, and you should never provide it on a Web site that stores personal user information or allows users to perform any significant financial, personal, or communication actions.


The FormsAuthenticationTicket class has an Expiration property that indicates when the authentication token expires, but this does not set the expiration date of the cookie itself. The cookie sent to the browser will have no expiration date unless you mark it as persistent. Once ASP.NET detects an old authentication token, it will revoke that token and issue a new one.


Forms authentication provides two settings that control how it handles token expiration: timeout and slidingExpiration. Timeout specifies the number of minutes until a cookie expires. SlidingExpiration, if set to true, updates the cookie’s expiration date with each browser request, providing that at least half the specified time has elapsed. In other words, setting the timeout to 20 and the slidingExpiration to true allows a user to go up to 20 minutes since the last page request before having to authenticate again. Setting slidingExpiration to false requires the user to reauthenticate 20 minutes after the first request.






Warning


Timeout settings have no effect on persistent cookies. If you set an authentication ticket as persistent, ASP.NET gives the cookie an expiration date 50 years from the time the server issued the cookie—even more reason not to use persistent cookies with forms authentication.




Although it is nice to be able to choose relative or absolute timeouts, it would be nicer to have both. That way you can timeout after a certain amount of idle time but also timeout after a set number of minutes. Without an absolute timeout, if someone leaves his browser open to a page that automatically refreshes, the session will never end. Attackers can also take advantage of this flaw by keeping a token alive for a session fixation attack.


Secure Cookies



A server can mark a cookie as secure to indicate to the client that it should take measures to protect the cookie. Although the RFC does not specify what security measures the browser should take, it usually means only sending the cookie over an encrypted SSL session. Nevertheless, marking a cookie as secure is only a suggestion from the server and the client browser does not have to honor that setting. In theory, the browser should provide the same level of security that the provided when issuing the cookie. Most common Web browsers do honor this setting.


If you protect your Web site with SSL, you should also mark your cookies as secure so that the client will not send them to a non-SSL page on your Web site.


You can configure forms authentication to always use a secure cookie with the requireSSL setting in the web.config file like this:


<forms name=".ASPXAUTH" 
loginUrl="/protected/login.aspx"
protection="All"
path="/protected/
timeout="15"
slidingExpiration="false"
requireSSL="true"
>


Note that if you mark the forms authentication cookie as true, you must provide an SSL connection for the entire protected area of the Web application. Otherwise, if the user visits a non-SSL page the browser will not send the cookie and the user will have to authenticate again to create a new FormsAuthenticationTicket and therefore a new cookie. If you require security for forms authentication cookies, make sure the entire protected area is SSL-enabled. Likewise, you may not want to mark session cookies as secure unless your entire Web application is SSL-enabled.


Cookie Values



The most common use for cookies is storing user variables, such as items in a shopping cart or user preferences. However, some developers use cookies to store sensitive information such as usernames, passwords, or even credit card details. You should never store sensitive information in a cookie, and you should always encrypt the other information that is appropriate to store


Security Policies





Always set a specific domain attribute and check the domain attribute when reading cookies.





Always set a specific cookie path and check the path on cookies the client sends your application.





Use short timeouts on session cookies to limit exposure to session-hijacking attacks.





If you are using SSL, mark cookies as secure.





Never store sensitive information such as authentication credentials or credit card numbers, and always encrypt what you do store.






Working with View State














Summary:




View State can be secure if you use the right settings




Threats:




Parameter manipulation, session fixation, information leakage




View State is an ASP.NET feature that allows you to persist form properties when a page posts back to itself. ASP.NET takes the current state of all form controls and stores them as an encoded string in a hidden form field. The risk of View State is that an attacker might be able to view or modify these form values to accomplish a variety of attacks. Fortunately, ASP.NET allows you to protect the View State data with encryption and detect tampering with hashes.


Enabling View State



You can enable View State on the machine, application, page, or control level. It might be tempting to enable View State for your entire site, but you might want to be more selective, to reduce exposure to attacks. Table 3.1 shows how to configure View State at various levels. In general, if you are not using View State for a page or control, you might want to disable it.

























Table 3.1: Enabling View State


Scope




Configuration




Machine




In the machine.config file, set <pages enableViewState=”true”/>.




Application




In the web.config file, set <pages enableViewState=”true”/>.




Page




In the page source, use <% @ Page enableViewState=”true” %> or in code set Page.EnableViewState=True.




Control




In the page source, set the control property EnableViewState=”True”.




Protecting View State



View State appears in the HTML source as a hidden form field, as shown in Figure 3.6. Although it looks cryptic, it is merely using base 64 encoding. You can decode this data and view it graphically using the ViewState Decoder tool shown in Figure 3.7, which is available at http://staff.develop.com/onion/resources.








<input type="hidden" name="__VIEWSTATE" value="dDwxNTQyMjY4Nzg2O3Q8O2w8aTw3Pjtp
PDk+Oz47bDx0PDtsPGk8MT47PjtsPHQ8QDA8cDxwP
Gw8RGF0YUtleXM7XyFJdGVtQ291bnQ7PjtsPGw8PjtpPDEwPjs+Pjs+Ozs7Ozs7Ozs+O2w8aTwwPjtpP
DE+O2k8Mj47aTwzPjtpPDQ+O2k8NT47aTw2PjtpPDc+O2k8OD47aTw5Pjs+O2w8dDw7bDxpPDA+Oz47b
Dx0PEA8MzEhU29ydGluZy9GaWx0ZXJpbmcgRml4ZWQgRGF0YVNldCBSZXN1bHRzOz47Oz47Pj47dDw7b
DxpPDA+Oz47bDx0PEA8MzA7VGhlIEJhc2ljcyBvZiBVc2luZyBTUUw7Pjs7Pjs+Pjt0PDtsPGk8MD47P
jtfPHQ8QDwyOTtVc2luZyBRdWVyeXN0cmluZyBSZXN1bHRzIGluIFNRTCBTdGF0ZW1lbnRzOz47Oz47P
j47dDw7bDxpPDA+Oz47bDx0PEA8Mjg7VXNpbmcgdGhlIE1TIElFIFRhYlN0cmlwIENvbnRyb2w7Pjs7P
js+Pjt0PDtsPGk8MD47PjtsPHQ8QDwyNztCZWdpbm5lcnMgR3VpZGUgVkI2IENvbSBPYmplY3RzIGluI
EFTUC5OZXQ7Pjs7Pjs+Pjt0PDtsPGk8MD47PjtsPHQ8QDwyNjtDcmVhdGluZyBhIExvZ2luL0VtYWlsL
0FjdGl2YXRpb24gUGFnZTs+Ozs+Oz4+O3Q8O2w8aTwwPjs+O2w8dDxAPDI0O1RoZSBCZWdpbm5lcidzI
Ed1aWRlIHRvIGFuIEFycmF5TGlzdDs+Ozs+Oz4+O3Q8O2w8aTwwPjs+O2w8dDxAPDIzO0NvbmZpZ3Vya
W5nIGEgVHJ1c3RlZCBTUUwgU2V6dmVyIENvbm5lY3Rpb247Pjs7Pjs+Pjt0PDtsPGk8MD47PjtsPHQ8Q
DwyMjtBZGRpbmcgRHluYW1pYyBDb250ZW50IHRvIFlvdXIgUGFnZXM7Pjs7Pjs+Pjt0PDtsPGk8MD47P
jtsPHQ8QDwyMTtDcmVhdGl33yBhIE1lbnUgVXNlciBDb250cm9sIHdpdGggUm9sbG92ZXJzOz47Oz47P
j47Pj47Pj47dDw7bDxpPDA+Oz47bDx0PEA8MDY3MjMyNTAxMjswNjcyMzI1MDEyO0FTUC5ORVQgRGF0Y
SBXZWJcPGJyXD5Db250cm9scyBLaWNrIFN0YXJ0IA0KO1Njb3R0IE1pdGNoZWxsOz47Oz47Pj47Pj47P
o/QlmEhBOdXCZBvDCRMGZGf0TBW" />







Figure 3.6: Sample View State Field






Figure 3.7: The ViewState Decoder


Because View State represents a form’s control properties, an attacker would be able to modify the form by modifying the View State properties. For example, an attacker might be able to change a product’s price on an online shopping cart or modify a parameter to perform an SQL injection attack. An attacker might try a number of other attacks such as cross-site scripting, unauthorized file access, or overflowing buffers.


To prevent attackers from manipulating View State, you can include a message authentication code (MAC). A MAC is essentially a hash of the data that ensures its integrity. You can enable the View State MAC on the machine, application, or page level. You can enable the MAC wherever you enable View State with this attribute:


enableViewStateMac="true"





Warning


Although many documents recommend not using the View State MAC unless necessary for performance reasons, I advise you always use it. There is a very slight performance hit but not enough that a human would notice. The security benefits far outweigh the performance hit.




The MAC protects you from someone tampering with View State data, discarding the contents if the MAC does not match. However, anyone can still decode and view the View State contents using the ViewState Decoder tool mentioned earlier. To overcome this problem, you can also encrypt the contents of the View State field. You can configure this encryption with the machineKey element in the machine.config file:


<machineKey validationKey="AutoGenerate,IsolateApps" 
decryptionKey="AutoGenerate,IsolateApps"
validation="3DES"
/>


The validation attribute can be MD5, SHA-1, or 3DES. The first two of these cause ASP.NET to create a MD5 or SHA-1 MAC hash, but 3DES encrypts the View State contents and creates an SHA-1 MAC. Setting the validation mode to 3DES protects the data from viewing and prevents parameter manipulation, but this still does not make View State completely secure. An attacker could prepopulate a form, save the View State field, and then trick another user into using that form. To prevent this type of attack, ASP.NET allows you to set a unique key for each user that makes the View State data valid for only that user. You can do this in the page_init event by setting the ViewStateUserKey property of the page object. With authenticated users, you can set this to the user’s name or session ID, but with an anonymous user, you should create a random number and save it in the user’s cookie. Figure 3.8 (C#) and Figure 3.9 (VB.NET) demonstrate how to employ the methods mentioned in this section.








private void Page_Init(object sender, System.EventArgs e) 
{
EnableViewState = true;
EnableViewStateMac = true;
ViewStateUserKey = User.Identity.Name;
}







Figure 3.8: Securing View State: C#










Private Sub Page_Init(ByVal sender As System.Object, ByVal e As 
System.EventArgs) Handles MyBase.Init
EnableViewState = True
EnableViewStateMac = True
ViewStateUserKey = True
InitializeComponent()
End Sub







Figure 3.9: Securing View State: VB.NET


To properly secure View State, you should use encryption, hashing, and unique user keys. You should always disable View State if you are not using it.


Security Policies





Disable View State unless you specifically use it.





Where you enable View State, always enable the View State MAC.





Set the validation attribute in machine.config to 3DES.





Set a unique View State user key for each user.





/ 96