<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    flag shop

    知識點:Ruby ERB SSTI

    備注:Ruby 摸得少,搜了一個下午都沒搜到 Ruby 的全局變量 – -后來結束了和出題人 evoA 師傅一聊才知道得用美元符號的全局變量,哭了。在這里也還是寫寫 WriteUp 記錄下。

    步驟:

    1、打開靶機,發現是這樣一個頁面。

    2、看下頁面源碼,主要關注后面這一段,先獲取信息,失敗就去請求 auth。


    auth 之后會得到一個 jwt token。看來之后的請求我們也得帶上這個。

    2、掃下敏感文件,有 robots.txt。

    3、訪問一下這個路徑,是源碼。

    require 'sinatra'
    require 'sinatra/cookies'
    require 'sinatra/json'
    require 'jwt'
    require 'securerandom'
    require 'erb'
    
    set :public_folder, File.dirname(__FILE__) + '/static'
    
    FLAGPRICE = 1000000000000000000000000000
    #ENV["SECRET"] = SecureRandom.hex(xx)
    
    configure do
      enable :logging
      file = File.new(File.dirname(__FILE__) + '/../log/http.log',"a+")
      file.sync = true
      use Rack::CommonLogger, file
    end
    
    get "/" do
      redirect '/shop', 302
    end
    
    get "/filebak" do
      content_type :text
      erb IO.binread __FILE__
    end
    
    get "/api/auth" do
      payload = { uid: SecureRandom.uuid , jkl: 20}
      auth = JWT.encode payload,ENV["SECRET"] , 'HS256'
      cookies[:auth] = auth
    end
    
    get "/api/info" do
      islogin
      auth = JWT.decode cookies[:auth],ENV["SECRET"] , true, { algorithm: 'HS256' }
      json({uid: auth[0]["uid"],jkl: auth[0]["jkl"]})
    end
    
    get "/shop" do
      erb :shop
    end
    
    get "/work" do
      islogin
      auth = JWT.decode cookies[:auth],ENV["SECRET"] , true, { algorithm: 'HS256' }
      auth = auth[0]
      unless params[:SECRET].nil?
        if ENV["SECRET"].match("#{params[:SECRET].match(/[0-9a-z]+/)}")
          puts ENV["FLAG"]
        end
      end
    
      if params[:do] == "#{params[:name][0,7]} is working" then
    
        auth["jkl"] = auth["jkl"].to_i + SecureRandom.random_number(10)
        auth = JWT.encode auth,ENV["SECRET"] , 'HS256'
        cookies[:auth] = auth
        ERB::new("&lt;script>alert('#{params[:name][0,7]} working successfully!')&lt;/script>").result
    
      end
    end
    
    post "/shop" do
      islogin
      auth = JWT.decode cookies[:auth],ENV["SECRET"] , true, { algorithm: 'HS256' }
    
      if auth[0]["jkl"] &lt; FLAGPRICE then
    
        json({title: "error",message: "no enough jkl"})
      else
    
        auth &lt;&lt; {flag: ENV["FLAG"]}
        auth = JWT.encode auth,ENV["SECRET"] , 'HS256'
        cookies[:auth] = auth
        json({title: "success",message: "jkl is good thing"})
      end
    end
    
    def islogin
      if cookies[:auth].nil? then
        redirect to('/shop')
      end
    end

    4、可以看到 /work 那里有 ERB 模板,還直接把可控參數 name 拼進去了,那么這里我們就可以傳入一些構造過的參數,來達到我們的目的了。比如 name=<%=1%>,就會得 1。


    5、 繼續看看源碼,同時注意有這樣一段意義不明的代碼。似乎得傳入 SECRET 參數。那么就一起帶上。

    unless params[:SECRET].nil?
        if ENV["SECRET"].match("#{params[:SECRET].match(/[0-9a-z]+/)}")
          puts ENV["FLAG"]
        end
      end

    5、對照 Ruby 全局變量表 ,不斷 fuzz,發現$`有東西,

    回溯到源碼看看

    unless params[:SECRET].nil?
        if ENV["SECRET"].match("#{params[:SECRET].match(/[0-9a-z]+/)}")
          puts ENV["FLAG"]
        end
      end

    其在模板渲染之前之前有個匹配,就是這里。要是 SECRET 參數存在則對其進行匹配,用傳入的這個值去和 ENV["SECRET"] 匹配,匹配上了就往終端輸出 FLAG。意義不明的代碼,但這里既然有匹配,就可以用全局變量讀出來了,也就是用 $` 來讀取匹配前的內容。

    那么這里讀出來的就是 ENV 的 SECRET 的一部分了。

    6、然后我們 SECRET 不傳試試,這樣括號里的匹配就不進行,只進行括號外的 ENV[“SECRET”] 的匹配,再用全局變量 $` 就可以讀出 ENV[“SECRET”] 了。

    7、拿到了 secret 之后,到 jwt.io 偽造一下 cookie 里的 auth 里存的 jwt 令牌。jkl 設置為 2000000000000000000000000000

    8、置 cookie,買 flag。

    9、然后再解析一下新的 jwt token。


    10、Flag 到手~

    本文章首發在 網安wangan.com 網站上。

    上一篇 下一篇
    討論數量: 0
    只看當前版本


    暫無話題~
    亚洲 欧美 自拍 唯美 另类