利用PHP扩展Taint找出网站的潜在安全漏洞实践

1、背景

笔者从接触计算机后就对网络安全一直比较感兴趣,在作PHP开发后对WEB安全一直比较关注,2016时无心中发现Taint这个扩展,体验以后发现确实好用;不过当时在查询相关资料时候发现关注此扩展的人数并很少;最近由于换了台电脑,须要再次安装了此扩展,发现这个扩展用的人仍是比较少,因而笔者将安装的过程与测试结果记录下来,方便后续使用同时也让更多开发者来了解taintphp

taint扩展做者惠新宸曾经在本身的博客上有相关介绍,参考文档:PHP Taint – 一个用来检测XSS/SQL/Shell注入漏洞的扩展html

2、操做概要

  1. 源码下载与编译
  2. 扩展配置与安装
  3. 功能检验与测试

3、源码下载与编译

Taint扩展PHP自己并不携带,在linux或mac系统当中笔者须要下载源码本身去编译安装mysql

3.1 源码下载

笔者的开发环境是mac系统,因此须要去PHP的pecl扩展网站去下载源码,其中taint的地址为:linux

https://pecl.php.net/package/taint
复制代码

在扩展网址的的尾部,能够看到有一排下载地址,以下图nginx

image

笔者须要选择一个本身合适的版本,笔者的开发环境使用的是PHP7.1,所以选择了最新的版本,对应下载地址以下:git

https://pecl.php.net/get/taint-2.0.4.tgz
复制代码

使用wget下载该源码,参考命令以下:web

wget https://pecl.php.net/get/taint-2.0.4.tgz
复制代码

下载下来以后,笔者须要解压,解压命令参考以下:sql

tar -zxvf taint-2.0.4.tgz
复制代码

解压以后,进入目录,参考命令以下:数据库

cd taint-2.0.4
复制代码

3.2 源码编译

如今笔者须要编译一下源码,在编译以前可使用phpze来探测PHP的环境,参考命令以下:vim

phpize
复制代码

返回结果以下

Configuring for:
PHP Api Version:         20160303
Zend Module Api No:      20160303
Zend Extension Api No:   320160303
复制代码

生成 Makefile,为下一步的编译作准备

./configure 
复制代码

返回结果

checking how to hardcode library paths into programs... immediate
checking whether stripping libraries is possible... yes
checking if libtool supports shared libraries... yes
checking whether to build shared libraries... yes
checking whether to build static libraries... no

creating libtool
appending configuration tag "CXX" to libtool
configure: creating ./config.status
config.status: creating config.h
复制代码

开始编译,并安装

make && make install
复制代码
(cd .libs && rm -f taint.la && ln -s ../taint.la taint.la)
/bin/sh /Users/song/taint-2.0.4/libtool --mode=install cp ./taint.la /Users/song/taint-2.0.4/modules
cp ./.libs/taint.so /Users/song/taint-2.0.4/modules/taint.so
cp ./.libs/taint.lai /Users/song/taint-2.0.4/modules/taint.la
----------------------------------------------------------------------
Libraries have been installed in:
   /Users/song/taint-2.0.4/modules

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR' flag during linking and do at least one of the following: - add LIBDIR to the `DYLD_LIBRARY_PATH' environment variable
     during execution

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------

Build complete.
Don't forget to run 'make test'. Installing shared extensions: /usr/local/Cellar/php71/7.1.14_25/lib/php/extensions/no-debug-non-zts-20160303/ 复制代码

4、配置与安装

在编译扩展以后,笔者还须要把Taint放到指定位置,以及修改配置文件让其生效

4.1 配置taint

笔者首先须要知道PHP的配置文件是多少,而后经过查看配置文件的扩展路径,才能把so文件放到对应里面去,查看配置文件位置命令以下:

php --ini
复制代码

返回结果以下

Configuration File (php.ini) Path: /usr/local/etc/php/7.1
Loaded Configuration File:         /usr/local/etc/php/7.1/php.ini
Scan for additional .ini files in: /usr/local/etc/php/7.1/conf.d
Additional .ini files parsed:      /usr/local/etc/php/7.1/conf.d/ext-opcache.ini
复制代码

笔者能够看到php.ini放置在/usr/local/etc/php/7.1/php.ini当中

知道配置文件以后,笔者须要找到扩展文件夹位置,参考命令以下

cat /usr/local/etc/php/7.1/php.ini | grep extension_dir
复制代码

命令执行结果以下,笔者能够看出扩展文件夹位置是 /usr/local/lib/php/pecl/20160303

