CVE-2026-73673: Netis NC63 Unauthenticated Firmware Update with Missing Cryptographic Firmware Authentication
On this page
- Netis NC63 | CVE-2026-73673 | Unauthenticated Firmware Update with Missing Cryptographic Firmware Authentication
- Zafiyet: Unauthenticated Firmware Update -> Missing Cryptographic Firmware Authentication
- CVE: CVE-2026-73673
- Araştırmacı: Özcan Ersan (@ozcanpng)
- Giriş
- Affected Target
- Kısa Özet
- Root Cause 1: Boa .cgi Requests Are Allowed
- Root Cause 2: netis.cgi Trusts the Boundary
- Firmware Update Path
- Non-Destructive Runtime Validation
- Privilege Context
- Impact
- Classification
- Disclosure Note
- References
- Final Thoughts
Netis NC63 | CVE-2026-73673 | Unauthenticated Firmware Update with Missing Cryptographic Firmware Authentication
Zafiyet: Unauthenticated Firmware Update -> Missing Cryptographic Firmware Authentication
CVE: CVE-2026-73673
Araştırmacı: Özcan Ersan (@ozcanpng)
Giriş
Bu yazıda Netis NC63 router firmware’i V3.0.0.3327 üzerinde tespit edilen CVE-2026-73673 bulgusunu, yani unauthenticated firmware update with missing cryptographic firmware authentication problemini anlatıyorum.
Firmware, Boa ve netis.cgi üzerinden /cgi-bin/upload_fw.cgi endpoint’ini expose ediyor. Bu endpoint geçerli bir admin session olmadan firmware update path’ine ulaşabiliyor. Firmware container validation ise cryptographic signature yerine forge edilebilir bir checksum ve statik product string’lerine dayanıyor.
Bu çalışmadaki testler orijinal vendor firmware binary’leri ile izole bir MIPS32 little-endian runtime içinde yapıldı. Fiziksel router flash’lanmadı, MTD write yapılmadı ve kullanılan proof-of-concept dosyası özellikle non-bootable olacak şekilde hazırlandı.
Affected Target
| Alan | Değer |
|---|---|
| Vendor | Netis Systems Co., Ltd. |
| Ürün | Netis NC63 Wireless AC1200 Router |
| Firmware | NC63_V3.0.0.3327 |
| Mimari | MIPS32 little-endian |
| Web server | Boa/0.94.14rc21 |
| CGI binary | /bin/netis.cgi |
| Firmware updater | /bin/fwd |
| Endpoint | POST /cgi-bin/upload_fw.cgi |
Test edilen image, vendor’ın NC63 download sayfasındaki kayıt ile eşleşiyor:
- Firmware name:
netis_NC63_V3.0.0.3327 - Published date:
01-02-2024 - Listed size:
7.02MB - Vendor sayfası: Netis NC63 downloads

Kısa Özet
Vulnerability chain şu şekilde:
Unauthenticated HTTP client
|
| POST /cgi-bin/upload_fw.cgi
| multipart/form-data field: update
v
Boa
|
| broad ".cgi" authorization branch
v
/bin/netis.cgi
|
| /tmp/boa_auth is read but not enforced before dispatch
v
FUN_004144dc
|
| cr6c header, checksum and NC63/NETISVC product tag checks
v
RunSystemCmd("fwd <shmid> <size> ...")
v
/bin/fwd
|
v
open("/dev/mtdblock0", O_RDWR)
Buradaki kritik problem tek bir küçük bug değil; authentication boundary’nin kırılması:
- Boa, authentication result’ı
/tmp/boa_authiçine yazıyor. - Boa daha sonra içinde
.cgigeçen tüm path’leri authorized kabul ediyor. netis.cgi,/tmp/boa_authdeğerini okuyor ama handler dispatch öncesinde authorization gate olarak kullanmıyor.- Firmware update handler,
/bin/fwdçalıştırıyor. - Update formatında cryptographic firmware authentication bulunmuyor.
Root Cause 1: Boa .cgi Requests Are Allowed
Authentication state önce gönderilen cookie üzerinden hesaplanıyor. CGI request’lerinde Boa bu state’i /tmp/boa_auth içine yazıyor.
Fakat daha sonraki authorization branch, path içinde .cgi geçiyorsa request’i authorized kabul ediyor. Yani cookie check başarısız olsa bile CGI request çalıştırılabiliyor.
Decompile edilmiş mantık şu şekilde özetlenebilir:
auth = 0;
if (cookie_matches_expected_value)
auth = 1;
if (strstr(request_path, ".cgi") != NULL)
system("echo <auth> >/tmp/boa_auth");
if (is_public_static_resource(request_path) ||
strstr(request_path, "config.dat") != NULL ||
strstr(request_path, ".cgi") != NULL) {
auth = 1;
}
if (auth == 0)
redirect_to_login();

Same Boa authorization routine için ek Ghidra evidence:

Bu karar CGI execution öncesinde veriliyor. Dolayısıyla konu sadece frontend’de menünün gizlenmesi değil, gerçek authorization flow’unun bozulması.
Root Cause 2: netis.cgi Trusts the Boundary
netis.cgi içinde authentication state, FUN_00404c70() ile /tmp/boa_auth dosyasından okunup global variable’a atanıyor.
Önemli nokta şu: dispatcher bu değeri kontrol edip request’i reject etmiyor. CGI handler resolve edilip doğrudan çağrılıyor.
apmib_init();
parse_parameters(¶ms, argv[1]);
DAT_00439e30 = FUN_00404c70();
if (strstr(cgi_name, ".cgi") != NULL)
FUN_00405244(cgi_name, ¶ms, output_path);

