豆知识 第一周
虽然是豆知识,但又不是关于豆子的知识。
linux 命令绕过 waf
l''s 命令执行的效果和 ls 一样,这个是shell的字符拼接特性导致的
除了l''s,l""s,'l''s','l's都能达到一个效果,甚至echo 出来都是ls
|
|
curl出网姿势
今天看到了两种基于curl的出网姿势
直接传
|
|
这里还涉及一个豆知识,在shell里面,@-表示标准输入,@/flag表示具体文件的内容
反向shell
|
|
后者需要在服务器写一个公网可访问的反向shell字符串
|
|
记得打开http.server: python3 -m http.server 8080 -d /var/www/html
然后只要在服务器打开nc监听对应端口就行了
pydash 原型链污染漏洞
虽然python里面没有js里原型链那一套东西,但是里面的原理差不多所以也跟着叫了(
pydash的老版本set_()函数没设置防御,如果不加额外waf让他改啥就改啥,我遇到的是5.1.2,看下面的代码:
|
|
这个pydash为了方便写作,不管是对象,字典还是数列,都统一用.表示从属关系,所以有__globals__.GLOBAL_CONFIG这个写法,这个真的挺好的,跑下来的结果是
|
|
flask-unsign
flask的session是塞到cookie里的,虽然有加密,但是暴露出来就有爆破的可能,特别是在那些拿时间戳做密钥的情况
flask-unsign 提供了从爆破到加密的工具
|
|
python LEGB规则
当你在 Python 代码里写下一个变量名(比如 print(x))时,Python 解释器会按照 L -> E -> G -> B 的顺序去寻找这个 x 到底是谁。
- Local -局部作用域
- 函数内部定义的变量
|
|
- Enclosing -嵌套作用域
- 嵌套函数中,外层函数的命名空间
|
|
- Global -全局作用域
- 当前.py文件最外部定义的变量,导入的库
这个很重要,但注意只包含当前文件最外层的,python里的函数自带__globals__属性来加载全局变量,当你能控制一个类或实例,可以通过类__init__函数接触globals,从而控制当前文件的,全局命名空间的变量和模块
|
|
- Build_in -内置作用域
- 兜底作用域,包含python解释器启动时自带的工具
像 print()、len()、int()、__import__() 这些函数,不必 import 任何东西就能用,因为它们都住在 Built-in 空间(对应的模块叫 builtins
如果在 L、E、G 里都找不到变量,Python 最后会来这里找。如果这里也没有,就会抛出 NameError
python sys模块
这个模块管的是python解释器本身,可以控制python的命令行参数,执行环境,IO之类的
这个sys底下有一个modules的字典,可以管理解释器加载的各种模块,包括自己利用sys.moudules可以访问到加载的所有模块
当你的文件import一个模块之后,由于命名空间隔离, 轮子模块内部加载的命名空间不会暴露给调用轮子的程序,但是可以在sys.modules这个控制python解释器所有模块的字典里面找到
如果当前文件没有sys模块而加载了其他模块,那你可以先从当前globals摸到一个模块,从这个模块开始,
可以通过__loader__和__spec__(用来处理模块加载和模板的函数)的__init__.__globals__来进入模块导入这个底层机制的命名变量实现逃逸,底层有sys
当然,如果直接就加载了sys直接在__globals__里面调用就行
|
|
那这个拿到的’jinja2’有什么用呢?
变量污染 + jinja2 -> RCE
我之前讲了
pydash模块的set_函数里面,可以通过属性链实现覆盖指定的变量实现污染,或者在flask代码里面,你有什么其他的方法可以做到变量污染的话,你就可以通过jinja2的一个特性实现RCE,或者直接连上shell,
我们先pip install 一下 flask
jinja2中中有这样一个列表,你也可以在你的xxenv/lib/python3.14/site-packages/jinja2/runtime.py里面找到他的定义
|
|
runtime(运行时)指的是模板渲染过程中动态解析和执行的核心环境,它决定了模板如何访问变量、调用函数以及处理逻辑流程。
但这里我们只需要知道runtime里面管理了渲染模板时会拼接进python代码的变量就行了,顾名思义,这里的exported就是别的地方的import:
在xxebv/lib/python3.14/site-packages/jinja2/compiler.py中有如下函数(只提取关键部分):
|
|
这里的compiler.py编译器负责的是具体的模板翻译逻辑,其中,会导入.runtime里的exported,然后把这个列表里面的值翻译进去,在渲染时执行
from jinja2.runtime import {exported_names)}其中这个exported_name是我们可以控制的,那只要修改列表中的某个元素为 *; import os; os.system('ls');#就可以实现
|
|
从而实现RCE,但是这个输出是在标准输出上的,不会像ssti一样打印在屏幕,需要出网
flask里面有这个渲染是直接拼接字符串到代码内部的问题,虽然说fxxk the frontend,但是轮子被改了也不能怪防御不到位,jinja2是没有锅的,问题是后端的人没好好防御
结语
由于ai的出现,传统安全越来越难做了,现在学计算机就像是在蚀之刻的前一天加入鹰之团,也许ai之于程序员就像纺织机之于织布工,现在你说你要自己织布做衣服我会觉得你挺有生活,但你说你要织布养活赚钱自己,那你最好是世界最顶级的手艺人,几年后代码估计也是这样。
织布机是一个伟大的发明,手工织布的时代现在没人怀念,那样的时代也不值得怀念,幸运的是我不像那些学了十几年前端的程序员,一觉醒来发现自己被取代了。我才刚刚起步,ai也才几年时间,去找总会有一些好的机会的,不要排斥ai,也不要屈从于他的淫威,多学点硬本事,懂安全的人总是需要的
再说,谁会期待一个没有可口可乐的世界呢
