<?xml version='1.0' encoding='UTF-8'?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <managingEditor>quininer kel</managingEditor>
        <link>https://quininer.github.io</link>
        <title>icebox</title>
        <lastBuildDate>Mon, 20 Apr 2015 04:05:53 -0000</lastBuildDate>
        <description><![CDATA[不知所云]]></description>
        <pubDate>Mon, 20 Apr 2015 04:05:53 -0000</pubDate>
        <generator>rssgen 1.0</generator>
        <copyright>BY-NC-SA 4.0</copyright>
        <language>zh</language>
        <item><author>quininer kel</author><title>the-grail-of-forward-secrecy</title><link>https://quininer.github.io/?the-grail-of-forward-secrecy</link><description><![CDATA[<h1>0-RTT and Forward Secrecy</h1>
<h2><em>Tue Sep 11 00:43:19 2018</em></h2>
<p>前向保密是一個已經被人熟知的安全特性。
基於密鑰交換的前向安全廣泛存在於各種密碼協議之中，例如 TLS、Signal Protocol、WireGuard。</p>
<h2>Session based</h2>
<p>一般我們所說的前向保密方案是基於會話的，每次會話通過握手產生一個獨立的會話密鑰。
會話結束之後銷毀該會話密鑰便可保證前向保密。</p>
<p>但基於會話的前向保密並不適用於所有場景，
很多情況下我們沒有握手的條件、或者通信開銷非常之大。
例如 Email、<ruby>IoT<rt>Internet of Things</rt></ruby>。</p>
<p>“如何在這些情況下保證前向保密”成爲了一個聖盃級的公開問題，
數十年來衆多密碼學家爲此付出心力。</p>
<p>幸運的是，這並非是無可能的。</p>
<h2>Interval based</h2>
<p>基於時間段的前向保密方案聽起來不太優雅，但非常實用。</p>
<p>基本思路是將密鑰分成不同的時間段。
在某個時間段過去之後，銷毀該時間段對應的私鑰，從而達到前向保密。</p>
<h1>Weekend scheme</h1>
<p>我相信這個方案在歷史上被設計過不止一次，最後一次見到它是在 openpgp 討論中 <sup>1</sup>。
我不清楚它的名字，本文將之稱爲週末方案。</p>
<p>用戶每逢週末更換一次自己的密鑰，並將新的公鑰公佈在網絡上。
其他用戶加密時必須檢索對方的最新公鑰。</p>
<p>這個方案很簡單，但缺點也很明顯</p>
<ul>
<li>要求其他用戶加密時有檢索最新公鑰的能力</li>
<li>多設備不友好</li>
</ul>
<p>每次都要更新公鑰實在是太麻煩了，那可不可以再給力點？</p>
<h1>HIBE scheme</h1>
<p>有的！我們首先通俗的介紹一下 <ruby>HIBE<rt>Hierarchical Identity Based Encryption</rt></ruby><sup>2</sup>。</p>
<p>HIBE 有一個中心的 <ruby>PKG<rt>Private Key Generator</rt></ruby>，它可以通過 ID 產生所有用戶的私鑰。
每個用戶也能通過子用戶的 ID 產生子用戶的私鑰，自然的，子用戶不能恢復父用戶的私鑰。</p>
<p>其他用戶加密時只需要知道 <ruby>MPK<rt>Master Public Key</rt></ruby> 和子用戶的 ID。</p>
<p>我們可以基於 HIBE 構造出一個不需要更換公鑰的前向保密方案。</p>
<ol>
<li>
<p>用戶加密時根據當時的時間產生用戶 ID，並用此進行加密。例如</p>
<p><code>CT = enc(MPK, ["2018", "9", "10"], MSG)</code></p>
</li>
<li>
<p>用戶解密時，根據 PKG 或父用戶的私鑰產生對應 ID 的私鑰，並用其解密，例如</p>
<p><code>SUB_SK = keygen(SK, ["2018", "9", "10"])
MSG = dec(SUB_SK, CT)</code></p>
</li>
<li>
<p>當一個時間段過去時，用戶先用 PKG 或父用戶的私鑰產生剩餘所有子用戶的私鑰，並銷毀 PKG 和父用戶的私鑰。例如</p>
<p><code>(_, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC) = keygen_year(YEAR)
delete(YEAR)</code></p>
</li>
</ol>
<p>完美！這個方案完全解決了週末方案的兩個缺點，
其他用戶不需要時時檢索對方的最新公鑰，用戶自己也不需要在多個設備之間同步自己的新私鑰。</p>
<p>但是基於時間段的方案有一個共同的缺點，</p>
<p>試想一個情景，alice 在 2018年9月30號 執行加密，但由於各種原因到達 bob 手中時遲了一日。
可惜當時 bob 已經將 9月 所對應的私鑰銷毀了，所以他無法解密 alice 的密文。</p>
<p>這顯然不是我們想要的效果，那可不可以再給力點？</p>
<h2>Puncture based</h2>
<p>除了時間段這個思路之外，我們還有沒有其他實現前向保密的辦法呢？</p>
<p>可穿刺加密是另一種思路，
原始狀態下的私鑰包含所有信息，可以解密所有密文。
當用戶成功解密一個密文後，用戶可以從私鑰中消除（我們將之稱爲<ruby>穿刺<rt>Puncture</rt></ruby>）一部分信息，
使得新私鑰不能解密該密文。</p>
<h1>Binary Tree Encryption scheme</h1>
<p><ruby>BTE<rt>Binary Tree Encryption</rt></ruby><sup>3,4</sup> 是一個有趣的設計，它同樣基於 HIBE。</p>
<p>它相當於使用 IBE 產生一個巨大的私鑰集，
然後使用和密文對應的 tag 確定其中一個 ID 或密鑰（通過一個 Hash）。</p>
<p>穿刺時，通過 Hash 該 tag 來確定私鑰，然後銷毀它。</p>
<p>但是一個夠用的私鑰集相當大，假設一個私鑰大小爲 64b，我們期望有 2^32 個私鑰可以用，
那最終儲存這個密鑰集我們需要 274877.907 MB。</p>
<p>這是不現實的。</p>
<p>但我們可以通過 HIBE 來懶惰式的生成私鑰，這可以有效的將最壞情況下的密文尺寸降低一半。</p>
<h1>Bloom Filter Encryption scheme</h1>
<p><ruby>BFE<rt>Bloom Filter Encryption</rt></ruby><sup>5</sup> 是 BTE 的一個有趣變種。</p>
<p>它使用一個 Bloom Filter 來降低 tag 的碰撞率，代價是較快的空間使用速度。</p>
<ul>
<li>加密時，使用 <ruby>IBBE<rt>Identity Based Broadcast Encryption</rt></ruby> 將消息廣播加密
    給 bloom filter 選擇出的 k 個 ID。</li>
