SHA-256 的 Length extension attack

Hacker News 上看到「Breaking SHA256: length extension attacks in practice (kerkour.com)」,在講不當使用 SHA-256 會導致 Length extension attack 類的安全漏洞,主要是因為 MD5SHA-1 以及 SHA-2 類的 hash function 最後生出 hash 值時會暴露出 hash function 的內部狀態而導致的問題。

這邊講的不當使用是指你沒有使用標準的 MAC,而是自己用字串組合實作造成的問題,通常是 S = H(secret || message) 這樣的形式,這邊的 || 是指字串相接。

拿 MD5 為例子,在維基百科上面可以看到 MD5 演算法對應的 pseudo code,最後輸出的部分可以看到是把 a0a1a2a3 這四個 32-bit variable 接起來,也就是把內部的狀態丟出來了:

// Process the message in successive 512-bit chunks:
for each 512-bit chunk of padded message do
    // ...

    // Add this chunk's hash to result so far:
    a0 := a0 + A
    b0 := b0 + B
    c0 := c0 + C
    d0 := d0 + D
end for

var char digest[16] := a0 append b0 append c0 append d0 // (Output is in little-endian)

於是你在可以反推 padding 的結構之後 (會需要知道 secret 的長度),就可以往後接東西繼續算下去,這就是被稱作 length extension attack。

本來只有 S = H(secret || message),你在不知道 secret 的情況下就可以疊字串到後面而且算出對應的 hash 值,變成 S' = H(secret || message || evildata)

維基百科給的例子也示範了怎麼「用」,這是原始的資料以及 server 端簽出來的 hash 值:

Original Data: count=10&lat=37.351&user_id=1&long=-119.827&waffle=eggo
Original Signature: 6d5f807e23db210bc254a28be2d6759a0f5f5d99

於是我們想要蓋 waffle 參數,就變成:

Desired New Data: count=10&lat=37.351&user_id=1&long=-119.827&waffle=eggo&waffle=liege

攻擊者則可以不斷的嘗試,去猜測 padding 的結構,把計算出來對應的 hash 值丟到 server 看反應,直到看到 200 OK 的回應:

New Data: count=10&lat=37.351&user_id=1&long=-119.827&waffle=eggo\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x28&waffle=liege
New Signature: 0e41270260895979317fff3898ab85668953aaa2

如同前面提到的,這是 hash function 在最後把內部狀態直接暴露出來造成的問題,在 MD5、SHA-1、SHA-2 (SHA-256、SHA-384、SHA-512) 都有類似的問題,而比較新的 hash function 在設計時就已經有考慮到了,不會出現這個問題,像是 SHA-3

另外一方面,不要自己發明演算法,使用標準的 MAC 演算法通常是比較好的選擇。這邊用的比較廣泛的應該就是 HMAC,超過 25 年了。

結論是 SHA-256 還是堪用,儘量拿現成的演算法套,不要自己搞。

Git 在 SHA-256 支援上遇到的問題

在 Hacker News 首頁上的「Whatever happened to SHA-256 support in Git?」這篇,大概半年前,今年六月的文章,在講 GitSHA-256 支援上遇到的問題。

最大的問題還是沒有 transition plan:

Bjarmason pointed out that there is still no interoperability between SHA-1 and SHA-256 repositories, and that none of the Git hosting providers appear to be supporting SHA-256.

這點導致了目前場上看的到的服務與 open source 軟體都沒有支援的計畫,這點算是一個超級失敗的 transition plan。

另外乾脆請 OpenAIChatGPT 幫忙寫:

Git是一種源代碼管理系統,它使用散列函數將每個對象(例如文件的每個版本)和每個提交都轉換為一個數值,用於存儲該對象。散列函數的安全性是整個倉庫完整性的重要組成部分。如果攻擊者可以用具有相同散列值的另一個提交替換提交,他們可能會在不冒檢測風險的情況下將惡意代碼植入倉庫中。這種前景令任何依賴 Git 倉庫中代碼安全性的人感到擔心,也就是所有人。

Git 項目早已選擇 SHA-256 作為 SHA-1 的替代品。Git 最初是使用 SHA-1 寫成的,但是這些代碼已被重構,並且可以處理多種散列類型,其中 SHA-256 是第二種支持的類型。現在可以使用 SHA-256 創建 Git 倉庫(只需使用 --object-format=sha256 標誌),大多數本地操作都會正常工作。Git 中支持替代散列算法的基礎是2020年發布的2.29版本的一部分,並且似乎很穩定。

然而,自從2021年3月發布的2.31版本中出現了修復程序以來,2.29版本是最後一個在任何重大方面支持替代散列的版本。專

續寫前文,Git 專案在支持 SHA-256 之前一直使用 SHA-1 作為散列算法。然而,由於 SHA-1 的終極破解,Git 項目被迫尋找替代方案。Git 原本的代碼是深深地嵌入 SHA-1 的,但是這些代碼已經被重構,並且可以處理多種散列類型,其中 SHA-256 是第二種支持的類型。因此,現在可以使用 SHA-256 創建 Git 倉庫(只需使用 --object-format=sha256 標誌),大多數本地操作都會正常工作。

然而,目前尚不存在 SHA-1 和 SHA-256 倉庫之間的相互操作性,並且 Git 托管提供商似乎都不支持 SHA-256。這種支持(或缺乏支持)很重要,因為無法推送到 Git 熔爐的倉庫對許多人來說將是無用的。此外,使用 SHA-256 的較長散列可能會破壞 Git 項目以外開發的工具,這種風險也無法完全消除。整體而言,這是一種尚未準備好用於現實世界的功能。

雖然如此,值得注意的是,迄今為止完成大部分散列轉換工作的 brian m. carlson 對 Bjarmason 的評估持不同看法。在他看來,目前唯一“可以辯解

的”使用 SHA-1 的原因是與 Git 熔爐提供商的相互操作性。否則,他認為 SHA-1 已經過時,並且使用 SHA-256 的性能可能“大幅提升”。但是,他同意所需的相互操作性目前尚不存在,且沒有人表示它即將在短期內到來。

因此,目前看來,Git 專案在支持 SHA-256 方面的工作似乎已經停止。至於什麼原因導致了這種情況,目前還不清楚。但是,這並不意味著 Git 將永遠不會支持 SHA-256 或其他散列算法。相反,可能是因為尚未解決所有技術問題,或者可能是因為其他原因(例如技術資源有限)。無論原因是什麼,重要的是要記住,Git 項目的開發人員一直在努力使其更強大、更安全,並且將繼續努力。

用圖片表示 SHA-256 的值

Hacker News 上看到的用法,把 SHA-256 的值表示成 avatar:「Representing SHA-256 Hashes As Avatars」,Hacker News 上的討論在「Representing SHA-256 Hashes as Avatars (francoisbest.com)」這邊可以看到。

做出來大概是這樣,這邊的 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 是空字串的 SHA-256 值:

裡面有提到一些演算法,讓圖片看起來不要那麼「奇怪」,還蠻有趣的...

在文章最後面還有一些其他的圖片類型,如果要自己搞 avatar service 的人可以參考演算法的部份,自己搞一套出來玩。

Django 3.1

看到「Django 3.1 Released」這邊的公告,比較完整的改變可以在「Django 3.1 release notes」這邊翻到。

這應該是第一次要把手上的專案跳 minor version 升級,看起來應該是還好,但天曉得會有什麼狀況... 看起來主要會是 sha1 要被換成 sha256 會有影響到。

另外看到這個:

SimpleTestCase now implements the debug() method to allow running a test without collecting the result and catching exceptions. This can be used to support running tests under a debugger.

看起來應該也蠻有用的,可以玩看看...

處理很久前用 OpenSSL 加密的備份資料

因為想要翻一些舊的文章 (小說),想把以前 BBS 的備份拉出來看看裡面有沒有,結果發現 OpenSSL 解半天都解不開,還跑去玩了 bruteforce-salted-openssl 這個專案:

Try to find the password of a file that was encrypted with the 'openssl' command.

後來也是因為這個專案提醒,發現 openssl enc 指令在 OpenSSL 1.0.x (以及之前) 預設是用 MD5 當 digest algorithm,而 1.1.x 換成了 SHA-256,而我的備份資料應該是在 0.9.x 的年代就生出來了...

指定 -md md5 後就正常解出來了:

openssl enc -bf -d -md md5 -in ooxx.tar.gz.bf -out ooxx.tar.gz

另外一個收穫是 CPU 溫度降了不少:因為跑 bruteforce-salted-openssl 的時候 CPU 到 80 度,感覺撞到安全值卡在 4.0Ghz,所以就把 CPU 電壓降了 0.1V,看起來溫度低了不少 (少了五度),但跑起來還是 4.0Ghz...

實際比較 Linode 的 Dedicated 主機與 AWS 的 c5.*

先前有提到 Linode 出了 Dedicated 主機:「Linode 推出 Dedicated CPU Instances」,現在找機會測試看看,拿了 Linode 的 Dedicated (4GB) 與 AWSc5.large 比較,同樣都是 2 vCPU 與 4GB RAM。

