[php-src] Issue #24640: ext/dba: tcadb backend path allows injecting Tokyo Cabinet connection-string parameters (e.g. bnum) via unescaped '#'

From: Date: Sat, 24 Oct 2026 12:27:32 +0000
Subject: [php-src] Issue #24640: ext/dba: tcadb backend path allows injecting Tokyo Cabinet connection-string parameters (e.g. bnum) via unescaped '#'
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-253156@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/24640 Author: kunwaratulhax0r ext/dba's tcadb backend concatenates the dba_open() path directly into Tokyo Cabinet's #key=value connection-string syntax with no escaping (ext/dba/dba_tcadb.c): ```c spprintf(&path_string, 0, "%s#mode=r", ZSTR_VAL(info->path)); ... tcadbopen(tcadb, path_string); ``` If the path an application passes to dba_open() contains an unescaped # (e.g. built from a user-influenceable component), an attacker can inject additional Tokyo Cabinet tuning parameters into the open call. **Confirmed, live PoC** (--enable-dba --with-tcadb, libtokyocabinet-dev 1.4.48): ```php <?php $db1 = dba_open('/tmp/test_normal.tcb', 'n', 'tcadb'); dba_close($db1); // filesize('/tmp/test_normal.tcb') === 135680 $db2 = dba_open('/tmp/test_injected.tcb#bnum=100000000', 'n', 'tcadb'); dba_close($db2); // filesize('/tmp/test_injected.tcb') === 402658048 (~384MB, ~3000x larger) ``` ``` -rw-r--r-- 1 root root 402658048 Oct 23 15:32 /tmp/test_injected.tcb -rw-r--r-- 1 root root 135680 Oct 23 15:32 /tmp/test_normal.tcb ``` **Mechanism:** on a create-mode open, PHP's own generic dispatcher (ext/dba/dba.c, php_stream_open_wrapper() on the literal path) creates a harmless 0-byte placeholder file at the literal injected name. Separately, Tokyo Cabinet's own tcadbopen() parses the string itself — splits on #, takes everything before the first # as the real path (a different file than the one PHP's generic layer touched), and applies every subsequent #key=value segment as a tuning parameter, including the injected bnum. I also tested whether this could override the intended open mode (inject #mode=wct ahead of PHP's appended #mode=r for a DBA_READER open) — that specific path does **not** work: PHP's generic php_stream_open_wrapper() pre-check requires the literal full path (injected #... included) to already exist for reader-mode opens, so the call fails before reaching the tcadb-specific handler at all. The confirmed impact above is specific to create-mode opens. **Suggested fix:** reject or escape # in the path before use in DBA_OPEN_FUNC(tcadb), same spirit as validating the path in other dba backends.

« previous php.bugs (#253156) next »