Pwning a Server using Markdown

背景介绍

Hashnode是一个面向开发人员的博客平台,您可以在其中使用自定义域免费托管您的博客,这包含许多功能,其中一项功能是"Bulk Markdown Importer"

当我将我的博客从Jekyll迁移到Hashnode时,我正在寻找一个导入功能,幸运的是Hashnode有一个markdown导入器,允许批量导入markdown帖子,但需要采用某种特定格式,出于某种原因,我在导入帖子时不断出错,我无法弄清楚,因为UI上没有描述性错误,然后我查看了我的Burp中的响应,就在那时我注意到了导致我写这篇博客的Bug。

这受到本地文件包含漏洞(LFI)的影响,该漏洞允许我们从服务器获取内部文件,我的伙伴Adhyayan通过查找Cloudflare背后服务器的实际IP将其升级为 RCE,以下是我们如何升级易受攻击的Markdown解析器中的错误以在服务器上执行代码

漏洞利用

寻找 LFI

Markdown有自己的语法和功能,允许在文件中引用图像,要在博客文章或任何MD文件中包含图像,以下是常用语法:

![image.png](https://image.url/image_file.png)

Hashnode的Bulk Importer接受一个包含所有要发布的Markdown帖子的ZIP文件,这是他们的示例帖子格式的外观:

---title: "Why I use Hashnode"date: "2020-02-20T22:37:25.509Z"slug: "why-i-use-hashnode"image: "Insert Image URL Here"---Lorem ipsum dolor sit amet

需要将此.md文件压缩到存档中才能上传到平台,这是响应在Burp Suite中的样子

 没什么有趣的,这只是一个正常的markdown解析帖子格式,这让我们想知道 Markdown功能允许用户通过指定路径来插入图像的请求处理

![anotherimage.png](/images/blog.jpg)

在Burp Suite中观察时,令人惊讶的是Hashnode触发了一个ENOENT错误,指出它无法找到该文件,如下面的屏幕截图所示

从这里开始只需连接点以从服务器获取内部文件,我们决定给出一个实际文件的位置,而不是一个不存在的路径,就像/etc/passwd希望它能在响应中给我们文件内容一样

这是我们用作最终有效负载的markdown文件:

---title: "Why I use Hashnode"date: "2020-02-20T22:37:25.509Z"slug: "why-i-use-hashnode"image: "Insert Image URL Here"---![notimage.png](../../../../../etc/passwd)

这一次应用程序尝试使用路径中指定的位置来获取图像,而不是直接使用Markdown正文中显示的图像,应用程序遍历目录并为我们获取passwd文件,但它没有将内容显示在响应中,而是将文件上传到Hashnode CDN

该contentMarkdown参数为CDN URL提供了上传内部文件的路径,我们能够直接下载/etc/passwd

由于我们已经从passwd文件中获得了用户的名称和他们的主目录的路径,因此我们考虑将其升级为进一步尝试RCE

创建SSH密钥时它会存储在~/.ssh/id_rsa私有密钥和~/.ssh/id_rsa.pub公共密钥的默认位置,我们相应地修改了我们的有效负载以从服务器获取私钥并且很幸运,它也被上传到CDN

![notimage.png](../../../../../home/username/.ssh/id_rsa)

现在我们进入服务器所需要做的就是找到IP地址,因为它隐藏在Cloudflare 后面

服务器IP和SSH

我们开始寻找历史DNS记录以找到IP地址,但没有成功,这就是Adhyayan进来的地方,之后我们查看了文件/proc/net/tcp,这些/proc接口提供有关当前活动 TCP连接的信息,这是它在我的服务器上的外观:

kernel.org文档很好地解释了该表

https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt

我们感兴趣的列是本地地址,这些地址存储为反向IP地址的十进制表示法的十六进制值,这是我在互联网上找到的一个漂亮的单行代码,可以完成所有工作并以人类可读的格式返回

grep -v "rem_address" /proc/net/tcp | awk  '{x=strtonum("0x"substr($2,index($2,":")-2,2)); for (i=5; i>0; i-=2) x = x"."strtonum("0x"substr($2,i,2))}{print x":"strtonum("0x"substr($2,index($2,":")+1,4))}'

这有效地为我们提供了我们正在寻找的东西-服务器的IP地址以及端口22,它的外观如下:

文末小结

谁会想到 Markdown解析器可以导致服务器上的命令执行呢?当与其他漏洞结合使用时,即使是最小的低严重性问题也可能升级,在这里描述性堆栈跟踪中的一个简单信息泄露错误帮助我们找出了Markdown解析器的行为,这反过来又允许我们从服务器获取内部文件

在代码中实现正确的错误处理和输入验证并在后端记录描述性错误始终是一个好主意,Hashnode团队修复了Markdown解析器中的漏洞,并轮换了他们所有的私钥以修复该错误

相信用户的输入总是一个坏主意

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值