這邊用了 n-st/nenchOpenSSL 的 speed (包括了 aes、md5、rsa、sha1 與 sha256) 測試,我把結果都貼到這邊:「Linode (Dedicated 4GB) v.s. AWS (c5.large)」。

可以看到在 CPU 方面主要的差異是 Linode 用的是 AMD,而 AWS 用的是 Intel,所以就會有蠻多不同的數字表現...

如果仔細看 OpenSSL 的測試數據,可以看到不同演算法的差異還蠻大的,馬上可以想到的應該是硬體加速方式與 cache 架構差異造成的:

  • 在 cipher 類的測試我只測了 AES (目前的主流),小的 block (16/64/256 bytes) 時 AMD 會輸一些,但大的 block (1024/8192/16384 bytes) 反而會贏不少。
  • 在 hash 類的測試中,跑 MD5 時 Linode 則是輸一些,但 SHA1 反而是贏一些,然後 SHA256 時效能好到爆炸贏了一倍 XDDD
  • 在 public key 類的測試我測了 RSA,則是 Linode 輸的蠻慘的...

如果考慮到價位大約只有 AWS 的一半,應該是還不錯...

Imgur 也漏資料了... (帳號與密碼)

Imgur 官方發佈公告說明他們發現資料洩漏了:「Notice of Data Breach」,資料的洩漏是發生在 2014 年,包括了帳號與密碼:

Early morning on November 24th, we confirmed that approximately 1.7 million Imgur user accounts were compromised in 2014. The compromised account information included only email addresses and passwords. Imgur has never asked for real names, addresses, phone numbers, or other personally-identifying information (“PII”), so the information that was compromised did NOT include such PII.

然後 2014 年用的是 SHA-256

We have always encrypted your password in our database, but it may have been cracked with brute force due to an older hashing algorithm (SHA-256) that was used at the time. We updated our algorithm to the new bcrypt algorithm last year.

以單台八張 GTX 1080hashcat 的速度來看 (出自「8x Nvidia GTX 1080 Hashcat Benchmarks」),是 23GH/z 左右:

Hashtype: SHA256

Speed.Dev.#1.: 2865.2 MH/s (96.18ms)
Speed.Dev.#2.: 2839.8 MH/s (96.65ms)
Speed.Dev.#3.: 2879.5 MH/s (97.14ms)
Speed.Dev.#4.: 2870.6 MH/s (96.32ms)
Speed.Dev.#5.: 2894.2 MH/s (96.64ms)
Speed.Dev.#6.: 2857.7 MH/s (96.78ms)
Speed.Dev.#7.: 2899.3 MH/s (96.46ms)
Speed.Dev.#8.: 2905.7 MH/s (96.26ms)
Speed.Dev.#*.: 23012.1 MH/s

這對於鍵盤可以打出的所有字元來計算 (95 chars),八個字的密碼只要 3.33 天就可以跑完;如果只考慮英文數字 (62 chars),九個字的密碼只要 6.81 天。

這些還不是最新的 GPU,而且是單機計算,對於現在的攻擊應該會用 ASIC,可以考慮多三到四個數量級的數度在算 (看財力才會知道買多少機器)。

不過 Imgur 的帳號主要是參與討論 (因為不用帳號密碼也可以上傳圖片),一般比較不會在上面註冊... 真的有註冊的因為沒有其他個資,主要是怕共用密碼的問題。如果有用 password manager 應該也還好。

GitHub 明年關閉 SSH 上 SHA1 相關的 Kx (Key Exchange) 演算法

GitHub 定下落日條款了:「Weak cryptographic standards deprecation update」。

這次目標是 diffie-hellman-group1-sha1diffie-hellman-group14-sha1,同時啟用了 diffie-hellman-group-exchange-sha256

Since the announcement, we have been focusing on the impact of disabling the diffie-hellman-group1-sha1 and diffie-hellman-group14-sha1 key exchanges for SSH. As of last week, we have enabled diffie-hellman-group-exchange-sha256. This key exchange method is widely supported and will allow most legacy clients to seamlessly transition away from diffie-hellman-group1-sha1 and diffie-hellman-group14-sha1.

明年二月拔掉 diffie-hellman-group1-sha1diffie-hellman-group14-sha1

This is a very small percentage of traffic, but we would like to see if we can reduce the incompatible traffic percentage even further before disabling support for the older key exchange algorithms on February 1, 2018.

Mozilla 對 WoSign 事件的決策 (草稿階段)

在「Mozilla 在考慮移除 WoSign 的 CA Root」這邊提到的事情,隨著時間的發展,大家發現事情愈來愈誇張。