<li>解密時，使用 k 個 ID 中其中一個可用的 ID 進行解密，若均不可用則解密失敗。</li>
<li>穿刺時，將這 k 個 ID 對應的私鑰銷毀。</li>
</ul>
<p>無論如何，基於 IBE 的可穿刺加密仍有相當大的私鑰尺寸。那，可不可以再給力點？</p>
<h1>Non-Monotonic ABE scheme</h1>
<p>照例我們先簡單介紹一下 <ruby>NM-ABE<rt>Non-Monotonic Attribute based encryption</rt></ruby><sup>6</sup>。</p>
<p>ABE 就像 IBE，但它使用<ruby>屬性<rt>Attribute</rt></ruby> 而不是 ID 來進行加密。
<ruby>KP<rt>Key Policy</rt></ruby>-ABE 是指是加密時爲密文指定屬性，只有符合某個規則的私鑰可以解密。</p>
<p>而一般 ABE 的規則是單調的，即是說只有 And 和 Or 兩種規則。
非單調性 ABE 的有趣之處是支持 Not 規則。</p>
<p>有了 NM-ABE，構建可穿刺加密變得非常直觀。加密解密時和普通 ABE 一樣。
穿刺時，只需在私鑰規則中增加一條 <code>Not(tag)</code>。<sup>7</sup></p>
<p>至此，該方案的私鑰大小只會隨着穿刺次數線性增長，而不會爆炸。</p>
<h1>Binary Tree Bloom Filter Encryption?</h1>
<p>我們可以將 BTE 和 BFE 結合，
利用 <ruby>HIBBE<rt>Hierarchical Identity Based Broadcast Encryption</rt></ruby>
構造出 <ruby>BTBFE<rt>Binary Tree Bloom Filter Encryption</rt></ruby>。</p>
<p>理論上這可以將 BFE 的私鑰尺寸降得更低，但我沒有找到合適的 HIBBE 方案實現它。</p>
<h2>Perfect?</h2>
<p>我們介紹了數個在限制情況下保證前向保密的加密方案，看起來似乎足夠讓人們戴着鐐銬跳舞。</p>
<p>如果這些方案足夠高效，是不是意味著我們再不需要握手，無延遲的 0-RTT 通信可以全面推廣呢？</p>
<p>很遺憾並不是，這些方案只能保證“前向保密”。</p>
<p>而基於會話的方案除了前向保密之外還保證了“弱後向保密”，
即在泄漏長期私鑰時，若敵手在之後沒有參與協議，那協議仍能保證之後密文的保密性。</p>
<p>當然，這一切在量子敵手面前都毫無意義。</p>
<hr />
<ol>
<li><a href="https://mailarchive.ietf.org/arch/msg/openpgp/mk8_FSS-n4DVGfh_VwuGtEOS2xk">Clarify status of subkeys with certification use</a></li>
<li><a href="http://cryptowiki.net/index.php?title=Identity-based_encryption_schemes#Hierarchical_Identity_Based_Encryption">Hierarchical Identity Based Encryption</a></li>
<li><a href="https://www.cs.umd.edu/~jkatz/papers/BTE-survey.pdf">Binary Tree Encryption: Constructions and Applications</a></li>
<li><a href="https://eprint.iacr.org/2017/223">0-RTT Key Exchange with Full Forward Secrecy</a></li>
<li><a href="https://eprint.iacr.org/2018/199">Bloom Filter Encryption and Applications to Efficient Forward-Secret 0-RTT Key Exchange</a></li>
<li><a href="http://cryptowiki.net/index.php?title=Attribute-based_encryption#Encryption_with_non-monotone_access_structure">Encryption with non-monotone access structure</a></li>
<li><a href="http://cs.jhu.edu/~imiers/pdfs/forwardsec.pdf">Forward Secure Asynchronous Messaging from Puncturable Encryption</a></li>
</ol>]]></description><guid>https://quininer.github.io/?the-grail-of-forward-secrecy</guid><pubDate>Wed, 12 Sep 2018 09:23:29 -0000</pubDate></item><item><author>quininer kel</author><title>ene</title><link>https://quininer.github.io/?ene</link><description><![CDATA[<h1><strong>E</strong>ncrypt o<strong>n</strong> <strong>E</strong>mail</h1>
<h2>什麼是 ENE？</h2>
<p>ENE 是一個實驗性質的、設計用於郵件的、<ruby>端到端<rt>End to End</rt></ruby>加密工具。
它基本上是我設想中的 OpenPGP 2.0，針對 PGP 的弱點作出了一些改進。</p>
<p>郵件是一個單次、無狀態的通信方案，這意味著爲它設計加密方案無法達到很多常見的安全要求。
例如經常被提到的 <ruby>完美前向保密<rt>Perfect Forward Secrecy</rt></ruby>。
事實上放寬其中一個限制，我們就可以做到很多，
例如 OpenPGP 實際上有一個有狀態的前向保密方案<sup>1</sup>。</p>
<p>但在這些條件下，我們可以做的事情並不多。</p>
<p>在早期，我們滿足於簡單的 <ruby>KEM<rt>Key encapsulation mechanisms</rt></ruby> + Encrypt 加密方案，
這些方案缺失了身份認證、完整性驗證。</p>
<p>而在 2018 年，我們可以做得更好。</p>
<p>ENE 將會提供：</p>
<ul>
<li><ruby>認證密鑰交換<rt>Authenticated Key Exchange</rt></ruby></li>
<li><ruby>可否認的郵件認證<rt>Deniable authentication</rt></ruby></li>
<li>郵件<ruby>完整性<rt>Integrity</rt></ruby></li>
<li>具有 Nonce-misuse Resistant 的加密方案</li>
<li>實驗性的 Post-quantum 密碼套件</li>
</ul>
<h1>我們需要認證？</h1>
<p>試想一個場景，Alice 向 Bob 發送一個沒有認證的加密消息，Mallory 可以輕鬆的攔截並轉發這個消息給 Bob。
Bob 會認爲這個消息是由 Mallory 發送的。</p>
<p>這是由於缺乏身份認證導致的。</p>
<p>可能很多人會覺得加簡單的增加一個簽名會解決所有問題，但並不是。簡單的簽名方案有兩個缺點</p>
<ol>
<li>
<p>可否認性<sup>2</sup>的丟失</p>
<ul>
<li>當你使用私鑰簽名一段消息時，實際上你背負了一定的法律責任。你將無法否認那段消息出自於你的手筆。</li>
</ul>
</li>
<li>
<p>Surreptitious Forwarding Attack<sup>3,4</sup></p>
<ul>
<li>Mallory 可以將 Alice 的簽名剝離，使用自己的簽名代替。</li>
<li>可能有人認爲 Sign-then-Encrypt 將會解決這個問題，但若加密方案達不到 CCA<sup>5</sup>，那它仍無法防止此攻擊。</li>
</ul>
</li>
</ol>
<p>ENE 有四種認證方案，用戶可以靈活選擇自己想要的安全性。</p>
<ol>
<li>
<p>One-Pass Authenticated Key Exchange<sup>6,7</sup></p>
<ul>
<li>一次通信的認證密鑰交換有良好的性能，因爲它不涉及複雜的簽名算法。</li>
<li>由於只能通信一次，我們仍無法做到完美前向保密。但我們可以做到發送者前向保密，這至少和公鑰加密一樣好。</li>
<li>one-pass ake 只提供隱式認證，
    這意味著它無法抵抗 <ruby>KCI<rt>Key Compromise Impersonation</rt></ruby>攻擊<sup>8</sup>。</li>
<li>one-pass ake 是 ENE 中最弱的認證方案，但它仍能防禦大多數攻擊。
    你應該用它代替早期郵件加密中無認證的加密方案。</li>
</ul>
</li>
<li>
<p>Signature-based Authenticated Key Exchange<sup>9,10</sup></p>
<ul>
<li>在密鑰交換中加入簽名可以做到顯式認證。這個增強將可以抵抗 KCI 攻擊。</li>
<li>簽名內容不包括消息，這意味著該方案仍能保持消息的可否認性。</li>
</ul>
</li>
<li>
<p>Signature Key Exchange and Message</p>
<ul>
<li>在 方案2 的基礎上，簽名內容包括明文消息。這將保證消息的<ruby>不可否認性<rt>Non-Repudiation</rt></ruby>。</li>
</ul>
</li>
<li>
<p>Signature Only</p>
<ul>
<li>只簽名明文消息，不作任何加密。</li>
</ul>
</li>
</ol>
<h1>我們需要 AEAD？</h1>
<p>我相信我不需要在 8102 年贅述完整性驗證的重要性。</p>
<p><a href="https://efail.de/">EFAIL</a> 就是一個未能很好處理完整性驗證導致的漏洞。</p>
<p>實際上 OpenPGP 有自己的完整性驗證方案 MDC<sup>11</sup>，
但在大多數應用中只當作警告處理，並且存在降級攻擊<sup>12</sup>。
而在 ENE 中，我們可以使用更現代的 AEAD 方案，更好的保證完整性。</p>
<p>關於 AEAD<sup>13</sup> 的研究已經有很多年，更多的安全性質被提出，例如 Nonce-misuse Resistant<sup>14</sup>。</p>
<p>由於郵件無狀態的特點，我們只能隨機的產生 nonce。
對於某些加密算法而言，nonce reuse 的後果是毀滅性的，例如 AES-GCM<sup>15</sup>。
雖然我們可能沒有如此大量的郵件以導致生日攻擊，
但使用一個 Nonce-misuse Resistant AEAD 將可以免疫這個問題。</p>
<h1>我們需要 Post-quantum？</h1>
<p>衆所周知，量子機可以打破所有當前流行的公鑰算法。
屆時，所有使用 RSA/ECC 加密的郵件都將無法保證保密性。
因此，有必要在實用的量子機出現之前進行防禦。</p>
<p>一般有兩種方法來對抗量子機</p>
<ol>
<li>使用預共享密鑰。</li>
<li>使用 Post-quantum 密鑰交換<sup>16</sup>。</li>
</ol>
<p>考慮到郵件的使用場景，預共享密鑰在很多情況下不太現實。
因而使用 Post-quantum 算法是一个有意义的选择。</p>
<h2>ENE 是完美的嗎？</h2>
<p>不是！</p>
<p>ENE 未來仍有很多工作要做。例如</p>
<ul>
<li>子密鑰支持</li>
<li>完全的前向保密<sup>17,18</sup></li>
<li><ruby>郵件列表<rt>Mailing list</rt></ruby>加密支持</li>
<li><ruby>側信道攻擊<rt>Side-Channel attacks</rt></ruby>抗性</li>
<li>協議<ruby>形式化驗證<rt>Formal verification</rt></ruby></li>
</ul>
<p>ENE 是一個非常年輕的工具，一切在未來必將發生變化。</p>
<h2>爲什麼不用 ENE？</h2>
<p>ENE 不是萬能的。它被設計用於加密郵件，不是 PGP 的完全替代品。</p>
<ol>
<li>
<p>Web of Trust<sup>19</sup></p>
<ul>
<li>我不打算討論 Web of Trust 的好壞。</li>
<li>ENE 不是信任系統，不考慮如何建立信任關係。</li>
<li>若需要，你可以使用 PGP 簽署 ENE 公鑰。</li>
</ul>
</li>
<li>
<p>爲 git commit、壓縮包以及其他公鑰簽名</p>
<ul>
<li>ENE 可以做，但在這些方面不會比 PGP 有什麼優勢。</li>
<li>當然，你也可以使用 <a href="https://boats.gitlab.io/blog/post/signing-commits-without-gpg/">pbp</a>。</li>
</ul>
</li>
<li>
<p>加密巨大的文件</p>
<ul>
<li>通常郵件文本不會太大，所以 ENE 不考慮這一點。</li>
<li>當然，這不意味著 GPG 適合做文件加密。</li>
</ul>
</li>
<li>
<p>需要可靠的、穩定的加密方案</p>
<ul>
<li>ENE 非常不穩定！隨時可能發生變化。</li>
<li>“現代 PGP” 依然是最好的選擇之一，例如 <a href="https://sequoia-pgp.org/">Sequoia</a>。</li>
</ul>
</li>
</ol>
<hr />
<p>ENE 是開源的，代碼託管在 <a href="https://github.com/quininer/ene">Github</a>。</p>
<hr />
<ol>
<li><a href="https://tools.ietf.org/html/draft-brown-pgp-pfs-03">Forward Secrecy Extensions for OpenPGP</a></li>
<li><a href="https://en.wikipedia.org/wiki/Deniable_authentication">Deniable authentication</a></li>
<li><a href="https://crypto.stackexchange.com/questions/5458/should-we-sign-then-encrypt-or-encrypt-then-sign">Should we sign-then-encrypt, or encrypt-then-sign?</a></li>
<li><a href="http://world.std.com/~dtd/sign_encrypt/sign_encrypt7.html">Defective Sign &amp; Encrypt in S/MIME, PKCS#7, MOSS, PEM, PGP, and XML</a></li>
<li><a href="https://en.wikipedia.org/wiki/Chosen-ciphertext_attack">Chosen-ciphertext attack</a></li>
<li><a href="https://eprint.iacr.org/2010/638.pdf">One-Pass HMQV and Asymmetric Key-Wrapping</a></li>
<li><a href="https://dl.acm.org/citation.cfm?id=2508859.2516695">OAKE: a new family of implicitly authenticated diffie-hellman protocols</a></li>
<li><a href="https://www.cryptologie.net/article/372/key-compromise-impersonation-attacks-kci/">Key Compromise Impersonation attacks (KCI)</a></li>
<li><a href="http://webee.technion.ac.il/~hugo/sigma.html">The SIGMA Family of Key-Exchange Protocols</a></li>
<li><a href="https://tools.ietf.org/id/draft-selander-ace-cose-ecdhe-08.html#protocol">AEAD variant of the SIGMA-I protocol</a></li>
<li><a href="https://tools.ietf.org/html/rfc4880#page-52">Modification Detection Code Packet</a></li>
<li><a href="https://www.ietf.org/mail-archive/web/openpgp/current/msg08285.html&lt;Paste&gt;">OpenPGP SEIP downgrade attack</a></li>
<li><a href="https://en.wikipedia.org/wiki/Authenticated_encryption">Authenticated encryption</a></li>
<li><a href="https://www.lvh.io/posts/nonce-misuse-resistance-101.html">Nonce misuse resistance 101</a></li>
<li><a href="https://eprint.iacr.org/2016/475.pdf">Nonce-Disrespecting Adversaries: Practical Forgery Attacks on GCM in TLS</a></li>
<li><a href="https://en.wikipedia.org/wiki/Post-quantum_cryptography">Post-quantum cryptography</a></li>
<li><a href="http://cs.jhu.edu/~imiers/pdfs/forwardsec.pdf">Forward Secure Asynchronous Messaging from Puncturable Encryption</a></li>
<li><a href="https://eprint.iacr.org/2017/223.pdf">0-RTT Key Exchange with Full Forward Secrecy</a></li>
<li><a href="https://en.wikipedia.org/wiki/Web_of_trust">Web of trust</a></li>
</ol>]]></description><guid>https://quininer.github.io/?ene</guid><pubDate>Fri, 03 Aug 2018 15:09:57 -0000</pubDate></item><item><author>quininer kel</author><title>tamarin-and-badake</title><link>https://quininer.github.io/?tamarin-and-badake</link><description><![CDATA[<h1>如何設計一個壞協議</h1>
<h2><em>Wed Jun 13 19:44:31 2018</em></h2>
<p>近幾日看 <a href="https://cyber.biu.ac.il/event/8th-biu-winter-school/">The 8th BIU Winter School on Cryptography</a> 的 slide，
這期冬令營主要內容是協議設計。</p>
<p>冬令營第二講 <a href="http://cyber.biu.ac.il/wp-content/uploads/2017/08/KE2_Hugo_BIU_Feb2018.pdf">Implicitly Authenticated KE Protocols</a> 拋磚引玉，
提出了一個相當簡潔的兩消息<ruby>隱式帶認證密鑰交換<rt>Implicitly Authenticated Key Exchange</rt></ruby>協議，</p>
<p>後文將稱之爲 <ruby>BADAKE<rt>Basic A-round Diffie-hellman Authenticated Key Exchange</rt></ruby>。</p>
<p><img alt="BADAKE" src="./upload/badake.png" /></p>
<p>這是一個相當乾淨的協議，甚至可能大家自己就在實踐中設計過類似的協議。
但這不是一個安全的協議。</p>
<p>slide 中已經舉出了一些該協議的攻擊，這些攻擊並不那麼直觀。</p>
<h2>Define</h2>
<p>在描述這些攻擊之前，我們先澄清一些定義。</p>
<ul>
<li>隱式帶認證密鑰交換:
    與顯式認證密鑰交換不同，隱式認證協議不會在協議執行中顯式的失敗，
    但只有雙方身份正確時會生成相同的密鑰。</li>
