文件读取下载漏洞
文件读取下载漏洞
介绍
文件下载漏洞属于文件类型漏洞的一种,是指造成不应该被下载的文件可通过恶意行为下载读取的安全漏洞。造成下载漏洞的文件有脚本、配置文件、日志、有权限管控的敏感文件等。这种漏洞通常出现在文件查看、文件下载功能中。
在分析该类漏洞或进行代码审计时,通常使用../来逐个层级查看推测路径信息。以最大限度地遍历所有可能存在文件下载漏洞的部分。常用的文件读取函数有file_get_contents()、file()、readfile()、fread()、fget()等。在CTF比赛中,则经常使用php://filter来查看源码信息。常见的漏洞表现方式有http://test.com/index.php?file=../../etc/passwd、http://test.com/index.php?file=..%2f..%2fconfig.php、http://test.com/index.php?file=ZG93bmxvYWQucGhw等。
可根据以下三个方面快速初步判断是否存在文件下载漏洞:
- 可下载或可读取文件的函数且参数是否可控。
- 可下载或可读取文件的路径是否未校验或校验不严谨。
- 下载或读取的文件是否为空,或者说能否看到文件的源内容。
危害
- 下载服务器任意文件,如脚本代码、服务及系统配置文件等;
- 可用得到的代码进一步代码审计,得到更多可利用漏洞。
同样任意文件读取也能在PHP中带来很多危害,比如比较严重的信息泄露,SSRF,反序列化问题
漏洞发现与利用技巧
Google Search
- inurl:readfile.php?file=
- inurl:read.php?filename=
- inurl:download.php?file=
- inurl:download.php?file=
常见连接名
- readfile.php?file=**.txt
- download.php?file=**.rar
常见参数名
- &RealPath=
- &RealPath=
- &FilePath=
- &file=
- &filename=
- &Path=
- &path=
- &inputFile=
- &url=
- &urls=
- &Lang=
- &dis=
- &data=
- &readfile=
- &filep=
- &src=
- &menu=
- &META-INF=
- &WEB-INF=
……
常用敏感文件路径
windows:
C:\boot.ini (查看系统版本)
C:\Windows\System32\inetsrv\MetaBase.xml (iis配置文件)
C:\Windows\repair\sam (存储系统初次安装的密码)
C:\Program Files\mysql\my.ini (Mysql配置)
C:\Program Files\mysql\data\mysql\user.MYD (Mysql root)
C:\Windows\php.ini (php配置信息)
C:\Windows\my.ini (Mysql配置信息)
…Linux:
/root/.ssh/authorized_keys (如需登录到远程主机,需要到.ssh目录下,新建authorized_keys文件,并将id_rsa.pub内容复制进去)/root/.ssh/id_rsa (ssh私钥,ssh公钥是id_rsa.pub)
/root/.ssh/id_rsa.keystore (记录每个访问计算机用户的公钥)
/root/.ssh/known_hosts (ssh会把每个访问过计算机的公钥(public key)都记录在~/.ssh/known_hosts。当下次访问相同计算机时,OpenSSH会核对公钥。如果公钥不同,OpenSSH会发出警告, 避免你受到DNS Hijack之类的攻击)
/etc/passwd (主机账号文件)
/etc/shadow (主机密码文件)
/etc/my.cnf (Mysql配置文件)
/etc/httpd/conf/httpd.conf (apache配置文件)
/root/.bash_history (root操作命令历史记录)
/root/.mysql_history (mysql命令历史记录)
/proc/self/fd/fd[0-9]*(文件标识符)
/proc/mounts (记录系统挂载设备)
/proc/config.gz (内核配置文件)/var/lib/mlocate/mlocate.db (全文件路径)
/porc/self/cmdline (当前进程的cmdline参数)
…
漏洞利用思路
常见利用思路
- 一般我拿到一个任意文件读取得先判断权限大不大,如果权限够大的话可以直接先把/etc/shadow读下来,权限不够就读/etc/passwd,先把用户确定下来,方便后续操作。
- 读取各个用户的
.bash_history能翻有用的信息,如编辑一些敏感文件。 - 下载各种
.log文件,从中寻找一些后台地址,文件上传点之类的地方,如果运气好的话会获得一些前辈们的后门。 - 读取程序配置文件(如数据库连接文件,可以利用数据库写shell)。
- 读取中间件配置文件(weblogic/tomcat/apache的密码文件、配置文件,确定绝对路径,方便后面读源码)。
- 读取一些软件的运维配置文件(redis/rsync/ftp/ssh等等程序的数据、配置、文档记录)。
- 读取web应用日志文件,中间件的日志文件,其他程序的日志,系统日志等(可以网站后台地址、api接口、备份、等等敏感信息)。
- 读取程序源代码,方便后面做代码审计,找突破口
java+oracle环境利用思路
可以先下载/WEB-INF/classes/applicationContext.xml 文件,这里面记载的是web服务器的相应配置,然后下载/WEB-INF/classes/xxx/xxx/ccc.class对文件进行反编译,然后搜索文件中的upload关键字看是否存在一些api接口,如果存在的话我们可以本地构造上传页面用api接口将我们的文件传输进服务器。
也可以先下载网站的配置文件,在根目录/WEB-INF/Web.xml的(一般都有很多内容,有时含有数据库连接用户名和密码等关键信息)。
具有root权限的利用思路
尝试读取/root/.bash_history看自己是否具有root权限。
在linux中有这样一个命令 locate 是用来查找文件或目录的,它不搜索具体目录,而是搜索一个数据库/var/lib/mlocate/mlocate.db。这个数据库中含有本地所有文件信息。Linux系统自动创建这个数据库,并且每天自动更新一次。
当我们不知道路径是什么的情况下,这个可以说是一个核武器了,我们利用任意文件下载漏洞将mlocate.db文件下载下来,利用locate命令将数据输出成文件,这里面包含了全部的文件路径信息。
locate 读取方法:locate mlocate.db admin(可以将mlocate.db中包含admin内容全部输出来)
文件读取函数
file_get_contents(),readfile(),highlight_file(),show_source(),fopen(),fread(),fgets(),fgetss(),file(),parse_ini_file(),fpassthru,curl除了这些正常的读取文件的函数之外,另外一些其他功能的函数也一样可以用来读取文件,比如文件包含函数include等,可以利用PHP输入输出流php://filter/ 来读取文件。
file_get_contents() 函数
file_get_contents() 函数把整个文件读入一个字符串中。
1 |
|
payload:
download.php?filename=../../../etc/passwddownload.php?filename=file:///etc/passwd
注:
Content-Disposition: attachment意味着消息体应该被下载到本地;大多数浏览器会呈现一个“保存为”的对话框,将 filename 的值预填为下载后的文件名。
readfile() 函数
readfile()函数输出一个文件。该函数读入一个文件并写入到输出缓冲。
1 |
|
payload:
readfile.php?filename=../../../etc/passwdreadfile.php?filename=file:///etc/passwd
highlight_file() 函数
highlight_file() 函数对文件进行语法高亮显示。show_source()函数为highlight_file()函数的别名。
1 |
|
payload:
readfile.php?filename=../../../etc/passwdreadfile.php?filename=file:///etc/passwd
fopen() + fread() 函数
1 |
|
payload:
readfile.php?filename=../../../etc/passwdreadfile.php?filename=file:///etc/passwd
fopen() + fpassthru() 函数
fpassthru() 函数从打开文件的当前位置开始读取所有数据,直到文件末尾(EOF),并向输出缓冲写结果。该函数返回传递的字符数,如果失败则返回 FALSE。
1 |
|
payload:
readfile.php?filename=../../../etc/passwdreadfile.php?filename=file:///etc/passwd
fopen() + fgets() 函数
fgets()函数用于一次读取一行数据。
1 |
|
payload:
readfile.php?filename=../../../etc/passwdreadfile.php?filename=file:///etc/passwd
fopen() + fgetss() 函数
fgetss() 函数是 fgets() 函数的变体,用于读取一行数据,同时 fgetss() 函数会过滤掉读取内容中的 HTML 和 PHP 标记。
1 |
|
payload:
readfile.php?filename=../../../etc/passwdreadfile.php?filename=file:///etc/passwd
file() 函数
file() 函数把整个文件读入一个数组中。
与 file_get_contents()类似,不同的是 file() 将文件作为一个数组返回。数组中的每个单元都是文件中相应的一行,包括换行符在内。
1 |
|
payload:
readfile.php?filename=../../../etc/php.inireadfile.php?filename=file:///etc/php.ini
parse_ini_file() 函数
parse_ini_file() 函数解析一个配置文件,并以数组的形式返回其中的设置。
注:该函数仅可读取ini配置文件。
1 |
|
payload:
readfile.php?filename=../../../etc/php.inireadfile.php?filename=file:///etc/php.ini
curl SSRF + file://伪协议
curl_exec函数执行给定的cURL会话。这个函数应该在初始化一个cURL会话并且全部的选项都被设置后被调用。
该函数在SSRF中也讲到过,可以利用SSRF漏洞结合file://伪协议达到任意文件读取。
1 |
|
payload:
readfile.php?url=file:///etc/passwdreadfile.php?url=file://192.168.1.12/etc/passwd
include 文件包含 + php://filter 伪协议
之后会对文件包含进行详细讲解。
使用 php://filter伪协议” 来进行包含。当它与包含函数结合时,php://filter流会被当作php文件执行。所以我们一般对其进行编码,阻止其不执行。从而导致任意文件读取。
1 |
|
payload:
- readfile.php?filename=php://filter/read=convert.base64-encode/resource=../../../etc/passwd
- readfile.php?filename=php://filter/read=convert.base64-encode/resource=file:///etc/passwd
再对结果进行base64解码即可。
漏洞防御修复
- 过滤
.点,使用户在url中不能回溯上级目录 php.ini配置open_basedir限定文件访问范围正则严格判断用户输入的参数
将下载区独立出来,放在项目路径外,给每个下载资源固定的URL,而不是所有的下载资源都是统一的URL:http://www.test.com/download?filename=文件名
- 净化数据:对用户传过来的文件名参数进行硬编码或统一编码,对文件类型进行白名单控制,对包含恶意字符或者空字符的参数进行拒绝。
- web应用程序可以使用chroot环境包含被访问的web目录,或者使用绝对路径+参数来访问文件目录,时使其即使越权也在访问目录之内。
www目录就是一个chroot应用。由chroot创造出的那个根目录,叫做“chroot监狱”(所谓”监狱”就是指通过chroot机制来更改某个进程所能看到的根目录,即将某进程限制在指定目录中,保证该进程只能对该目录及其子目录的文件有所动作,从而保证整个服务器的安全。
详细具体chroot的用法,可参考:http://blog.csdn.net/frozen_fish/article/details/2244870 - 任意文件下载漏洞也有可能是web所采用的中间件的版本低而导致问题的产生,例如ibm的websphere的任意文件下载漏洞,需更新其中间件的版本可修复。
- 要下载的文件地址保存至数据库中。
- 文件路径保存至数据库,让用户提交文件对应ID下载文件。
- 用户下载文件之前需要进行权限判断。
- 文件放在web无法直接访问的目录下。
- 不允许提供目录遍历服务。
- 公开文件可放置在web应用程序下载目录中通过链接进行下载。
- 记录文件下载日志。