extension_dir = "/usr/local/lib/php/pecl/20160303"
; extension_dir = "ext"
; Be sure to appropriately set the extension_dir directive.
;sqlite3.extension_dir =
复制代码

4.2 安装扩展

如今笔者须要把扩展文件复制到,PHP的扩展文件位置,参考命令以下

cp /usr/local/Cellar/php71/7.1.14_25/lib/php/extensions/no-debug-non-zts-20160303/taint.so /usr/local/lib/php/pecl/20160303/
复制代码

复制完成以后,笔者须要编辑配置文件,将taint的配置项复制进去

vim /usr/local/etc/php/7.1/php.ini
复制代码

增长Tain的配置项到php.ini文件当中,参考配置以下:

[taint]
extension=taint.so
taint.enable=1
taint.error_level=E_WARNING
复制代码

4.3 安装结果验证

保存配置文件并退出以后,则表明笔者的安装已经完成,如今须要重启一下php让其生效,参考命令以下

brew services restart php@7.1
复制代码

重启完成以后,能够经过命令查看PHP当前的扩展有没有Taint,参考命令以下:

php -i | grep taint
复制代码

返回结果若是出现了一下信息,基本上已经安装成功。

taint
taint support => enabled
taint.enable => On => On
taint.error_level => 2 => 2
复制代码

5、功能检验与测试

完成上面的两步操做以后,笔者安装阶段已经大功告成了,如今笔者须要用taint来检验效果,检验分为三部分,首先用taint做者的demo代码进行检验,以后用渗透测试系统permeate来检验,最后以笔者平时所开发的代码进行测试。

5.1 demo文件测试

用demo文件测试的目的是检验笔者安装的taint是否真的已经生效,并确认taint有没有意义。

5.1.1 复制demo代码

在做者的GitHub上面有下面的这样一份demo代码,笔者将其复制到web目录,位置以下:

/Users/song/mycode/safe/permeate
复制代码

demo代码内容以下,读者实验时能够将其拷贝:

<?php
$a = trim($_GET['a']);

$file_name = '/tmp' .  $a;
$output    = "Welcome, {$a} !!!";
$var       = "output";
$sql       = "Select * from " . $a;
$sql      .= "ooxx";

echo $output;

print $$var;

include($file_name);

mysql_query($sql);
复制代码

5.1.2 配置虚拟主机

当代码文件保存以后,笔者须要在nginx配置文件中增长一个虚拟主机,用于浏览器访问此文件,参考配置以下:

server {
        listen       80;
        server_name  test.localhost;
        root  /Users/song/mycode/safe/permeate;
	    location / {
            index index.html index.htm index.php; 
        }

        location ~ \.php$ {
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
	        include        fastcgi_params;
        }
    }
复制代码

5.1.3 浏览器访问

接着笔者经过浏览器访问对应代码文件,URL地址以下:

http://test.localhost/taintdemo.php?a=1
复制代码

浏览器访问页面以后,笔者能在页面中看到一些警告信息,内容以下:

Warning: main() [echo]: Attempt to echo a string that might be tainted in /Users/song/mycode/work/test/taintdemo.php on line 10
Welcome, 1 !!!
Warning: main() [print]: Attempt to print a string that might be tainted in /Users/song/mycode/work/test/taintdemo.php on line 12
Welcome, 1 !!!
Warning: main() [include]: File path contains data that might be tainted in /Users/song/mycode/work/test/taintdemo.php on line 14

Warning: include(/tmp1): failed to open stream: No such file or directory in /Users/song/mycode/work/test/taintdemo.php on line 14

Warning: include(): Failed opening '/tmp1' for inclusion (include_path='.:/usr/local/Cellar/php@7.1/7.1.19/share/php@7.1/pear') in /Users/song/mycode/work/test/taintdemo.php on line 14

Fatal error: Uncaught Error: Call to undefined function mysql_query() in /Users/song/mycode/work/test/taintdemo.php:16 Stack trace: #0 {main} thrown in /Users/song/mycode/work/test/taintdemo.php on line 16
复制代码

从警告信息当中能够看出,笔者的taint已经生效,给出了不少警告提示,提示参数可能受到污染,由于参数并无通过任何过滤;

5.1.4 参数过滤测试

若是不想让taint给出警告提示,能够将demo代码中的第二行代码更改或增长一下过滤规则,参考代码以下:

$a = htmlspecialchars($_GET['a']);
复制代码

再次回到浏览器当中,刷新当前页面,能够看到返回的信息已经发生了变化,返回内容以下

Welcome, 1 !!!Welcome, 1 !!!
Warning: include(/tmp1): failed to open stream: No such file or directory in /Users/song/mycode/work/test/taintdemo.php on line 15

