攻防世界web(入门)11-20 刷题笔记

题目网址:攻防世界

参考资料:

​​​​​​【CTF合辑】攻防世界WEB-1分难度_哔哩哔哩_bilibili

前十道请到:攻防世界web(入门)1-10 刷题笔记-优快云博客

第十一题:PHP2

本题涉及:url二次解码
1、打开场景
2、url+/index.phps ,会得到一个php代码
//通过dirsearch进行搜索,py -3 dirsearch.py -u http://61.147.171.105:56616 -e phps,html,js
3、分析代码,代码详解在下方:
因为_GET有一次urldecode,然后代码中还有$_GET[id] = urldecode($_GET[id]);又一次urldecode解码,因此有两次解码。
4、打开编码网址,进行编码,a-%61-%2561
5、url+?+%2561dmin

注:
1、phps文件就是php的源代码文件,通常用于提供给用户(访问者)查看php代码,因为用户无法直接通过Web浏览器看到php文件的内容
2、编码网址:https://www.toolhelper.cn/EncodeDecode/Url

<?php
// 如果通过GET请求的参数'id'等于字符串'admin',则输出一条消息并终止脚本执行
if("admin"===$_GET[id]) {
  echo("<p>not allowed!</p>");
  exit();
}

// 对GET请求的参数'id'进行url解码
$_GET[id] = urldecode($_GET[id]);

// 如果解码后的'id'参数等于字符串'admin',则输出一条允许访问的消息和密钥
if($_GET[id] == "admin")
{
  echo "<p>Access granted!</p>";
  echo "<p>Key: xxxxxxx </p>";
}
?>

第十二题:ics-06

1、打开场景,进入报表中心
2、打开Burp Suite,浏览器打开bp,进行拦截
3、右键-发送到Intruder(快捷键:Ctrl+I)
4、到Intruder页面-payload,按图0操作,进行开始攻击
5、按图1操作,可知id为2333,url+?id=2333

图0
图1

第十三题:inget

方法1:
url+?id=' or 1=1 --+

url+?id=':这是URL参数的一部分,通常用于向服务器传递数据。id是一个参数名,'是一个单引号,表示字符串的开始。正常情况下,id参数应该是一个具体的值(如数字或字符串),但这里故意以单引号结尾,目的是破坏正常的SQL语句结构。

or 1=1:这是一个逻辑条件,1=1始终为真。当它被插入到SQL语句中时,会使得原本的查询条件失效。

--+:--是SQL中的注释符号,用于注释掉后面的SQL语句。+通常用于绕过某些过滤器,防止过滤器将--识别为非法字符。它的作用是确保注入的SQL语句不会因为后续的SQL代码而报错。
方法2:
工具:sqlmap
暂时不会,后续深入学习后进行补充,可观看原视频讲解

第十四题:fileclude

先学习一个新知识:
1、include() 是PHP中的一个语句,用于将一个文件的内容包含到当前脚本中。类似于 C 语言中的 #include,但 PHP 的 include() 是在运行时执行的。
举个例子:假设有一个文件 example.php,内容如下:

<?php
echo "Hello, world!";
?>


如果在另一个脚本中使用 include() 包含这个文件:

<?php
include("example.php");
?>


运行结果将是:
Hello, world!
2、file_get_contents($file2):读取$file2指定的文件内容

<?php
// 包含当前目录下的 flag.php 文件,可能用于引入一些配置或标志(flag)信息
include("flag.php");

// 使用 highlight_file() 函数高亮显示当前文件的代码
highlight_file(__FILE__);

// 检查是否同时存在 GET 参数 'file1' 和 'file2'
if (isset($_GET["file1"]) && isset($_GET["file2"])) {
    // 获取 GET 参数 'file1' 和 'file2' 的值
    $file1 = $_GET["file1"];
    $file2 = $_GET["file2"];

    // 检查 $file1 和 $file2 是否为空
    if (!empty($file1) && !empty($file2)) {
        // 检查 $file2 指定的文件内容是否等于 "hello ctf"
        if (file_get_contents($file2) === "hello ctf") {
            // 如果条件满足,则包含 $file1 指定的文件
            include($file1);
        }
    } else {
        // 如果 $file1 或 $file2 为空,终止脚本并输出错误信息
        die("NONONO");
    }
}
?>

题目:(整体讲解在上方)
1、if (file_get_contents($file2) === "hello ctf");
这个是说明:file2指定的文件内容要等于 "hello ctf"才可以通过。


2、include($file1);
攻击者可以利用一段php脚本(题解会讲),将flag.php文件的内容转换为Base64编码,并通过include()将其包含到当前脚本中。
当include()包含一个Base64编码的字符串时,PHP会尝试将其作为PHP代码执行。但由于Base64编码的内容不是有效的PHP代码,它会被直接输出到页面上。

题解:
1、URL+?file1=php://filter/read=convert.base64-encode/resource=flag.php&file2=data://text/plain,hello%20ctf
解释:
先看参数:
参数file1
php://filter:允许在读取文件内容时,对内容进行即时处理。
read=convert.base64-encode:将文件内容转换为Base64编码。
resource=flag.php:要处理的资源文件为flag.php。说明:flag.php文件的内容会被读取并转换为Base64编码。

参数file2
data://:是PHP的data流封装器,允许直接从URL中传递数据。
text/plain:指定数据的类型为纯文本
hello%20ctf:这是URL编码后的字符串"hello ctf",会被解码为"hello ctf"。//是因为URL中不允许直接包含空格,而URL编码是解决这一问题的标准方法。

2、打开Burp Suite,浏览器打开bp,进行拦截
3、右键-发送到Repeater(快捷键:Ctrl+R),发送
4、右侧滑动到,选中最下面的乱码,进行转码:右键-转换选中内容-Base64-Base64-decode(快捷键:Ctrl+shift+B),操作方法如图2

图2

第十五题:fileinclude

题目:
Ctrl+U,查看源码(详细解释在下方)


1、$lan = $_COOKIE['language'];
从$_COOKIE数组中获取language的值
如果language不存在于$_COOKIE中,会触发Notice: Undefined index: language错误。


2、if (!$lan) {
    @setcookie("language", "english");
    @include("english.php");//果$lan为空(即language Cookie不存在或为空),脚本会设置language为english,并包含english.php文件。
} else {
    @include($lan . ".php");//如果$lan不为空,则尝试包含$lan . ".php"文件。
}

题解:
1、打开Burp Suite,浏览器打开bp,进行拦截
2、右键-发送到Repeater(快捷键:Ctrl+R),发送
3、Connection: close,前面加Cookie:language=php://filter/read=convert.base64-encode/resource=flag
注:
php://filter:允许在读取文件内容时,对内容进行即时处理。
read=convert.base64-encode:将文件内容转换为Base64编码。
resource=flag.php:要处理的资源文件为flag.php。说明:flag.php文件的内容会被读取并转换为Base64编码。

4、右侧滑动到,选中Base64乱码,进行转码:右键-转换选中内容-Base64-Base64-decode(快捷键:Ctrl+shift+B)

<?php
if (!ini_get('display_errors')) {
    ini_set('display_errors', 'On');
}
error_reporting(E_ALL);

// 定义允许的语言列表
$allowed_languages = ['english', 'chinese'];

// 从Cookie中获取'language'的值
$lan = isset($_COOKIE['language']) ? $_COOKIE['language'] : null;

// 检查$lan是否为空或是否在允许的语言列表中
if (!$lan || !in_array($lan, $allowed_languages)) {
    // 如果$lan为空或不在允许列表中,设置默认值为"english"
    $lan = 'english';
    setcookie("language", $lan);
}

// 包含对应的语言文件
include($lan . ".php");

// 读取并输出当前文件内容
$x = file_get_contents('index.php');
echo $x;
?>

第十六题:file_include

