In general terms, SQLi is the most prevalent and dangerous code insertion technique. An SQLi attack is meant to send malicious SQL commands to the database server. The most common attack goal is bulk extraction of knowledge. Attackers can dump database tables with many thousands of customer records. Depending on the environment, SQL injection also can be exploited to switch or delete data, execute arbitrary OS commands, or launch denial-of-service (DoS) attacks.
Building SQL Injection Scanner in Python
Using the below approach we will extract the web forms first because SQL injection is carried through user input. Then, we will check whether a web page has SQL errors in it, this will be useful when checking for SQL injection attacks and finally, we will test it on HTML forms.
For this, we will require requests and BeautifulSoup package.
Approach:
- Import Modules:
- Use
requestsfor HTTP requests,BeautifulSoupfor parsing HTML, andurljointo handle relative URLs.
- Use
- Initialize Session:
- Create a session with
requests.Session()and set a User-Agent header to mimic a real browser.
- Create a session with
- Extract Forms:
- Fetch all forms from the page using
BeautifulSoupand return a list of form tags.
- Fetch all forms from the page using
- Extract Form Details:
- Get form
action(submission URL),method(POST/GET), andinputs(name, type, and value).
- Get form
- Check for Vulnerabilities:
- Search for common SQL error messages in the response (e.g., "quoted string not properly terminated").
- Test SQL Injection:
- For each form, inject special characters (
',") into the inputs and submit the form. - Check if the response contains SQL errors indicating a vulnerability.
- For each form, inject special characters (
- Submit Data & Detect:
- Use POST or GET to submit the form data and check if it’s vulnerable to SQL injection based on the response errors.
- Run Script:
- Pass the URL as an argument and scan for SQL injection vulnerabilities on the page.
Program:
import requests
from bs4 import BeautifulSoup
import sys
from urllib.parse import urljoin
s = requests.Session()
s.headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
def get_forms(url):
# Make a GET request to the URL and parse the HTML content with BeautifulSoup
soup = BeautifulSoup(s.get(url).content, "html.parser")
# Find all form tags on the page and return them
return soup.find_all("form")
def form_details(form):
detailsOfForm = {}
# Get the form action (URL to which the form is submitted)
action = form.attrs.get("action", "").lower() # Default to empty string if no action attribute
# Get the form method (POST or GET)
method = form.attrs.get("method", "get").lower() # Default to "get" if no method attribute
inputs = []
# Iterate through all input tags inside the form
for input_tag in form.find_all("input"):
input_type = input_tag.attrs.get("type", "text") # Default to "text" if no type attribute
input_name = input_tag.attrs.get("name")
input_value = input_tag.attrs.get("value", "") # Default to empty string if no value attribute
inputs.append({"type": input_type, "name": input_name, "value": input_value})
# Store form details in the dictionary
detailsOfForm["action"] = action
detailsOfForm["method"] = method
detailsOfForm["inputs"] = inputs
return detailsOfForm
def vulnerable(response):
errors = {"quoted string not properly terminated",
"unclosed quotation mark after the character string",
"you have an error in your sql syntax;"}
for error in errors:
if error in response.content.decode().lower():
return True
return False
def sql_injection_scan(url):
forms = get_forms(url)
print(f"[+] Detected {len(forms)} forms on {url}.")
# Iterate over all forms found on the page
for form in forms:
details = form_details(form)
# Test for SQL injection using common special characters
for c in "\"'":
data = {}
for input_tag in details["inputs"]:
if input_tag["type"] == "hidden" or input_tag["value"]:
# If the input type is hidden or it already has a value, append the character to the value
data[input_tag["name"]] = input_tag["value"] + c
elif input_tag["type"] != "submit":
# If the input is not a submit button, inject the test character
data[input_tag["name"]] = f"test{c}"
# Construct the URL to which the form will be submitted
url = urljoin(url, details["action"])
# Send the request based on the form method (POST or GET)
if details["method"] == "post":
res = s.post(url, data=data)
elif details["method"] == "get":
res = s.get(url, params=data)
# Check if the response indicates a possible SQL injection vulnerability
if vulnerable(res):
print(f"SQL Injection attack vulnerability detected in form at {url}")
else:
print("No SQL Injection vulnerability detected")
if __name__ == "__main__":
url_arg = "https://www.geeksforgeeks.org/python/python-programming-language-tutorial/"
sql_injection_scan(url_arg)
Output:
[+] Detected 2 forms on https://www.geeksforgeeks.org/python/python-programming-language-tutorial/
No SQL Injection vulnerability detected
No SQL Injection vulnerability detected
No SQL Injection vulnerability detected
No SQL Injection vulnerability detected