我本來以為這張是搞笑:
出自 2010 年的「SQL Injection License Plate Hopes to Foil Euro Traffic Cameras」
不過我開始覺得在台灣是真的有機會...
幹壞事是進步最大的原動力
我本來以為這張是搞笑:
出自 2010 年的「SQL Injection License Plate Hopes to Foil Euro Traffic Cameras」
不過我開始覺得在台灣是真的有機會...
Bruce Schneier 的說明:「I've Joined Co3 Systems」,以及 Co3 Systems 的公告:「Bruce Schneier Joins Co3 Systems as CTO」。
所以跑去 Co3 Systems 當 CTO 了... 把放假的時間算進去,速度真迅速 :p
有時候我們會因為效能問題,在 HTML 內嵌入 JSON object,而不是再多一個 HTTP request 取得。
但「嵌入」的行為如果沒有處理好,就產生非常多 XSS attack vector 可以玩。
首先最常犯的錯誤是使用錯誤的 escape function:
<!DOCTYPE HTML> <html> <body> <script> var a = "<?= addslashes($str) ?>"; </script> </body> </html>
這樣可以用 </script><script>alert(1);//
攻擊 $str
。因為 addslashes()
並不會過濾到這個字串,而產生這樣的 HTML:
<!DOCTYPE HTML> <html> <body> <script> var a = "</script><script>alert(1);//"; </script> </body> </html>
而這個字串會造成 DOM parser 解讀上產生不是我們預期的行為:
可以看到在字串裡面的 </script>
被拆開了。
這是因為瀏覽器會先拆解產生 DOM tree,再把 <script></script>
內的程式碼交給 JavaScript engine 處理。所以在一開始產生 DOM tree 的時候,是看不懂 JavaScript 程式邏輯的...
正確的方法是用 json_encode()
處理,因為 PHP 的 json_encode()
預設會把 /
(slash) 變成 \/
(這是 JSON spec 裡合法的轉換):
<!DOCTYPE HTML> <html> <body> <script> var a = <?= json_encode($str) ?>; </script> </body> </html>
這會產生出:
<!DOCTYPE HTML> <html> <body> <script> var a = "<\/script><script>alert(1);//"; </script> </body> </html>
但上面這段 HTML 與 PHP code 仍然有問題,如果 $str
是 <!--<script
時,你會發現 DOM 又爛掉了:
<!DOCTYPE HTML> <html> <body> <script> var a = "<!--<script>"; </script> </body> </html>
而 escape.alf.nu 的 Level 15 就是利用這個問題,再加上其他的漏洞而完成 XSS 攻擊。
為了這個問題去 StackOverflow 上問:「Why does <!--<script> cause a DOM tree break on the browser?」,才又發現上面這段 code 並不是合法的 HTML5 (先不管 head & title 的部份,補上後仍然不是合法的 HTML5)。
原因在於 DOM parser 對 <script></script>
的特殊處理:「4.3.1.2 Restrictions for contents of script elements」。(話說這段 ABNF 差點讓我翻桌...)
解法是在 <script></script>
的開頭與結尾加上 HTML 註解:(這剛好是 HTML 4.01 建議的方法)
<!DOCTYPE HTML> <html> <body> <script> <!-- var a = "<!--<script>"; --> </script> </body> </html>
那段 ABNF 的目的是希望可以盡可能往後找到 -->
與 </script>
結尾的地方。
當然你也可以用 json_encode()
的 JSON_HEX_TAG
把 <
與 >
硬轉成 \u003c
與 \u003e
避開這個問題,但這使得呼叫 json_encode()
時要多一個參數 (而非預設參數),用起來比較卡...
這個問題會變得這麼討厭,是因為 DOM parser 與 JavaScript 語法之間有各自的處理方式,然後又有些 pattern 是之前的 spec 遺留下來的包袱 (像是 HTML 4.01 在「18.3.2 Hiding script data from user agents」裡有提到用 <!--
與 -->
包裝 <script></script>
),變成在設計 HTML5 時都要考慮進去相容...
之前會習慣用 <!--
與 //-->
包裝 <script></script>
倒不是這個原因,而是因為不這樣做的話,jQuery 在 IE 使用 html()
時遇到有 <script></script>
的字串會爛掉,所以後來寫的時候變成習慣了...
反而因為這個習慣而避開了這個問題...
超難搞啊...
上一篇「Filter Input & Escape Output...」有提到 Non-null UTF-8 string 的 filter,結果剛剛洗澡的時候想了想,好像寫錯了?
問題在於「到底是先 de-null 再 iconv()
,還是先 iconv()
再 de-null」的問題。
這個問題其實跟 iconv()
成 UTF-8 時遇到不合法字元時怎麼實做有關,也就是 undefined behavior... 由於 \0
是合法的 UTF-8 character,所以我們假設某一種實做是當 iconv()
遇到不合法字元時會用 \0
帶進去:
這是上一篇文章提到的方法。但在上面提到的 iconv()
實做下卻是有問題的方法。原因很簡單,de-null 後沒有 \0
的字串,卻會因為 iconv()
而產生 \0
。
這邊要考慮的是最後 de-null 後會不會變成 invalid UTF-8 string。答案是不可能,因為 iconv()
轉出來後保證是 UTF-8 string (不論如何處理非 UTF-8 character 的部份),而 UTF-8 string 內的 \0
一定可以當 separator,所以切下去一定還是 UTF-8 string。(可以參考下圖關於 UTF-8 character 的規則)
可能以現在的 iconv()
實做來說,兩者都不會有問題,但寫程式的時候總是要避免 side-effect,所以後者的方法會比前者好。
維基百科上有一篇「Secure input and output handling」說明要怎麼處理 input 與 output (對資安方面的說明)。標題的 Filter Input 與 Escape Output 是 Gasol 之前提到後才知道的名詞,以前只知道要 validate & escape,沒想過一個比較好記的念法...
這邊都以 PHP 為主,其他程式語言也應該會有對應的方式...
Input 有很多管道,有可能是使用者或是 3rd party 廠商透過 Form 傳進來的資料 (在 PHP 裡可能是 $_GET
或是 $_POST
),也有可能是 cookie 的資料 (因為使用者可以修改,所以視為不安全的資料)。從檔案讀資料進來 (可能是普通的文字檔,或是 XML,也可能是圖片) 也算是 input。
Output 也有很多管道,像是 HTML、JSON,或是組 SQL statement 時使用變數。
在處理 input data 時,一般常常忘記的是「先強制轉成 Non-null UTF-8 string」(現在一般都是用 UTF-8,所以這邊就只講 UTF-8)。
這是因為很多 PHP function 對非 Non-null UTF-8 string 有非定義行為 (undefined behavior,不保證效果與輸出結果的正確性),加上一般常見的產品需求可以用 Non-null UTF-8 string 滿足,所以在 PHP 內拿到資料時可以先 filter 過。
Update:下面說的步驟錯了,請參考「關於 Non-null string 的處理...」這篇的說明。
有兩個步驟要做,第一個是確保他是 Non-null,直接把 \0
以及以後的東西幹掉:
$str_out = preg_replace('/\0.*/g', '', $str_in); $str = preg_replace('/\0.*/g', '', $str); // 直接取代原來字串
第二個是確保他是 UTF-8 string。這點可以直接用 iconv()
轉,而不用自己寫 regex 處理了:
$str_out = iconv('UTF-8', 'UTF-8', $str_in); $str = iconv('UTF-8', 'UTF-8', $str);
用 iconv()
從 UTF-8 轉到 UTF-8 是一個特別的用法,我是在 Cal Henderson 的「Building Scalable Web Sites: Building, Scaling, and Optimizing the Next Generation of Web Applications」上看到的 (有中譯版)。
如果傳進來的值本來就假設是整數,那麼就用 intval()
轉一次。如果假設是非負整數 (包含 0),那麼就用 abs()
與 intval()
。如果是文字類的 (像是 e-mail),可以再用其他的 regex 檢查。
一般來說,白名單會比黑名單好。不過這也是一般性,很多時候還是很囧的...
Escape 指的是 Escape character (轉義字元)。不同的情況下會有不同的 escape character,所以保護的方式也不一樣。
以 HTML 來說,想要顯示小於符號 <
,實際上要用 <
表示。而在 PHP 裡面常用的 htmlspecialchars()
定義了「只 escape 五個符號」,剛好可以拿來用:
<div><?= htmlspecialchars($str) ?></div>
也有人推薦 htmlentities()
,不過因為轉的比較多 (所以要考慮的行為比較多),我比較不喜歡...
對於 XML,在 XML 的規範裡規定一定要把 <
與 &
換成 <
與 &
(Character Data and Markup),但 >
則可以 (非必要) 換成 >
。也允許把雙引號 "
換成 ",以及單引號 '
換成 '
。
所以 XML 剛好可以直接用 htmlspecialchars()
(確認完全符合 spec 要求),反過來 htmlentities()
就不保證了。
再來是 MySQL 的 escape 與 charset 有關,所以要用 mysql_real_escape_string()
或是 PDO::quote()
,但更好的方法應該是使用 prepare & execute (binding variables)...
而 shell 的 escape 則應該用 escapeshellarg()
再帶入 string 裡。
每一種 output 所需要的 escape function 不同,都不能直接拿 addslashes()
來用... (這個 function 的設計就很 PHP...)
純粹 JSON 的話,用 json_encode()
就可以幫你處理好。問題是在 HTML + JSON 時會讓你處理到抱頭痛哭... 這就是另外的故事了 +_+
Filter Input + Escape Output 只是最基本的一步,不過在大多數的狀況下,這個方法就可以擋下不少問題了,算是很實用的 policy...
還是在 Zite 上看到的,對最大的一百萬個網站分析與安全有關的 HTTP Header:「Security Headers on the Top 1,000,000 Websites: November 2013 Report」。
數字大致上都有增加,不過對我來說的重點在於有列出所有與安全有關的 HTTP Header...
可以看到有這幾個:
剛好可以拿來 review 設定...
讓我意外的是,只有 FreeBSD 10.0-BETA (還沒出 RELEASE 的版本) 有問題,9.2-RELEASE 並不在內:「OpenSSH AES-GCM memory corruption vulnerability」。
本來 9.2 的機器有上 workaround 把 AES-GCM 強制拔掉,看起來可以 revert 回來了...
Google Online Security Blog 上對四種 cipher 的分析:「A roster of TLS cipher suites weaknesses」。
分別是 RC4、AES-CBC、AES-GCM、ChaCha20-Poly1305 四個 cipher。其中 RC4 與 AES-CBC 的問題都很多,而 AES-GCM 與 ChaCha20-Poly1305 是目前還沒有有效攻擊的 cipher。
前面三個都算熟悉,第四個是到是頗意外會出現... 不過 ChaCha20-Poly1305 不只一家打算跳下去實做了:
ChaCha20 與 Poly1305 都是 D. J. Bernstein (djb) 的作品,不知道 OpenSSL 會不會納進去...
在「ChaCha20 and Poly1305 for TLS」這邊有些為什麼有了 AES-GCM 後還要用 ChaCha20-Poly1305 的原因,主要是速度考量。兩者的速度差非常多...
先講結論,不要用,甚至連 copper 這家公司的產品都應該避開。
看到「Stackdock: Blazing Fast Docker-as-a-Service with SSDs – for $5」這篇文章,提到用 Docker 建立的服務。
首先是註冊流程就很有問題,註冊完後他要你收信登入 (這邊沒什麼問題),結果收信後發現他的連結是:
https://stackdock.com/login?email=my_account@gmail.com
意思就是根本不用認證... (暈倒)
當你想看使用條款,回到官網 https://stackdock.com/ 上發現沒有使用條款?另外在母站 http://copper.io/ 也沒有?
再來收費方式也不清楚,只說了 USD$5/month,但如果以 Docker 的性質,開一次就收 USD$5,那麼就太鳥蛋了。但也沒有講是按照「小時」收費,還是按照「日」收費...
登入後 UI 動線上卡卡的 (速度也不太快,不過應該跟放在德國有關),如果你建立 Deck 時 (像是樣板) 沒有開 Instance,你是沒辦法用儲存好的 Deck 開 Instance 的... (會 failed,然後只有一個「read timeout reached」的錯誤訊息...)
你只有在建立時選擇「Save & Distill Drop」才有機會建立起來 (不過還是有可能會失敗)。
如果想要改密碼而點選上方的 Profile 時,發現被導到 sso.copper.io,而 sso.copper.io 是沒有 HTTPS 的,而且修改密碼時不需要輸入原密碼?(那你本站用 HTTPS 幹嘛啊?更該保護的不保護是怎樣?)
然後在 sso.copper.io 按下 logout 要二十秒... 然後出現白頁... -_-
最後,在測完後,我找不到地方 cancel 信用卡...
這家公司有滿滿的問題...
Twitter 上看到 Gasol 轉推的 OpenSSH 安全性問題:「OpenSSH Security Advisory: gcmrekey.adv」。
開頭就直接寫:
If exploited, this vulnerability might permit code execution with the privileges of the authenticated user and may therefore allow bypassing restricted shell/command configurations.
這噴飯了... OpenSSH 的安全性相當強,這次出這種包... XDDD
影響的範圍是 OpenSSH 6.2 與 6.3,並且 OpenSSL 有編 AES-GCM:
OpenSSH 6.2 and OpenSSH 6.3 when built against an OpenSSL that supports AES-GCM.
如果不允許升級到 OpenSSH 6.4,那麼暫時性的解法是不允許 AES-GCM,在 /etc/ssh/sshd_config
內可以設:
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc
結果 FreeBSD 9.2 看起來在範圍內中槍,先上 workaround 再來等 freebsd-update 提供的修正吧...