İlgili Ghidra ekranları /tmp/boa_auth reader’ı, netis.cgi main flow’u, CGI dispatcher’ı ve handler resolver’ı gösteriyor:




Upload endpoint’i privileged CGI listesinde bulunuyor ve upload handler’a dispatch ediliyor.
Firmware Update Path
upload_fw.cgi handler’ı FUN_004144dc fonksiyonuna ulaşıyor. Handler, multipart upload data’sını shared memory içine alıyor ve sonunda /bin/fwd binary’sini çalıştırıyor.
/cgi-bin/upload_fw.cgi
-> FUN_004144dc
-> isUpgrade("upload_fw")
-> RunSystemCmd("fwd %d %d > /dev/null 2>&1 &", shmid, size)
-> /bin/fwd

FUN_004144dc, shared-memory upload identifier’larını parse ediyor, statik NC63/NETISVC product marker’ını hazırlıyor, uploaded buffer’ı attach ediyor ve ardından validation path’e giriyor:

Validation branch upload’ı durdurmadığında final handler branch FUN_004028e0() üzerinden firmware daemon’ı çalıştırıyor:

Normal firmware container path’i cr6c header’ını, additive checksum’u ve statik NC63/NETISVC product suffix’ini kontrol ediyor. Update image’ını koruyan digital signature check, trusted certificate, signed manifest veya public-key verification routine tespit etmedim.
Bu ayrım önemli: checksum accidental corruption yakalayabilir, fakat firmware’in vendor tarafından üretildiğini kanıtlamaz.
Non-Destructive Runtime Validation
Request, orijinal Boa, netis.cgi ve fwd binary’leriyle izole runtime içinde tekrarlandı. Test request’inde Cookie veya Authorization header’ı yoktu.
Minimal request formatı:
POST /cgi-bin/upload_fw.cgi HTTP/1.0
Host: 127.0.0.1:28081
Content-Type: multipart/form-data; boundary=BOUNDARY
Content-Length: ...
--BOUNDARY
Content-Disposition: form-data; name="update"; filename="probe.bin"
Content-Type: application/octet-stream
<harmless cr6c validation container>
--BOUNDARY--
Runtime response:
HTTP/1.0 200 OK
Set-Cookie: path=/ ;Max-Age=0
["SUCCESS"]

Harmless probe, orijinal updater’a ulaştı ve firmware validation boundary’yi geçti. İzole runtime içinde MTD device expose edilmediği için execution şu noktada durdu:
open("/dev/mtdblock0", O_RDWR) = -1 ENOENT


Bu bilinçli bir safety boundary idi: validation ve updater reachability doğrulandı, fakat test ortamında flash write mümkün değildi.
Privilege Context
Orijinal Boa config dosyasında web server root olarak çalışıyor:
User root
Group root

Fiziksel cihaz üzerinde bu privilege context, firmware updater path’inin MTD block device’lara erişmesi için yeterli.
Impact
Management interface’e erişebilen unauthenticated attacker, structurally valid fakat unsigned bir firmware image gönderebilir.
Olası etkiler:
- persistent router compromise
- trusted firmware’in attacker-controlled firmware ile değiştirilmesi
- traffic interception veya modification
- credential theft
- botnet enrollment
- cihazın brick olması
Realistic default exposure genellikle router management interface’e adjacent-network access’tir. Remote management aktifse veya interface internete açılmışsa attack surface network-reachable hale gelebilir.
Classification
Suggested primary weaknesses:
- CWE-306: Missing Authentication for Critical Function
- CWE-494: Download of Code Without Integrity Check
CWE-306, firmware-update path’ini koruması gereken authentication boundary’nin eksikliğini kapsar. CWE-494 ise updater’a verilen firmware için yeterli cryptographic firmware authentication bulunmamasını kapsar.
Suggested CVSS v3.1:
8.8 (High)
CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Bu CVSS score, router management interface’in typical deployment’ta adjacent local network üzerinden reachable olduğu varsayımına dayanır. Management interface routed veya WAN-accessible bir network üzerinden exposed ise Attack Vector assessment farklı yapılabilir.
Disclosure Note
VulnCheck disclosure yazışmasında bu bulgu için CVE-2026-73673 ID’sini sağladı. Bu yazı yayınlandığı anda CVE kaydı henüz tamamen populate edilmemiş olabilir.
Destructive validation bilinçli olarak yapılmadı. Reporting için kullanılan PoC, gerçek flash write öncesinde duracak şekilde hazırlanmış non-bootable validation container’dı.
References
- CVE-2026-73673
- CVE-2026-73673 PoC and Evidence Repository
- Netis NC63 Firmware Download Page
- VulnCheck
Final Thoughts
Bu bug, embedded sistemlerde authentication boundary’nin binary seviyesinde doğrulanması gerektiğini iyi gösteriyor. Frontend protected görünebilir, web server authentication result hesaplıyor olabilir, CGI process bu sonucu okuyor olabilir. Fakat privileged handler dispatch koşulsuz devam ediyorsa bunların hiçbiri yeterli değil.
Bu firmware’de sonuç, authentication gerektirmeden erişilebilen ve cryptographic firmware authentication içermeyen critical update path.