AcmeFoo / AcmeWebSite

New website
0 stars 0 forks source link

CONTRAST: Session Rewriting Allowed in forms section of \web.config #93

Open zencid42 opened 4 years ago

zencid42 commented 4 years ago

Vulnerability ID: QXUL-R9OQ-YZCF-HCRH

Application Name: test

Vulnerability Link: https://apptwo.contrastsecurity.com/Contrast/static/ng/index.html#/6119fcd6-5a74-48e8-aff8-092520138ef3/applications/5352360a-ecd4-4b7b-b40d-2e8af08acbea/vulns/QXUL-R9OQ-YZCF-HCRH

What Happened?

The configuration in forms section of \web.config has cookieless set to a value other than UseCookies:

54:     <!-- set up users --> 55:     <authentication mode="Forms"> 56:       <forms name="customer_login" timeout="30" loginUrl="~/WebGoatCoins/CustomerLogin.aspx" requireSSL="false" protection="All" path="/"> 57:         <credentials passwordFormat="Clear"> 58:           <user name="admin" password="**" /> 59:           <user name="mario" password="**" /> 60:           <user name="bob" password="**" /> 61:         </credentials> 62:       </forms> 63:     </authentication>

What's the risk?

The application allows browsers that don't support cookies to rewrite session IDs into the URL. Having this ability presents a few problems. The first, most basic problem is that the session ID, which is as good as a username and password, is logged in the following places, which log the complete URL:

They'll also be sent in the "Referer" header to any off-site resources in pages. Normally, session IDs are a secret. If an attacker can steal a victim's session ID, they'll be recognized as the victim to the server. Many developers assume that some network control like IP restrictions, user-agent fingerprinting, or something else will prevent an attacker from using a session ID stolen from the victim. There is almost never such a compensating control, and thus session IDs must be protected.

Although the overexposure in the various log files is undesirable, it may not appear to be a serious issue. The bigger problem with session rewriting is that it allows an attack called Session Fixation. Session Fixation is an umbrella term for any attack that can allow an attacker to cause a victim to use a session ID that they know. If the victim then authenticates under the attacker's chosen session ID, they can present the same session ID to the server and be recognized as the victim.

Here's a very simple scenario, taken from Wikipedia's Session Fixation page: Mallory visits http://vulnerable.example.com/ and checks which SID is returned. For example, the server may respond: Set-Cookie: SID=0D6441FEA4496C2. Mallory is now able to send Alice an e-mail: "Check out this new cool feature on our bank, http://vulnerable.example.com/?SID=0D6441FEA4496C2.&quot; Alice logs on, with fixated session identifier SID=0D6441FEA4496C2.

The following request contained the session ID rewritten into the URL, which is how this issue was uncovered:

Recommendation

The .NET framework implements session management via the <sessionState> directive in Web.config. Using the attribute cookieless="true", the session token will be stored in the URL instead of a cookie. We recommend setting the cookieless option to UseCookies to force all session management to be provided using cookies. For .NET's AJAX client libraries, the attribute must be set to UseCookies per the Microsoft documentation: http://msdn.microsoft.com/en-us/library/h6bb9cz9%28v=vs.100%29.aspx. Here is an example of Web.config set to use cookies:

<sessionState cookieName="MySiteToken" timeout="30" cookieless="UseCookies" ... >

&lt;providers&gt; ... &lt;/providers&gt;

</sessionState>

NOTE: It's also a good idea to rotate the user's session ID after they've logged in. That way, if an attacker has compromised or seeded the session in any way, only the user who just proved they are who they say they are (via authentication) will have continued access. This won't affect the user. Unfortunately, rotating the session ID in ASP.NET applications is more difficult than it needs to be. You can't simply force .NET to create a new session like you can in Java. Instead you have to do two things as described in this article on Generating New SessionIDs in ASP.NET: http://stackoverflow.com/questions/12148647/generating-new-sessionid-in-asp-net/, and these steps need to be done on the login page itself so when the user logs in, they won't have a session. With no session, a brand new session (and sessionID) will be created when the user actually completes the login process.

Session.Abandon();  // This destroys the existing session
Response.Cookies.Add(new HttpCookie(&quot;ASP.NET_SessionId&quot;, &quot;&quot;)); // This erases the session cookie out of the browser. 

Note that without clearing the old session cookie out of the browser, the browser will present it to the server as part of the Login request and the server will create a new session, but adopt the old session ID presented by the cookie. This thwarts the whole point of rotating the session ID, which is why this second line is required.

Also note that this simplistic solution completely loses all state during the rotation process. If you need to retain user state across this session rotation, then you'll have to create a separate temporary cookie, and store the session state on the server in a place referenced by this cookie. And then once the new session is created, copy the session state back from this temporary location into the new session.

First Event

(no event)

Last Event

(no event)

HTTP Request

(No HTTP Request)