[SCTF2019]Flag Shop
[SCTF2019]Flag Shop
考点
ruby代码审计
ruby erb模板注入
wp
给了uid,金坷垃,flag价格三个参数,同时三个按钮,抓包。
buy flag按钮是POST请求/shop,在后端判断金坷垃是否够买flag
reset是GET请求/api/auth,返回新的cookie,auth=eyJhbGciOiJIUzI1NiJ9.eyJ1aWQiOiJhOTNkMDI3MS1iYjZlLTQyNTEtOGQ5Mi1lZjgxOWY1MTgxODQiLCJqa2wiOjIwfQ.F4fAw7T3hcalQsKyKjkLs6zbylPHTKEj6s9pJ7_XEcA,然后请求/shop获取主页,最后请求/api/info,获取用户uid和金坷垃
work是GET请求/work?name=bot&do=bot%20is%20working,随机增加金坷垃,然后请求/shop获取主页,最后请求/api/info,获取用户uid和金坷垃
把cookie放在jwt.io看一下

需要密钥才能修改,尝试jwt-crack破解未果
扫目录,发现robots.txt,提示访问/filebak,得到源码
第一种方法
查一下sinatra是ruby的一个Web框架,erb是ruby自带的模板渲染包,如果输入可控,它会导致模板注入。
枚举当前类的可用方法
Ruby ERB模板注入读取文件的payload:<%= File.open('/etc/passwd').read %>
看给的代码,在访问work时,有两个判断
一个是传入SECRET参数,params[:SECRET].nil?判断是否传入SECRET参数,然后匹配SECRET中的小写字母和数字并返回,再用#{}获取这个变量,最后和ENV["SECRET"]进行匹配。
#{var}在Ruby中进行变量替换。例如
match是进行匹配。例如
另外是传入do和name参数,满足name[0:7] is working==do,然后使用ERB渲染name
也就是说,传入的name不超过7个字符,并且符合这种形式name=1234567&do=1234567 is working。而ERB模板渲染的字符<%=%>就用了5个,只有两个字符可用。
使用<%=1%>测试,URL编码之后再传入

这里先进行两次匹配操作,还能够进行模板注入,可以通过模板注入返回全局变量
输出
可以得到结论
$~ 返回最后一次匹配到的内容
$` 返回最后一次未匹配到内容前面的部分
$' 返回最后一次未匹配到内容后面的部分
得到payload:GET /work?name=%3c%25%3d%24'%25%3e&do=%3c%25%3d%24'%25%3e%20is%20working&SECRET=

得到密钥
jkl改成10000000000000000000000000000重新加密
更改cookie再点击buy flag,在cookie中返回flag
第二种方法
前面提到,传入的name不超过7个字符,并且符合这种形式name=1234567&do=1234567 is working。而ERB模板渲染的字符<%=%>就用了5个,那只剩下两个字符可用。
对于这点,可以使用数组绕过。Ruby中存在数据类型自动强制转换机制。
结果
如果传入数组,那就从原本的7个字符,变成了7个数组长度
payload:
小结
最后更新于