I reviewed uwsgi 2.0.31-6build1 as checked into stonking. This shouldn't be
considered a full audit but rather a quick gauge of maintainability. It was
done by reviewing static analysis output, build logs, packaging, and the
source code of the package.

uwsgi is a C application server container that hosts web applications
written in many languages (e.g., Python/WSGI, PHP, Ruby, Perl, Java, Go) via
a large plugin architecture. It listens on TCP or Unix-domain sockets
speaking the uwsgi, HTTP, FastCGI and SCGI protocols, typically deployed
behind a web server, and provides a master/emperor process manager that
supervises worker and vassal processes. Its main interfaces are untrusted
network input on those sockets and its ini/yaml/xml/json configuration.

- CVE History
  - CVE-2018-6758: stack-based buffer overflow in uwsgi_expand_path(); fixed
    upstream in 2.0.16 roughly a month after disclosure, so upstream was
    responsive
  - CVE-2018-7490: directory traversal in the PHP plugin when --php-docroot
    is used; fixed upstream in 2.0.17 within about a month
  - CVE-2020-11984: recorded against uwsgi in the tracker but the flaw is in
    Apache's mod_proxy_uwsgi module; uwsgi itself is not affected in stonking
    (the module moved to the apache2 source package since focal)
  - No documented upstream security policy (no SECURITY.md or security
    contact) and the project states it is in maintenance mode, which is a
    maintainability concern for future security response
- Build-Depends
  - Depends on sensitive libraries in main: libssl-dev (OpenSSL for TLS
    sockets and the https/ssl router), libcurl4-openssl-dev (outbound curl
    alarm/cron plugins), libldap2-dev and libpam0g-dev (auth plugins),
    libwrap0-dev (TCP wrappers ACL plugin), libcap-dev, and input parsers
    (libxml2, libxslt1, libpcre2, libjansson, libyajl, libyaml)
  - Three build-deps are in universe in stonking: libgloox-dev (gloox,
    alarm-xmpp plugin), libgeoip-dev (geoip, geoip plugin) and libzmq5-dev
    (zeromq3); of these, only libzmq5-dev has promotion impact
    - libzmq5-dev (zeromq3) is the universe build-dep that becomes a
      runtime dependency of the promoted binaries; this will possibly be
      resolved via a zmq plugin split
    - libgloox-dev (gloox) and libgeoip-dev (geoip) only serve the
      uwsgi-plugin-alarm-xmpp and uwsgi-plugin-geoip binaries, and since
      plugin binaries are not considered for promotion, these packages
      don't require additional MIRs
- pre/post inst/rm scripts
  - All maintainer scripts are debhelper-generated (service enable/start,
    update-alternatives) with symmetric cleanup in postrm; nothing dangerous
  - uwsgi-emperor and uwsgi-initscripts use --skip-systemd-native without
    the init-system-helpers Pre-Depends (lintian warning, minor policy bug)
- init scripts
  - /etc/init.d/uwsgi starts app instances from root-owned /etc/uwsgi
    apps-enabled configs and /etc/init.d/uwsgi-emperor runs the emperor as
    root with a pidfile in /run; both run the master as root with privilege
    dropping left to the ini configs, which is inherent to uwsgi's design
- systemd units
  - [email protected] uses DynamicUser=yes with a per-app user and
    [email protected] exposes /run/uwsgi/%i.socket mode 0600 www-data, so
    app instances are well isolated
  - However uwsgi-emperor.service runs as root, and none of the units have
    systemd sandboxing directives (ProtectSystem, NoNewPrivileges,
    PrivateTmp, CapabilityBoundingSet) and no AppArmor profile is shipped,
    which is a low-severity hardening gap
- dbus services
  - None
- setuid binaries
  - None
- binaries in PATH
  - /usr/bin/uwsgi-core (symlinked as /usr/bin/uwsgi via update-alternatives)
    is the app server and runs with the invoking user's privileges, with one
    /usr/bin/uwsgi_<plugin> symlink per plugin package for argv0-based plugin
    autoloading; no elevated bits, and /usr/bin/dh_uwsgi is a build-time helper
- sudo fragments
  - None
- polkit files
  - None
- udev rules
  - None
- unit tests / autopkgtests
  - No unit tests run during build
  - testing is via autopkgtest: an integration suite (t/runner) that boots
    uwsgi instances with various configs and verifies them over HTTP
    requests, covering core features (cache, cron, routing, websockets,
    spooler, cgi, mountpoints); good coverage
- cron jobs
  - None
- Build logs
  - No compiler errors; hardening flags are fully applied
    (stack-protector-strong, FORTIFY_SOURCE=3, stack clash protection,
    control-flow protection, format-security, RELRO/PIE on the main
    binary)
  - core/ssl.c uses deprecated OpenSSL 3.0 APIs (PEM_read_bio_DHparams,
    DH_free, EC_KEY_new_by_curve_name, SHA1_*, MD5_*); the SHA1/MD5 code
    implements internal digest helpers (uwsgi_sha1/uwsgi_md5) rather than
    certificate checks, but the aging API usage will need migration when
    the low-level OpenSSL interfaces are eventually removed
  - plugins/xslt uses deprecated libxml2 interfaces, and the alarm_curl
    and curl_cron plugins pass wrong pointer types to curl_easy_setopt
    (benign in practice but sloppy)

- Processes spawned
  - Spawning uses execv/execvp with argv arrays (CGI scripts, emperor
    vassals, daemons), so that there is no shell injection from request data;
    shell execution is limited to admin-configured hook commands
    (exec-as-root etc.) and the forkptyrouter feature, which run /bin/sh on
    configuration by design, so config files are root-executed and must
    stay root-owned
- Memory management
  - None