Warning: include(): Failed opening '/tmp1' for inclusion (include_path='.:/usr/local/Cellar/php@7.1/7.1.19/share/php@7.1/pear') in /Users/song/mycode/work/test/taintdemo.php on line 15

Fatal error: Uncaught Error: Call to undefined function mysql_query() in /Users/song/mycode/work/test/taintdemo.php:17 Stack trace: #0 {main} thrown in /Users/song/mycode/work/test/taintdemo.php on line 17
复制代码

由于笔者在代码中增长了参数转义,此时再次刷新浏览器,会看到taint再也不给发出警告提醒。

5.2 渗透测试系统验证

用demo系统验证taint扩展生效以后,如今笔者将用一个渗透测试系统来作一个实验,在这个系统中自己存在了不少安全问题,使用taint来找出这些问题,使用的渗透测试系统为 permeate渗透测试系统,地址以下

笔者以前有写过一篇文章介绍此系统,参考文档:WEB安全Permeate漏洞靶场挖掘实践

https://git.oschina.net/songboy/permeate
复制代码

5.2.1 下载permeate

笔者经过git将其源码下载下来,参考命令以下

https://gitee.com/songboy/permeate.git
复制代码

下载下来以后,一样建立一个虚拟主机,能够参考上面的nginx配置

5.2.2 导入数据库

由于这个系统会用到数据库,因此笔者下载以后须要新建数据库给permeate使用

image

新建完成数据库以后,笔者须要将一些数据表结构以及初始化数据导入到数据库当中,在使用git下载下来以后,在其跟目录有一个doc的文件夹,笔者打开它以后,能看到有一个sql文件,以下图所示

image

打开此文件并将其里面的内容复制,将复制的内容到管理数据库的Navicat Premium当中,而后执行这些SQL语句,以下图所示

image

5.2.3 修改配置文件

导入数据库完成以后,笔者修改数据库配置文件,让permeate可以链接次数据库,配置文件在根目录 conf/dbconfig.php,里面的配置代码以下,将其地址帐户以及密码和数据库名称一一对应填写

<?php
	!defined('DB_HOST') && define('DB_HOST','127.0.0.1');
	!defined('DB_USER') && define('DB_USER','root');
	!defined('DB_PASS') && define('DB_PASS','root');
	!defined('DB_NAME') && define('DB_NAME','permeate');
	!defined('DB_CHARSET') && define('DB_CHARSET','utf8');
    $sex=array('保密','男','女');
    $edu=array('保密','小学','初中','高中/中专','大专','本科','研究生','博士','博士后');
    $admins=array('普通用户','管理员')

复制代码

5.2.4 验证安装结果

设置好数据库以后,笔者安装permeate便已经完成了,此时打开首页,看到的界面应该以下图所示:

image
若是在首页当中没有看到板块以及分区等信息,颇有多是数据库没有链接成功或者数据库没有正确导入数据所致。

5.2.5 挖掘漏洞

下面开始进行测试,笔者点击第一个板块SQL注入,并点击列表下发的下一页按钮,此时看到的页面以下图所示:

image
在这个板块列表页中没看到任何问题,可是实际上taint已经给笔者发出了警告提醒。

笔者能够经过查看源代码时候来看到这些问题,以下图所示,taint提示在代码文件 /Users/song/mycode/safe/permeate/core/common.php的50行,存在参数被污染的状况。

image

5.2.5 漏洞分析

笔者找到对应的代码位置,发现代码内容以下:

function includeAction($model, $action)
{
    //判断控制器是否存在
    $filePath = "./action/$model.php";
    if (is_readable($filePath)) {
        require_once $filePath;
        $class = new $model;
        if (is_callable(array($class, $action))) {
            $class->$action();
            return true;
        }
    }

复制代码

在代码中笔者看到有一个require_once函数加载了文件,里面的参数使用了变量 $model$action ,经过最终变量来源,在代码文件/Users/song/mycode/safe/permeate/home/router.php发现这两个参数确实没有通过过滤,以下代码所示:

<?php
require_once "/core/common.php";
$model = !empty($_GET['m']) ? $_GET['m'] : 'index';
$action = !empty($_GET['a']) ? $_GET['a'] : 'index';

includeAction("$model","$action");
复制代码

最后须要提醒你们,Taint在开发环境安装便可,不要安装到生产环境当中,不然可能会把网站的安全问题直接暴露给攻击者。


做者:汤青松

日期:2018年08月16日

微信:songboy8888

相关文章
相关标签/搜索