What steps will reproduce the problem?
1. Use the Cross Site Reference Forgery lab solution from the ESAPI SwingSet
1.0 release (http://code.google.com/p/swingset-demo/). The solution URL is
https://localhost:8443/SwingSet/main?function=CSRF&solution, which forwards to
CSRFSolution.jsp. CSRFSolution.jsp uses a form to authenticate the user from
an HTML form to populate the ESAPI current user.
2. After the user has logged in, they can use the Transfer Funds link
(https://localhost:8443/SwingSet/main?function=TransferFunds&solution&ctoken=...
) to access TransferFundsSolution.jsp, which validates that the CSRF token
inserted by CSRFSolution.jsp matches the token associated with the current
ESAPI user.
3. The SwingSet TransferFundsSolution.jsp uses
ESAPI.authenticator.getCurrentUser() to retrieve the current user. This should
only succeed if the same thread processes both JSP requests. Since this will
not be true for most web containers, I modified the JSP to use the no-argument
version of ESAPI.authenticator.login() instead to retrieve the ESAPI current
user.
What is the expected output? What do you see instead?
Using login() to populate the ESAPI current user should guarantee that the CSRF
tokens will match once a user has successfully logged in.
TransferFundsSolution.jsp should successfully load, and the scripted logic on
the page should indicate that the CSRF token was validated.
Instead, using ESAPI.authenticator.login() in TransferFundsSolution.jsp causes
an AccessControlException to be thrown during the processing of
TransferFundsSolution.jsp. The SwingSet Controller servlet catches this error
and silently redirects to the application index.jsp.
What version of the product are you using? On what operating system?
ESAPI 2.0RC10 (built from
http://owasp-esapi-java.googlecode.com/svn/tags/releases/2.0_rc10)
Sun Java version 1.5.0_21
Windows XP Professional Version 2002 SP3
Tomcat 5.5.26
Does this issue affect only a specified browser or set of browsers?
The behavior appears to reproduce consistently in IE 7.0.5730.11, Firefox
3.6.12, and Google Chrome 7.0.517.44.
Please provide any additional information below.
AbstractAuthenticator.login(HttpServletRequest, HttpServletResponse) first
attempts to locate the ESAPI current user in the HttpSession (i.e.
getUserFromSession()). This call succeeds, setting the local variable user to
the object retrieved from HttpSession.
After the host address is updated on the user object, login() calls
ESAPI.httpUtilities().assertSecureRequest(). Assuming the default
implementation in DefaultHTTPUtilities, this does two things: 1) assert that
the protocol used in the request was HTTPS 2) assert that the method used by
the request was POST. Since login() was called from a JSP that was invoked
through a simple link traversal, the second assertion fails, and login() throws
AccessControlException. A stack trace containing a failing run is attached.
It appears that requiring all calls to login() to use method POST may be too
restrictive, and that this validation should only be performed when the HTTP
request is being used as the source of authentication information (i.e. when
loginWithUsernameAndPassword() is called).
As a possibly unrelated observation,
ESAPI.httpUtilities().assertSecureRequest() is being passed
ESAPI.currentRequest(), rather than a reference to the HttpServletRequest
object ("request") in the login() signature. In many cases, both of these will
reference the same object, but in the case where login() is explicitly called
with HttpServletRequest and HttpServletResponse objects. it seems like this may
promote counterintuitive behavior.
Original issue reported on code.google.com by kevin.c...@scynexis.com on 6 Dec 2010 at 6:05
Original issue reported on code.google.com by
kevin.c...@scynexis.com
on 6 Dec 2010 at 6:05Attachments: