diff options
| author | Paul Buetow <paul@buetow.org> | 2026-06-30 12:04:42 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-06-30 12:04:42 +0300 |
| commit | 11aa2791771b6d8b87605511de146e4dd4cdef6e (patch) | |
| tree | c46cac67654a1a6fd08f3254117d323104323ae3 /yhttpd/scripts | |
| parent | ce5180fbc09dc400b20d5946751106d80820dcbe (diff) | |
Fix path traversal (file read) and dlopen-traversal (RCE)
Three path-traversal vulnerabilities, all caused by sanitizing the raw
URL before url_decode (so %-encoded %2e%2e / %2f survive the check and
decode to '..' afterwards), and by concatenating attacker-controlled
names into filesystem paths:
1. Arbitrary file read via the HTML template path. src/sock/sock.cpp
stripped the literal '/..' from the raw query before tool::url_decode,
so 'GET /..%2f..%2fetc%2fpasswd' decoded to '../../etc/passwd' and
src/html.cpp opened ifstream(templatedir + request), escaping html/.
Confirmed: returned /etc/passwd, /etc/hosts, and the app's own
etc/ychat.conf (leaking the MySQL password).
Fix: add tool::path_has_traversal (rejects any '.'/'..' path component
and embedded NULs on the DECODED path) and redirect to the notfound
page in handle_client_read when it triggers.
2. Arbitrary shared-object load (RCE) via the html-module dlopen path.
reqp::run_html_mod built 'htmldir + yc_ + s_event + .so' from the
attacker-controlled event query param and dlopen()'d it; 'event=..%2f..'
could load a .so outside the modules dir.
Fix: reject non-alphanumeric s_event before building the path.
3. Same via the command-module dlopen path. user::command built
'commandsdir + yc_ + s_command2 + .so' from the first token of a '/'
chat message and dlopen()'d it.
Fix: reject non-alphanumeric s_command2 before building the path.
Verified in a container: file-read traversal now returns the notfound
page (not file contents); command/module-name traversal is blocked and
not dlopen'd; legit /time, normal pages, login and streaming all still
work. Builds clean.
Independent fresh-context review: APPROVE-WITH-NITS; the dlopen-traversal
and NUL-hardening findings were addressed here; the (disabled-by-default)
CGI popen command-injection was noted as a separate follow-up.
Diffstat (limited to 'yhttpd/scripts')
0 files changed, 0 insertions, 0 deletions
