來源鏈接:xdxd.love
作者:xdxd
歷史上的安全漏洞
spotify的漏洞
相關資料:
https://labs.spotify.com/2013/06/18/creative-usernames/
spotify的漏洞相比于github的漏洞來說是一個真正的高危漏洞,可以修改任意用戶的密碼。
github的漏洞
相關資料:
https://twitter.com/GitHubSecurity/status/757686530748125184 https://bounty.github.com/researchers/jagracey.html?ljh
github的郵箱名允許unicode字符,導致可以把找回密碼的token發送到攻擊者的郵箱。從twitter的討論來以及自己的測試結果來看提供郵箱服務的產品大部分都是白名單了郵箱的用戶名,所以都是不可以使用unicode字符的。測試了網易的企業郵箱和騰訊的企業郵箱,都不可以使用unicode字符。所以只能自己搭一個郵件服務器來測試這個問題。
魔法在哪里
編碼的基礎知識、unicode編碼和同形字
參考資料: http://www.freebuf.com/articles/web/25623.html http://www.irongeek.com/homoglyph-attack-generator.php
了解了編碼是二進制和字符之間的映射關系之后,可以了解到unicode字符無非也是一種字符而已,只要程序支持,應該不會有任何問題。為什么這個unicode字符在處理過程中變成了另外一個字符,而且是看起來很相似的字符,難道程序也跟人眼看一樣,被相同的外表迷惑了。顯然程序處理的是二進制的數據,只要二進制不同,無論外表看起來多么一樣,程序都應該可以分辨出來。關于unicode同形字的問題,unicode homoglyphs,其實早就有不少討論。不過大多是利用同形字來迷惑人釣魚之類。那么機器怎么也會被同形字迷惑呢。
github的漏洞描述中是這么寫的:a flaw in the way email addresses were being normalized to standard character sets when used to look up accounts during the password recovery flow. 在郵件地址標準化成標準的字符集的時候出現問題。
而spoity中對有對詳細漏洞的代碼分析:可以看到也是對字符串的標準化操作導致unicode字符轉換成了與他同形的ascii字符。
unicode轉ascii
參考資料:
https://www.peterbe.com/plog/unicode-to-ascii http://savanttools.com/unicode-to-ascii.asp
這里才是最有意思的地方,為什么對unicode字符的標準化會導致unicode轉變成了對應的同形字。電腦應該是只看二進制,又不是跟人一樣,會被同形的字迷惑。通過搜索發現,原來有專門的unicode轉ascii函數,對unicode于同形的ascii之間有對應的map。
比如github中提到的例子,轉成對應的ascii就剛好對的上。

漏洞原理
漏洞的原理比較有意思,主要的條件是用戶的id支持unicode。比如兩個ID:mike@example.org vs m?ke@example.org 然而在一些業務邏輯中會對用戶id做標準化的操作,比如重置密碼的時候,m?ke@example.org標準化之后變成了mike@example.org,從而重置了mike@example.org的密碼。
所以關鍵的條件就是用戶識別的ID(包括可以用來登錄的郵箱)支持unicode。而在某些業務邏輯中有對unicode字符進行所謂標準化,轉換成了對應的ascii。其實假如某些業務邏輯不支持unicode,直接丟掉了那部分unicode,應該也是一樣的,目前沒有看到類似的案例。導致在這部分業務邏輯中出現了越權的問題。典型的場景就是修改密碼,導致可以修改他人的密碼。
對微信的測試記錄
實際中的場景比較少,大部分產品都會對用戶登錄名做白名單限制了。經過一番尋找發現微信的綁定郵箱是支持unicode的,而且是郵箱的用戶名和域名部分都支持unicode。當然最后的測試結果是不存在這個漏洞。作為一個典型的測試過程記錄一下。
搭建支持unicode用戶名的郵件服務器
使用iredmail方便快速搭建郵件服務器。然后發現iredmail對用戶名也是有過濾的。代碼在iRedAdmin-0.6.1/libs/iredutils.py 中的is_email方法。修改該方法直接返回True,不檢查郵件用戶名。
######################
# Regular expressions.
#
# Email.
reEmail = r'''[\w\-][\w\-\.\+\=]*@[\w\-][\w\-\.]*\.[a-zA-Z0-9\-]{2,15}'''
# Domain.
reDomain = r'''[\w\-][\w\-\.]*\.[a-z0-9\-]{2,15}'''
# End Regular expressions.
####
#####################################
# Pre-defined values of SQL functions.
sqlUnixTimestamp = web.sqlliteral('UNIX_TIMESTAMP()')
#####
##############
# Validators
#
INVALID_EMAIL_CHARS = '~!#$%^&*()\\/\ '
INVALID_DOMAIN_CHARS = '~!#$%^&*()+\\/\ '
def is_email(s):
#return True 直接返回true,不檢查email名稱合法性。
s = str(s)
if len(set(s) & set(INVALID_EMAIL_CHARS)) > 0 \
or '.' not in s \
or s.count('@') != 1:
return False
reCompEmail = re.compile(reEmail + '/span>, re.IGNORECASE)
if reCompEmail.match(s):
return True
else:
return False

然后發現依然無法收到郵件,發現服務器返回505。拒絕了含有unicode字符的郵箱。

采用的解決方式在數據庫中插入了一條域名的郵箱,轉發到一個正常的郵箱。這樣可以接受這個域名所有的郵件。

因為iredmail默認開啟了SSL,為了調試,查看具體的smtp信息,關閉了SSL,直接明文傳。
綁定郵箱以及重置密碼
微信郵箱綁定支持unicode字符的郵箱。

綁定郵箱后,重置密碼。

正常重置了自己的密碼。鏈接中的email字段是base64編碼的。解碼出來是含有unicode字符的郵箱。所以微信的重置密碼業務邏輯中沒有標準化unicode字符這個處理。不存在unicode同形字引起的漏洞。
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/77/
暫無評論