First things first:
In this case we will base the token on the Session ID, the user's remote IP address, a random GUID, and the current time. These values will be hashed using SHA1 and a random salt. The resultant token (hash) will be written to the form as a hidden form field as well as to the user's browser as a cookie. Assuming the form is served over SSL/TSL it would be nearly impossible for an attacker to:
In addition, there is a five minute time limit so any attack against the token, in an attempt to get the Session ID is going to take too long to be successful. Therefore, it would not be possible for an attacker to gather the necessary information to submit a form on behalf of another person which is the whole purpose of CSRF.
In this example page the token is revealed with a submit button. If the token is tampered with the "Check Token" result will be false, but you won't see that because your session will be destroyed and you will be redirected to a forbidden page. If the cookie is tampered with the check token function will similarly fail. Finally, if you wait longer than 5 minutes to submit the form the check token function will fail.
If you have a multi-page form, or will allow the user to go back to a previous form (using the back button, for example) the token won't be valid and the user would be redirected wrongly to the forbidden page. In those cases you must maintain the same token from page to page until the entire transaction is complete. That may require you lengthen the time allowed or remove the time check from the checkToken function.
In this example a new CSRF token is created on each form submission. For a more detailed explanation of CSFR please refer to the OWASP projects CSRF page. If you are protecting a high value site (banking, financial services, etc.) you should probably use the OWASP's CSRF Guard implementation and you may also choose to require the user to re-authenticate before completing a transaction.
<% ' Requires include/hashSHA1.asp function checkToken '***************************************************************************************** ' Check the posted token for correctness '***************************************************************************************** Dim oldToken, testToken, tokenStr oldToken=request.form("token") tokenStr = "IP:" & Session("ip") & ",SESSIONID:" & Session.SessionID & ",GUID:" &Session("guid") testToken=base64_encode(HashEncode(tokenStr&Session("salt"))&Session("salt")) checkToken=false If oldToken=testToken Then If Request.Cookies("token")=oldToken Then If DateDiff("s", Session("time"), Time)<=300 Then ' Five minutes max checkToken=true Else Session.Abandon ' change to match your domain and needs - et = error-time Response.Redirect "http://www.yourdomain.com/forbidden.asp?t=et" End If Else Session.Abandon ' change to match your domain and needs - ec = error-cookie Response.Redirect "http://www.yourdomain.com/forbidden.asp?t=ec" End If Else Session.Abandon ' change to match your domain and needs - e = error-token check Response.Redirect "http://www.yourdomain.com/forbidden.asp?t=e" End If End Function function writeToken '***************************************************************************************** ' Create and set a new token for CSRF protection ' on initial entry or after form errors and we are going to redisplay the form. '***************************************************************************************** Dim salt, tokenStr salt = getSalt(10) Session("salt")=salt Session("guid")=getGUID Session("ip") = Request.ServerVariables("REMOTE_ADDR") Session("time") = Time tokenStr = "IP:" & Session("ip") & ",SESSIONID:" & Session.SessionID & ",GUID:" &Session("guid") Session("token")=base64_encode(HashEncode(tokenStr&Session("salt"))&Session("salt")) Response.Cookies("token") = Session("token") Response.Write("<input id=""token"" name=""token"" type=""hidden"" accesskey=""u"" tabindex=""999"" value=""" & Session("token") & """>") End Function
<html> <head> <title>Your Form</title> </head> <body> <form name="yourForm" method="post" action="your-form-handler.asp"> <p>...form fields ...<br> <%=writeToken %><input type="submit" value="submit"></p> </form> </body> </html>
<%
If LCase(Request.ServerVariables("HTTP_METHOD"))="post" Then
If checkToken Then
... all is okay, process the form
End If
%>Date Validation Using JavaScript .
Cross-Browser Clipboard Copy .
Loading Images With Remote Scripting .
Why JavaScript In Hyperlinks Is Bad .
Change The Submit Button To Show Waiting For AJAX Response .
European Date Validation Using JavaScript .
Database Results To Client Side Array .
Reading Files With JavaScript .
AJAX For Plain Text And HTML .