Hackergame 2019(中科大信安赛)write up

这应该算苏卡卡第一次打 CTF(之前帮朋友测试用 ctfd 搭建的平台不算)。Hackergame 对于苏卡卡这种 CS 零基础、信安零基础、CTF 零基础这种菜鸡来说很友好,玩的还是很开心的(除了苏卡卡发现自己还是太菜了以外)。

签到题

签到题就在这里 ~

hacklug-2019/1.png

看到按钮被禁用了,下意识就会 F12 去把按钮的 disabled 属性去掉。

hacklug-2019/2.png

甚至可以看到出题人的贴心小提示呢,可能是给 No JavaScript 和 curl 玩家的(所以签到题都用了 Webpack 了为什么还在用 HTML4 时代的 hidden 属性隐藏元素,可能是因为赛博朋克吧

白与夜

这是一个关于白猫,嗯不对,关于黑猫的故事。

直接「Open image in new tab」就可以发现,白猫的图片变成了黑猫,甚至出现了 flag。

可以发现这是一张半透明的图片,在不同的背景下会变成不同的样子。我在这里直接演示一下。

<div style="margin: 0px; background: #ffffff; max-width: 100%">
    <img style="-webkit-user-select: none;margin: auto;background-color: transparent" src="https://cdn.jsdelivr.net/npm/sks@1.1.1/img/hacklug-2019/3.png">
</div>

<div style="margin: 0px; background: #0e0e0e; max-width: 100%">
    <img style="-webkit-user-select: none;margin: auto;background-color: transparent" src="https://cdn.jsdelivr.net/npm/sks@1.1.1/img/hacklug-2019/3.png">
</div>

<div style="margin: 0px; background: #0000ff; max-width: 100%">
    <img style="-webkit-user-select: none;margin: auto;background-color: transparent" src="https://cdn.jsdelivr.net/npm/sks@1.1.1/img/hacklug-2019/3.png">
</div>

Chrome 的图片查看页面其实就是一个拥有暗色背景的网页(代码如下所示),所以这道题其实不离开浏览器就能做:

<html>
  <head>
    <meta name="viewport" content="width=device-width, minimum-scale=0.1">
    <title>Filename (Resolution)</title>
  </head>
  <body style="margin: 0px; background: #0e0e0e;">
    <img style="-webkit-user-select: none;margin: auto;"
       src="/path/to/image">
  </body>
</html>

信息安全 2077

2077 年很快到来了。此时正值祖国 128 周年华诞,中国科学技术大学也因其王牌专业信息安全,走出国门,成为了世界一流大学。作为向信息安全专业输送人才的重要渠道,第 64 届信息安全大赛也正在如火如荼地开展着。
千里之行,始于足下。作为一名渴望进入信息安全专业的学生,你的第一个任务是拿到第 64 届信息安全大赛的签到题的 flag。我们已经为你找到了签到题的入口[1],你只需要把 flag.txt 的内容读出来就可以了。
注:为了照顾到使用黑曜石浏览器的用户,第 64 届信息安全大赛的签到题决定沿袭之前 63 届信息安全大赛的惯例,仍然基于 HTTP 1.x。当然了,使用其他浏览器也是可以顺利完成任务的。

(嘿阔浏览器(黑曜石浏览器)的梗可能真的可以玩到 2077 年,不过「国产红芯浏览器」那时候又会在哪里呢?)

打开题可以看到 Loading... 一会就变成了 Not yet! The competition will start after 21163 days and 50894 seconds.
这是怎么回事呢?Ctri + U 一下看网页源码,发现是一个使用 Fetch 发的 POST 请求、带着嘿阔浏览器的 UA 和 If-Unmodified-Since 请求头。

网页源码备份

有趣,F12 一下去 Network Panel 看看有什么请求是怎么回事。

hacklug-2019/4.png

一个响应码为 412 PRECONDITION FAILED 的发给 flag.txt 的 POST 请求,还可以看到响应头 Last-Modified: Fri, 01 Oct 2077 00:00:00 GMT

在请求上右键,Copy -> Copy as cURL(bash),然后在终端里粘贴、把 If-Unmodified-Since 改成 2077 年以后的日期即可:

curl  'http://202.38.93.241:2077/flag.txt' -X POST -H 'Origin: http://202.38.93.241:2077' -H 'Accep
t-Encoding: gzip, deflate' -H 'If-Unmodified-Since: Tue, 22 Oct 2077 09:54:38 GMT' -H 'User-Agent: M
ozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120
Safari/537.36' -H 'Cache-Control: max-age=0' -H 'Referer: http://202.38.93.241:2077/' --compressed
--insecure

既然题目说了,不要求使用 黑曜石浏览器 发起请求(没有校验 User-Agent),所以这道题也可以不离开浏览器完成。直接在 console 里重发一个 Fetch 请求就行:

fetch('flag.txt', {method: 'POST', headers: {'If-Unmodified-Since': "Tue, 15 Oct 2078 23:41:20 GMT"}}).then((res) => {
    if (res.ok) {
        res.text().then((text) => {
            console.log(text)
        })
    }
})

补充一下,在 Fetch 里指定 User-Agent 本来就不是合法的做法。虽然你可以在 https://mdn.io/fetch 是可以看到 Fetch 中指定 User-Agent 的样例代码,但是实际上你可以在 F12 的 Network Panel 里看到,请求头中 User-Agent 是不会变化的。

宇宙终极问题

天何所杳, 十二焉分?
日月安属, 列星安陈?
浩瀚宇宙的一个寻常星系里, 弥漫六合的暗物质晕中, 远古的诗歌在狄拉克海上无声回荡。
史诗般的超级计算机 Deep Thought , 寒冷星空下的百万亿场效应管, 人类终得以一窥这个宇宙最深层的奥秘。
没错, 就是 42, 对于生命, 对于宇宙, 对于世间万物的答案。

第一小题是个 Meme:请给出一组 x y z,使得 x^3 + y^3 + z^3 = 42。我在 Twitter、Telegram 上看到了很多次。所以这道题本质上还是一个考察如何使用搜索引擎的题,所以这道题拿来做签到题多好

hacklug-2019/5.png

第二小题是给定 n = random_prime(2^256) * random_prime(2^256) ,请给出一组 a b c d i j k l,使得 a^3 + b^3 + c^3 + d^3 = i^2 + j^2 + k^2 + l^2 = n;第三小题是给定 n = randint(2^256) ,请给出一组 p q,使得 p^2 + q^2 = n

后面这两道题其实是一个平方求和和立方求和问题,好好学数学吧。后来看到 Coxxs 大佬写的 Write Up 说他用搜索引擎找到了两个在线求解网站:四平方 四立方果然苏卡卡还是太菜了

网页读取器

今年,刚刚学会网络编程的小 T 花了一点时间,写了一个非常简单的网站:输入一个 URL,返回对应的内容。
不过小 T 想对用户访问的站点进行一些限制,所以他决定自己来解析 URL,阻止不满足要求的请求。这样也顺便解决了 SSRF(Server-Side Request Forgery, 服务器端请求伪造)的问题。
想象很美好,但小 T 真的彻底解决了问题吗?

网页存档

hacklug-2019/6.png

从网页中下载 源代码,可以看到 check_hostname 函数自己实现了一个 URL 检查。简单一看就发现,小 T 将 @ 之前的内容全部视为用户名、将第二个出现的 :/ 之间的全部内容视为了端口。看来自己造轮子就是不靠谱(

构建一个 URL 以拿到 Flag:

http://web1/flag?hen+hen+hen+aaaaaaaaaaa@example.com:1145141919810

其实没有必要这么长的但是苏卡卡就是忍不住

刚好几天前在和 curbeng 重构 Hexo 的 encodeURL()、涉及到对 URL 的处理(hexojs/hexo-util#83hexojs/hexo-util#85 (comment)),所以去读了 NodeJS 的 URL API,在做题中算帮上了不少忙。

苏卡卡写这篇 Write Up 的时候,NodeJS 13 刚好发布;年底时 NodeJS 8 的 LTS 周期就会结束,NodeJS 的 Legacy URL API 将会被正式弃用、并需要迁移到 WHATWG URL API。
WHAT WG URL API 有一个挺烦人的「Feature」就是当 协议为 ftp、gopher、http/ws、https/wss、且没有指定其他端口时,url.port 会默认为空字符串(因为这些协议有默认端口 21、70、80、443)。也许 WHATWG URL API 这个特性未来也会成为某一道题呢。

达拉崩吧大冒险

某一天,C 同学做了一个神奇的梦。在梦中,他来到了蒙达鲁克硫斯伯古比奇巴勒城……

hacklug-2019/7.png

这道题取材自教主 ilem 的「达拉崩吧」,教主的又一首梗曲。

在料理市场这里,买入鲜美香脆可口甘甜现炸童子鸡可提升攻击力。通过解析网页的 JS 代码发现,数据提交直接读的 option.value 属性:

hacklug-2019/8.png

经过尝试,通过 F12 大法修改 value,你甚至可以买入负数只鸡。接下来做法就和去年的「猫咪银行」那道题一样了,设法让买入鸡的数量溢出(-MaxInt64 = -9223372036854775808)使攻击力变成非常小的负数,然后再买入 -1 只鸡让攻击力溢出爆表。接下来就可以直接干掉恶龙啦。

hacklug-2019/9.png

其实这道题还有一个彩蛋,如果在错误的地方修改了错误的 value

hacklug-2019/10.png

果然是「罪恶的一生」(

Happy LUG

在今年信安大赛命题组的内部聊天记录中,出现次数最多的 emoji 是什么?
答案是:「😂」(喜极而泣的表情,Face with Tears of Joy)。这是大家最喜欢使用的 emoji 之一。
或许是因为这个原因,最近几天,命题组某位同学收到了一张神秘的字条。
看起来是一个域名,但里面怎么会有 😂 这个 emoji?而且,虽然浏览器访问不了,但这个域名确实是存在着的。
你能解开其中隐藏着的信息吗?

hacklug-2019/11.png

这道题考察的是 Punycode,将 Unicode 字符转换为 ASCII 字符。什么「中国自主」的中文域名和 Emoji 域名原理都是这个。浏览器地址栏就是最好的转换工具,将 😂.hack.ustclug.org 复制到地址栏、再复制出来就能得到 xn--g28h.hack.ustclug.org

浏览器打不开网址并不意味着这个子域名不存在。让我们 dig 一下看看:

$ dig xn--g28h.hack.ustclug.org
dig: 'xn--g28h.hack.ustclug.org.' is not a legal IDNA2008 name (string contains a disallowed character), use +noidnout

$ dig xn--g28h.hack.ustclug.org +noidnout
; <<>> DiG 9.11.5-P4-5.1+b1-Debian <<>> xn--g28h.hack.ustclug.org +noidnout
;; [redacted]
;; QUESTION SECTION:
;xn--g28h.hack.ustclug.org. IN A
;; AUTHORITY SECTION:
ustclug.org. 120 IN SOA ns-a.ustclug.org. lug.ustc.edu.cn. 2017042791 3600 600 3600 120   ;; Query time: 681 msec
;; [redacted]

$ dig xn--g28h.hack.ustclug.org +noidnout AAAA
; <<>> DiG 9.11.5-P4-5.1+b1-Debian <<>> xn--g28h.hack.ustclug.org +noidnout
;; [redacted]
;; QUESTION SECTION:
;xn--g28h.hack.ustclug.org. IN AAAA
;; AUTHORITY SECTION:
ustclug.org. 120 IN SOA ns-a.ustclug.org. lug.ustc.edu.cn. 2017042791 3600 600 3600 120   ;; Query time: 681 msec
;; [redacted]

原来既没有 A 记录也没有 AAAA 记录,别说浏览器打不开了,curl、nc、nmap 都是没法用的。

那么换一个记录类型呢?我们知道 TUNA 和 USTCLUG 的 Telegram 群加群链接都是藏在某个 TXT 解析记录里的,所以在这里也试一试 TXT 呢?

$ dig xn--g28h.hack.ustclug.org +noidnout TXT
; <<>> DiG 9.11.5-P4-5.1+b1-Debian <<>> xn--g28h.hack.ustclug.org +noidnout TXT
;; [redacted]
;; QUESTION SECTION:
;xn--g28h.hack.ustclug.org. IN TXT
;; ANSWER SECTION:
xn--g28h.hack.ustclug.org. 60 IN TXT "flag{DN5_C4N_H4VE_em0ji_haha}"
;; [redacted]

Bingo!

其实可能很多人不知道,根据 RFC 1035 规定,有一种非常规的记录类型 ANY 可以返回当前 域名/子域名 下所有的记录:

$ dig xn--g28h.hack.ustclug.org +noidnout ANY @[redacted]
; <<>> DiG 9.11.5-P4-5.1+b1-Debian <<>> xn--g28h.hack.ustclug.org +noidnout ANY @[redacted]
;; [redacted]
;; QUESTION SECTION:
;xn--g28h.hack.ustclug.org. IN ANY
;; ANSWER SECTION:
xn--g28h.hack.ustclug.org. 60 IN TXT "flag{DN5_C4N_H4VE_em0ji_haha}"
;; Query time: 4976 msec
;; [redacted]

但是 ANY 这种类型非常危险,因为包含了所有的解析记录、返回的结果可能会非常长,iana.org,非常易于提升 DNS 反射放大攻击的效果,所以在 RFC 8482 中,ANY 终于被弃用。目前主流权威 DNS 和 公共 DNS 如 DNS Flag Day 成员都已经不再响应 ANY 请求。但是国内 ISP 的递归 DNS 并没有及时跟进,所以(

正则验证器

小 F 是一位狂热的正则表达式爱好者。今天,他写了一个在线的正则验证服务:服务器会运行你的正则,返回匹配结果。
小 F 还说,如果有人能卡住服务器(运行时间超过 1 秒),他就会送出自己的 flag。
当然,为了避免太容易拿到 flag,小 F 限制了正则和字符串的长度,具体内容请查看源代码。

这道题一看就是受了今年 Cloudflare 全球大范围 502 故障事件的启发(TL;DR 由于 Cloudflare WAF 工程师编写的一条错误的正则表达式会引发大量回溯、导致 Cloudflare 全球数据中心的 CPU 算力耗尽),详细事故报告可以查看 Cloudflare 的博客原文 或者 我的中文翻译。Cloudflare 那条正则表达式的核心是 .*(?:.*=.*),去除捕获组后可以简化为 .*.*=.*

题目说「限制了正则和字符串的长度」,根据题目提供的 源代码 可以发现限制正则表达式不超过 6 个字符、匹配字符串不超过 24 个字符。

所以这道题就变成了如何在 6 个字符长度的限制内构造一个会回溯的正则表达式。分析简化后的正则表达式 .*.*=.* 可以发现关键在于两个相邻的任意匹配。
使用非捕获组进行分段以后可以构造出下述正则表达式和字符串:

Regex: (s+)*b
String: sssssssssssssssssssssssk

苏卡卡之前在为 Hexo 4.0 优化生成性能时,很重要的一部分就是用正则表达式代替 cheerio 解析 HTML:hexojs/hexo#3680hexojs/hexo#3685hexojs/hexo#3697。那时候恶补了不少正则表达式,这次也派上了一些用场。

不同寻常的 Python 考试

「第一节:听下面 5 段代码,每段代码后有一个小题,请根据题目补全代码,并写在答题卡的相应位置。听完每段代码后,你都有 10 秒钟的时间来回答有关小题和阅读下一小题。每段代码仅读一遍。」
小 Q 突然从梦中惊醒,心想,这又是什么奇怪的梦,一定是因为最近的学习压力太大了。
虽然已经无法回忆起梦里自己为什么要参加这样的考试,但广播里字正腔圆读代码的声音一直在小 Q 耳边萦绕,挥之不去。
「If……空格……a……点……count……左括号……b……右括号……等于等于……」
小 Q 冷静下来,把 20 道 Python 补全题都记了下来。但她发现,梦里的考试,自己竟然连 60 分都做不到。

题目可以看 这里。做这道题时感觉整个人都不好了,从此再也不敢说自己会 Python。

这道题就不一一解析了,苏卡卡只拿到了第一个 flag(果然还是太菜了)。这里推荐大家去阅读 wtfpython,看完后绝对会眼界大开。苏卡卡相信出题人肯定也读的这个(

我想要个家

有一天,C 同学做了一个梦,他竟然搬进了大房子,只是似乎有些地方 C 同学不太满意……
注意:
此题考察的是对于 Linux 基础知识的掌握。尽管可以,但不建议使用逆向工程的方式完成。
在根目录(/)下的文件夹对 Linux 系统的运行十分重要,请不要为了完成此题目删除自己的 /usr, /bin 等文件夹!

下载文件

啥?题目说不建议逆向?好,IDA Pro,启动!
(然后啥也看不懂)(苏卡卡太菜了)

好吧,既然题目都说了,那肯定不能拿自己的系统乱来了。你看在线的 Container、Web IDE、REPL 还蛮多的,可以在上面玩,玩坏了就直接 destroy 掉重建,没问题的

苏卡卡用的是哈佛提供的 CS50 IDE(Powered by Cloud9),开了一个 Blank 的 Ubuntu Container,修改 root 用户的密码、进入 root shell、下载文件、chmod +x、运行文件一气呵成:

hacklug-2019/12.png

一开始让我在根目录建几个文件夹,但接着就要我删除根目录下所有系统目录。这还不容易,sudo rm -rf / --no-preserve-root

正确的姿势是尽量使用 mv 命令,mv 不了的比如 /proc 目录用 mount

# mkdir /0
# mount --move /proc /0

接下来的要求基本不难,除了要注意 /bin 目录被移动掉以后、使用二进制要用新的绝对路径;始终能够获得当前的北京时间的文件可以写个用 while true 搭配 datetee 的脚本解决(苏卡卡直接复制了一份自己 为 KoolClash 写的那个 watchdog,改了改就拿来用了)。

拿到 flag 以后,直接关闭浏览器标签页中断与 Container 的连接,耶!(

hacklug-2019/13.png


像苏卡卡这种菜鸡还能拿 1650 分,Hackergame 的确能算是一个「新手友好的 CTF」(别说了,苏卡卡菜就对了)。最后跟苏卡卡一起大喊:废理兴工~~!

本文作者 : Sukka
本文采用 CC BY-NC-SA 4.0 许可协议。转载和引用时请注意遵守协议、注明出处!
本文链接 : https://blog.skk.moe/post/hackergame-2019-write-up/

喜欢这篇文章?为什么不考虑打赏一下作者呢?

评论加载中 ...