A survey of crossdomain.xml vulnerabilities

Aug 15, 2014

Vulnerable crossdomain.xml files can be used by malicious people to run CSRF attacks if the victim has Flash installed on their computer. In response to a post by chs on crossdomain.xml proofs of concept and Seth Art’s real-world exploit of Bing using crossdomain.xml, I created an application in Ruby which parses the Alexa top million site list (CSV, 10MB) and scans for vulnerable crossdomain.xml files. Vulnerable here is defined as a crossdomain.xml file which permits connections from any domain name (*). It sorts the domains into four categories:

  • Unable to connect: Ruby was unable to establish a connection to the website. Interestingly enough, a significant portion of Alexa’s top million sites were inaccessible during this survey.
  • Invalid or 404: Returned 404 or the returned XML was not valid.
  • Secure: The XML returned does not contain a reference to allow-access-from domain=”*”. This does not necessarily mean that the whole crossdomain.xml file is secure, just that it is not vulnerable to the most basic of CSRF exploits.
  • Permissive: The XML returned from a GET to /crossdomain.xml does allow access from any domain.

Without further ado, let’s get into it.

The Code

I chose Ruby for this project because it has good XML processing libraries, is reasonably fast, and because I needed an excuse to practice Ruby.

require 'net/http'
require 'rexml/document'
include REXML
require 'csv'

counters = {
	'unconnect'   => 0,
	'invalid-404' => 0,
	'permissive'  => 0,
	'secure'      => 0,
	'total-count' => 0
}

trap 'SIGINT' do
	print counters.inspect
	exit 130
end

permissive = CSV.open('permissive.csv','wb')

CSV.foreach('top-1m.csv') do |row|
	counters['total-count'] += 1
	print "\n"+'Getting '+row[1]+'... '
	begin
		xd = Net::HTTP.get(row[1], '/crossdomain.xml')
	rescue
		counters['unconnect'] += 1
		print 'unable to connect'
		next
	end
	begin
		xd = REXML::Document.new(xd)
	rescue
		counters['invalid-404'] += 1
		print 'invalid xml'
		next
	end
	wildcard_access = false
	XPath.each(xd,'//allow-access-from') do |access|
		next unless access.attributes['domain'] == '*' # <allow-access-from domain="*">
		wildcard_access = true
		counters['permissive'] += 1
		print 'permissive'
		permissive << row
		break
	end
	unless wildcard_access
		counters['secure'] += 1
		print 'secure'
	end
end

print counters.inspect

The Results

After 160,169 websites were inspected over the course of a few days, the script hung.

  • 3,535 (2.2%) of the websites were down at the time of the scan.
  • 84,883 (53%) of the websites had invalid or non-existent XML files at /crossdomain.xml.
  • 67,097 (41.9%) of the websites surveyed had a “secure” crossdomain.xml file.
  • 4,653 (2.9%) of the websites surveyed had insecure crossdomain.xml files.

A wildcard crossdomain.xml file is fine for certain websites, but a quick scan of the results reveals a number of banks, bitcoin websites, and popular entertainment sites (9gag and Vimeo included) with poor crossdomain.xml files. The results as a CSV with columns corresponding to the Alexa rank and the domain name.

Although a full scan of the Alexa top million was not completed, an alarmingly large number of sites have overly permissive and insecure crossdomain.xml files.

Comments