在兩個小時前 MozillaGervase Markham 提出了對 WoSign + StartCom 處置的草稿:「WoSign and StartCom」,草稿在 Google Docs 上的「WoSign and StartCom」這邊可以看到。另外 Mozilla 在 wiki 上「CA:WoSign Issues」將 WoSign + StartCom 的事情都整理了出來,也是重要的資料。

文章很長,先講結論:目前 Mozilla 打算把 WoSign 與 StartCom 所簽出的 certificate 都照當年 CNNIC 的方式拔掉。

從頭說明,事情發生於八月底的時候 Google 通知了 Mozilla 一連串 WoSign 出包卻沒有主動通報的事件,當時知道的大約有三或四件。而在 mozilla.dev.security.policy 不斷的討論的情況下,由於關注度變得超高,在搜尋大量的資料下發現更多問題,到現在 Mozilla 的 wiki 上已經列出了 13 個。

而這邊以 Mozilla 最後整理的草稿,將 13 個事件整合起來成幾件來說明:

WoSign and Back-Dated SHA-1

在瀏覽器會對 2016 後所簽出直接跳 error 的情況下 (像是「An update on SHA-1 certificates in Chrome」),直接偽造是 2015 年簽出的 certificate。

WoSign’s Ownership of StartCom

Mozilla 的 CA program 要求當公司擁有權轉移時必須揭露:

[...], Mozilla’s program requirements say that a change of CA ownership must be disclosed. In this case, that was not done - and in fact, the change was directly denied a few months after it happened.

直到最近被抓到而揭露後,發現 WoSign 所揭露的也不正確,StartCom 已經開始使用 WoSign 的 infrastructure 了:

More recently, even after the evidence of total control was public, WoSign referred to their interest in StartCom in a press release as “an equity investment”, and maintain that the two businesses continue to be separate even today. They say “the original system ... of StartCom remains unchanged”.

However, there is technical evidence that around a month and a half after the acquisition, StartCom issuances switched to using WoSign’s infrastructure - either the same instance of it, or their own instance.

而 Mozilla 要求 WoSign 提供他們產生 serial number 的程式碼時:(在 WoSign 簽出重複的 serial number 問題時得到的)

Mozilla asked WoSign how they generated their serial numbers, and was told that they used the Java package java.crypto.SecureRandom. They supplied the following code snippet:

[...]

However, as can be seen from this simple test harness, this code snippet does not produce serial numbers matching WoSign’s idiosyncratic pattern.

再度發現 WoSign 給的程式碼對不上。(hey)

然後再多方面分析後發現 WoSign 宣稱跟 StartCom 只共用 CRL/OCSP (revoke 機制) 是假的。Mozilla 由多方面判斷發現,至少程式碼是共用的 (i.e. clone),甚至猜測整個系統都是共用的 (在更後面提到):

We believe that, taken together, all this shows that StartCom’s certificates are now being issued using either WoSign’s existing infrastructure or a clone of it, and that WoSign’s operational control of StartCom began straight after the November 1st 2015 sale date. This evidence should be compared against WoSign’s recent assertion that “Even now, it still independent in the system, in the validation team and management team, we share the CRL/OCSP distribution resource only.”

SHA-1 Exceptions Process

再來是講一些背景。因為金流產業到了 2016 年還是有系統不支援 SHA-256 certificate,而 CA/Browser Forum 已經禁止簽發 SHA-1 憑證了,所以 2016 年二月的時候 WorldPay 跑上來尋求例外:

This became clear in February of 2016, where a payment processor called WorldPay applied to the CAB Forum for an exception so they could acquire 8 SHA-1 certificates to keep SSL working for their legacy payment terminals. Their CA was unable to help them because of the ban in the CAB Forum Baseline Requirements, and to issue in violation of the ban would lead to a “qualified” (not clean) audit, which might lead to browsers no longer accepting their audit as valid to keep them trusted.

而在亞利桑那的 face-to-face meeting 中剛好就討論了這點,允許 Symantec 簽發,而要提出來的是,WoSign 的 Richard Wang 也在場:

This issue was discussed at length in the CAB Forum face-to-face meeting from 16th-18th February 2016 in Scottsdale, Arizona (where Richard Wang of WoSign was present). Mozilla then had a public discussion about it in our policy forum starting on 23rd of February. In the end, the browsers reluctantly agreed to let Symantec issue these certificates for Worldpay - or rather, they agreed to accept that Symantec’s next audit would be qualified in this way.

所以 Mozilla 再次強調,當下大家的結論是特別許可,簽發被禁止的 SHA-1 certificate 是很嚴重違反規定的事情:

Even at this point, in February 2016, it was (or should have been) clear to all CAs, including WoSign, that issuing SHA-1 certificates in violation of the ban was a Very Big Deal, and that permission had to be sought from the browsers in order for the CA not to face difficulty.

Tyro

接下來是 Tyro,這是一家澳洲金流廠商,直接複製草稿上的時間表:

Feb 3rd 2010 GeoTrust issues a SHA-1 certificate for *.tyro.com from their Equifax root, valid until May 6th 2013.
Apr 6th 2013 A month before their old cert expires, GeoTrust issues a replacement SHA-1 certificate for *.tyro.com from a GeoTrust root, valid until June 7th 2016. A simple roll-over replacement.
Jan 1st 2016 SHA-1 issuance ban comes into effect.
May 24th 2016 A month before their old cert expires, GeoTrust issues a SHA-256 certificate for *.tyro.com from a GeoTrust root, valid until June 23rd 2019.

但 Tyro 在 2016 年五月拿到的 SHA-256 憑證很明顯不合用,於是試著找 SHA-1 憑證... 結果不管怎樣,後來拿到了 StartCom 所簽出來的 SHA-1 憑證,而藉由技術上的 pattern 可以發現這是 back-dated (偽造日期簽發):

But the strong evidence is that this SHA-256 certificate did not meet Tyro’s needs. We can see a SHA-1 certificate for *.tyro.com which was logged in CT on June 8th 2016, a day after their previous SHA-1 certificate expired. This certificate is not issued by GeoTrust (who still provide the cert for their main website) or Comodo, tyro.com’s usual providers, but by StartCom. And the notBefore date is that magic date of 20th December, 2015 - a date on which, as noted above, StartSSL.com was closed for upgrading, and on which we have seen many Macau certificates issued by WoSign, which we believe are back-dated.

也可以很清楚的確認到現在還在使用:

The SHA-1 certificate in question is still in use today on https://iclient.tyro.com/.

Conculsions

最後 Mozilla 得到的結論:

  • StartCom are using WoSign’s infrastructure (the same or a clone);
  • Certificates on this infrastructure with a notBefore of 2015-12-20 (China time) are indeed back-dated - this further confirms our suspicions about the Macau certificates we saw issued by WoSign; and
  • StartCom’s hierarchy has been directed by management to mis-issue “WoSign-style”.

同時他們認為最後一點是最嚴重的一點,你必須將 StartCom 視為與 WoSign 完全同樣的公司,所有對 WoSign 的檢查與處置都必須相同對應到 StartCom 上:

This last point is important; the practices at WoSign are now being seen at StartCom. Therefore, we conclude that all of ownership, infrastructure and control are sufficiently common between the two companies that it would therefore be reasonable for any action Mozilla chooses to take against WoSign to also be taken against StartCom and vice versa.

另外一個很嚴肅的問題,CA 架構是建立在稽核機制上,而 WoSign 所選擇的稽核單位無法稽核出應有的「多個問題」:

WoSign’s auditors, Ernst & Young (Hong Kong), have failed to detect multiple issues they should have detected. (Issue J, Issue X)

提案的處理方式類似於 CNNIC 當時被拔掉的方式,針對某個日期之後的都不信任。這同時包括了 WoSign 與 StartCom 的 certificate。這真是可喜可賀啊...

OpenSSL 產生並簽出 SHA2 (SHA256) 的憑證

因為 Google Chrome 39 出來的關係,一些以前簽出來只包含 SHA-1 的 SSL certificate 因此導致了綠色 icon 變成黃色 icon,所以都要重簽一次產生 SHA-2 資訊。

有人說可以只要在簽名產生 crt 的部份做就好,不過這邊還是都提出來,並且給驗證的方式。

如果本來就已經有寫好 script,那麼只要在產生 csr 與簽名產生 crt 的步驟都加上 -sha256 就可以解決了。

這是產生 csr 的:(${HOST} 以及 subj 的內容自己代換)

openssl req -new -key ${HOST}.key -subj "/C=TW/ST=Taiwan/L=Taipei/O=MyOrganization/OU=MyUnit/CN=${HOST}" -sha256 -out ${HOST}.csr

而 csr 檢查的方式是:

openssl req -in ${HOST}.csr -text

看 Signature Algorithm 是不是 sha256WithRSAEncryption。

簽名產生 crt 也要加上 -sha256

openssl x509 -req -days 365 -in ${HOST}.csr -CA ca/ca.crt -CAkey ca/ca.key -sha256 -out ${HOST}.crt

而 crt 檢查的方式是:

openssl x509 -in ${HOST}.crt -text

一樣是看 Signature Algorithm 這邊是不是 sha256WithRSAEncryption。