The second version of the .NET port of the ESAPI project is available for general review. The code is available on Google Code here.
The ESAPI (Enterprise Security API) is a set of OWASP projects that support secure software in a variety of languages. I’ve worked closely with the ESAPI team to create a .NET version. While there has been .NET ESAPI code available for quite some time, this release should be much more applicable to real-world projects, especially ASP.NET development. This blog post is meant to cover some of the highlights in an FAQ format.
What is the general design of the .NET ESAPI?
If you’ve looked at the Java ESAPI before, you won’t be surprised about the structure and design of the .NET version. The .NET ESAPI is split into three projects: Esapi, EsapiTest, and SwingSet.
The first project is named Esapi, and contains the interfaces and the reference implementation. This is all you need if you are developing a .NET application from scratch. You would simply add the assembly from this project as a reference (along with the other required references), update your configuration file to add the appropriate ESAPI configuration elements, and extend the reference classes as you see fit.
This project contains four sub-namespaces.The Codecs and ValidationRules namespaces are used for the reference implementation of the Encoder and the Validator components, respectively. The Errors namespace contains the Exceptions used in the reference implementation. The Interfaces namespace contains the interfaces, which are implemented in the reference implementation, which is in the base namespace.
The EsapiTest project is a Visual Studio test project which contains several test cases for the reference implementation. If you have a patch, you could create a test case for whatever functionality you are updating and include it in the patch. There are over fifty unit tests currently in the project.
The SwingSet project is an ASP.NET application that has a few different purposes. One purpose is to demonstrate how to integrate the ESAPI components into an ASP.NET application. However, it also demonstrates security best practices outside of the scope of the the ESAPI. For example, it contains an example of how Membership can be configured securely. Additionally, the web.config file is annotated with security descriptions for some settings.
What different ESAPI components are supported?
The following components are supported:
- IAccessController: The IAccessController interface defines a set of methods that can be used in a wide variety of applications to enforce access control. In most applications, access control must be performed in multiple different locations across the various application layers. The interface is built around the idea of subjects, actions, and resources. A specific subject/action/resource combination is known as a rule.
- IAccessReferenceMap:The IAccessReferenceMap interface is used to map from a set of internal direct object references to a set of indirect references that are safe to disclose publicly. This can be used to help protect database keys, filenames, and other types of direct object references.
- IEncoder: The IEncoder interface contains a number of methods related to encoding input so that it will be safe for a variety of interpreters.
- IEncryptor:The IEncryptor interface provides a set of methods for performing common encryption, random number, and hashing operations.
- IHttpUtilities:The IHTTPUtilities interface is a collection of methods that provide additional security related to HTTP requests, responses, sessions, cookies, headers, and logging. This class handles CSRF protection.
- IIntrusionDetector: The IIntrusionDetector interface is intended to track security relevant events and identify attack behavior.
- ILogger: The ILogger interface defines a set of methods that can be used to log events.
- IRandomizer: The IRandomizer interface defines a set of methods for creating cryptographically random numbers and strings.
- ISecurityConfiguration: The ISecurityConfiguration interface stores all configuration information that directs the behavior of the ESAPI implementation.
- IValidator: The Validator interface defines a set of methods for validating untrusted input.
How is the .NET ESAPI different from the Java ESAPI?
The two projects are very similar in spirit, but there are some key differences. Most of the differences exist because the .NET ESAPI is a less complex project, although in some cases they exist because I disagree with the direction of the Java team.
- There is no User component in the .NET ESAPI. While this is a big piece of the Java functionality, it significantly overlaps with the existing .NET Membership API. I’ve decided to use the Membership API in the reference classes, rather than re-invent the wheel of user management.
- The Encoder class uses the AntiXss library. Again, there was significant overlap, and I felt there was no need to duplicate functionality. However, this means that canonicalization is not fully supported yet, since AntiXss only does encoding, not decoding.
- HttpUtilities is extremely simple, with only a few supported methods. There are no wholesale request validation or logging methods, and interactions with the request itself are not protected.
- The Logger implementation is very simple. It points to the Log4Net logger, which is configured independently of the ESAPI. There is no requirement to use Log4Net – you can write your own ILogger implementation that uses a different library.
- IAccessReferenceMap has a somewhat different and, in my opinion, more consistent interface.
- IAccessController is significantly simpler. It is based on the subject, action, resource access control paradigm (who does what to whom) and makes no assumption about how you will store these rules in your project.
- SwingSet is both a reference and a starter kit. It contains examples of how to use the ESAPI in addition to other secure ASP.NET best practices.
How do I use the .NET ESAPI?
There are a couple of ways to get started with the .NET ESAPI.
If you simply want to start using the functionality, you can download the assembly and supporting files here. You will need to add Owasp.Esapi.dll and log4net.dll as references, and add the App.config settings to your configuration file. The documentation is available for download as a .chm file here or online here.
I would recommend downloading and exploring the entire solution so that you can become comfortable with the code. You can download the solution from Google Code with SVN. The solution is created with VS 2008 and .NET 3.5 (the actual code should be compatible with .NET 2.0, so it should be pretty simple to get it to compile in most environments). You can then run the unit test project and the SwingSet project to see how the .NET ESAPI works.
You will need to download and install the AntiXss library separately, in order to respect the code licensing.
The SwingSet application requires you to login – first you need to register a username. To do this, you also need to supply a SMTP host in the web.config file in SwingSet so that you can get an activation email. You can just use the external SMTP server for an email account you own and use that - i.e.
<mailSettings>
<smtp from="dot-net-esapi@owasp.com">
<network
host="you fill this part in, for example d.mx.mail.yahoo.com for a yahoo.com mail account"
port="25"
/>
</smtp>
</mailSettings>
Is the .NET ESAPI mature/stable?
It’s getting there. At this point, it’s still a little early to call the .NET ESAPI a beta project – I hope that this release will allow enough people to provide feedback and join the team that we can get there soon.
How can I contribute?
First and foremost, join the ESAPI list. Feel free to contact me (me AT alexsmolen DOT com) and let me know if your interested in helping out – my first reply will be to download, use, and provide feedback on the current project. So far, I’ve had some real help from people like Paul Apostolescu and Taco Ditiecher. Thanks!
Secure Sockets Layer (SSL), also known as Transport Layer Security (TLS), is a security mechanism that gives you three guarantees:
1) No one can listen in on my traffic. (Confidentiality)
2) No one can modify my traffic. (Integrity)
3) I am talking to the correct server. (Authentication)
Over the web, trust is hard to come by. HTTPS takes the somewhat shaky building blocks of the web (DNS, HTTP) and adds SSL to make the communication channel more secure.
SSL doesn’t always work as advertised. An attacker can perform a Man-In-The-Middle (MITM) attack and defeat all of the guarantees above. However, the browser will issue a warning when the certificate the attacker presents isn’t valid (assuming the attacker hasn’t actually compromised the private key of the domain in question). This should let the user know when the security of the SSL channel has been compromised.
I’d like to examine browser SSL warning messages. Lately, I’ve been thinking about the trade-offs that we make between security and usability. Jakob Nielsen’s article on Password Masking made me think about the security “cargo culture” – we use the security mechanisms we’re used to using, even if they aren’t effective. And SSL warning messages are pretty ineffective at communicating risk to the average user.
I believe that the overwhelming majority of the SSL warning messages received in the real world are false positives. I’m basing that on my personal experience, of course, and I assume that I can reliably tell the difference between a malicious MITM attack and a bad web server configuration. I can’t remember ever feeling there was a chance that someone was actually attempting to hijack my SSL session by presenting a false certificate, but I’ve encountered numerous SSL warning messages for a variety of tamer causes.
Certificates can be expired, malformed, revoked, for the wrong domain, or self-signed – there are plenty of reasons why SSL certificates don’t validate properly. There are only a few causes, however, that I’ve seen with any frequency: expired certs, certs for the wrong subdomain, certs for the wrong domain, and self-signed certs.
The problem is that people (including myself) have been trained to ignore SSL warning messages, because they effectively mean “do you want to wait until the server administrator fixes the problem, or do you want to do your job right now?” Once people start to ignore these messages, it makes the attackers job easier. As with any security technology, we should be wary of the callousness caused by false positives.
I’d like to humbly suggest that we re-consider the current binary approach to SSL warning message (the certificate is valid, or it isn’t) and consider incorporating the role of human foibles (specifically, the web server administrator) in the SSL experience. Let’s examine two common configurations errors I mentioned previously:
Expired Certificates
Based on personal experience, I would guess that expired certificates are probably one of the most common SSL warnings. They are also one of the most benign.
Meaning: The expiration date on the certificate, or one of the certificates in the validation chain, is in the past.
Usual cause: The server administrator forgot to create and install a new certificate.
Risk: As an attacker, I’d find it a lot more difficult to find an expired legitimate certificate for a domain than create my own self-signed certificate. Alternatively, it’s easy for an administrator to forget to swap out old certificates before they expire. The likelihood of attack here is low.
Certificate with an Invalid Sub-domain
This warning is also fairly common, especially when you manually enter the an HTTPS URL. Yahoo (https://mail.yahoo.com/, certificate is for www.yahoo.com) and Verisign (https://verisign.com, certificate is for www.verisign.com) exhibit this error. These warnings are, in my opinion, usually pretty trivial.
Meaning: The certificate is for a different domain than the URL, but the root level domain is the same.
Usual cause: The server administrator is using the same SSL cert for multiple DNS-resolved endpoints.
Risk: If an attacker can get a hold of a valid certificate for anything on the domain, something is usually wrong. Perhaps there’s a shared hosting situation or some other extenuating circumstance. This is much more likely to be a configuration error than an attack.
I’d like to suggest that both of these cases display a more appropriate warning message. Something like :
The SSL certificate is expired. Please contact your administrator to remind them to update the certificate. There is a small chance the security of the session is compromised.
For bad sub-domain errors, the message could read
Although you are visiting <sub-domain>, the owner of <domain> can read your data. Would you like to continue?
We could even provide some metaphors - perhaps the idea of an expired or out-of-state drivers license may be helpful.
Certificates with completely mismatched domains or certificates that are self-signed could also be legitimate, but are also pretty easy for an attacker to create. We can at least draw attention to these more dangerous scenarios if we soften the user experience around the previous two problems.
I know the latest versions of browsers such as IE and Firefox have changed their SSL warning message strategies, usually in a bid to scare people away from using sites with broken certs. IE has a scary red button you need to click. Firefox requires a half-dozen clicks to continue. I think there should be a little more emphasis on clearly expressing the risk to the user instead of assuming all broken certs are created equal. While the user may not make the right security decision every time, the overwhelming majority of false positive SSL warnings indicates to me that the current system isn’t working.
Occasionally, someone who is learning about security will ask insightful questions like “how long should passwords be?” or “how long should it be before a user is logged out for inactivity?” The correct answer, of course, is “it depends” followed by a smoke bomb and a disappearing act. If, however, you are cornered with a question like this, I think there are some reasonable guidelines everyone can agree on.
There are things you can get 100% right (like eliminating cross-site scripting) and there are some things that you get for free (like using a strong session ID token from a framework). But, there can be big tradeoffs in performance or usability for certain security mechanisms. The appropriate tradeoff varies with the risk profile of the site. Let’s take a look at a few example security requirements, viewed through the light of two site risk profiles.
Weak: Something with no financial or private data. Forums, wikis, twitter, etc.
Strong: Anything with financial or private data. Banks, webmail, web hosting accounts, etc.
Is this too coarse to describe every site in the world? Yes, but it’s a start.
Use of SSL
Weak: SSL is optional for everything but the login page (and the form it’s served on).
Strong: HTTP redirects to HTTPS. SSL only.
Account Lockout
Weak: Either no brute force detection or basic request rate throttling.
Strong: Time-based lockout with increasing durations (5 minutes after 5 bad attempts, 10 minutes after 10 bad attempts, 20 minutes after 15 bad attempts, etc).
Session Timeout
Weak: A few weeks. Seriously! Look at GMail.
Strong: After ten minutes of inactivity, and no longer than a few hours, even with activity.
Password Strength
Weak: Six characters, and your password cannot be “password” (seriously)
Strong: At least eight characters, at least three character sets (upper, lower, numeric, special)
Password Reset
Weak: Email-based reset.
Strong: Email plus secret question/answer based reset.
Page Caching
Weak: All pages can be locally cached
Strong: No pages are locally cached
Username Enumeration
Weak: After a failed login, tell the user if the username they entered is valid.
Strong: After a failed login (or successful password reset, etc), do not disclose if the username the use user entered is valid.
Your requirements may vary, but I think this covers some of the common policy-based ones. Wouldn’t it be a happier web application security world if everyone followed these guidelines?
I’ve recently been accepted to the Masters program at the iSchool at UC Berkeley. I'm not starting until the Fall, but I’m already experiencing some life changes. I’ve moved out of my house in Long Beach, and I’m currently staying with friends and family throughout Southern California. I’m stopping work at Foundstone on July 1st, and moving up to Berkeley sometime in August. Hopefully, that will give me a little summer vacation to relax while I prepare to go back to school.
I completed my undergraduate work at Berkeley, so this will be a homecoming. I visited the iSchool during the open house and my expectations were exceeded by the students, both prospective and current, and the staff. It’s a “post-disciplinary” program that is centered on information and technology, but branches into fields like psychology, security, usability, economics, business, and sociology. I am not set on what I want to study and research, but I know that I’ll have plenty of inspiration from like-minded peers – check out the cool final projects from this year. The school itself is located in South Hall, the oldest building in the UC system.
I’ll continue to keep this blog updated. I hope to find some time to increase the content and improve the functionality of the site, as well as work on my other projects during the break. To be continued!
Update:
Arshan Dabirsiaghi noted that if you use cmd.exe, /bin/sh, or any other equivalently chainable executable loader, you can still introduce command injection vulnerabilities in .NET in Java. See the Webgoat lesson for an example of this.
Rudolph Araujo pointed out an interesting security note on MSDN about the CreateProcess function (which is called by Process.Start()) regarding the fact that unintended executables may be executed if there is whitespace in the path.
Dan Cornell made two really cool test projects for Java and .NET. Both of them demonstrated that a healthy set of shell meta-characters are ineffective at introducing new commands into system calls in Java and .NET.
System calls should probably be avoided in any case, since the executables aren't constrained by the security features of managed languages. However, it certainly seems like this threat is pretty well mitigated in these platforms, at least until someone finds a vulnerability.
Original:
Command injection (also called shell injection) can be a huge problem. Recently, I was working on an old Perl/CGI system that allowed command injection through the system command that ultimately led to a reverse shell on the web server.
I was trying to develop some examples of command injection in .NET, using the Process.Start method. The Process.Start method takes a file and arguments as parameters. You can't specify additional commands through meta-characters like semi-colons (;) and pipes (|). Java seems to be similarly invulnerable - according to this OWASP page:
There are many sites that will tell you that Java's Runtime.exec is exactly the same as C's system function. This is not true. Both allow you to invoke a new program/process. However, C's system function passes its arguments to the shell (/bin/sh) to be parsed, whereas Runtime.exec tries to split the string into an array of words, then executes the first word in the array with the rest of the words as parameters. Runtime.exec does NOT try to invoke the shell at any point. The key difference is that much of the functionality provided by the shell that could be used for mischief (chaining commands using "&", "&&", "|", "||", etc, redirecting input and output) would simply end up as a parameter being passed to the first command, and likely causing a syntax error, or being thrown out as an invalid parameter.
Obviously, if you let the user specify the first argument (the file name) then you are in trouble, but that's not really injection. Additionally, if you get into native/unmanaged code in your app you lose any protection. Those caveats aside, are Java and .NET impervious to command injection?
More Posts
Next page »