Skip to content

[BUG] netutils/xmlrpc: xmlrpc_parseparam never bounds argsize against MAX_ARGS, overflowing the fixed args[10]/arguments[10] in the static g_xmlcall (remote global buffer overflow) #3902

Closed

Description

@K-ANOY

Description / Steps to reproduce the issue

The XML-RPC request parser stores one entry per <param> into the fixed arrays args[MAX_ARGS] and arguments[MAX_ARGS] (MAX_ARGS == 10, include/netutils/xmlrpc.h:75) inside the static g_xmlcall (netutils/xmlrpc/xmlparser.c:74), indexing by argsize and incrementing it per parameter — with no check against MAX_ARGS, and the driver loop has no cap either.

netutils/xmlrpc/xmlparser.c, xmlrpc_parseparam():

g_xmlcall.args[g_xmlcall.argsize] = 's';                               /* :214 */
...
strlcpy(g_xmlcall.arguments[g_xmlcall.argsize].u.string, g_data,       /* :241 attacker bytes */
        sizeof(g_xmlcall.arguments[g_xmlcall.argsize].u.string));
...
g_xmlcall.argsize++;                                                   /* :249 no MAX_ARGS check */

Driver xmlrpc_parseparams() loops while (1) (:288) with one argsize++ per <param> and no cap. For argsize >= 10, arguments[argsize] / args[argsize] write past the arrays; the <string> path writes attacker bytes, the int/double paths write attacker values. The struct layout (xmlrpc.h:93) is arguments[10], args[10], argsize, int arg, response[2048], error, so once the overflow reaches argsize itself the index becomes attacker-influenced.

Scope note: writes land in the static g_xmlcall and then into whatever the linker places after it in .bss. g_entries (the handler table, xmlparser.c:76) is a separate static; whether the overflow reaches it is link-order dependent, so control-flow hijack is possible-but-unproven — the reliable outcome is global-state corruption / crash.

Steps:

  1. Build and run the in-tree example XML-RPC server (examples/xmlrpc, CONFIG_EXAMPLES_XMLRPC) — this is the only in-tree consumer of xmlrpc_parse, and it is opt-in, not a default build.
  2. Send one unauthenticated HTTP POST whose body is a methodCall with more than ten <param><value><string>…</string></value></param> elements.
  3. xmlrpc_parse (xmlparser.c:363) → xmlrpc_parseparams → xmlrpc_parseparam writes the 11th parameter past args[10].

Reproduction: logic-level only — a standalone extraction of the parser under ASan (reports/repro/xmlrpc-argsize-overflow/) shows heap-buffer-overflow WRITE ... 0 bytes to the right of a 10-byte region on the 11th <param>. Not reproduced on a real NuttX build.

Expected: a request with more than MAX_ARGS parameters is rejected.
Actual: the write runs past args[10]/arguments[10] into adjacent global state.

Suggested fix: at the top of xmlrpc_parseparam, before the args[argsize] write: if (g_xmlcall.argsize >= MAX_ARGS) return XMLRPC_PARSE_ERROR;

On which OS does this issue occur?

[OS: Linux]

What is the version of your OS?

Ubuntu 22

NuttX Version

master

Issue Architecture

[Arch: all]

Issue Area

[Area: Networking]

Host information

No response

Verification

  • I have verified before submitting the report.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type: BugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions