CSRF and Cross Domain Response Extraction in Era of CORS

CORS has certain critical response headers. It is required if the application needs to share resources on a  cross domain to other applications over Internet or Intranet. This type of scenario can lead to Cross Domain Response Extraction. For example application is sending following response header as part of HTTP.
 Access-Control-Allow-Origin: *
This makes it global and cross domain can access the resources from the server. In this condition it is possible to exploit response content by reading through the other domain.
Let’s take an example of an intranet application as in the layout shown in the figure below. The attacker can not access the internal resources through the firewall but can access it using the browser. If the internal user ends up being at the attacker’s site, he/she can send a payload that can start accessing a target internal application and crawl the resources.
Figure 1 - CSRF with CORS - Two Way Channel
For example, one of the server is marked accessible for cross domain call which we can see in following response.
HTTP/1.1 200 OK
Date: Wed, 12 Sep 2012 08:30:17 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: *
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 13539
This particular server can be crawled methodically and one can harvest all information from the server. For example, here is a very simple one page crawl where we are fetching all the links.
function crawl()
{
    var http;
    http = new XMLHttpRequest();

    http.open("GET", "http://192.168.149.128/", false);
    http.send();
    response = http.responseText;
    links = response.match( /<a href="(.*?)">[^<]+<\/a>/g );
    document.getElementById('result').innerText = links; 

}
This function will go and make a connection to the internal IP address and then fetch the response. Here, since the response is marked with the following directive, it gets loaded onto the browser.
Access-Control-Allow-Origin: *
Hence, through JavaScript one can extract the content now and send it back to the attacker server. In this case, for simplicity, we display it on the browser using the following call.
document.getElementById('result').innerText = links;
It will appear as below in the browser.
We can see all links and now, step by step, can start crawling each page. We can pretty much harvest and access all the information from the internal servers. It is also possible to perform a quick internal port scan using XHR or WebSocket.
Hence, it is important to scan through the resources and make sure that none of the critical resource is exposed to CORS issue.
For example, the following simple ruby script (CORScan.rb) can quickly look at the CORS header.
require 'socket'

ip = "192.168.149.128"
port = "80"
request = "GET / HTTP/1.0\r\n\r\n"

s = TCPsocket.open(ip,port)
s.write(request)
response = s.read
headers,body=response.split("\r\n\r\n",2)
puts "-----------HTTP Header----------------"
puts headers
puts "--------------------------------------"
headers.each do |header|    
    if(header =~ /^Access-Control-Allow-Origin:/i)
        puts header
        head,value=header.split(" ",2)
        value=value.chomp("\r\n")        
        if (value=="*")
            puts "[+] CORS Vulnerable Resource"
        end
    end
end
We have kept it simple for one HTTP request, but one can take multiple IPs and crawl the results to go over multiple pages and resources. But objective is to analyze access origin policy by looking at “Access-Control-Allow-Origin”.
If we run to our target application we get following response.
D:\Tools\ruby>CORScan.rb
-----------HTTP Header----------------
HTTP/1.1 200 OK
Connection: close
Date: Wed, 12 Sep 2012 11:02:48 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Access-Control-Allow-Origin: *
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 13539
--------------------------------------
Access-Control-Allow-Origin: *
[+] CORS Vulnerable Resource
Hence, we can find the resource accessible over cross domain in this case.

 CSRF countermeasures

The following countermeasure should help in protecting applications.
1.) Critical forms and HTTP request should be validated for human event either by CAPTCHA or by having a unique identifier number going back to the browser. Hence, when an actual request comes back to server it is human enabled and not automated from cross domain.
2.) The CORS policy should be implemented and cross origin requests should be denied, or allowed from selected  trusted domains only.
3.) “Content-type” must be validated before processing the HTTP requests - if the stream is JSON, XML etc. Unless  it is a really critical business call, it must be validated thoroughly.
“Origin” and “Referer” tag can be processed to identify the HTTP requets’s actual origin. This check can give a good primary defense against CSRF vector.
4.) Application should be XSS free and all protection for XSS should be provided to the application. If XSS is found then it can be leveraged to initiate same origin CSRF attack vector or HTTP request to the application.