<li>認證協議安全要求: 一個合格的認證協議應該在協議完成之後保證<ul>
<li><ruby>基本僞裝抗性<rt>Basic Impersonation Resistance</rt></ruby>: 若 A 正確執行協議，當敵手不知道 A 的長期密鑰時，敵手不可以僞裝成 A。</li>
</ul>
</li>
<li>密鑰交換協議安全要求: 一個合格的密鑰交換協議應該保證，<ul>
<li><ruby>完美前向保密<rt>Perfect Forward Secrecy</rt></ruby>: 長期密鑰泄漏時，不會影響之前會話密鑰的安全性。</li>
<li><ruby>弱前向保密<rt>weak Perfect Forward Secrecy</rt></ruby>: 由於兩消息的認證密鑰交換協議無可能滿足 PFS，所以對於這些協議，退而求其次，我們只要求 wPFS。
    若敵手在長期密鑰泄漏之前沒有參與協議，那長期密鑰泄漏時，不會影響之前會話密鑰的安全性。</li>
<li><ruby>已知密鑰安全<rt>Known-Key Security</rt></ruby>: 會話密鑰泄漏時，不會影響長期密鑰及其他會話密鑰的安全性。</li>
<li><ruby>臨時祕密揭露抗性<rt>Ephemeral Secrets Reveal Resistance</rt></ruby>: 臨時密鑰泄漏時，不會影響長期密鑰及其他會話密鑰的安全性。</li>
<li><ruby>未知密鑰共享<rt>Unknown Key-Share</rt></ruby>抗性: 當 A 和 C 協商出會話密鑰時，A 不會認爲該密鑰是與 B 協商得到的。</li>
</ul>
</li>
</ul>
<h2>Signature + DH</h2>
<p>在分析 BADAKE 前，slide 先給出了一個簡單的簽名與密鑰交換的組合協議。
這個協議在簽名中加入了目標身份，以避免交錯攻擊。</p>
<p>但這個協議仍然是不安全的。</p>
<p>當 A 的臨時密鑰 <code>x</code> 泄漏時，
攻擊者可以重放消息 <code>g^x, SIG{A}(g^x, B)</code>，與 B 進行握手。
從而達成僞裝 A 身份的目的。</p>
<p>一般情況下防止重放攻擊的最好方案是添加一個 challenge，
但這需要增加一輪通信。</p>
<p>這個例子說明了使用 Signature + DH 的簡單組合無法實現安全的兩消息帶認證密鑰交換。</p>
<h2>Implicitly Authenticated DH</h2>
<p>slide 給出了 BADAKE 的兩種簡單組合方式。</p>
<p>第一種組合方式相當簡單，
<code>K = H(g^ab, g^xy)</code></p>
<p>slide 中描述它受到 <code>Open to known key and interleaving attacks</code> 的威脅。
一開始我不太明白這個攻擊如何實現。</p>
<p><a href="https://gist.github.com/quininer/5e29437c3c6e1d66942c8fddb39a8536">藉助 tamarin</a>，
我們可以輕鬆找到針對這個協議的多個攻擊方案，這裏我們舉出兩個</p>
<ul>
<li>反射攻擊</li>
</ul>
<p><img alt="reflection attack" src="./upload/reflection_attack.png" /></p>
<p>A 向 B 發起兩個握手請求，敵手將這兩個請求作爲響應發回給 A。</p>
<p>A 不會知道他正在和自己通信。（呆萌</p>
<ul>
<li>會話密鑰揭露時的交錯攻擊</li>
</ul>
<p><img alt="interleaving attack" src="./upload/open_key_interleaving_attack.png" /></p>
<p>這圖片中描述的攻擊與 slide 可能有所不同。</p>
<p>此攻擊需要 B 在握手結束之後泄漏會話密鑰。</p>
<p>B 向 A 發起兩個握手請求，敵手將一個請求作爲響應發回給 B。
兩個會話產生相同的密鑰，結束其中一個會話，B 泄漏會話密鑰 <code>K</code>。
敵手使用該密鑰繼續與 B 通信。</p>
<p>最終達成僞造 A 身份的目的。</p>
<h2>KCI Attack</h2>
<p>第二種組合方式添加了角色因素，
可以對抗反射、並行會話等攻擊方式。
<code>K = H(g^ab, g^xy, g^x, g^y)</code></p>
<p>這相比第一種組合方式要好一點，但仍不是一個理想的 AKE 方案。</p>
<p>slide 中提到了<ruby>密鑰泄漏僞裝攻擊<rt>Key-Compromise Impersonation</rt></ruby>。
簡單來講就是，在 A 的長期密鑰泄漏之後，敵手不但可以僞裝成 A 與 B 通信，也可以僞裝成 B 與 A 通信。</p>
<p>這個漏洞在使用密鑰交換作認證的協議裏很常見，例如 <a href="https://github.com/TokTok/c-toxcore/issues/426">Tox</a> 就有這個問題。</p>
<p>很多人會覺得泄漏長期密鑰之後，協議可以不保證認證安全性。但一個好的認證協議應該要避免這一點。</p>
<hr />
<p>上文的內容在冬令營的演講中只佔不到半分鐘時間，而後面關於 MQV、HMQV 的各種變種佔了將近兩個小時。</p>
<p>設計一個好的密碼協議並不是一件容易的事情。</p>
<p>而想要設計一個壞協議？只需要拍腦袋式的想一個簡潔的協議就可以了。</p>]]></description><guid>https://quininer.github.io/?tamarin-and-badake</guid><pubDate>Fri, 15 Jun 2018 04:15:41 -0000</pubDate></item><item><author>quininer kel</author><title>wasm-stack-overflow</title><link>https://quininer.github.io/?wasm-stack-overflow</link><description><![CDATA[<h1>WebAssembly StackOverflow</h1>
<h2><em>Mon Apr 30 16:50:47 2018</em></h2>
<p><a href="http://webassembly.org/">WebAssembly</a> 是一個設計運行在瀏覽器上的類彙編語言，
藉助它可以令 C / C++ 之類的語言運行在瀏覽器上，以期得到性能提升。</p>
<p>新功能自然會引入新攻擊面，可以預見 C / C++ 上經常出現的緩衝區溢出並不會在 WebAssembly 上消失。</p>
<h2>有什麼不同</h2>
<p>WebAssembly 同常見的彙編有很多不同的地方，例如</p>
<ul>
<li>它是一個 <a href="https://docs.google.com/document/d/1CieRxPy3Fp62LQdtWfhymikb_veZI7S9MnuCZw7biII/edit">Stack Machine</a></li>
<li>它使用 <a href="http://webassembly.org/docs/semantics/#linear-memory">Linear Memory</a></li>
<li>指令與數據隔離</li>
<li>…</li>
</ul>
<p>因爲第三點，WebAssembly 在一定程度上是 <a href="https://en.wikipedia.org/wiki/Harvard_architecture">Harvard architecture</a>，這爲 WebAssembly 帶來了很大的安全優勢，但棧溢出仍是可能的。</p>
<h2>一個例子</h2>
<p>我們舉個虛構的例子來證明 WebAssembly 棧溢出的可行性。</p>
<p>Rust 代碼:</p>
<p>```rust
// ...</p>
<h1>[wasm_bindgen]</h1>
<p>pub fn hash_with_key(key: &amp;str, data: &amp;str) -&gt; u32 {
    let mut val = [0; 32];
    let key = key.as_bytes();
    let data = data.as_bytes();</p>
<pre><code>val[..3].copy_from_slice(&amp;key[..3]);
val[3] = 0x33;
val[4..][..data.len()].copy_from_slice(&amp;data);

js_hash(&amp;val)
</code></pre>
<p>}</p>
<h1>[wasm_bindgen]</h1>
<p>pub fn table_index(i: usize) -&gt; u8 {
    let a = [b'a', b'd', b'c', b'b'];
    unsafe { *a.get_unchecked(i) }
}
```</p>
<p>WebAssembly 的 wat 格式基於 <a href="https://en.wikipedia.org/wiki/S-expression">S-expression</a>，指令精簡，與傳統彙編相比，相對容易閱讀。</p>
<p>但鑑於編譯出的 wasm 較長，下面我們只看我們關心的內容，
完整的內容可以看<a href="https://gist.github.com/quininer/53820dbf2bcadfca807aee1e9adb4865#file-wasm_stack_overflow_zero_bg-wat">這裏</a>。</p>
<p><code>(global (;0;) (mut i32) (i32.const 1050544))</code></p>
<p>指令 <code>global</code> 定義了一塊可變的全局內存。
其中 <code>1</code>MB 是棧空間，剩下的是數據段。</p>
<p>```
  (func $hash_with_key (type 2) (param i32 i32) (result i32)
    (local i32 i32 i32)
    get_global 0
    i32.const 32
    i32.sub</p>
<pre><code>;; ...

    get_local 2
    get_local 0
    i32.load16_u align=1
    i32.store16
    get_local 2
    get_local 0
    i32.const 2
    i32.add
    i32.load8_u
    i32.store8 offset=2

;; ...
</code></pre>
<p>)
```</p>
<p>函數 <code>hash_with_key</code> 在棧上開闢 <code>32</code>bytes，將 key 寫入棧上，而退棧時未將其清零。</p>
<p>```
  (func $table_index (type 4) (param i32) (result i32)
    (local i32)
    get_global 0
    i32.const 16
    i32.sub</p>
<pre><code>;; ...

i32.const 12
i32.add
get_local 0
i32.add
i32.load8_u)
</code></pre>
<p>```</p>
<p>函數 <code>table_index</code> 在棧上開闢 <code>16</code>bytes，偏移 <code>12</code>bytes 讀取一個 byte。</p>
<p>簡單分析可以知道，在用戶正常調用 <code>hash_with_key(..)</code> 之後，
攻擊者只需要調用 <code>table_index(16 - 12 - 32 + x)</code> 便可獲得寫入棧上的 key。</p>
<p><img alt="Read Stack Overflow" src="/upload/wasm-read-stack.png" /></p>
<h2>侷限</h2>
<p>雖然棧溢出是可行的，
但指令與數據的分離，使得我們只能讀寫棧內容而不能改變控制流。
這意味著 ROP、return2libc 之類的技巧不再有效，
棧溢出將只能在邏輯方面造成一些影響，危險度下降不止一個等級。</p>
<h2>柳暗花明</h2>
<p>而 WebAssembly 想要支持 函數指針、虛函數、trait 對象，就必須引入一些動態方案。</p>
<p>WebAssembly 的方案是將所有需要動態使用的函數放入 <a href="https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format#WebAssembly_tables">Table</a>，
在運行時通過引索指定，並且在調用時會檢查函數簽名。</p>
<p>這個設計試圖在最大程度上降低風險，但無可避免的爲攻擊者開了一扇窗。</p>
<h2>XSS Game</h2>
<p>基於 WebAssembly 棧溢出，我做了一個簡單的 <a href="https://quininer.github.io/wasm-xss-game/">XSS Challenge</a>，
源代碼託管在 <a href="https://github.com/quininer/wasm-xss-game">wasm-xss-game</a>。
有興趣的讀者可以一試。</p>
<hr />
<ul>
<li>本文有意忽略堆溢出，以避免引入衆多 Allocator 的複雜性。</li>
<li>作者不熟悉二進制安全、計算機原理。胡言亂語不知所云，有錯勿怪。</li>
</ul>]]></description><guid>https://quininer.github.io/?wasm-stack-overflow</guid><pubDate>Thu, 10 May 2018 18:31:44 -0000</pubDate></item><item><author>quininer kel</author><title>Stratis</title><link>https://quininer.github.io/?Stratis</link><description><![CDATA[<h1>Stratis</h1>
<h2><em>Sun Apr 15 18:14:39 2018</em></h2>
<p><a href="https://stratis-storage.github.io/">Stratis</a> 是 redhat 放棄 Btrfs 之後推出的代替品，
使用類似 LVM 的方案來提供有如 btrfs、zfs 般強大的功能。</p>
<p>其實 <a href="https://stratis-storage.github.io/">Stratis</a> 釋出 0.5 有一段時間了，今次抽出時間來嚐下鮮。
<a href="https://stratis-storage.github.io/">Stratis</a> 目前沒有面向用戶的文檔，故久違的寫一篇博文用以記錄。</p>
<h2>準備工作</h2>
<p>從 AUR 安裝 <a href="https://aur.archlinux.org/packages/stratisd/">stratisd</a>
同 <a href="https://aur.archlinux.org/packages/stratis-cli/">stratis-cli</a>，
然後啟動 stratisd</p>
<p><code>$ systemctl start stratisd</code></p>
<h2>開始</h2>
<p>首先我們清理要用的塊設備</p>
<p><code>$ sudo wipefs -a /dev/sda</code></p>
<p>但當前版本創建 pool 的時候會碰到錯誤，stratisd 認爲這個塊設備已經被使用</p>
<p><code>$ stratis pool create stratis /dev/sda
Execution failed: 1: Device /dev/sda appears to belong to another application</code></p>
<p>根據 <a href="https://github.com/stratis-storage/stratisd/issues/822#issuecomment-371585235">issue</a>，
如果塊設備的前 <code>4</code>/<code>8</code>k 字節未置零，stratisd 不會使用它。</p>
<p>知道原因就簡單了，我們將它置零</p>
<p><code>$ dd if=/dev/zero of=/dev/sda bs=1024 count=8</code></p>
<p>然後就可以正常創建 pool</p>
<p><code>$ stratis pool create stratis /dev/sda
$ stratis pool list
Name       Total Physical Size  Total Physical Used
stratis           &gt; 238.47 GiB               52 MiB</code></p>
<p>隨後創建 fs</p>
<p><code>$ stratis fs create stratis storage
$ stratis fs list stratis
Name
storage
$ la /dev/stratis/stratis/storage
Permissions Size User Date Modified Name
lrwxrwxrwx     9 root 15 4月  18:21 /dev/stratis/stratis/storage -&gt; /dev/dm-6</code></p>
<h2>完成</h2>
<p>創建完成，直接掛載就可以使用啦</p>
<p><code>$ sudo mount /dev/stratis/stratis/storage /run/media/quininer/storage
$ sudo chown quininer /run/media/quininer/storage</code></p>
<p>用得開心。 ;-)</p>]]></description><guid>https://quininer.github.io/?Stratis</guid><pubDate>Sun, 15 Apr 2018 16:27:40 -0000</pubDate></item><item><author>quininer kel</author><pubDate>Tue, 06 Oct 2015 06:49:18 -0000</pubDate><guid>https://quininer.github.io/?%E5%9F%BA%E4%BA%8EserviceWorker%E7%9A%84%E7%BC%93%E5%AD%98%E6%8A%95%E6%AF%92</guid><link>https://quininer.github.io/?%E5%9F%BA%E4%BA%8EserviceWorker%E7%9A%84%E7%BC%93%E5%AD%98%E6%8A%95%E6%AF%92</link><title>基于serviceWorker的缓存投毒</title><description><![CDATA[<h1>基于serviceWorker的缓存投毒</h1>
<h2><em>Sat May  2 20:52:57 2015</em></h2>
<p>前几天才察觉到 Chromium 42 已经支持 Fetch API 了，
鉴于我早就想用 Fetch 代替 Ajax，
所以今天把 ice.js 的<code>$.http</code>部分改用 Fetch <a href="https://github.com/quininer/quininer.github.io/commit/df932e8111e716a0813f6c3fa856d196626352a6">实现</a>了。</p>
<p>没想到的是 Firefox 目前还是 37 版本，不支持 Fetch。所以不得不引入一个 fetch.js 做兼容。</p>
<hr />
<h2>以上都不是重点</h2>
<p>和 Fetch 搭配使用的还有一个有趣的东西，<code>serviceWorker</code>。
其实早就在某牛的<a href="http://www.web-tinker.com/article/20879.html">博客</a>中看到过，
当时没有太深想，也因为没有实际上支持 Fetch 的浏览器，所以并没在意。</p>
<p>因为上文的事件，想起了这东西。
简单来说，这个API能拦截 HTTP Request，并返回预定的 Response。</p>
<p>自然，Response 里也包括 HTTP Headers，
所以只要简单的在 HTTP Header 里控制一下缓存时间即可，比如</p>
<pre><code>Cache-control: max-age=99999999999999999999999999999999999999
</code></pre>
<p>下面是一些截图</p>
<p><img alt="1" src="/upload/cache-tests-1.png" />
<img alt="2" src="/upload/cache-tests-2.png" />
<img alt="3" src="/upload/cache-tests-3.png" /></p>
<p>POC: <a href="https://quininer.github.io/tests/cache-tests/serviceworker/index.html">cache tests</a></p>
<p>实际上也并非所有 HTTP Header 都能使用，这里有一个<a href="https://fetch.spec.whatwg.org/#concept-header-list">禁表</a>。</p>
<hr />
<p>~~总之这套东西不管从哪方面来说都好方便。 :)~~</p>
<h2>实际上</h2>
<p>收回上一句话。
和<a href="https://twitter.com/filedescriptor">FD</a>测试了一会，
上面的POC看上去很美，实际上<code>serviceWorker</code>限制多多。</p>
<p>比如</p>
<ul>
<li>只能拦截<strong>同源</strong>且子路径的 Requests</li>
<li>scriptURL 必须<strong>同源</strong>，且 <a href="https://github.com/slightlyoff/ServiceWorker/issues/262">原则</a> 上必须是<strong>实际</strong>存在网络的资源</li>
<li><code>worker.js</code> 的处理和一般 script 处理不一样，必须<strong>符合</strong>规范，否则将会静默的失败</li>
<li><code>serviceWorker</code>只能工作在 <ruby>开发环境<rt>localhost</rt></ruby> 和 <a href="https://github.com/slightlyoff/ServiceWorker/issues/385">HTTPS</a> 下</li>
</ul>
<p>且不说要求 HTTPS 这样涉及协议的奇葩规定，
要求 scriptURL 必须实际存在这一点就让利用变得几无可能。</p>
<p>实际上使用也会变得极不方便，难以和各种完全由 JavaScript 生成的框架整合。
也没有实际上解决安全问题。</p>
<p>我倒是更希望 scriptURL 能允许使用 Blob，而<code>Cache</code>被加入 HTTP Header 禁表。</p>]]></description></item><item><pubDate>Tue, 21 Apr 2015 09:28:47 -0000</pubDate><link>https://quininer.github.io/?Surface</link><title>Surface</title><description><![CDATA[<h1>Surface Pro 3</h1>
<h2><em>Mon Mar 30 17:19:12 2015</em></h2>
<p><img alt="Surface Pro 3" src="/upload/surface.jpg" /></p>
<p>事情是這樣的，我買了一臺 Surface Pro 3，並給它裝了 Arch Linux。</p>
<h2>關於Windows</h2>
<p>用了兩天 Windows 8，其實感覺還不錯，按照之前的<a href="https://twitter.com/quininers/status/555389735594496003">想法</a>，
試圖裝上 <a href="http://gooseberrycreative.com/cmder/">Cmder</a> 和 <a href="https://msys2.github.io/">msys2</a> 來讓 Windows 上的終端也達到可用狀態。</p>
<p><a href="https://twitter.com/quininers/status/581435255137030144">效果</a>不盡人意，</p>
<ul>
<li>cmder 不知是字體或是什麼問題，Vim 下字符會混亂，有點像不等寬字體，而且還有鍵捕獲不到以及亂碼的奇怪問題</li>
<li>msys2 的包太少，完全不夠用</li>
<li>mingw 不會用= =</li>
<li>一開始 msys2 用 pacman 裝的 Mingw Python 找不到，需要手動把<code>/mingw64/bin</code>加入 PATH</li>
<li>試圖安裝上 yaourt，但是依賴的依賴 yajl 編譯報錯，似乎還要做許多設置</li>
</ul>
<p>雖然 Windows 的觸屏體驗確實很棒，但是我早有裝 Arch Linux 的想法。所以上面的問題只是藉口。</p>
<h2>關於Arch Linux</h2>
<p>自從 Debian 換成 Arch Linux 之後便很喜歡。</p>
<h3>Secure Boot</h3>
<p>開機時<code>音量鍵上 + 開機鍵</code>進 UEFI 關掉就好了，
雖然不關也能通過<a href="https://wiki.archlinux.org/index.php/Unified_Extensible_Firmware_Interface#Secure_Boot">這個方法</a>來啓動，
但是實際上安裝完成之後依然會提示錯誤。</p>
<h3>Install</h3>
<p>雖然 <a href="http://www.reddit.com/r/SurfaceLinux/">reddit</a> 上都說 WiFi 驅動在 3.19 內核才被合併，
但是被 #archlinux-cn 頻道的 Feb-Chip 告知親測 Arch Linux 目前 3.18 內核的鏡像也能直接使用。
livecd 裏的 tty 下不能使用 Type Cover 鍵盤(猜測 3.19 內核之後就可以了)，所以使用 SD卡 引導。
和 U盤 一樣，<code>音量鍵下 + 開機鍵</code>即可。</p>
<p>安裝過程完全參考<a href="https://wiki.archlinux.org/index.php/Beginners%27_guide">新手指南</a>，沒有碰上特殊問題。</p>
<h3>KDE</h3>
<p>HiDPI 依然按照 <a href="https://wiki.archlinux.org/index.php/HiDPI">wiki</a> 配置。</p>
<p>Firefox 效果不錯，
而<a href="https://twitter.com/quininers/status/582090512603033600">Chromium 效果糟糕</a>，<code>--force-device-scale-factor=2</code> 就像被直接放大，沒有任何優化。
比較好的方案是手動把網頁調到 175% 的大小。</p>
<p><a href="https://github.com/nuclearsandwich/surface3-archlinux/issues/8">電磁筆</a>和觸屏幾乎完美。可惜沒有什麼對觸屏有優化的應用。
這一點 Chromium 做的比 Firefox 好。
配置一下可以讓電磁筆的<a href="https://github.com/nuclearsandwich/surface3-archlinux/issues/4#issuecomment-68158518">按鈕</a>起些作用。</p>
<p>當然 Type Cover 也要<a href="https://github.com/nuclearsandwich/surface3-archlinux/issues/4#issuecomment-62277004">配置</a>。~~不過我碰到了一些問題，
一旦碰到 Type Cover 的觸摸板，X 便段錯誤崩潰了。
我沒有找到類似的案例，推測是個例。~~</p>
<p>此問題已解決，更新 linux-surfacepro3 內核時重新配置了一下 <code>/etc/X11/xorg.conf.d/50-synaptics.conf</code>，觸摸板使用正常~</p>
<h3>Kernel</h3>
<p>編譯 aur 裏的 <a href="https://aur.archlinux.org/packages/linux-surfacepro3/">linux-surfacepro3</a> 內核，
最主要的是打上了電源補丁，終於可以看到電量了。</p>
<p>装内核時碰上一個坑，/tmp 掛載的大小只有 2G，因爲之前從 aur 打包了幾個軟件而內核又很大，
所以打包 linux-surfacepro3 時塞滿了 /tmp，導致打包失敗。
編譯了兩次之後才發覺..
默默修改 /etc/yaourtrc 中的<code>TMPDIR</code>，</p>
<pre><code>TMPDIR="$HOME/Aurs"
</code></pre>
<h3>Battery</h3>
<p>在 Windows 下粗略計過一下續航，<ruby>平常使用<rt>瀏覽網頁</rt></ruby>確實能有 8h 之長。
換到 Linux 之後，用秒錶計算，提示 10% 的電量時，续航 4:29:59 。其中包括 40m- 的 FEZ 遊戲時間。</p>
<p>估計用 <a href="https://wiki.archlinux.org/index.php/Laptop_Mode_Tools">laptop-mode</a> 之類的動態調頻能延長一些續航。</p>
<p>最後，編譯 YCM 只用了 2分8秒，而上一個筆記本需要 5分鐘 左右。</p>
<hr />
<p>寫完博客第二天 linux-surfacepro3 就<a href="https://github.com/matthewwardrop/linux-surfacepro3">更新</a>了，不得不再編譯一次內核。
過程順利。</p>
<p>順便找到一個<a href="https://github.com/AykoPoel/surface3-scripts">自动旋转脚本</a>，雖然不夠流暢，但也可用。</p>
<p>剩下唯一的問題就是 KDE 缺少一個好用的屏幕鍵盤了吧。</p>
<hr />
<p>在 Laptop-mode 下測試，正常使用至 10% 電量，續航 6:21:40。</p>
<h2>參考</h2>
<ul>
<li><a href="https://wiki.archlinux.org/index.php/Unified_Extensible_Firmware_Interface#Secure_Boot">Unified Extensible Firmware Interface - Secure Boot</a></li>
<li><a href="https://wiki.archlinux.org/index.php/Beginners%27_guide">Beginners' guide</a></li>
<li><a href="https://wiki.archlinux.org/index.php/HiDPI">HiDPI</a></li>
<li><a href="https://github.com/nuclearsandwich/surface3-archlinux/issues/8">N-Trig Touch Pen - Works great but I have no idea how to configure it!</a></li>
<li><a href="https://github.com/nuclearsandwich/surface3-archlinux/issues/4">Type Cover 3 not working even after kernel patch</a></li>
<li><a href="https://aur.archlinux.org/packages/linux-surfacepro3/">aur - linux-surfacepro3</a></li>
<li><a href="https://wiki.archlinux.org/index.php/Laptop_Mode_Tools">Laptop_Mode_Tools</a></li>
<li><a href="https://github.com/matthewwardrop/linux-surfacepro3">github - linux-surfacepro3</a></li>
<li><a href="https://github.com/AykoPoel/surface3-scripts">Surface3-Scripts - autorotate.py</a></li>
</ul>]]></description><guid>https://quininer.github.io/?Surface</guid><author>quininer kel</author></item><item><pubDate>Tue, 21 Apr 2015 09:28:37 -0000</pubDate><description><![CDATA[<h1>Google-Cloud-Security-Scanner</h1>
<h2><em>Thu Mar  5 14:12:39 2015</em></h2>
<p>一回来上推就看到个有趣的东西——<a href="https://twitter.com/paradoxengine/status/568436963960877056">Google Cloud Security Scanner</a>，
虽然目前只是Beta，主要只有XSS检测和分析功能，不过怎么说也是<strong>Google</strong>出品。</p>
<p><a href="https://cloud.google.com/tools/security-scanner/"><img alt="" src="/upload/gcsscan.png" /></a></p>
<p>亲测一番效果一般，可以选择前端测试环境。
有一点比较麻烦，目前只允许扫描自己有权限的Gae应用。
不过只要用Gae做个Proxy应用就能随意扫了。</p>
<p>没有太大亮点。不过比上不足比下有余，比起市面上大部份云扫描器算是好得多了。</p>
<hr />
<p>其实用<code>asyncio</code>写了半个Proxy应用来着，才反应过来Gae没有<code>Python 3.4</code>。
在Github里找了个<a href="https://github.com/kitek/GAE-http-proxy">成品</a>，效果不错。</p>]]></description><link>https://quininer.github.io/?Google-Cloud-Security-Scanner</link><title>Google-Cloud-Security-Scanner</title><guid>https://quininer.github.io/?Google-Cloud-Security-Scanner</guid><author>quininer kel</author></item><item><description><![CDATA[<h1>关于expressjs的一个小坑</h1>
<h2><em>Tue Dec  9 01:07:53 2014</em></h2>
<p>都知道在PHP里，<code>/?key[arr]=value</code> 会被解析为</p>
<pre><code>array(1) { ["key"]=&gt; array(1) { ["arr"]=&gt; string(5) "value" } }
</code></pre>
<p>却一直没注意到expressjs里也会如此，</p>
<pre><code>// GET /shoes?order=desc&amp;shoe[color]=blue&amp;shoe[type]=converse
req.query.order
// =&gt; "desc"

