ctf-web:文件包含漏洞和举例-HCTF2018 WarmUp「建议收藏」

ctf-web:文件包含漏洞和举例-HCTF2018 WarmUp「建议收藏」我又回来更新了,这次是关于web方面的文件包含漏洞.我会在后面以详细的角度来写清楚这个漏洞的利用方法.当然,以下都是我自己的理解,表述什么的都有些野人化了.所以希望各位大佬手下留情.一.漏洞产生的原因这个漏洞可以追溯到很久.更准确来说,其实是人为产生的.由于我php学的不是很专业,所以我就拿c语言来举例了.php里面使用的是include命令,c语言使用的是#include预处理命令.作用是相似的.我新建了两个文件,内容如图.wzc.h:#include”stdio.h”voidpri.

大家好,又见面了,我是你们的朋友全栈君。

我又回来更新了,这次是关于web方面的文件包含漏洞.我会在后面以详细的角度来写清楚这个漏洞的利用方法.
当然,以下都是我自己的理解,表述什么的都有些野人化了.所以希望各位大佬手下留情.

一.漏洞产生的原因

这个漏洞可以追溯到很久.更准确来说,其实是人为产生的.由于我php学的不是很专业,所以我就拿c语言来举例了.php里面使用的是include命令,c语言使用的是#include预处理命令.作用是相似的.
我新建了两个文件,内容如图.
wzc.h:

#include "stdio.h"
void print_f(){ 
   
	printf("this is test file");
}

main.c:

#include "wzc.h"
int main(){ 
   
    print_f();
    return 0;
}

程序运行结果如图:
在这里插入图片描述
学过c语言的应该都知道我刚才干了件什么事情.我先写了一个自己创建的头文件库,里面存放了一个”print_f”函数,作用是在屏幕上显示一句话.
然后我使用预处理命令将文件进行了一个包含的操作,这样我后面就可以多次调用这个print_f函数了.
这么做在工程量少的情况下是看不出来有什么作用的,但是当你在做一个大工程时,需要多次实现某个功能的时候,就可以派上用场了,很完美的一个操作,对吧?
但是,凡事都有例外.
假如我是黑客,然后我在某个公司开发的c语言程序的被包含文件中,偷偷把被包含的文件中添加一些后门命令,是不是就产生问题了呢?最起码能让你这个程序崩溃不能运行.
不过这并不是我们文件包含漏洞主要被利用的地方,我们要说的是利用语法来钻空子.
观察我们的代码第一行:

#include "stdio.h"

在c语言中,被包含的文件名左右的包含符号有两种.
第一种是两个尖括号.(<>)
这种写法编译器会在系统自带的头文件库中寻找所需要的文件进行包含.例如:

#include <stdio.h>

第二种是两个双引号(“”)
这种写法编译器会首先在c文件目录下寻找需要被包含的文件,如果没有,就会去系统文件夹下寻找.
ok,了解这两种写法以后,我们可以继续往下走了.
虽然说如果使用(“”)这种写法,机器会自动寻找当前目录下的规定文件,但是有时候我们的头文件库特别多,需要专门建一个文件夹来存放,那这时候该怎么引用呢?
比如我们如图的形式.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
就像这样,当我们文件存放在不同地方的时候,我们的c程序在引用的时候就需要改变一下形式了.
main.c:

#include <stdio.h>
#include "..\\include\\wzc.h"
#include "..\\include\\wzc2.h"
int main(){ 
   
    print_one();
    print_two();
    return 0;
}

像这样,类似于cmd命令中写路径的时候一样的,”…“代表上一级目录.不过由于需要考虑c语言的转义字符的关系,所以我们需要把反斜杠打成两个才可以.
很好,我想你们应该已经认识到了关于使用c语言的预处理命令来进行文件包含了.
但是,想一想这个问题,假如说被包含的文件名如果可以通过用户自己输入的话,那是不是就很恐怖?如果我在被包含的文件多写几个”…/”,是不是就代表着我们就可以没有限制的访问任何目录下的某个文件的内容了?
当然,由于c语言是编译器处理这个事情的,所以不会产生这个问题.
但是php就不一样了,因为它可以直接使用类似于echo的方法直接使用include,甚至允许用户自己输入被包包含的内容,这样做的后果就不需要我说了吧?十分危险.
因此.一些网站在需要使用这个命令的时候,就会对用户的输入进行一个过滤,从而防止用户使用这个漏洞进行一些非法操作.

