[SCTF2019]Flag Shop
点击buy flag会显示你的JinKela不够,如果点击reset会重置你的uid(好像没啥用),点击工作的话你的JinKela会上升,但是不会明显的上升
f12并没有发现什么东西,dirsearch扫描一下发现了robots.txt
访问得/filebak
继续访问得到源码:
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, file
end
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] = auth
end
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
发现了jwt字样,bp抓包发现了jwt内容
解密(JSON Web Tokens - jwt.io)发现与题目网站的信息一样
但是在jwt修改钱数的话需要secret,而代码中也给出了secret的生成方式
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
需要传参,传do和name,当两者相等的时候就会生成secret,但是也发现了ERB(【技术分享】手把手教你如何完成Ruby ERB模板注入 - 安全客,安全资讯平台),需要<%= xxx %>传值,在ERB中发现ruby,查看ruby预定义变量(globals - Documentation for Ruby 2.4.0),发现$'表示最后一次匹配右边的字符串。
于是开始构造payload:/work?SECRET=&name=<%=$'%> is working
出现了400 Bad Request,可能是过滤了一些字符将字符进行url加密(在线url网址编码、解码器-BeJSON.com),构造出新的payload:/work?SECRET=&name=%3c%25%3d%24%27%25%3e&do=%3c%25%3d%24%27%25%3e%20is%20working,传入就获得了secret
有了secret就可以修改jwt了
填入secret,然后修改金额,这里用科学计数法,只要比需要的金额大就可以,得到新的jwt,返回bp传入,这里要将开头的GET改为POST
又给我们返回了jwt,拿去解密一下得到flag
至此结束,撒花