php代码审计及文件包含漏洞
一、文件包含漏洞介绍
1.什么是文件包含
相同代码重复出现在不同文件中出现代码亢余,所以出现了文件包含函数,就是让代码更为高效。需要用到的部分会去调用,且被包含的文件会当PHP代码执行,忽略本身后缀名。文件包含分为本地文件包含(Loacl File Inclusion,LFI)和远程文件包含(Remote File Inclusion,RFI),远程文件包含需要在php.ini中设置allow_url_include = on 和 allow_url_fopen = on
2.文件包含漏洞的定义
文件包含本身并不是漏洞,在程序写死的文件包含不会形成漏洞,几乎所有漏洞的成因都是相关参数可控,攻击者利用包含的特性,加上应用本身对文件(包含)控制不严格,最终造成攻击者进行任意文件包含。通常文件包含漏洞出现在php语言中。
3.文件包含出现的函数
include()函数:使用include引用外部文件,只有代码执行到include代码段时,调用的外部文件才会被引用并读取,当引用的文件发生错误是 ,系统只会给出个警告错误,而整个php文件会继续执行。
require()函数:在php文件被执行之前,php解析器会用被引用的文件的全部内容替换require函数语句,然后与require语句之外的其他语句组成个新的php文件,最好按新的php文件执行程序代码。
include_once()函数:使用include_once会在导入文件前先检测该文件是否在该文件的其他部分被引用过,如果有,则不会重复引用该文件,程序只能引用一次。
require_once()函数:功能与require()相同,区别在于当重复调用同一文件时,程序只能调用一次。
二、漏洞实例
对phpadmin-4.8.1系统代码审计
1.首先在审计系统全局搜索include函数关键字,发现有一处request[target]传参。
2.点进去,有五个条件
分别是
1、target传参不为空和0
2、target传参必须为字符串
3、传参不能index开头
4、传参不能是import.php、export.php
继续跟进checkPageValidity()函数
发现有三种情况,checkPageValidity()函数返回ture,且都是要求
p
a
g
e
在
page在
page在whitelist数组中,
先看第一种情况,如果whitelist为空,则重新赋值。
跟进 $goto_whitelis数组,发现是一个白名单。如下图
我们来看第一个返回ture的地方,要求是传参的字符串是否在数组里面,在这里完全可以输入一个白名单的文件名,但是没有什么意义,包含一个已经写好了的文件,无法达成任何目标。
在看第二个
mb_substr()函数:截取字符串。语法:mb_substr(
a
,
0
,
3
)
,
意
思
是
截
取
字
符
串
a
的
前
三
位
m
b
s
t
r
p
o
s
(
)
函
数
:
判
断
位
置
的
函
数
,
首
先
把
传
参
a,0,3),意思是截取字符串a的前三位 mb_strpos()函数:判断位置的函数,首先把传参
a,0,3),意思是截取字符串a的前三位mbstrpos()函数:判断位置的函数,首先把传参page连接一个问号,在查找问号的位置并返回,只会返回第一个问号的位置,如果我们传参里面有问号的话,但是在php中get传参问号会报错,因为在url中问号代表接下来是传参的意思,而自身无法作为传参值。继续看下一个判断
。
看到有一个urldecode()函数:进行一次解码。那我们把?进行二次url编码不就可以了,编码后为%25%3f,url解码后为%3f,代码进行到这里,问号不就出来了。
去一个白名单里的文件server_binlog.php,
构造playload:target=server_binlog.php%253f/…
/1.txt
但是怎么去写webshell呢,
这个1.txt我是写服务器上的,这里的phpadmin没有上传功能
解决方法,
先找到存储位置,select @@datadir //数据存储位置,这里显示的位置是绝对路径
建一个新表,输入一句话木马
找到数据库存储文件。
测试phpinfo