One
使用docker 拉取环境 docker-compose.exe -f .\docker-compose.yml up -d
进行访问
首先看到从上而下看到一个 base64 编码的数据
然后就是 引入lib.php
然后就是输出一个 编码过的flag
对第一行的base64 编码进行解密操作 ,进行反向解密操作
对每一个函数进行解释
:::info
base64-encode() 进行base64加密
hex2bin 16进行转换为 ASCII 码
strrev 进行反转
bin2hex ASCII 码转为 16 进制
:::
编写PHP 脚本
对其进行反转操作就可以了 我们最终的数据是ASCII码 不是 16 进行 所以这里不要按照直的顺序进行编码
得到flag
如果按照纯顺序来做会报错
Two
1 |
|
参数 time
第一个if 不能为数字
第二个判断
必须大于
>>> 606024302
5184000
第三个判断 必须小于
>>> 606024303
7776000
第四个判断
sleep(int())
必须要在 5184000 和 7776000 之间
然后这里又是sleep 函数 必须是整数
在中间的值取个整数 6000000
但是这样的话他会执行 6000000秒 这不行
这里可以使用科学计数法
6e6
———————————————————————————————————–
1、当一个字符串被当作一个数值来取值,其结果和类型如下:如果该字符串没有包含’.’,’e’,’E’并且其数值值在整形的范围之内,该字符串被当作int来取值。其他所有情况下都被作为float来取值,该字符串的开始部分决定了它的值,如果该字符串以合法的数值开始,则使用该数值,否则其值为0。
2、在进行比较运算时,如果遇到了0e这类字符串,PHP会将它解析为科学计数法。(也就是说只靠最前面的进行判断)
3、在进行比较运算时,如果遇到了0x这类字符串,PHP会将它解析为十六进制。
Three
三个传参值 id a b
前两个好绕过
and $id==0
利用php弱类型比较,数字与字符串等值比较时,字符串取开头的有效数字,无则为0,结合id不为0或null,id可取值开头不带有效数字的字符串,$id=a0
绕过 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! 即可
绕过 b
eregi(“111”.substr($b,0,1),”1114”) and substr($b,0,1)!=4
%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
1 |
|
Four
首先看见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()
是可以成功执行 的
那就可以写一句去连shell
http://172.18.52.58:23114/challenge4.php?hello=);eval($_POST[cmd]
Five
就没见过 sha1 === sha1 这种
但是尝试一下md5 弱比较绕过
就绕过了 ….
我也没想到 。。。。
“分析代码逻辑,发现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
查看源代码也没有发现啥数据
扫描目录也没有发现啥 发现了 flag.php 和 index.php 但是没有数据
后面才才发现 代码在docker 启动目录下
1 |
|
定义了两个变量
$_403 $_200
这里如果不是 POST去 访问 就会BugsBunnyCTF is here :p…
所以一开始 是 GET 就会出现 BugsBunnyCTF is here :p…
首先传入的参数 是flag
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 |
|
这样就完成了 变量覆盖
解法 1 : 将真实的flag覆盖$_200并输出$_200
GET传一个变量_200 的 值 为flag
POST 方法传 一个变量为flag 值 为 任何数 ,这里传一个flag=1
相当于$_200=$flag,将真flag给了$_200
$flag被修改为1,与$_POST[‘flag’]等值等类型,不满足$_POST[“flag”] !== $flag
输出$_200即输出真flag
1 |
|
解法二 : 将真实的flag 覆盖给 $_403 并构造$_403 能输出
把真实的flag 传给了 403
然后构造两个flag=2 flag=1
$flag被修改为1,与$_POST[‘flag’]不等,满足$_POST[“flag”] !== $flag,输出$_403
Eight
1 |
|
一道php 无数字字母webshell 的题
挺难得 , 看p神的blog 有几种解法
方法一 是 位运算 进行 异或
方法二 是 进行取反运算
方法三
方法是理解了但是实际操作还是不会 。。。。。 哎
参考师傅们的文章:
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
docker 拉取不了 给了源文件 开始代码审计
这个题 有全局变量 ip
shell_exec 函数 稳稳的RCE了
$substitutions = array(
‘&’ => ‘’,
‘;’ => ‘’,
‘|’ => ‘’,
‘-‘ => ‘’,
‘$’ => ‘’,
‘(‘ => ‘’,
‘)’ => ‘’,
‘`’ => ‘’,
‘||’ => ‘’,
);
存在过滤
尝试输入一个ip地址
是可以执行命令的 ,但是由于我这里是window系统 看看能不能存在 windows的过滤方法
找了半天没有存在的绕过windows的方法 ,这里由于是windows搭建的 参加的方法被过滤掉了
linux可以使用 %0a 去进行 绕过
完整payload
http://localhost:3000/challenge9.php?ip=127.0.0.1%0acat$IFS$9flag.php
这里$IFS$9是绕过空格
Ten
**端口 23120 **
1 |
|
主要在于
1 |
|
one =1 nine = 9
不能大于等于1 小于等于 9
否则就是false
然后这里 传入的number 还必须等于 3735929054
看见 == 就可以使用php 弱比较
把 3735929054 这个转为 16进制看看
十六进制的3735929054,只包含字母与0,满足条件
Payload 为
answer=0xdeadc0de