奇虎360:一個官網首頁的偶發 Bug 分析

程序員小助手 發佈 2020-02-10T02:55:37+00:00

前言如果不是行業相關,也就輕描淡寫,F5 刷新過去算了。可是,給出的提示信息那麼的熟悉,老味道,老配方,是可忍孰不可忍。與其說是BUG,不如說是偶發現象,這樣開發人員可無需修復了。祝你們玩的開心。官網首頁 home.html怎麼發生的正常進入 kuai.360.

前言

如果不是行業相關,也就輕描淡寫,F5 刷新過去算了。可是,給出的提示信息那麼的熟悉,老味道,老配方,是可忍孰不可忍。

與其說是BUG,不如說是偶發現象,這樣開發人員可無需修復了。祝你們玩的開心。



怎麼發生的

正常進入 kuai.360.cn 之後,給出這麼一個 json 字符串,

{"code":1,"msg":"\u53c2\u6570\u9519\u8bef"}

格式化之後為

{"code":1,"msg":"參數錯誤"}

為什麼首頁會產生這個錯誤呢,到底是那個環節出現的?是 web 伺服器嗎?是應用拋出的異常嗎?查看之後發現,是首頁網址進行了重定向。被索引到這個資源訪問位置

http://kuai.360.cn/%3Cbr%20/%3E%0A%3Cb%3ENotice%3C/b%3E:%20Undefined%20variable:%20redis%20in%20%3Cb%3E/usr/share/nginx/html/logger.php%3C/b%3E%20on%20line%20%3Cb%3E228%3C/b%3E%3Cbr%20/%3E%0A%3Cbr%20/%3E%0A%3Cb%3EFatal%20error%3C/b%3E:%20Call%20to%20a%20member%20function%20select()%20on%20a%20non-object%20in%20%3Cb%3E/usr/share/nginx/html/logger.php%3C/b%3E%20on%20line%20%3Cb%3E228%3C/b%3E%3Cbr%20/%3E%0A

對上述字符串進行 urldecode 轉碼得到

http://kuai.360.cn/<br />

<b>Notice</b>: Undefined variable: redis in <b>/usr/share/nginx/html/logger.php</b> on line <b>228</b><br />

<br />

<b>Fatal error</b>: Call to a member function select() on a non-object in <b>/usr/share/nginx/html/logger.php</b> on line <b>228</b><br />

已經很明顯的指出了錯誤位置,文件

/usr/share/nginx/html/logger.php

第228行變量名 redis 沒有定義。這個錯誤級別是 Notice。

還有一個致命錯誤 Fatal error,大概是這個錯誤之後拋出的。

Call to a member function select() on a non-object

然後使用 select() 方法,作用在了一個空對象上。

猜測,該處代碼類似是

if ($conditions){
    $redis = blabla;
}  
$redis->select('key_name')

這樣就符合了兩處觸發 fatal error 的錯誤信息。

為什麼提示信息Notice也會拋出?這與PHP的運行解析機制有關,設置項

error_reporting = E_ALL

這是 php.ini 配置文件配置項,顯然本項目沒有修改。或者在 logger.php 文件內顯式聲明。所以才會把所有的故障信息拋出給客戶端顯示。


JSON 字符串是如何拋出的?

經過上面的提示,以及訪問所在文件位置,可以推斷

  1. 不是web伺服器的問題。
  2. php文件有可能是意大利麵寫法,隨寫隨用。
  3. 如果是Object寫法,可能觸發了 try - catch 語句。
  4. 猜測可能使用redis緩存一部分資料庫交互的數據。
  5. 猜測可能是鍵值不存在,觸發了 undefined variable 錯誤。
  6. php錯誤信息類型默認為 E_ALL,事無巨細都要匯報。
  7. 數據交互是在不同主機之間進行。
  8. redis 緩存伺服器單獨做的部署?
  9. web 伺服器請求與 redis 伺服器發生了網絡問題?

那麼上面這個notice + fatal error 錯誤信息,怎麼就附加到了 url 請求上。

由於水平有限,只能挖掘到這裡了,請大神在評論區附上更深度的發現。


正常流程的請求

如果該網頁訪問正常,會有哪些內容和請求呢。在谷歌瀏覽器內使用 F12 進行查看。


可以看到,整體頁面加載完畢,使用了 jQuery 發起的四個AJAX請求。我們將有數據返回的請求貼在下面。

Request URL: https://kuai.360.cn/pb/lists?type=all&page=1&sign=50caadb0eca62c816aba2094871a4b1f&t=1581337695467&

返回的內容是JSON,經過美化後如下圖:


網頁內的動態數據均使用此方式渲染。


寫在最後

雖然有效的信息,可以供我們深挖的信息不多,整個路由體系,以及數據交互方式,都不清楚。

那麼僅僅知道首頁路由,使用了根目錄下的一個 logger.php 文件

且該文件內的方法,意外地因為緩存鍵值不存在,而獲取失敗

最不應該的,這個 $redis 聲明在局部

PHP 是弱類型語言,其變量聲明,變量類型,和數組索引極易出現不在掌控之內的事。360 的程式設計師應該打上這個補丁。


我是@程式設計師小助手,持續分享編程與程式設計師成長相關的內容,歡迎關注~~

關鍵字: