Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2026-76070 — Original research and PoC for a pre-auth Base64-decoded password stack buffer overflow in Netis NC63 login.cgi | Kitploit
工具/GitHubGitHub/ozcanpng/cve-2026-76070
Embedded Systems SecurityIoT SecurityVulnerability AnalysisExploitationReverse EngineeringFirmware AnalysisBinary Exploitation
GitHubozcanpng/cve-2026-76070

CVE-2026-76070

Original research and PoC for a pre-auth Base64-decoded password stack buffer overflow in Netis NC63 login.cgi

查看仓库
12620天前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享
内容在请求的语言中不可用。显示英文版本。

CVE-2026-76070: Unauthenticated Pre-Auth Stack Buffer Overflow via Base64-Decoded Password in Netis NC63 login.cgi Leading to RCE

Researcher: Özcan Ersan (@ozcanpng)

Disclosure status

  • CVE: CVE-2026-76070
  • Vendor: Netis Systems Co., Ltd.
  • Product: Netis NC63 Wireless AC1200 Router
  • Tested firmware: NC63_V3.0.0.3327
  • Affected component: /bin/netis.cgi
  • Endpoint: POST /cgi-bin/login.cgi
  • Parameter: Base64-encoded password
  • Authentication: none; the unsafe decode occurs before credential comparison
  • Architecture: MIPS32r2 little-endian, o32 ABI, uClibc
  • Vulnerability class: stack-based buffer overflow with saved return-address control
  • Validation: original-hash production CGI in an isolated QEMU user-mode runtime
  • CVE record state at preparation: assigned; CNA record details pending population

Executive summary

The public login handler in Netis NC63 firmware V3.0.0.3327 retrieves the attacker-controlled password parameter and decodes it with the custom Base64 routine FUN_00402bd4. The caller supplies a 64-byte local stack buffer but does not pass its capacity to the decoder. The decoder derives its work from the encoded input and writes decoded bytes without checking the destination end.

The saved MIPS return address is 136 bytes from the beginning of the decoded buffer. Dynamic tests against the original-hash production CGI confirmed:

  1. a decoded 140-byte B pattern produces a fault at 0x42424242;
  2. replacing saved ra with 0x0041a2e0 causes a second observed entry at the login handler, proving program-counter control; and
  3. an isolated observation-only test reaches the original binary's direct system() call with an attacker-selected MIPS a0 value. The replacement /bin/sh logged /bin/sh -c NC63_RCE_PROOF and executed no command.

The public PoC in this repository deliberately stops at a crash pattern. It contains no return chain, shellcode, command, reverse shell, or persistence. The separately maintained RCE script in poc/exploit-db/ is prepared for an Exploit-DB submission and is intended for authorized testing of affected systems only.

Affected artifact integrity

193f6a5e2ce65972b1805bf076f8d3521379a8441c8aaeb5ad0ba174bbee0792  netis_NC63_V3.0.0.3327.bin
23faa747b7d2f067aa5431bcc227ceca97a7977cf3e7c372f715cbba57f9209b  squashfs-root/bin/boa
eb298774c27070dc595fefcabb4e8c12a46cb5f4fd08f91c3ca92282c3a289a2  squashfs-root/bin/netis.cgi

The dynamically tested /bin/netis.cgi copy has the same SHA-256 as the vendor-extracted executable.

Original and runtime hashes

Attack surface and authentication status

The vendor frontend sends the password to the public endpoint as Base64:

obj.password = base64encode(utf16to8(password));
request({
    url: "/cgi-bin/login.cgi",
    data: obj
});

The HTML field uses maxlength="63", but that is only a browser-side restriction. A direct HTTP client can submit a larger encoded value.

Frontend request and client-only limit

login.cgi is necessarily reachable before authentication. The unsafe decode happens before the decoded password is compared with the configured administrator password. No valid session, Cookie header, Authorization header, or correct password is required.

Source-to-sink trace

Unauthenticated HTTP client
  |
  | POST /cgi-bin/login.cgi
  | password=<attacker-controlled Base64>
  v
/bin/netis.cgi: FUN_0041a2e0
  |
  | get_request_param("password")
  v
FUN_00402bd4(decoded_stack_buffer, encoded_password)
  |
  | no destination-capacity argument
  | decoded output exceeds 64 bytes
  v
saved s8 at decoded offset 132
saved ra at decoded offset 136
  |
  v
attacker-selected MIPS PC

Vulnerable code

Ghidra-derived pseudocode, with names normalized for readability:

int login_cgi(void *request)
{
    char decoded[64];
    char stored[68];
    char *password;

    memset(decoded, 0, 64);
    memset(stored, 0, 64);
    password = get_request_param(request, "password");
    if (password != NULL)
        FUN_00402bd4(decoded, password); /* no capacity argument */

    apmib_get(0x15e, stored);
    if (strcmp(decoded, stored) == 0)
        printf("[\"SUCCESS\"]");
    else {
        system("echo 0 >/tmp/boa_auth");
        printf("[\"%d\"]", 0x15);
    }
    return 0;
}

Vulnerable login handler

The decoder at FUN_00402bd4 receives only destination and source pointers. Its loop advances the destination pointer and stores up to three decoded bytes for each four Base64 symbols. No comparison checks the destination against decoded + 64.

Custom Base64 decoder write loop

Base64 is the input transformation, not the underlying defect. The root cause is the mismatch between attacker-controlled decoded length and a fixed-size destination whose capacity is never enforced. For ordinary padded input, four encoded characters represent up to three decoded bytes; server-side checks must therefore calculate and validate decoded size before writing.

Stack corruption analysis

FUN_0041a2e0 starts at 0x0041a2e0 and creates a 0xa8-byte frame:

0041a2e0  addiu sp,sp,-168
0041a2e4  sw    ra,164(sp)
0041a2e8  sw    s8,160(sp)
0041a2ec  move  s8,sp

The decoded destination begins at s8+0x1c; saved s8 and saved ra are at s8+0xa0 and s8+0xa4:

decoded[64]  s8+0x1c   decoded offset 0
saved s8     s8+0xa0   decoded offset 132
saved ra     s8+0xa4   decoded offset 136

The exact return-address distance is 0xa4 - 0x1c = 0x88, or 136 bytes.

Stack frame and saved-ra offset

Dynamic verification

Saved return-address overwrite

A 140-byte decoded B pattern replaced the four-byte saved return address:

--- SIGSEGV {si_signo=SIGSEGV, si_code=1, si_addr=0x42424242} ---
qemu: uncaught target signal 11 (Segmentation fault)

Fault at attacker-selected return address

Program-counter control

A separate 140-byte input set saved ra to 0x0041a2e0. QEMU CPU tracing recorded an ordinary first handler entry followed by a second entry with s8=0x41414141 and ra=0x0041a2e0.

Controlled second handler entry

Observation-only command boundary

下载工具