作者:joyqi

已經跟報告漏洞的相關方討論過這個事情,大家的初心還都是技術層面的交流,之前在流程上由于溝通不暢造成了一些誤解,現在誤解已經消除,大家也不要惡意去揣測他人的意圖,讓我們把焦點放在技術本身。我們也一致表達了在安全層面加強合作的意向。

作為開發者其實不太想寫這種針對性的回復文章。一般針對安全問題,如果有人報告我都是在第一時間提交修復。但這兩天很多關心 Typecho 的朋友通過各種渠道向我詢問最新爆出來的兩個嚴重的安全漏洞,我看了網絡上的分析文章,前面技術性的分析我在后面做回復。但是文中某些技術細節之外的無端猜測,是促使我寫這篇文章的理由。

原文鏈接: https://mp.weixin.qq.com/s/IE9g6OqfzAZVjtag-M_W6Q

修復方法

這一點是你務必知道的,為了你的站點安全,你可以先暫時刪除掉根目錄下掉 install.php 文件,或者你也可以直接升級到最新的 Beta 版

注意在升級的時候也要覆蓋 install.php 文件。

關于 XMLRPC 漏洞

第一個漏洞是 XMLRPC 里的 Pingback 協議,很多人可能不知道 Pingback 協議是干嘛的。我在這里簡單解釋下,這個協議誕生在 Web 2.0 概念誕生之初,由于在互聯網世界各個博客站點之間是獨立的存在,而它們之間又經常存在互相引用的情況。作為一個原創博主,我是無法知道我這篇文章被哪些站點引用過的,因此 Pingback 協議就是為了解決這個問題存在的。

當你在寫的文章發表后,如果文中引用了某個鏈接,系統會自動向那個鏈接發一個 PING,告訴對方我引用了這篇文章,地址是: xxx。對方收到這個 PING 以后會根據你給的原文地址回去檢驗一下是否存在這個引用,這就是一次 BACK。檢驗完以后,會把這次引用記錄下來,大家經常在 Typecho 或者 WordPress 之類博客評論列表里看到的引用記錄,就是這么來的。

而造成這個漏洞的關鍵就在于這個 BACK 過程。系統回訪的時候會調用網絡接口(在 Typecho 里還對 CURL 做了基于 Socks 的 fallback),而當時的代碼沒有對回訪的 URL 做驗證,結果本意是讓這個網絡接口去訪問 http 或者 https 的地址,但由于沒做驗證,導致它可以被用來訪問任何協議,這就為攻擊者創造了便利條件。

這個漏洞已經在上個月得到了修復,我們對訪問的協議和地址都做了雙重驗證,只限于訪問 http 或者 https 協議,并且限制了它的訪問范圍,不能用于訪問內網或者本機的地址,而且還針對今后可能普及的 IPV6 做了預防。

關于 install.php 漏洞

這個漏洞本質其實比上一個漏洞更簡單,原文的分析有點繞,其實只看最開始的部分就可以了,一句話解釋就是 install.php 本身對安裝狀態驗證存在漏洞,導致了可以繞過它向系統寫入一些非法代碼。

下面解釋三個大家最關心的問題

首先安裝的過程會分很多步驟,而且每一步都要驗證后再跳轉到下一步。具體到填寫配置信息的這一步,我們在你填寫完以后會驗證你的配置信息是否合法,比如數據庫連接是否正確等等,這些信息是通過 HTTP POST 傳遞到 PHP 的。當這一步做完驗證后,并寫入相應信息后(也有可能不寫入,比如 GAE 之類的容器環境,根本沒有可寫的環境),再 Location 跳轉到下一步,也就是去寫入初始數據。

熟悉一點編程的朋友,請回答我一個問題。如何在兩個 GET 請求間傳遞配置數據?用 querystring?太丑陋了吧。用 session?對不起,很多主機都沒有配好 session。用臨時文件?不好意思,就像上面說的,很多運行環境根本沒有可寫的權限。用數據庫?不行,數據表是在下一步的時候才建的。

所以我最后就用了 Cookie 來傳遞數據,這樣你的安裝過程會顯得比較干凈。

我個人認為,原文作者認為這可能是個后門之類的原因就在于,我對 Cookie 做了個 base64 的編碼,這是黑客最愛的做事風格,把不可告人的代碼隱藏在無意義的 base64 編碼下面。

