Sholo.Web.Security contains several tools to improve the security of ASP.NET applications. Make FormsAuthentication stateful, strengthen FormsAuthTicket validation, kick/ban users & IP's, detect multiple logins from different IP's, etc.
The EnhancedSecurityModule can change the behavior of the FormsAuthentication subsystem to strengthen the ticket validation process significantly. Since FormsAuthentication is such a low-level component in ASP.NET, this provides
the same protections and features to WebForms and MVC applications. The module works by altering FormsAuthentication cookie after a user logs into a web application but before the cookie is sent to the browser. It adds a salted hash to the cookie
payload along with a GUID key to a record about that cookie stored on the server side. On subsequent requests, the module validates the hash, looks up the record on the server, and compares everything that can possibly be compared about the cookie and
the payload of that cookie to ensure that it hasn’t been tampered with. If anything doesn’t match, the cookie is destroyed and stripped out of the current request’s context before the FormsAuthenticationModule’s verification even
kicks in. Essentially, the request becomes anonymous.
Even if a user had obtained the server’s machineKey and knew exactly how to encrypt and decrypt FormsAuthenticationTickets on the client side, they couldn’t possibly trick the web server into accepting the ticket for 2 reasons.
They would not know the salt value that was added to the hashing step to produce the hash code.
They would not be able to read or write to the state stored in memory on the server and the ticket would fail the enhanced validation process.
Other Features and Possibilities
Stateful FormsAuthentication causes the server to be the authoritative source for information on the validity of outstanding tickets. Coupled with the IP address information collected at the time the tickets are issued, various other
use cases become possible. Here are some of the plans for this project (they’re not all here yet):
Tamper Proof FormsAuthenticationTickets: the MaintainState option not only copies the validation data of the cookie & ticket to the server, it moves the UserData to the server and replaces it with a salted hash of
the properties in the FormsAuthenticationTicket. Even if the SHA-512 algorithm proves to be breakable, an attacker will be unable to fool the server without knowing the hash value. The MaintainState option makes it impossible for a malicious user
to tamper with or create a FormsAuthenticationCookie/FormsAuthenticationTicket that validates successfully, even if they managed to compromise the cryptographic keys on the server. It also detects and prevents exploits based on the type and timing of
error conditions, the attack vector leveraged by the Padding Oracle exploit.
No FormsAuthenticationCookie sharing: the MaintainState option can associate a FormsAuthenticationCookie/FormsAuthenticationTicket with the IP address of the client that initially requested them. If the ticket is
presented from a different IP address, it can be automatically revoked before your code even executes. Since this might be annoying (if your users IP addresses change often), it’s optional.
Kick users: simply revoke their ticket on the server-side and they’ll be logged out on their next request.
Ban users: prevent users from logging in with a particular username for a certain period of time.
Ban IP addresses: prevent any access from a particular IP address for a certain period of time.
Show your users who’s online: as accurate as your FormsAuthentication’s Timeout property.
Intrusion detection/prevention: prevent multiple failed validations/IP address/minute by automatically banning access from that IP address.
Random delay on errors: When a suspicious or malicious condition is detected on the server, the execution of the request can be delayed for a random amount of time to discourage attackers using brute-force techniques.
Track or prevent multiple user logins from different IPs:
3 tickets with 1 username and 3 different IP addresses either means someone is logging in from multiple devices, they are sharing their credentials, or they move quickly.
Enforce policies around account sharing
Automatically log-out previously created session
Automatically ban users for policy violations
Warn users that they are logged in from other IP addresses
- Cluster and/or WebFarm Capable: The ITicketStore interface defines a set of methods for manipulating the server records. At this point, the only concrete implementation depends on the ASP.NET Cache feature for server-side storage. This
prevents the solution from working in web-farms, certain cluster, round-robin, or load balancing scenarios. With database-backed ticket storage, these restrictions would be eliminated in exchange for reduced performance.
- UserData & Cookie size resolution: If you are explicitly populating the UserData property in FormsAuthenticationTickets, you may have stumbled on a strange issue where the cookie doesn’t save. The reason for this is
that browsers enforce a maximum cookie size (generally 4kb) and silently refuse to save the cookie. The MaintainState option moves the UserData onto the server and replaces it with a relatively small string (hash & GUID).
A majority of the code in this project is derived from my contributions to the Jasig CAS authentication system's .NET client (http://www.jasig.org
). While the foundation is there, some of the use
cases above are still on the whiteboard. If you find bugs, please report them and/or send patches.
How you can help
I’m working on these projects largely in my spare time. If you have any experience with FormsAuthentication or HttpModules in general and would like to help out, please get in touch with me. I slapped this thing together as
quickly as I possibly could because I am well aware of the urgency of the situation if this exploit goes viral and/or gets into the hands of the script kiddies. I can use any help testing, debugging, and fixing.
If you are looking for a robust single sign-on solution, consider becoming a part of the CAS community (http://www.jasig.org/
). we’d love to have more help on the DotNetCasClient or on this project.
I’d eventually like to make the DotNetCasClient link to this module so both worlds can benefit from enhancements and I don’t have to maintain both.