1、打开Burp Suite,浏览器打开bp,进行拦截
2、右键-发送到Repeater(快捷键:Ctrl+R),发送
3、第一句修改为
GET /?filename=php://filter/convert.iconv.UTF-8*.UCS-4LE*/resource=flag.php HTTP/1.1
php://filter:允许在读取文件内容时,对内容进行即时处理。

解释:
convert.iconv过滤器用于字符编码转换。它的格式是:convert.iconv.源编码.目标编码
resource参数指定了要处理的文件路径。在这里,目标文件是flag.php。
这个过滤器使用 iconv 函数进行字符编码转换。具体来说,它将 flag.php 文件中的内容从 UTF-8 编码转换为 UCS-4LE 编码。这里的 * 是一个通配符,用于匹配任意字符。
去把php标签打乱,使其无法正常解析,其中的代码就会当作字符串被输出

4、右侧滑动找到flag

注:

详解php://filter以及死亡绕过_filter绕过过滤-优快云博客,可以再看看这个理解一下

第十七题:easyphp

题目:
1、先看a和b的条件
第一部分:
// 检查变量 $a 是否已设置,并且其整数值是否大于 6000000,同时字符串长度不超过 3 个字符

if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
    // 如果 $a 满足条件,继续检查变量 $b 是否已设置
    // 并且 $b 的 MD5 哈希值的最后 6 位是否等于 '8b184b'
    if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
        // 如果 $b 也满足条件,将 $key1 设置为 1,表示第一部分验证通过
        $key1 = 1;
    } else {
        // 如果 $b 不满足条件,终止脚本并输出提示信息
        die("Emmm...再想想");
    }
} else {
    // 如果 $a 不满足条件,终止脚本并输出提示信息
    die("Emmm...");
}



$a 的验证:
1、必须存在(isset($a))。
2、转换为整数后必须大于 6000000(intval($a) > 6000000)。
3、字符串长度必须小于或等于 3(strlen($a) <= 3)。

$b 的验证:
1、必须存在(isset($b))。
2、其 MD5 哈希值的最后 6 位必须等于 8b184b(substr(md5($b), -6, 6) === '8b184b')。

如果 $a 和 $b 都满足条件,则将 $key1 设置为 1,否则终止脚本(die)。

第二部分:

// 从 $_GET['c'] 获取数据,解码为 JSON 格式,并强制转换为数组
$c = (array)json_decode(@$_GET['c']);
// 判断 $c 是否是一个数组,且 $c["m"] 是否存在且不是数字,同时其值大于 2022
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
    // 如果 $c["n"] 是一个数组,且其长度为 2,并且 $c["n"][0] 也是一个数组
    if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
        // 在 $c["n"] 中查找值为 "DGGJ" 的元素
        $d = array_search("DGGJ", $c["n"]);
        // 如果没有找到 "DGGJ",终止脚本并输出 "no..."
        $d === false ? die("no...") : NULL;
        // 遍历 $c["n"] 中的每个元素
        foreach($c["n"] as $key=>$val){
            // 如果某个元素的值等于 "DGGJ",终止脚本并输出 "no......"
            $val === "DGGJ" ? die("no......") : NULL;
        }
        // 如果所有条件都满足,设置 $key2 为 1
        $key2 = 1;
    } else {
        // 如果 $c["n"] 的结构不符合要求,终止脚本并输出 "no hack"
        die("no hack");
    }
} else {
    // 如果 $c 的结构不符合要求,终止脚本并输出 "no"
    die("no");
}

得:
$c 的验证:
1、从 $_GET['c'] 中获取 JSON 字符串并解码为数组(json_decode)。
2、必须是一个数组(is_array($c))。
3、$c["m"] 必须存在且不是数字(!is_numeric(@$c["m"]))。
4、$c["m"] 的值必须大于 2022($c["m"] > 2022)。