二.漏洞的实际利用

1)分析源码

这个是我偶然遇到的一个web题,来自于buuctf网站的web的第一题.如图,我们首先访问靶机,显示的是一张图片.
在这里插入图片描述
右键查看源码.
在这里插入图片描述
发现在注释中有个source.php,我们尝试进行访问发现成功.
在这里插入图片描述
很好,又到了我们喜闻乐见的代码审计环节.我对代码的分析放在了下面.

<?php
    highlight_file(__FILE__);
    //这个函数是将文件按照语法的高亮来显示.后面那个__FILE__我没有查到,应该是代表本文件的意思
    class emmm
    //新建一个emmm类
    { 
   
        public static function checkFile(&$page)
        //类中的checkFile函数
        { 
   
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
            //新建一个列表,列表中添加了两个key,并且有两个对应关系.这个列表的作用类似于白名单
            if (! isset($page) || !is_string($page)) { 
   
                echo "you can't see it";
                return false;
            }
			//这是第一个对page进行判断的地方.检查page变量,判断是否是空变量和判断是否是字符串
            if (in_array($page, $whitelist)) { 
   
                return true;
            }
            //判断page变量是否存在于白名单之中
            $_page = mb_substr($page,0,mb_strpos($page. '?','?'));
            //_page变量储存在page变量中从第一个字符开始搜索"?"号出现的位置,"."代表将"?"号和字符串相连.
            
            if (in_array($_page, $whitelist)) { 
   
                return true;
            }
			//也就是说,这个其实是实现了一个截断的方法,因为我们下面会使用get的方法进行提交参数,但是将我们的"?"号和"?"号后面的内容给截断了,因此就造成了我们无法提交参数的尴尬情况.想想看该怎么办.
            $_page = urldecode($page);
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            if (in_array($_page, $whitelist)) { 
   
                return true;
            }
            //这也是进行了一个截断,不过这个是进行一次url解码以后的截断.
            echo "you can't see it";
            return false;
        }
    }

    if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])
    ) { 
   
        include $_REQUEST['file'];
        exit;
    } else { 
   
        echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
    }  
    //我们看到有include这个命令,因此我们就可以利用这个漏洞.
    //我们观察发现,脚本使用get的方式提交file变量的内容,然后进行检查.假如我们能绕过这三个检查,我们就能成功读取到flag.
?>

2)解法分析

我们大概走了一遍这个流程,大概知道了怎么运行的.因此,就需要更深入的研究了.
我们的目的是为了过三个if保护,代码:

    if (! empty($_REQUEST['file'])
        && is_string($_REQUEST['file'])
        && emmm::checkFile($_REQUEST['file'])

这三个条件是:
1)判断file变量是否为空
2)判断file变量是否为字符
3)用checkFile函数进行检查
前两个比较简单,关键是最后一个.刚才分析的过程中,我们最主要过的保护其实的就是关于那个截断的保护.
要知道,我们的目的就是为了使checkFile函数返回ture才可以。四个判断我们经过观察发现,最后一个判断是最容易过的保护。
因此,我们想想该如何绕过这个截断?
其实很简单,我们找一个和”?”作用像同的符号但是不是问号的符号不就行了么?
所以,我们要学会一个最简单的绕过方法–url编码绕过
首先,当我们在百度搜索一些东西的时候,我们会发现我们输入的汉字都变成了一些由百分号开头的奇怪编码.
这些编码就是经过浏览器url编码以后得到的结果.但是假如我们直接在网址栏输入编码后的代码,浏览器是不会进行url编码的.
最后服务器那头解码一次,就得到我们输入的结果了.
因此,我们就可以利用这个原理来进行一个简单的绕过.详细来看下过程.

            $_page = urldecode($page);
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            if (in_array($_page, $whitelist)) { 
   
                return true;
            }

