BKPCTF-利用open-uri模块查看服务器文件

作者: 分类: CTF 时间: 2016-03-07 浏览: 2612 评论: 暂无评论

这是一道ruby题... bkp真会玩,web只有rb和py

题目首页只有一句话 浏览/flag 和/source

web31.png

妹的 我当然浏览/flag 然后...

web32.png

2333 进入正题 看源码 不要怕 每一行我都在后面解释了~

require 'nokogiri'
require 'open-uri'
require 'sinatra'
require 'shellwords'
require 'base64'
require 'fileutils'

set :bind, "0.0.0.0"
set :port, 5300
cdir = Dir.pwd
get '/' do
        str = "welcome to the automatic resource inliner, we inline all images"
        str << " go to /example.com to get an inlined version of example.com"
        str << " flag is in /flag"
        str << " source is in /source"
        str
end

get '/source' do
        IO.read "/home/optiproxy/optiproxy.rb"
end

get '/flag' do
        str = "I mean, /flag on the file system... If you're looking here, I question"
        str << " your skills"
        str
end

get '/:url' do
        url = params[:url]
        main_dir = Dir.pwd
        temp_dir = ""
        dir = Dir.mktmpdir "inliner"
        Dir.chdir dir
        temp_dir = dir
        exec = "timeout 5 wget -T 2 --page-requisites #{Shellwords.shellescape url}"
        `#{exec}`
        my_dir = Dir.glob ("**/")
        Dir.chdir my_dir[0]
        index_file = "index.html"
        html_file = IO.read index_file
        doc = Nokogiri::HTML(open(index_file))
        doc.xpath('//img').each do |img|
                header = img.xpath('preceding::h2[1]').text
                image = img['src']
                img_data = ""
                uri_scheme = URI(image).scheme
                begin
                        if (uri_scheme == "http" or uri_scheme == "https")
                                url = image
                        else
                                url = "http://#{url}/#{image}"
                        end
                        img_data = open(url).read
                        b64d = "data:image/png;base64," + Base64.strict_encode64(img_data)
                        img['src'] = b64d
                rescue
                        # gotta catch 'em all
                        puts "lole"
                        next
                end
        end
        puts dir
        FileUtils.rm_rf dir
        Dir.chdir main_dir
        doc.to_html
end

这篇准备给自己以后研究ruby的时候用 所以会写的很详细

对于一个完全不会的语言,我的想法就是本地测试。

  1. apt-get install ruby
  2. apt-get install rails

搭建完成 如果第2步出现require什么错误 apt-get install ruby-dev
(环境加测试搞了一个下午...)

require加载模块

set :bind, "0.0.0.0"
set :port, 5300
cdir = Dir.pwd

绑定地址端口 然后把当前目录给cdir(puts相当于print)

web33.png

get do end 就不讲了..

get '/:url' do
        url = params[:url]
        main_dir = Dir.pwd
        temp_dir = ""

这个段卡了很久 最后发现/后面的所有字符被传给url

获取url.png

dir = Dir.mktmpdir "inliner"
        Dir.chdir dir
        temp_dir = dir

在/tmp下创建一个临时文件(用的sinatra模块)再进入该路径

web35.png

exec = "timeout 5 wget -T 2 --page-requisites #{Shellwords.shellescape url}"
`#{exec}`

这句好理解 调用系统命令wget Shellwords.shellescape用来防止命令注入

讲讲这个--page-requisites参数

web36.png

简单的说就是下载网站的静态文件 比如js,img,css 来试一下

web37.png

可以看到建立了一个文件夹 不但下载了主页 还建立了对应的文件夹 下载了css

web38.png

my_dir = Dir.glob ("**/")
Dir.chdir my_dir[0]
index_file = "index.html"
html_file = IO.read index_file
doc = Nokogiri::HTML(open(index_file))

glob和php里的glob函数一样 这里匹配wget下来的文件夹,然后进入,读index.html

最后一句 Nokogiri::HTML 是一个解析html文件的模块
这个操作相当于把doc当做index.html的资源句柄(简单的理解就是把index.html的内容给doc)

doc.xpath('//img').each do |img|
                header = img.xpath('preceding::h2[1]').text
                image = img['src']
                img_data = ""
                uri_scheme = URI(image).scheme

在doc(也就是index.html)中搜索img标签,然后在img标签里找一个文本给header 这个不管。
把img的src给image,把image作为一个uri来解析,取它的scheme,也就是冒号前的协议。

web39.png

接着

begin
        if (uri_scheme == "http" or uri_scheme == "https")
        url = image
        else
        url = "http://#{url}/#{image}"
        end
        img_data = open(url).read
        b64d = "data:image/png;base64," + Base64.strict_encode64(img_data)
        img['src'] = b64d

打开img的url(用的是open-uri模块的open方法) 然后把图片内容用base64转码输出到src

rescue
    # gotta catch 'em all
    puts "lole"
    next

抛出异常就跳过 next相当于continue

puts dir
FileUtils.rm_rf dir
Dir.chdir main_dir
doc.to_html

输出,删除临时目录,转回主目录,输出网页。

源码理解了,再重新整体看一遍。

命令注入应该是不行了,再结合那个base64输出,联想到isg的那个任意文件读取然后用图片base64返回

思路非常明确 尝试简化一下代码然后读取/etc/passwd

web40.jpg

完美! 于是问题就变成怎么绕过这段代码

if (uri_scheme == "http" or uri_scheme == "https")
        url = image
else
        url = "http://#{url}/#{image}"
end
img_data = open(url).read

这里卡了很久很久 怎么在有http开头的情况下读取本地文件

最后找到了这篇文章(基友给的 他搜的ruby uri scheme vuln 我搜的open-uri bug.. 论搜索姿势的重要性)

http://sakurity.com/blog/2015/02/28/openuri.html

根据文中给出的姿势 只要能在服务器端创建一个名为http:的文件夹 就可以用
http:/../../../../../etc/passwd 这种姿势读取 那么怎么创建?

没想到?

还记得wget --page-requisites么..

这就是真相~

最后姿势

web31.png

解下base64,flag到手 用基友的图

web41.jpg

BKPCTF{maybe dont inline everything.}

ps flag为啥在hackbar? 有解码功能~

标签: ruby

订阅本站(RSS)

添加新评论