跳至内容

Jixun's Blog 填坑还是开坑,这是个好问题。

二进制补丁修正 CVE-2024-6387 (EL9)

今日(2024-07-01)公开了一个新的 OpenSSH 服务端的漏洞(虽然是以前修过的一个漏洞重新漏了…),在足够多的尝试下可以利用该条件竞争漏洞得到 root 权限。

RHEL 系列发行版中,只有 EL9 能被利用。

缓解方案是 (1) 将 LoginGraceTime 设置为 0,但可能会导致服务器拒绝访问;或 (2) 等待发行版发表更新。某些情况下它们更新会比较慢,就需要手动根据技术信息进行补丁了。

目前 AlmaLinux 官方已经提供更新的包,直接更新即可;Rocky Linux 需要加入 Security SIG 仓库才有修正补丁。

二进制补丁

根据公开的信息,可以得知将 sshsigdie 内的 sshlogv 调用删除即可:

Because this fix is part of a large commit (81c1099), on top of an even larger defense-in-depth commit (03e3de4, “Start the process of splitting sshd into separate binaries”), it might prove difficult to backport. In that case, the signal handler race condition itself can be fixed by removing or commenting out the async-signal-unsafe code from the sshsigdie() function; …

因此修改目标也是很简单,将这个 CALL 干掉就行。

如果对这个有兴趣,使用 Ghidra 打开 sshd 二进制文件,并找到 sshsigdie 方法即可快速定位修改点。

利用 Ghidra 快速找到修改点

知道对应的字节码后就可以想办法定位文件偏移了(Hint: 十六进制搜索)。

注意:二进制补丁脚本需要 Python3 支援。

※ 因为 Alma 发行版已经提供了更新包,不推荐使用下方的补丁;留在此处做归档、学习用途。

  1. 将下述代码保存为 patch.py
#!/usr/bin/python3

from hashlib import sha256
import sys
import os

print('''
openssh-server-8.7p1-38.el9 bin-patch for Alma/Rocky EL9 (x86-64 & aarch64)

Usage:

  {} </path/to/sshd>

by Jixun <https://jixun.uk/>

'''.format(sys.argv[0]))

patches = [
    dict(
        name='AlmaLinux: openssh-server-8.7p1-38.el9.x86_64',
        before='2526374c30da03dea655c0c5835882a7953d7179f3acf598a7de516a70e6b2d1',
        after='d30cdcdd04ae5f60d295bdc07b6f8e1ce6e21321f48df4cd62c8a3b45883325b',
        offset=0x81EF6,
        payload=b'\x90\x90\x90\x90\x90',
    ),
    dict(
        name='AlmaLinux: openssh-server-8.7p1-38.el9.aarch64',
        before='09130656a2dd53e19fdeb28b39aaef489191f7ae4c8f3e1b90a7a60f02bf143d',
        after='8de58238fbef8cd5f879476a3690f28a8f7d41bb2f26cb89d6ddccc972ffcf79',
        offset=0x7AD20,
        payload=b'\x1F\x20\x03\xD5'
    ),
    dict(
        name='RockyLinux: openssh-server-8.7p1-38.el9.x86_64',
        before='6bfc9552d9f976e5cbe01256ba43737cfdc6c9109ebb93d3ee4942a3669408c0',
        after='1bcb71692078d7c95488e2bad3c1b0b0f525c178f033d1c875dc872ad554aef8',
        offset=0x81EF6,
        payload=b'\x90\x90\x90\x90\x90',
    ),
    dict(
        name='RockyLinux: openssh-server-8.7p1-38.el9.aarch64',
        before='e869b20162cead2be4d83f1735f9ed119cf9c5e79e0c3e62e62c8200dca19b39',
        after='caebae2953d438c1c9c7c631c1baa4006ef4d7efaf2f0341d8b4c5cf73964f1f',
        offset=0x7AD20,
        payload=b'\x1F\x20\x03\xD5'
    ),
]

file = sys.argv[1]
with open(file, 'rb') as f:
    sshd_bin = f.read()
sshd_hash = sha256(sshd_bin).hexdigest()

for patch in patches:
    print('[*] Checking {}...'.format(patch['name']))
    if sshd_hash == patch['after']:
        print('    Already patched!')
        continue
    if sshd_hash != patch['before']:
        print('    No match')
        continue

    print("    validating patch...")
    offset = patch['offset']
    payload = patch['payload']
    payload_len = len(payload)
    patched_bin = bytearray(sshd_bin)
    patched_bin[offset:offset+payload_len] = payload
    patched_hash = sha256(patched_bin).hexdigest()
    if patched_hash != patch['after']:
        print('FATAL: hash does not match (got {}, expected {})'.format(
            patched_hash, patch['after']))
        sys.exit(1)

    print("    backup...")
    os.replace(file, file + '.bak')

    print("    writing...")
    with open(file, 'wb', opener=lambda path, flags: os.open(path, flags, mode=0o755)) as f:
        f.write(patched_bin)

    print("    ok, remember to restart sshd service!")
  1. 执行补丁 sudo python3 patch.py /usr/sbin/sshd
  2. 重启 SSHD 服务: sudo systemctl restart sshd

适配 RPM:

直接更新

推荐直接更新:

sudo dnf makecache
sudo dnf update

# 检查更新后的版本,应为 openssh-server-8.7p1-38.el9.alma.2.<架构>
rpm -qa openssh-server

碎碎念

Alma 的安全补丁响应速度相比其它发行版确实是慢了些…

不过能当天解决已经不错了,RedHat 的安全通告到现在都还就一个缓解步骤(Mitigation)

知识共享许可协议 本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。

评论区