这个是进行url解码以后进行的一个判断.此处就是我们要利用的地方.
假如我们将编码一次后的问号传过来,服务器解码一次得到问号.
然后网站后台脚本会进行一次解码,上一步出来的是问号,解码出来依然是问号,仍旧能发现我们的操作.因此,我们需要编码两次.
第一次,服务器将编码解码,得到问号编码一次的结果.
第二次解码是由后台脚本解码的.仔细研究一下这段代码的逻辑就明白了.
先解码,解出来是问号,然后将问号后面的都截掉,放到白名单里面一判断,成功返回truth,我们就成功了.
很好,此刻我们已经成功将三个判断都绕过了,接下来执行的就是include命令,将我们需要的文件包含进来就行了.这个用法和我前面说的c语言类似,就不赘述了.这个是关于这个漏洞的官方描述,被收录在了cve上面,英语好的同学可以看看.
在这里插入图片描述
文章参考链接:https://www.jianshu.com/p/36eaa95068ca

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/136121.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 大数据经典案例有哪些?

    大数据经典案例有哪些?“互联网还没搞清楚的时候,移动互联就来了移动互联还没搞清楚的时候,大数据就来了”。近两年,“大数据”这个词越来越为大众所熟悉,“大数据”一直是以高冷的形象出现在大众面前,面对大数据,相信许多人都一头雾水。下面我们通过几个经典案例,让大家实打实触摸一把“大数据”。你会发现它其实就在身边而且也是很有趣的。1.啤酒与尿布全球零售业巨头沃尔玛在对消费者购物行为分析时发现,男性顾客在购买婴儿尿片时,常常会顺便搭配几瓶啤酒来犒劳自己,于是尝试推出了将啤酒和尿布摆在一起的促销手段。没想到这个举措居然使尿布

  • freemarker 教程_freemarker自定义标签

    freemarker 教程_freemarker自定义标签FreeMarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成XML,JSP或Java等。页面的静态化有的较多中的注释都是以#号表示的第一个项目结构代码的实现[java…

  • java 怎么更新session值_java – 如何更新session.setAttribute(name,value)值,其中名称相同?…「建议收藏」

    java 怎么更新session值_java – 如何更新session.setAttribute(name,value)值,其中名称相同?…「建议收藏」我有一种情况,我需要更新名称保持不变的setAttribute的值.考虑以下情况作为示例–假设我有三个JSP:abc.jsp,xyz.jsp,pqr.jsp.现在首先运行abc.jsp然后控制前进到xyz.jsp&然后转发到pqr.jsp.现在执行pqr.jspt后,再次使用setAttribute中的更新值控制回xyz.jsp.abc.jsp:ArrayListgetSupplyS…

    2022年10月16日
  • java 对象拷贝方法beanutils_java copy方法

    java 对象拷贝方法beanutils_java copy方法一、简介:BeanUtils提供对Java反射和自省API的包装。其主要目的是利用反射机制对JavaBean的属性进行处理。我们知道,一个JavaBean通常包含了大量的属性,很多情况下,对JavaBean的处理导致大量get/set代码堆积,增加了代码长度和阅读代码的难度。二、用法:如果你有两个具有很多相同属性的JavaBean,一个很常见的情况…

  • Session.Abandon与Session.Clear之间的区别

    Session.Abandon与Session.Clear之间的区别Session.Clear()就是把Session对象中的所有项目都删除了,Session对象里面什么都没有。但是Session对象还保留。Session.Abandon()就是把当前Session

  • 二叉树算法应用案例

    笔者在1月4号将在CSDN学院开设一门公开课《算法与游戏实战》,在这里先把课程内容透露一部分给读者。首先讲述二叉树算法,二叉树在IT领域应用是非常广泛的,它不仅在游戏开发中,在当前比较火的人工智能上也得到了广泛的应用。作为使用者,首先要清楚二叉树的特性:它是n(n≥0)个结点的有限集;它的孩子节点做多是2个;它的遍历有先序,中序,后序;它的存储结构分为线性和链式存储等等;还有一种是最优二叉树也称为

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号