uest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim str As String = context.Request.Params("name")
Dim sw As StreamWriter
Dim strDate As String
strDate = context.Timestamp
sw = New StreamWriter(context.Server.MapPath("logs.txt"), True)
sw.WriteLine(strDate + " : " + str)
context.Response.ContentType = "text/plain"
context.Response.Write("Hello " + str)
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
The above code is the content of my remote .ashx handler hosted on http://localhost:81 (okay, I’ve written the above code in VB but who cares! As long as you understand what it does, language doesn’t matter. My next demos will be using Java Servlets/PHP..yes, I’m coding in these recently..yay!)
So web developers who have used AJAX and are moving towards HTML5 should know this subtle but important difference.
Cross origin form submission now AJAXified in CORS!
Not sure if you have observed or not, the first code snippet in this post uses a content-type “application/x-www-form-urlencoded”. If you haven’t figured it out, there is a more familiar version of it which you already know:
<form method="post" action="http://localhost:81/handler.ashx">
<input type="text" name="name" value="fake form">
<input type="submit" value="Submit">
When HTML forms are submitted, they use “application/x-www-form-urlencoded” as the default content type. Since forms anyways do cross origin posts inherently, this “feature” was also included in HTML5 CORS specifications. This is the reason why we were able to log the CORS message in the second snippet. So all the three content types which are supported by HTML forms (“application/x-www-form-urlencoded”, “multipart/form-data”, “text/plain”) can be used in CORS to do a cross origin request (Don't you smell attack scenarios here? Stealth mode attacks? Yeah!)
No preflight request for CORS POST request?
The HTTP methods GET and HEAD are called “safe methods” since they should not cause any state changes on the server. POST requests are meant to change the state on the server and can be misused. So there should have been a preflight request for the above CORS POST request, but browsers did not do such thing in the above demo.
The reason for this boils down to what is allowed vs not allowed prior to HTML5 specs. In HTML4, we could do cross origin requests using <img src=’…’>, <script src=’…’>, <form method=”GET/POST” action=’…’> etc. Following the same rules, cross origin GET requests and some POST requests can still be done using CORS. So what are those “some” POST requests? These are nothing but what we have seen above in the form submission case. i.e., POST requests with various form content-types. Other than these, any sort of POST request will require a preflight request, which is the security enhancement in CORS.
HTML Forms and CSRF attacks go hand in hand. What about CORS & CSRF?
Yes, CSRF attacks using HTML forms are quite popular and one of the well known defenses is sending random, unique nonce in every request. Since CORS POST requests mimic HTML form requests, they can be victims of CSRF attacks and hence every CORS POST request should use CSRF defenses. If this is not considered seriously, it paves way to a number of stealth attacks such as silent file uploads. In the first snippet, if you set “xhr.withCredentials=true”, even cookies can be sent in the POST requests and hence replay attacks can be done.
Winding up the show, CORS is beautiful and enhances the modern web interactions in many ways. We already know how bad the state of AJAX security has been, owing to poorly written code. If CORS is studied as ‘yet another new thing on the web’, without understanding the internal details, web applications will suffer big time leading to serious attacks. Time to focus on the security aspects of modern web specifications! No escape!!
Update: You may check the source code of the demo used in the article here: https://github.com/novogeek/AJAX-vs-CORS