[DDCTF 2019]homebrew event loop
[DDCTF 2019]homebrew event loop
考点
Python源码审计
购买功能中的逻辑漏洞
wp
给了源码,下载审计
从路由入手,只有一个路由/d5afe1f66147e857/
,request.query_string
是获取?
之后的所有内容,其格式为action:ACTION;ARGS0#ARGS1#ARGS2
,通过给定格式的query_string实现不同的功能。在初始状态对session中的值做一系列定义
然后把获取的query_string传给trigger_event这个函数,这个函数把query_string按照先后顺序放在request.event_queue
列表中
在路由的最后执行execute_event_loop
函数,它会获取request.event_queue
列表中的第一个元素,然后把剩下的元素重新赋值给request.event_queue
,并且限制了query_string的组成,只能由字母数字和_:;#
组成,然后截取ACTION
和ARGS
的值,对ACTION
进行拼接后用eval执行,用于获取ACTION()
这个函数,最后再把参数传入ACTION()
函数。
这里action用了拼接的方式,会导致可以执行任意函数,在action后面加上#
就可以绕过对后缀的限制。那么这里肯定会问,为什么不直接执行FLAG()函数呢,因为FLAG()函数没有参数,这里在执行函数时是传入参数的,所以只能用get_flag_handler()函数获取flag
然后去看相关的功能,view_handler()用于展示页面,index_handler()用于展示和下载源码,get_flag_handler()用于获取flag,条件是num_items大于等于5,这个在一开始定义为0个,然后是关键的buy_handler()和consume_point_function()
在正常购买逻辑中的request.event_queue
是由['action:buy;1']
变成['func:consume_point;1', 'action:view;index']
,它是先在session中增加完num_items再去consume_point_function()中验证的
可以通过构造request.event_queue
为['action:buy;5','action:get_flag;']
,这样在执行完buy_handler之后,trigger_event会把剩下的内容进行拼接request.event_queue += event
,变成['action:get_flag;','func:consume_point;5', 'action:view;index']
,然后会执行get_flag_handler(),这时候的num_items为5,所以可以获取flag
而构造request.event_queue
可以通过前面的任意函数执行,执行trigger_event函数完成
最后的payload
总结
代码审计跟着功能搞明白执行顺序
在购买的逻辑中,如果是先把商品加1再判断余额,可能存在逻辑漏洞
最后更新于