- File IO
  - Request-derived file serving (static router, CGI docroot walk) uses
    realpath/stat-then-open, which is a time-of-check-time-of-use race for
    an attacker with local filesystem access to the served directories;
    impact is constrained but the pattern recurs (Coverity TOCTOU hits)
- Logging
  - None
- Environment variable usage
  - None (the CGI plugin exports request-derived variables to child
    processes by protocol design, and the internal UWSGI_* variables set
    by the root master use fd passing with credentials checks)
- Use of privileged functions
  - Sockets are bound as root and workers drop to configured uid/gid with
    return checks; the emperor re-gains root to spawn vassals as arbitrary
    users, which requires running as root by design
  - --chmod-socket without a value in lazy mode, and emperor on-demand
    vassal sockets (unconditionally), chmod listening sockets to 0666, so
    any local user can connect directly to the app bypassing front-door
    access controls; both need admin awareness when configuring
- Use of cryptography / random number sources etc
  - None (TLS contexts disable SSLv2/SSLv3 and compression with checked
    return codes; randomness comes from RAND_bytes and /dev/urandom, and
    rand() only appears in non-security filename noise where O_EXCL
    creation prevents prediction attacks)
- Use of temp files
  - None (O_TMPFILE or mkstemp with random suffix for temp files, and
    spool files are created O_CREAT|O_EXCL 0600)
- Use of networking
  - The raw uwsgi protocol sockets accept packets that directly define
    request variables (PATH_INFO and headers) and are meant to sit behind
    a trusted web server on localhost or a Unix socket; exposing them to
    untrusted networks hands an attacker the same control as the web
    server backend, and this is also the reachability path for the CGI
    plugin defect reported under Coverity
  - The subscription system accepts node registration packets from
    untrusted network peers, and its defenses (signature and credentials
    checking) are optional per-configuration, so subscription-enabled
    routers should always enable them
- Use of WebKit
  - N/A
- Use of PolicyKit
  - None

- Any significant cppcheck results
  - None (all warnings verified as false positives, e.g. guarded
    list-append uninitvar pattern and non-returning _exit paths)
- Any significant Coverity results
  - plugins/cgi/cgi_plugin.c:352,431,463: uwsgi_cgi_walk() calls
    memcpy(dst, part, part_size-1) where part_size stays 0 when PATH_INFO
    does not start with '/', giving a negative length converted to a huge
    size_t and an out-of-bounds write; it is reachable through request path
    handling in the CGI plugin, the same area as the old CVE-2018-7490, and
    needs an upstream fix
  - core/subscription.c:221: the weight round-robin divides by min_weight,
    which stays 0 when every subscription node registers weight 0, so a
    subscription packet from an untrusted network peer can crash the
    subscription router with a division by zero (remote denial of service)
  - core/zlib.c:27,39,128,133: possible use-after-free of the zlib stream
    state in the deflate/gzip error paths (worker crash class, needs
    upstream confirmation)
  - core/logging.c:74: a log line whose formatted length lands between the
    remaining buffer space and 4096 makes write() read up to a few dozen
    bytes past the 4096-byte stack buffer (minor stack disclosure to
    stderr)
  - Wide noise mass (194 STRING_NULL, 80 RESOURCE_LEAK, 66 CHECKED_RETURN,
    35 PRINTF_ARGS) is mostly false positives from uwsgi's length-based
    string helpers, error-path leaks and unchecked append returns; several
    TAINTED_SCALAR hits in the fastcgi/scgi protocol parsers were verified
    as guarded, but they mark the untrusted-input hot spots
- Any significant shellcheck results
  - None (all hits are in unshipped contrib/test scripts, or false
    positives in the init script whose variables are consumed by sourced
    helper files)
- Any significant bandit results
  - uwsgiconfig.py and the plugin build scripts use shell=True subprocess
    calls extensively, but they are build-time tooling with no runtime
    exposure (equivalent of configure scripts)
  - The shipped uwsgidecorators.py imports pickle for the @spool decorator:
    spooler tasks are pickled to the spool directory and deserialized in the
    worker, so anyone able to write to that directory can execute code in
    the worker context; documented behavior, but the directory permissions
    are security-critical
- Any significant govulncheck results
  - N/A
- Any significant Semgrep results
  - None

The upstream source is a maintenance-mode C code base of about 82K lines with
more than 100 plugins, of which the Ubuntu build ships only a small subset,
so many of the raw static-analysis findings sit in code that Ubuntu does not
build or ship; the significant findings concentrate in the shipped core
request-handling code. Upstream moves slowly but is still alive and fixes
security bugs when reported, and the Debian maintainer actively maintains
the packaging, so the defects below can be carried to a fix.

Security team ACK for promoting uwsgi (uwsgi-core, uwsgi and
uwsgi-emperor) to main. No blocking conditions; the only dependency note
is that the libzmq5 runtime dependency of the promoted binaries (the
emperor_zeromq, logzmq and mongrel2 plugins link -lzmq) is being resolved
via the zmq plugin split with the Debian maintainer. The unconfirmed
Coverity leads (e.g., plugins/cgi/cgi_plugin.c, core/subscription.c:221
and core/zlib.c) should be reported upstream for confirmation and fixing.
They are still present verbatim in current upstream master, and I will
report them, but none are demonstrated vulnerabilities and do not block
promotion.


** CVE added: https://cve.org/CVERecord?id=CVE-2018-6758

** CVE added: https://cve.org/CVERecord?id=CVE-2018-7490

** CVE added: https://cve.org/CVERecord?id=CVE-2020-11984

** Changed in: uwsgi (Ubuntu)
     Assignee: Ubuntu Security Team (ubuntu-security) => (unassigned)

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2151202

Title:
  [MIR] uwsgi

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/uwsgi/+bug/2151202/+subscriptions


-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to