req.query.shoe.color
// =&gt; "blue"

req.query.shoe.type
// =&gt; "converse"
</code></pre>
<p>而在<a href="http://expressjs.com/4x/api.html#req.query">req.query</a>里仅仅是这样不太显眼的一笔带过，似乎嵌套解析已成标配。
但是不得不说的是嵌套解析至少在Node.js里很危险。</p>
<p>例如</p>
<pre><code>app.get('/', function(req, res){
    sql.find({_id:req.query.id})
    .exec(function(err, data){
        res.json({data:data});
    });
});
</code></pre>
<p>访问<code>/?id[$ne]=1</code>则会返回不该有的数据，正如<a href="http://drops.wooyun.org/tips/3939">这里</a>。</p>
<p>当然这不是mongodb的问题，参数的属性也可能被劫持</p>
<pre><code>app.get('/', function(req, res){
    if(req.query.name.length &lt;= 5){
        // TODO
        res.json({'err':null, 'name':req.query.name});
    }else{
        res.json({'err':'名字过长！'});
    };
});
</code></pre>
<p>使用<code>/?name[length]=1</code>即能绕过这个名字长度的限制。</p>
<p>同样的利用方法在更奇怪的环境可能会造成更严重的后果，最终导致<strong>code injection</strong>也并非不可能。<br />
大概是意识到了这点，开发团队在下一个Web框架<a href="http://koajs.com/#request-query">koa</a>里取消了对嵌套解析的支持。<br />
后续分离的<a href="https://github.com/expressjs/cookie-parser">cookie-parser</a>也不支持嵌套解析。</p>
<p>最后，我的粗略的解决方案是</p>
<pre><code>app.get('/', function(req, res){
    var name = (typeof req.query.name == 'string')?req.query.name:undefined;
    // TODO
});
</code></pre>
<p>或是使用中间件</p>
<pre><code>app.use(function(req, res, next){
    for(var i in req.query)if(typeof req.query[i] != 'string')delete req.query[i];
    for(var i in req.body)if(typeof req.body[i] != 'string')req.body[i] = JSON.stringify(req.body[i]);
    next();
});
</code></pre>
<hr />
<p><strong>总之，务必先验证<code>req.query.name</code>，<code>req.body.name</code>以及<code>req.param('name')</code>的类型</strong></p>]]></description><author>quininer kel</author><pubDate>Tue, 21 Apr 2015 09:28:15 -0000</pubDate><link>https://quininer.github.io/?%E5%85%B3%E4%BA%8Eexpressjs%E7%9A%84%E4%B8%80%E4%B8%AA%E5%B0%8F%E5%9D%91</link><title>关于expressjs的一个小坑</title><guid>https://quininer.github.io/?%E5%85%B3%E4%BA%8Eexpressjs%E7%9A%84%E4%B8%80%E4%B8%AA%E5%B0%8F%E5%9D%91</guid></item><item><author>quininer kel</author><pubDate>Tue, 21 Apr 2015 09:27:02 -0000</pubDate><title>ArriettySong</title><link>https://quininer.github.io/?ArriettySong</link><guid>https://quininer.github.io/?ArriettySong</guid><description><![CDATA[<h1>Arrietty'sSong</h1>
<h2><em>Sun Sep 21 17:20:47 2014</em></h2>
<p><img alt="“Karigurashi”作者Studio Ghibli - 官方网站。来自Wikipedia - http://zh.wikipedia.org/wiki/File:Karigurashi.jpg#mediaviewer/File:Karigurashi.jpg" src="https://upload.wikimedia.org/wikipedia/zh/3/38/Karigurashi.jpg" />
<audio src="https://www.dropbox.com/s/qqxsp3nvw3gvaea/Arrietty%27s%20Song.mp3?dl=1" autoplay type="audio/mpeg"></p>]]></description></item></channel>
</rss>
