HAWebSSO.nl未受保护API端点泄露1.5万医生敏感数据

荷兰医疗单点登录系统HAWebSSO.nl因未受保护的API端点泄露超过1.5万名医生的用户名和密码哈希值。安全研究员通过分析JavaScript文件发现IDOR漏洞,无需认证即可访问所有用户数据。

未受保护的API端点导致HAWebSSO.nl泄露1.5万医生用户名和密码哈希

背景

我白天是全科医生,晚上是安全研究员。在道德黑客领域,我的目标之一是尽可能多地学习,以便能够审计医疗保健产品、应用程序、网站或基础设施的安全性。

今天我们将审视荷兰全科医生协会(NHG)和荷兰全科医生联盟(LHV)的安全性。这些都是荷兰全科医生的专业组织。NHG为全科医生制定标准并提供教育和培训,而LHV代表全科医生的利益,致力于提高初级保健的质量和可及性。

侦察,从何处开始?

NHG和LHV都有许多在线应用程序,允许医生登录和交互。例如HAweb.nl(一个医生在线社区)和richtlijnen.nhg.org(允许医生在专业指南中添加个人笔记)。

今天我只是从点击LHV.nl主网站开始,寻找不同的子域名以及登录流程如何工作。

大多数LHV和NHG应用程序共享的是使用hawwebsso.nl域的单点登录(SSO)身份验证方法。每当你尝试访问需要授权的应用程序时,它就会弹出。

SSO系统分析

SSO是一种身份验证方法,允许用户使用一组登录凭据访问多个应用程序和服务。这消除了用户记住和管理多组登录信息的需要,可以大大改善用户体验和生产力。

好消息是,如果我们入侵SSO,我们就获得了一切访问权限。坏消息是,大多数使用的SSO系统都是经过严格测试的软件。

快速查看SSO系统可能范围的一个好技巧是检查OpenID端点,尝试访问:https://hawebsso.nl/.well-known/openid-configuration

SSO系统保存有趣的用户数据(在OpenID中称为声明)。此外,它支持许多不同的范围。例如,它有范围"HAWeb_SSO_Scope_WaarneemApp",可以访问WaarneemApp(医生之间交换班次的工具)。

我快速检查的另一件事是,我是否得到关于SSO背后运行系统的任何提示。我查看这个HTTP请求的响应头:

SSO运行在Microsoft IIS/10.0上。没有关于此处使用软件的提示。

源代码分析

登录页面引用了一个名为admin.js的JavaScript文件。

下一步是查看登录页面的源代码。是否有关于用于SSO的系统的任何线索,或者我们看到其他奇怪的东西?

Admin.js

我们可以看到登录页面加载不同的JavaScript文件,有些是为了向登录表单添加功能。没有一个文件泄露关于实际使用系统的提示,可能这个SSO前端是自定义构建的;它包装在ASP驱动的SSO后端系统周围。

然而,一个加载的文件引起了我的注意:admin.js。每当我们看到"admin"这个词时,我们都渴望了解更多。

admin.js文件中的部分源代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
$scope.GetAdmin = function () {
    return $http({
        method: 'GET',
        url: '/api/v1/user/admin',
    }).then(function (response) {
        $scope.adminUser = response.data;
        if ($scope.adminUser.roles != null && $scope.adminUser.roles.length > 0) {
            var roles = $scope.adminUser.roles.split(",");
            $scope.permissions = {
                admin_level_1: roles.indexOf("Admin_level_1") > -1,
                admin_level_2: roles.indexOf("Admin_level_2") > -1,
                allow_edit: roles.indexOf("Admin_allow_edit") > -1,
                allow_merge: roles.indexOf("Admin_allow_merge") > -1,
                allow_activate: roles.indexOf("Admin_allow_activate") > -1,
                allow_deactivate: roles.indexOf("Admin_allow_deactivate") > -1,
                allow_make_admin: roles.indexOf("Admin_level_1") > -1,
                allow_deactivate_admin: roles.indexOf("Admin_level_1") > -1,
                show_field_id: roles.indexOf("Admin_show_field_id") > -1,
                show_field_firstname: roles.indexOf("Admin_show_field_firstname") > -1,
                show_field_insertion: roles.indexOf("Admin_show_field_insertion") > -1,
                show_field_lastname: roles.indexOf("Admin_show_field_lastname") > -1,
                show_field_lhv_id: roles.indexOf("Admin_show_field_lhv_id") > -1,
                show_field_nhg_id: roles.indexOf("Admin_show_field_nhg_id") > -1,
                show_field_emailaddress: roles.indexOf("Admin_show_field_emailaddress") > -1,
                show_field_cat_override: roles.indexOf("Admin_show_field_cat_override") > -1,
                congres_admin: roles.indexOf("Admin_congres") > -1
            };
        }
    }).catch(function (response) {
        $scope.addMessage(response.data, response.status, response.status == 200 ? "success" : "error");
    });
}

$scope.GetAdmin();

所以有一个管理员可以访问的端点,返回用户的不同角色。在这种情况下是/admin用户。在主登录屏幕上共享此代码很奇怪。

作为拥有SSO登录的全科医生之一,我可以登录并访问该端点。

糟糕。该端点返回当前登录用户的所有数据。包括密码哈希。

该端点没有正确检查谁请求它,并返回我们所有的用户信息。包括电子邮件、全名、密码哈希和一些会员详细信息。

如果我们访问相同的端点并将/admin替换为ID会怎样?如我们所见,我有ID 2027。让我们看看如果我们尝试访问ID 15000会发生什么:https://hawebsso.nl/api/v1/user/15000

用户ID 15000存在,所有账户详细信息都与我们共享,包括密码。

我们现在已经展示了此端点的影响,它泄露了注册在SSO服务hawwebsso.nl中的所有用户的详细信息。

在技术术语中,我们称这种错误为IDOR;不安全的直接对象引用。

漏洞利用

端点/api/v1/user/1是一个通用端点,可以很容易被黑客发现。可以使用单词列表在这样的资产上暴力破解端点,一个很好的例子是Assetnote.io他们共享的单词列表。单词列表https://wordlists-cdn.assetnote.io/data/automated/httparchive_apiroutes_2020_11_20.txt包含这个特定的端点与一个会返回命中的ID。

黑客可以采取的另一种方法是扫描所有使用的JavaScript文件以查找端点。例如LinkFinder可以为你做这件事。

无需身份验证

我们现在已经展示了一个特定的端点泄露了用户详细信息,但是它需要身份验证吗?可以在未登录的情况下访问此端点吗?

在浏览器的隐身模式下打开相同的端点。没有设置cookie,我没有登录。所有用户详细信息都被返回。

答案是肯定的。此端点不需要任何登录。在技术术语中,我们现在有另一个错误,关键功能缺少身份验证。在浏览器中打开端点而不登录会返回我们所有的用户详细信息。

密码哈希,如何破解?

现在我们有了密码的哈希。使用密码哈希减少了数据泄露的影响,因为必须首先破解哈希才能检索密码。过去,像MD5这样的密码哈希很容易通过使用彩虹表之类的东西被破解;所有可能哈希的列表,预先计算以破解哈希。

如今,这通过使用更安全的哈希算法和包括盐来解决。

通过将我的密码更改为我拥有的相同密码,我可以确认生成了新的唯一哈希。这给了我们一个线索,彩虹表可能在这里不起作用(例如,如果它们为每个用户包含唯一的盐)。

经过一段时间的黑客攻击,你可以通过查看它来识别大多数哈希类型,就像皮肤病一样。

然而,在这里我现在不知道使用了哪种哈希算法。在联系到我的一位道德黑客同行后,我被告知这看起来像一个base64编码的字符串,解码后正好是255字节长。

从我们的侦察中知道ASP在服务器上运行,我们可能会从Microsoft提供的文档中获得更多线索:https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity

后来我发现了这篇(5年前的)关于不同哈希算法的博客https://andrewlock.net/exploring-the-asp-net-core-identity-passwordhasher/并发现了以下有趣的部分:

ASP.NET Core Identity版本3:PBKDF2 with HMAC-SHA256,128位盐,256位子密钥,10000次迭代

这给了我一个提示,ASP开箱即用地使用了适当的哈希算法,一个我目前无法轻易破解的算法。关于PBKDF2和未来的一些有趣讨论可以在这里阅读。

目前我放弃了破解这些哈希。

结论

我们发现了一个数据泄露,泄露了荷兰全科医生使用的所有电子邮件和密码哈希。此端点未受保护,不需要任何授权。由于它是一个通用路径,可以很容易被黑客猜到。此外,对此端点的引用隐藏在了登录页面包含的admin.js文件中,像LinkFinder这样的工具会通知任何扫描黑客此特定端点。

讨论

LHV在其网站上发布了负责任的披露政策,允许我进行这项研究:https://www.lhv.nl/cvd-coordinated-vulnerability-disclosure/ 这是一个如何支持道德黑客的好例子。

此外,他们试图通过制定如何处理数据泄露的指南来提高初级保健的整体安全性。最近他们在全科医生阅读的一本杂志中发表了关于此的内容:https://www.syntheshis.nu/wp-content/uploads/2022/12/Synth-2022-03-Totaal.pdf(荷兰语,第22页)。相关成员能够查看此指南:https://www.lhv.nl/product/praktijkwijzer-informatiebeveiliging/

然而,如果每个人都能访问此文档,那将是很棒的,我们分享的越多,我们就越能对抗风险。

另一件重要的事情是在每个在线资产上添加负责任的披露政策。例如hawwebsso.nl不包括任何引用。此外,NHG.org网站(使用SSO)没有共享任何在线负责任的披露政策。一个好的做法是尽快发布此政策,并让在NHG工作的每个人都适应这种良好实践;参见https://www.ncsc.nl/onderwerpen/cvd-beleid/cvd-beleid-opstellen以了解作为组织如何继续。

防止此类数据泄露的一个好保护是双因素身份验证(2FA),HAwebsso.nl支持此功能,但默认情况下未激活。我的建议是激活此功能,以便在密码泄露时使攻击者更难访问你的账户。此外,重要的是不要重复使用密码,如本报告所示,当泄露(和破解)时,它可能在其他服务上被滥用;凭据填充。

时间线

  • 2022年12月4日 — 发现错误,通过电子邮件向LHV隐私官报告
  • 2022年12月5日 — 隐私官回复确认错误
  • 2022年12月6日 — 隐私官更新
  • 2022年12月8日 — 隐私官更新:错误存在3年(自2019年底以来),过去2年的日志中没有滥用迹象
  • 2022年12月11日 — 写了这篇博客
  • 2022年12月12日 — 通过电子邮件将博客草稿发送给隐私官
  • 2022年12月12日 — LHV和NHG通过电子邮件通知所有成员数据泄露;要求成员重置密码
  • 2022年12月13日 — LHV建议一些小的更改
  • 2022年12月14日 — 发布博客
  • 2022年12月15日 — 读者告知我Admin.js文件在2017年存在;https://web.archive.org/web/20170905141113/https://hawebsso.nl/Js/admin/admin.js 这是否意味着错误存在了+5年?向LHV询问了关于此的一些见解,得到回复他们将与开发人员再次检查。
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计