Rand函数引发的安全问题 —— OSSN任意文件读取漏洞(CVE-2020-10560)
2020-04-29 10:24:00 Author: xz.aliyun.com(查看原文) 阅读量:383 收藏

前言

Open Source Social Network(OSSN),是一款用PHP编写的社交网络软件。OSSN允许用户创建一个社交网站,帮助拥有相似专业或个人兴趣的人建立社交关系。该软件拥有约50万下载量。

OSSN官网地址:

https://www.opensource-socialnetwork.org/

漏洞简介

Open Source Social Network(OSSN)5.3之前版本中存在一处任意文件读取漏洞(CVE-2020-10560)。漏洞因OSSN生成的Site_Key强度过低从而可以遭受被暴力破解而产生,成功破解Site_Key的攻击者可以利用Site_Key构造出任意文件读取链接,通过components\OssnComments\ossn_com.php文件提供的文件预览接口,读取文件。

漏洞分析

Open Source Social Network应用可以从如下官网链接下载:

https://www.opensource-socialnetwork.org/download

应用首页如下图

OSSN中提供Comment功能,访问者可以对帖子进行评论,见下图:

评论帖子时,用户可以上传图片以及表情,如下图红框处:

当选择本地图片并上传后,将在评论中生成一个预览,见下图:

注意,这时还没有点击发布评论,上图图片只是上传成功后的一个预览图片。该临时图像文件存储于tmp目录并在前端呈现了预览。

我们来看下这个临时图片文件是如何获取并在页面中展示的。查看一下图片链接,如下图:

链接如下:

http://192.167.30.119/comment/staticimage?image=UiszT0RJYStoQll2N2g5cHhmQW9PRHlCNVgrSWFKVzFQRHE4eTJqSWthVUVjUFBIb3pxME1FNUJFdk5ER2pONXI4V2pyeXJSMm9VPQ==

我们可以猜测出image参数对应的字符串应该是文件地址的加密形式,只有构造出正确的base64字符串,攻击者就可以读取任意文件。

最重要的是,经过测试发现,访问这个链接并不需要用户登陆。任何人都可以通过这个链接直接访问我们上传的这个图片文件。

接下来分析下后台代码,看看这个base64字符串是如何还原出文件路径以及如何被构造出来的

上文链接对应的后台代码位于 \components\OssnComments\ossn_com.php

在ossn_com.php中case 'staticimage'分支里,程序将请求中image参数值取出,并进行base64_decode解码。见下图:

随后,对解码后的值再次base64_decode解码,然后利用ossn_string_decrypt方法解码并获取文件地址。见下图:

接着,通过ossn_validate_filepath方法对文件路径进行校验。见下图红框:

ossn_validate_filepath方法如下图所示,可见该方法对目录遍历进行了过滤

即使过滤了../ 我们仍然可以通过绝对路径来进行文件读取,例如直接读取/etc/passwd

最后,程序利用file_get_contents方法对文件内容进行读取,并使用echo进行打印。见下图红框:

通过阅读代码也可以验证之前的测试结果:该接口并未进行身份校验,未登录的用户依然可以通过该接口访问文件。

问题又回到了如何构造加密字符串上。我们首先来看一下程序是如何解码的,位于libraries\ossn.lib.system.php文件中

通过上图的代码看,在解码过程中,需要用到site_key值。

经过分析后发现,程序通过ossn_site_settings方法在数据库中读取site_key值,我们先来看一下存储于ossn_site_settings表中site_key值是什么,见下图:

site_key值为c1a725ed,可见是一个8位数

这样看来,只要破解出这个8位数的site_key,即可构造出指向任意文件路径的链接。

我们接着分析这个site_key是如何生成的,生成代码位于libraries\ossn.lib.upgrade.php文件中,见下图:

通过分析上图加密过程不难发现,该8位随机数是通过如下方式产生的:

  1. 以字符串“ ossn”开头。

  2. 通过rand方法生成一个随机数并拼接到“ ossn”字符串后。

  3. 计算此字符串的md5值。

  4. 将字符3-11取出作为site_key值。

本次漏洞就出在计算site_key值的第二步,也就是通过rand产生随机数这一步。

关于rand方法,可以参考php官网

在官网介绍页面中明确的给出了警告,见上图底部

警告

此函数不会生成加密安全值,并且不应将其用于加密目的。如果需要密码安全的值,请考虑改用random_int(),random_bytes()或openssl_random_pseudo_bytes()。

rand方法之所以不安全,其中一个比较重要的原因是它能产生的随机数范围有限:

rand方法在没有提供可选参数 minmax时,返回 0 到 RAND_MAX之间的伪随机整数.

在笔者的windows主机上,RAND_MAX值仅为32767

而在笔者的Linux环境中,这个值为2147483647

据资料显示,rand最大可能值为2,147,483,647

因此,只需要生成最多20亿个rand值,将其依次带入ossn_generate_site_secret计算出对应的site_key值,这些site_key值即为所有的site_key值可能值。如果运气好,目标主机是一台windows主机,这样的操作仅仅重复3万多次即可,因为windows主机下rand产生的最大值仅为32767。

在分析了弱密钥是如何生成之后,我们需要一种方法来识别生成的密钥是否有效。在临时图片文件被上传到服务器时,会被存储于ossn_data/tmp/photos文件夹中,见下图:

因此上文中的加密数据成功解码后,其字符串中一定会包含tmp/photos字符串。我们这里用我们的密钥解一下上文中的编码,看一下这个推论是否正确,结果如下图:

可见成功解开的文件路径中的确存在tmp/photos字符串

因此,暴力破解的思路很明朗了

1、攻击者在评论里上传一个图片,不点击发送,查看此时图片临时预览链接,获取链接中image参数值。例如:http://192.167.30.119/comment/staticimage?image=UiszT0RJYStoQll2N2g5cHhmQW9PRHlCNVgrSWFKVzFQRHE4eTJqSWthVUVjUFBIb3pxME1FNUJFdk5ER2pONXI4V2pyeXJSMm9VPQ==中的UiszT0RJYStoQll2N2g5cHhmQW9PRHlCNVgrSWFKVzFQRHE4eTJqSWthVUVjUFBIb3pxME1FNUJFdk5ER2pONXI4V2pyeXJSMm9VPQ==>

2、将数字0-2147483647依次带入ossn_generate_site_secret中计算出对应的site_key

3、依次将site_key与image值带入ossn_string_decrypt中,获取解密后的明文

4、如果明文中含有tmp/photos字符串,解密成功,此时的site_key即为正确的site_key值

漏洞利用

在获取site_key值后,可以通过ossn_string_encrypt方法,对想要读取的文件进行加密,通过http://192.167.30.119/comment/staticimage?image=接口进行读取即可

上文所涉及的工具如下:

site_key计算工具

https://github.com/LucidUnicorn/CVE-2020-10560-Key-Recovery

加密解密工具

https://github.com/kevthehermit/CVE-2020-10560


文章来源: http://xz.aliyun.com/t/7654
如有侵权请联系:admin#unsafe.sh