寫在前面
最近真的有點(diǎn)忙,同時(shí)做著4個(gè)項(xiàng)目
,對(duì)接客戶,溝通需求,技術(shù)造型,搭建項(xiàng)目框架,設(shè)計(jì)后端接口,定義對(duì)接流程,編寫文檔,督促前端partner,每一項(xiàng)都要親力親為,所以代碼質(zhì)量難免有折扣。這不,一不小心,就爆了。。。項(xiàng)目剛上線就被攻擊了,幸好沒有造成損失!
問題表象
昨天下午,我打開項(xiàng)目后臺(tái),發(fā)現(xiàn)直接跳到了項(xiàng)目首頁
,我以為是有哪個(gè)地方有重定向,或是登陸狀態(tài)有誤,才會(huì)跳到了項(xiàng)目首頁,連續(xù)試了幾個(gè)url,都是如此,所以就登陸服務(wù)器看了一下,發(fā)現(xiàn)public/index.php
被修改了,并且public/vendor/laravel-admin/
下面多了幾個(gè)文件,當(dāng)時(shí)也沒多想,直接把文件恢復(fù)了,多出來的文件也刪除了,以為是客戶誤操作,所以他們才沒有嘮叨
我。
結(jié)果今天下午,我再次打開項(xiàng)目后臺(tái),還是直接跳到了項(xiàng)目首頁
,還是不管什么url都會(huì)跳到了項(xiàng)目首頁,這才意識(shí)到可能是被攻擊
了,于是登錄服務(wù)器確認(rèn),昨天刪除的文件又重新產(chǎn)生了,public/index.php
又被修改了。心里雖然罵娘,但是問題還是得解決。
初步解決
因?yàn)閱栴}的表象是public/index.php
被修改,所以我想到的第一個(gè)操作就是,不讓它修改,于是直接就給它"上鎖
"了,如下
chattr +i public/index.php
這樣做雖然可以防止public/index.php
被修改,但是沒有查到根本原因,就無法解決根本問題。本著盡職盡責(zé)的態(tài)度,晚上又接著往下看這個(gè)問題了。
繼續(xù)追蹤
根據(jù)以往的經(jīng)驗(yàn)來說,這種問題,一般都是通過上傳文件接口把病毒植入到服務(wù)器上來的,于是就查看了nginx
的access_log
,果然發(fā)現(xiàn)了幾個(gè)可疑
的請(qǐng)求,如下
,果然發(fā)現(xiàn)了幾個(gè)可疑
的請(qǐng)求,如下
3605:127.0.0.1 - - [05/May/2025:16:42:26 +0800] "GET / HTTP/1.1" 200 832 "http://www.seocx.net/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
3616:127.0.0.1 - - [05/May/2025:16:52:54 +0800] "GET /storage/avatars/1_1745770882.php HTTP/1.1" 200 4289 "https://xxx.com/tags.php" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
3624:127.0.0.1 - - [05/May/2025:16:53:44 +0800] "GET /vendor/laravel-admin/AdminLTE/bootstrap/css/bootstrap.php HTTP/1.1" 200 2204 "https://xxx.com/tags.php" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
3626:127.0.0.1 - - [05/May/2025:16:53:57 +0800] "POST /tags.php HTTP/1.1" 200 3066 "https://xxx.com/tags.php" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
第一個(gè)www.seocx.net
在瀏覽器上打開一看,應(yīng)該是seo網(wǎng)站,所以問題應(yīng)該不是它。
第二個(gè)storage/avatars/1_1745770882.php
顯然問題就大了,因?yàn)?span style="background-color: rgb(248, 248, 250);">storage/avatars
是存放用戶頭像的目錄,不可能有php
文件,而且這種命名就是通過上傳頭像產(chǎn)生的。
第三個(gè)bootstrap.php
就是多出來的文件之一。
第四個(gè)tags.php
并不存在,應(yīng)該是一種輪詢測(cè)試方式,也是有問題的。
故不難看出,漏洞
就是第二個(gè)請(qǐng)求產(chǎn)生的,或者說漏洞
與第二個(gè)請(qǐng)求有直接關(guān)系。查看相關(guān)代碼,如下
$member_id = auth('api')->id();
$file = $request->file('avatar');
$folder_name = "storage/avatars";
$upload_path = public_path() . '/' . $folder_name;
// 獲取文件的后綴名,因圖片從剪貼板里黏貼時(shí)后綴名為空,所以此處確保后綴一直存在
$extension = strtolower($file->getClientOriginalExtension()) ?: 'png';
$fileName = $member_id . '_' . time() . '.' . $extension;
// 將圖片移動(dòng)到我們的目標(biāo)存儲(chǔ)路徑中
$file->move($upload_path, $fileName);
此處我們沒有判斷文件的后綴,用戶就利用了這個(gè)漏洞上傳了帶有攻擊性的php
文件。
修改起來也不困難,增加一下文件后綴的判斷即可
,如下
if( !in_array($extension, ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'heic']) ) {
Log::error('50006 --> illegal attacking');
return response()->json(err('圖片格式不正確'));
}
本來問題到這就算解決了,但是帶攻擊性的php
文件名是1_1745770882.php
,從上面的代碼可以看出,1_1745770882.php
開頭的1
是member_id
,而且第一個(gè)用戶一般要么是開發(fā)人員
,要么是客戶
,又不是無間道,兩者皆不可能上傳病毒文件,所以還得繼續(xù)往下看。
回到登陸
由于申請(qǐng)小程序帳號(hào),需要使用企業(yè)主體,所以很多流程我們是無法代勞的,只能客戶自己完成申請(qǐng),需要一定的時(shí)間。所以登陸的時(shí)候,為了快速測(cè)試
,我做了一個(gè)特殊
的登陸方式,如下
if( $request->jscode == 'test' && env('FOR_APP_SESSION_KEY') == true ) {
$data = [
'session_key' => 'test_session_key_000000000000001',
'openid' => 'test_openid_000000000000001',
];
} else {
$wechat = Factory::miniProgram($config);
$data = $wechat->auth->session($request->jscode);
}
意思就是當(dāng).env
配置文件里面的FOR_APP_SESSION_KEY
等于true
時(shí),jscode
傳test
就會(huì)模擬平臺(tái)接口的返回,然后拿到的member_id
就是1
。攻擊都就是利用了這個(gè)登陸方式,成功登陸了。
這個(gè)終歸還是我的問題,沒有及時(shí)將.env
配置文件里面的FOR_APP_SESSION_KEY
改掉。于是改掉配置之后,又刪除了此用戶,并且為了確保萬無一失,又在middleware
里面增加了判斷,如下
if( auth('api')->id() == 1 ) {
Log::error('50005 --> ',[$request->all(), $request->header()]);
return response()->json(err(50005, 'Invalid user'));
}
檢查無誤
這個(gè)問題的產(chǎn)生,就是由于當(dāng)時(shí)大意
,
- 1. 沒有及時(shí)修改配置,關(guān)閉特殊登陸方式
- 2. 沒有檢查用戶上傳的文件的后綴
所以就再三檢查了
本次的修復(fù)
步驟
- 1. 使用
chattr
設(shè)置文件不可修改 - 2. 檢查用戶上傳的
文件的后綴
,只能是圖片類型 - 3. 關(guān)閉
特殊登陸
方式 - 4. 刪除
member_id
為1
的用戶 - 5. 禁止
member_id
為1
的用戶訪問