FlawOpen

flawopen.com/AI Security/hermes-agent-native-signin-redirect-parser-confusion

● Pemetaan FlawOpen: CWE-601 · CVSS v4 8.6[1] · Tinggi
Riset Keamanan · FlawOpen

Cacat parsing pengalihan masuk native Hermes Agent

Tenable mengungkap cacat validasi pengalihan berisiko tinggi pada proses masuk native Hermes Agent. Versi sebelum 0.21.6 terdampak. Perbaikan 0.21.6 tersedia untuk Docker/Hermes Cloud dan instalasi CLI/git; versi 0.21.7 yang dirilis pada 11 Oktober juga mencantumkan aplikasi Desktop, Microsoft Store/MSIX, installer, Docker, dan Hermes Cloud. Catatan rilis yang diperiksa tidak menyebut Termux, jadi verifikasi kanal tersebut secara terpisah. Tenable menilainya High (CVSS 4.0 8.6); tidak ada CVE yang ditetapkan. CWE-601 adalah pemetaan editorial untuk dampak pengalihan.[1], [2], [5]

💡 Penjelasan Sederhana (ELI5)

Bayangkan petugas resepsionis memeriksa alamat pada satu peta, menyalin teks asli tanpa perubahan, lalu menyerahkannya kepada kurir yang memakai peta lain. Kurir dapat menuju tempat yang tidak disetujui resepsionis. Hermes memeriksa callback dengan parser Python, tetapi kemudian memberikan teks mentah kepada browser yang dapat menafsirkannya secara berbeda.[1]

Konsep Kunci & Istilah

Native-app callback
Alamat web lokal sementara yang dipakai aplikasi desktop untuk menerima hasil masuk melalui browser.[1], [4]
URL parser differential
Dua parser URL memberi makna berbeda pada masukan yang sama; memvalidasi satu tafsir lalu memakai tafsir lain merusak batas keamanan.[1], [3]
PKCE
Proof Key for Code Exchange mengikat kode otorisasi ke verifier rahasia yang disimpan aplikasi pemulai proses masuk.[1], [4]
Loopback address
Alamat IP yang kembali ke perangkat yang sama, misalnya 127.0.0.1 atau ::1. Perbaikan Hermes hanya menerima literal IP kanonis, bukan host jarak jauh sembarang.[3], [4]

Pemetaan kerangka kerja

  • Pemetaan konseptual FlawOpen ke MITRE CWE; tidak ada vendor atau catatan CVE yang menetapkan ID kelemahan ini untuk demonstrasi riset tersebut. CWE-601

Alur Serangan Langkah demi Langkah

Langkah 1

Rute masuk native publik menerima callback

Endpoint otorisasi menerima URI pengalihan dan PKCE challenge sebelum pengguna diautentikasi.[1]

Langkah 2

Server dan browser menafsirkan callback secara berbeda

Validator rentan memeriksa hostname hasil parsing Python, tetapi menyimpan string asli. Sintaks URL ambigu dapat membuat browser menuju authority lain.[1], [3]

Langkah 3

Kode otorisasi dapat terekspos setelah masuk selesai

Setelah korban menyelesaikan proses masuk normal, browser dapat mengirim kode ke authority yang ditafsirkannya. Penyerang yang memilih PKCE challenge terkait dapat mencoba menukarkan kode. Korban harus masuk; ini bukan pengambilalihan akun tanpa interaksi.[1]

Langkah 4

Kanonisasi URI dan perbarui build yang tersedia

Perbaikan menolak sintaks ambigu dan authority nonkanonis, mengembalikan URI kanonis, lalu menyimpan nilai tersebut. Perbarui ke 0.21.7 atau lebih baru melalui kanal yang didukung; verifikasi Termux secara terpisah karena catatan rilis 0.21.7 yang diperiksa tidak menyebutnya.[2], [5], [3]

Kode Sumber: Rentan vs Aman

Ini model ilustratif batas keamanan, bukan seluruh source Hermes Agent atau exploit. Contoh rentan merangkum pola memeriksa host hasil parsing lalu menggunakan masukan mentah. Contoh aman menunjukkan properti perbaikan yang digabungkan: menolak masukan ambigu, hanya mengizinkan authority loopback kanonis, mengembalikan URI kanonis, lalu menyimpan/menggunakan nilai itu. Implementasi dan pengujian sebenarnya ada di PR tertaut.[1], [3]

IMPLEMENTASI RENTAN
from urllib.parse import urlparse

def validate_callback(raw):
    parsed = urlparse(raw)
    # Alur asli memeriksa host yang telah diurai, lalu tetap menyimpan URL mentah.
    if parsed.scheme == "http" and parsed.hostname in {"127.0.0.1", "::1"}:
        return raw
    raise ValueError("callback must be loopback")
PERBAIKAN AMAN & KUAT
from urllib.parse import urlparse, urlunparse

LOOPBACK_HOSTS = {"127.0.0.1": "127.0.0.1", "::1": "[::1]"}

def validate_callback(raw):
    if not raw.isascii() or "\\" in raw or any(ord(c) <= 0x20 or ord(c) == 0x7f for c in raw):
        raise ValueError("callback must use canonical loopback syntax")
    try:
        parsed = urlparse(raw)
        host, port = parsed.hostname, parsed.port
    except ValueError as exc:
        raise ValueError("invalid callback") from exc
    if parsed.scheme != "http" or "#" in raw or parsed.username is not None or parsed.password is not None:
        raise ValueError("callback must be a plain loopback URL")
    authority_host = LOOPBACK_HOSTS.get(host)
    if authority_host is None:
        raise ValueError("callback host must be a loopback IP literal")
    authority = authority_host + (f":{port}" if port is not None else "")
    if parsed.netloc != authority:
        raise ValueError("callback authority is not canonical")
    return urlunparse(parsed._replace(path=parsed.path or "/"))

Daftar Periksa Penguatan Sistem Rekayasa

Sumber

← AI Security Directory →