但是,我用 base64 只是為了避免可能存在的 Cookie 編碼問題,這樣一種很正常的思路,給它預設不好的前提后,往往會得出令人不快的結論。

原文作者指出他不明白為什么這里要有這段代碼 https://github.com/typecho/typecho/blob/242fc1a4cb3d6076505f851fdcd9c1bbf3e431a5/install.php#L230

                <?php else : ?>
                    <?php
                    $config = unserialize(base64_decode(Typecho_Cookie::get('__typecho_config')));
                    Typecho_Cookie::delete('__typecho_config');
                    $db = new Typecho_Db($config['adapter'], $config['prefix']);
                    $db->addServer($config, Typecho_Db::READ | Typecho_Db::WRITE);
                    Typecho_Db::set($db);
                    ?>

如果你不聯系上下文,當然不知道為什么要有這段代碼。

首先解釋為什么要在這一步連接數據庫,因為這段代碼看起來就是這個作用。初一看這一步好像跟數據庫沒什么關系,該寫入的數據上一步已經寫完了,這一步就是告訴用戶安裝成功

但是我們的目光再往下移 https://github.com/typecho/typecho/blob/242fc1a4cb3d6076505f851fdcd9c1bbf3e431a5/install.php#L258

                    <?php
                        if (isset($_REQUEST['user']) && isset($_REQUEST['password'])) {
                            $loginUrl = _u() . '/index.php/action/login?name=' . urlencode(_r('user')) . '&password='
                            . urlencode(_r('password')) . '&referer=' . _u() . '/admin/index.php';
                            $loginUrl = Typecho_Widget::widget('Widget_Security')->getTokenUrl($loginUrl);
                        } else {
                            $loginUrl = _u() . '/admin/index.php';
                        }
                    ?>

這是一段生成快速登錄鏈接的代碼,方便你在安裝完成不需要輸入密碼直接進入后臺,請關注 Typecho_Widget::widget('Widget_Security')->getTokenUrl($loginUrl) 這一段代碼。

在 Typecho 0.9 里面,我們加入了防跨站模塊,而它的核心就是在每次提交的時候加入一個 Token 供系統驗證。而這個 Token 的生成是需要加鹽 salt 的,而每個站點的 salt 都是在安裝的時候寫入到數據庫中的隨機字符串。

所以看到了么?生成一個合法的后臺 URL 是需要數據庫連接的。

然后再解釋為什么要從 Cookie 里取數據,我們不是已經創建了 config.inc.php 文件了么?但是由于 config.inc.php 里定義的常量以及一些初始化動作,會與 install.php 頭部的代碼有所沖突。所以,我們無法在 install.php 去直接 require 它(這一點已經在新版里解決,我在這里只是解釋當時那么做的理由)。因此,我們又要初始化數據庫,就只能從 Cookie 里讀取信息并解碼了。

為什么不刪除 install.php?

首先,刪除 install.php 意味著需要給根目錄賦予額外的寫入權限,這本身就會造成安全問題。其次,很多容器環境,比如 GAE SAE BAE 之類的,代碼是基于版本控制管理的,根本不可能讓你去更改文件。那安裝完成后提醒用戶修改刪除可以嗎?首先,這么做沒有技術問題,但我認為安裝完以后再去刪除,是一件很麻煩的事情,在保證沒有漏洞的前提下,應該做到安裝后即可使用,當然用戶也可以自行去刪除 install.php。

寫在最后

首先,我歡迎任何以技術為目的質疑和交流,Typecho 這個項目也是依靠大家的力量一點點完善起來的。其次,我希望僅僅將這種質疑局限在技術本身,畢竟取一個吸引眼球的標題,最后再加一些揣測,又有多少人會真的去細思呢?大多數人都是會被帶著節奏,而接受預設立場,這一點不利于問題的解決。

所以你們看,即使我認真寫了這么多,仔細去看去分析的人估計也不會有多少。

Typecho 的社區個性一直是低調踏實,我們會認真對待每一項改進的提議。我想向那些因為此次軟件漏洞可能造成損失的用戶,表達歉意。

新的正式版,會在本周放出。


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/428/