$c["n"] 的验证:
1、$c["n"] 必须是一个数组(is_array(@$c["n"]))。
2、数组长度必须为 2(count($c["n"]) == 2)。
3、$c["n"][0] 必须是一个数组(is_array($c["n"][0]))。
4、$c["n"] 中必须包含字符串 "DGGJ"(array_search("DGGJ", $c["n"]))。
5、遍历 $c["n"],确保每个元素都不是 "DGGJ"($val !== "DGGJ")。

如果所有条件都满足,则将 $key2 设置为 1,否则终止脚本(die)。

题解:
1、GET /?a=9e9&b=53724&c={"m":"3333dd","n":[[],0]}
解释:
1、a=9e9:
(一)intval($a) > 6000000:9e9是一个科学计数法,结果是 9000000000,大于 6000000
(二)strlen($a) <= 3:strlen("9e9") 的结果是 3,满足条件。


2、'8b184b' === substr(md5($b), -6, 6):需要找到一个字符串 $b,使得其 MD5 哈希值的最后 6 位字符正好是 8b184b。可以使用python脚本,放在下方。
计算 md5("53724") 的结果是 f2b224f6429577d988d88b184b。
提取最后 6 位:substr("f2b224f6429577d988d88b184b", -6, 6) 的结果是 8b184b。

3、c={"m":"3333dd","n":[[],0]}
(一)is_array($c):用于检测变量是否是一个数组。因为$c=(array)json_decode(@$_GET['c']);中json_decode 函数将这个 JSON 数据解码为 PHP 数据时,它会被转换为一个 PHP 的关联数组。
(二)!is_numeric(@$c["m"]):$c["m"] 的值是 "3333dd",不是数字。
$c["m"] > 2022:PHP 在比较字符串和数字时,会尝试将字符串转换为数字。"3333dd" 转换为数字是 3333,大于 2022。
(三)is_array(@$c["n"]):$c["n"] 是一个数组
count($c["n"]) == 2:$c["n"] 的长度是 2
is_array($c["n"][0]):$c["n"][0] 是一个空数组,满足条件。
(四)

// 在 $c["n"] 中查找值为 "DGGJ" 的元素,并返回其键(索引)
// 如果没有找到,返回 false
$d = array_search("DGGJ", $c["n"]);

// 检查 $d 是否为 false
// 如果 $d 是 false,说明 $c["n"] 中没有值为 "DGGJ" 的元素
// 此时,输出错误信息 "no..." 并终止脚本
// 如果 $d 不是 false,说明找到了 "DGGJ",但脚本不会立即终止
$d === false ? die("no...") : NULL;

// 遍历 $c["n"] 中的每个元素
foreach($c["n"] as $key=>$val){
    // 检查当前元素的值是否严格等于字符串 "DGGJ"
    // 如果等于 "DGGJ",输出错误信息 "no......" 并终止脚本
    // 如果不等于 "DGGJ",继续检查下一个元素
    $val === "DGGJ" ? die("no......") : NULL;
}

这里说是为了双重检查,确保脚本在任何情况下都能正确终止,则保留 foreach 循环。(不太懂,不过我感觉不重要,可以看一下,在评论区讨论一下)

 

//b=53724
import hashlib

def find_md5_match(target, length=6):
    """
    暴力枚举找到满足条件的值
    :param target: 目标哈希值的最后几位
    :param length: 目标哈希值的长度(默认为6)
    :return: 满足条件的值
    """
    i = 0
    while True:
        # 将当前值转换为字符串
        current_value = str(i)
        
        # 计算当前值的 MD5 哈希值
        hash_value = hashlib.md5(current_value.encode()).hexdigest()
        
        # 检查哈希值的最后 length 位是否匹配目标值
        if hash_value[-length:] == target:
            return current_value
        
        # 尝试下一个值
        i += 1

# 目标哈希值的最后 6 位
target = '8b184b'

# 找到满足条件的值
result = find_md5_match(target)
print(f"找到满足条件的值: {result}")
print(f"其 MD5 哈希值为: {hashlib.md5(result.encode()).hexdigest()}")

第十八题:待更新

第十九题:待更新

第二十题:待更新

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值