├── .gitignore ├── README.md ├── afl-toolchain.sh ├── fuzz.patch.c ├── fuzzer-dir ├── afl-runner.sh ├── conf │ └── default.conf ├── dict │ └── http_request_fuzzer.dict.txt ├── input-cases │ ├── test.txt │ ├── test1.txt │ ├── test10.txt │ ├── test11.txt │ ├── test12.txt │ ├── test13.txt │ ├── test14.txt │ ├── test15.txt │ ├── test16.txt │ ├── test17.txt │ ├── test18.txt │ ├── test19.txt │ ├── test2.txt │ ├── test20.txt │ ├── test21.txt │ ├── test22.txt │ ├── test23.txt │ ├── test24.txt │ ├── test25.txt │ ├── test3.txt │ ├── test4.txt │ ├── test5.txt │ ├── test6.txt │ ├── test7.txt │ ├── test8.txt │ └── test9.txt └── out-dir │ └── .gitignore └── insert-fuzz.py /.gitignore: -------------------------------------------------------------------------------- 1 | httpd-*/ 2 | .vscode/ 3 | .DS_Store 4 | */**/.DS_Store 5 | httpd-*/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # apache-afl 2 | 3 | An automated setup for compiling & fuzzing Apache httpd server. 4 | 5 | More info about the process/journey can be found here: https://0xbigshaq.github.io/2022/03/12/fuzzing-smarter-part2 6 | 7 | # Usage 8 | 9 | To start the build process, run: 10 | 11 | ``` 12 | ./afl-toolchain.sh 13 | ``` 14 | 15 | To start fuzzing: 16 | ``` 17 | cd fuzzer-dir/ 18 | ./afl-runner.sh 19 | ``` 20 | 21 | > Tested on: AFL Version ++4.00c (release) under a `aflplusplus/aflplusplus` docker image 22 | -------------------------------------------------------------------------------- /afl-toolchain.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # deps fixup 4 | apt-get update 5 | apt-get install -y brotli libbrotli-dev libxml2-dev libssl-dev wget curl 6 | 7 | export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH 8 | 9 | mkdir -p /usr/local/apache_lab/ 10 | PREFIX=/usr/local/apache_lab/ 11 | 12 | ## Download Apache httpd 13 | # ----------------------------- 14 | wget https://archive.apache.org/dist/httpd/httpd-2.4.52.tar.gz 15 | tar -xvzf httpd-2.4.52.tar.gz && rm httpd-2.4.52.tar.gz 16 | cd ./httpd-2.4.52/ 17 | 18 | 19 | # handling dependencies 20 | # ----------------------------- 21 | mkdir -p deps-dir/ 22 | cd ./deps-dir 23 | 24 | # APR 25 | wget https://archive.apache.org/dist/apr/apr-1.7.0.tar.gz 26 | tar -xvzf apr-1.7.0.tar.gz && rm apr-1.7.0.tar.gz && mv ./apr-1.7.0 apr 27 | cd apr/ 28 | ./configure --prefix="$PREFIX/apr/" 29 | make && make install 30 | cd .. 31 | 32 | 33 | # APR-UTIL 34 | wget https://archive.apache.org/dist/apr/apr-util-1.6.1.tar.gz 35 | tar -xvzf apr-util-1.6.1.tar.gz && rm apr-util-1.6.1.tar.gz && mv ./apr-util-1.6.1 apr-util 36 | cd apr-util/ 37 | ./configure --prefix="$PREFIX/apr-util/" --with-apr="$PREFIX/apr/" 38 | make && make install 39 | cd .. 40 | 41 | # EXPAT 42 | wget https://github.com/libexpat/libexpat/releases/download/R_2_4_1/expat-2.4.1.tar.gz 43 | tar -xvzf expat-2.4.1.tar.gz && rm expat-2.4.1.tar.gz && mv ./expat-2.4.1 expat 44 | cd expat/ 45 | ./configure --prefix="$PREFIX/expat/" 46 | make && make install 47 | cd ../ 48 | 49 | # PCRE 50 | wget http://ftp.cs.stanford.edu/pub/exim/pcre/pcre-8.45.tar.gz 51 | tar -xvzf pcre-8.45.tar.gz && rm pcre-8.45.tar.gz && mv ./pcre-8.45 pcre 52 | cd pcre/ 53 | ./configure --prefix="$PREFIX/pcre/" 54 | make && make install 55 | cd ../ 56 | 57 | 58 | 59 | ## Compile httpd 60 | # ----------------------------- 61 | 62 | # return to the httpd directory 63 | cd ../ 64 | 65 | # apply hot-patching to enable fuzzing via AFL 66 | chmod +x ../insert-fuzz.py 67 | ../insert-fuzz.py 68 | 69 | # configure compiler, flags and DSOs/apache modules 70 | CC=afl-clang-fast \ 71 | CXX=afl-clang-fast++ \ 72 | CFLAGS="-g -fsanitize=address -fno-sanitize-recover=all" \ 73 | CXXFLAGS="-g -fsanitize=address -fno-sanitize-recover=all" \ 74 | LDFLAGS="-fsanitize=address -fno-sanitize-recover=all -lm" \ 75 | ./configure --with-apr="$PREFIX/apr/" \ 76 | --with-apr-util="$PREFIX/apr-util/" \ 77 | --with-expat="$PREFIX/expat/" \ 78 | --with-pcre="$PREFIX/pcre/" \ 79 | --disable-pie \ 80 | --disable-so \ 81 | --disable-example-ipc \ 82 | --disable-example-hooks \ 83 | --disable-optional-hook-export \ 84 | --disable-optional-hook-import \ 85 | --disable-optional-fn-export \ 86 | --disable-optional-fn-import \ 87 | --with-mpm=prefork \ 88 | --enable-static-support \ 89 | --enable-mods-static=reallyall \ 90 | --enable-debugger-mode \ 91 | --with-crypto --with-openssl \ 92 | --disable-shared 93 | 94 | # compile 95 | make -j $(nproc) 96 | make install 97 | -------------------------------------------------------------------------------- /fuzz.patch.c: -------------------------------------------------------------------------------- 1 | /* ---------------------------------- */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | static void netIfaceUp(const char *ifacename) 26 | { 27 | int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); 28 | if (sock == -1) { 29 | perror("socket(AF_INET, SOCK_STREAM, IPPROTO_IP)"); 30 | exit(1); 31 | } 32 | 33 | struct ifreq ifr; 34 | memset(&ifr, '\0', sizeof(ifr)); 35 | snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", ifacename); 36 | 37 | if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) { 38 | perror("ioctl(iface='lo', SIOCGIFFLAGS, IFF_UP)"); 39 | exit(1); 40 | } 41 | 42 | ifr.ifr_flags |= (IFF_UP | IFF_RUNNING); 43 | 44 | if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) { 45 | perror("ioctl(iface='lo', SIOCSIFFLAGS, IFF_UP)"); 46 | exit(1); 47 | } 48 | 49 | close(sock); 50 | } 51 | 52 | void unsh(void) 53 | { 54 | unshare(CLONE_NEWUSER | CLONE_NEWNET | CLONE_NEWNS); 55 | 56 | if (mount("tmpfs", "/tmp", "tmpfs", 0, "") == -1) { 57 | perror("tmpfs"); 58 | exit(1); 59 | } 60 | netIfaceUp("lo"); 61 | } 62 | 63 | static void fuzzer_thread(void) 64 | { 65 | int BUFSIZE=1024*1024; 66 | usleep(10000); 67 | char buf[BUFSIZE+1]; 68 | while ( __AFL_LOOP(10000)) { 69 | printf("[+] Looping\n"); 70 | memset(buf, 0, BUFSIZE); 71 | size_t read_bytes = read(0, buf, BUFSIZE); 72 | buf[BUFSIZE-2] = '\r'; 73 | buf[BUFSIZE-1] = '\n'; 74 | buf[BUFSIZE] = '\0'; 75 | 76 | int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); 77 | if (sockfd == -1) { 78 | perror("socket"); 79 | exit(1); 80 | } 81 | 82 | int sz = (1024 * 1024); 83 | if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sz, sizeof(sz)) == -1) { 84 | perror("setsockopt"); 85 | exit(1); 86 | } 87 | 88 | printf("[+] Connecting\n", buf); 89 | 90 | struct sockaddr_in saddr; 91 | saddr.sin_family = AF_INET; 92 | saddr.sin_port = htons(80); 93 | saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 94 | while (connect(sockfd, &saddr, sizeof(saddr)) == -1) { 95 | perror("connect"); 96 | usleep(100000); 97 | } 98 | 99 | printf("[+] Sending buf %s\n", buf); 100 | 101 | if (send(sockfd, buf, read_bytes, MSG_NOSIGNAL) != read_bytes) { 102 | perror("send() failed 1"); 103 | exit(1); 104 | } 105 | 106 | if (shutdown(sockfd, SHUT_WR) == -1) { 107 | perror("shutdown"); 108 | exit(1); 109 | } 110 | 111 | char b[1024 * 1024]; 112 | while (recv(sockfd, b, sizeof(b), MSG_WAITALL) > 0) ; 113 | 114 | printf("[+] Received %s\n", b); 115 | close(sockfd); 116 | } 117 | printf("[+] Done\n"); 118 | usleep(100000); 119 | exit(0); 120 | } 121 | 122 | static void launch_fuzzy_thread(void) 123 | { 124 | pthread_t t; 125 | pthread_attr_t attr; 126 | 127 | pthread_attr_init(&attr); 128 | pthread_attr_setstacksize(&attr, 1024 * 1024 * 8); 129 | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 130 | 131 | pthread_create(&t, &attr, fuzzer_thread, NULL); 132 | } 133 | 134 | /* ---------------------------------- */ 135 | int main(int argc, const char * const argv[]) 136 | { 137 | // enable fuzzing :^) 138 | if (getenv("NO_FUZZ") == NULL) { 139 | unsh(); 140 | launch_fuzzy_thread(); 141 | printf("[+] Launched AFL loop\n"); 142 | } 143 | printf("[+] Continue with normal apache execution\n"); 144 | 145 | // ------------------------------------ 146 | 147 | -------------------------------------------------------------------------------- /fuzzer-dir/afl-runner.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # run fuzzer 4 | export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/apache2/lib/:$LD_LIBRARY_PATH 5 | 6 | AFL_MAP_SIZE=256000 \ 7 | SHOW_HOOKS=1 \ 8 | ASAN_OPTIONS=detect_leaks=0,abort_on_error=1,symbolize=0,debug=true,check_initialization_order=true,detect_stack_use_after_return=true,strict_string_checks=true,detect_invalid_pointer_pairs=2 \ 9 | AFL_DISABLE_TRIM=1 \ 10 | afl-fuzz \ 11 | -t 2000 \ 12 | -m none \ 13 | -i './input-cases/' \ 14 | -o './out-dir' \ 15 | -x './dict/http_request_fuzzer.dict.txt' \ 16 | -- '/usr/local/apache2/bin/httpd' -X -f $(pwd)/conf/default.conf 17 | 18 | -------------------------------------------------------------------------------- /fuzzer-dir/conf/default.conf: -------------------------------------------------------------------------------- 1 | ServerRoot "/usr/local/apache2" 2 | Listen 80 3 | 4 | 5 | User daemon 6 | Group daemon 7 | 8 | 9 | ServerAdmin you@example.com 10 | 11 | 12 | AllowOverride none 13 | Require all denied 14 | 15 | 16 | 17 | DocumentRoot "/usr/local/apache2/htdocs" 18 | 19 | Options Indexes FollowSymLinks 20 | AllowOverride None 21 | Require all granted 22 | 23 | 24 | 25 | 26 | DirectoryIndex index.html 27 | 28 | 29 | 30 | 31 | Require all denied 32 | 33 | 34 | 35 | 36 | ErrorLog "/dev/stdout" 37 | LogLevel warn 38 | 39 | LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined 40 | LogFormat "%h %l %u %t \"%r\" %>s %b" common 41 | 42 | LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio 43 | 44 | 45 | 46 | 47 | 48 | ScriptAlias /cgi-bin/ "/usr/local/apache2/cgi-bin/" 49 | 50 | 51 | 52 | 53 | AllowOverride None 54 | Options None 55 | Require all granted 56 | 57 | 58 | 59 | 60 | RequestHeader unset Proxy early 61 | 62 | 63 | 64 | 65 | TypesConfig conf/mime.types 66 | AddType application/x-compress .Z 67 | AddType application/x-gzip .gz .tgz 68 | 69 | 70 | 71 | Include conf/extra/httpd-default.conf 72 | 73 | Include conf/extra/proxy-html.conf 74 | 75 | 76 | 77 | SSLRandomSeed startup builtin 78 | SSLRandomSeed connect builtin 79 | 80 | -------------------------------------------------------------------------------- /fuzzer-dir/dict/http_request_fuzzer.dict.txt: -------------------------------------------------------------------------------- 1 | # misc 2 | "HTTP/1.0" 3 | "HTTP/1.1" 4 | 5 | # verbs 6 | "CONNECT" 7 | "DELETE" 8 | "GET" 9 | "HEAD" 10 | "OPTIONS" 11 | "PATCH" 12 | "POST" 13 | "PUT" 14 | "TRACE" 15 | 16 | 17 | # Webdav/caldav verbs 18 | "ACL" 19 | "BASELINE-CONTROL" 20 | "BIND" 21 | "CHECKIN" 22 | "CHECKOUT" 23 | "COPY" 24 | "LABEL" 25 | "LINK" 26 | "LOCK" 27 | "MERGE" 28 | "MKACTIVITY" 29 | "MKCALENDAR" 30 | "MKCOL" 31 | "MKREDIRECTREF" 32 | "MKWORKSPACE" 33 | "MOVE" 34 | "ORDERPATCH" 35 | "PRI" 36 | "PROPFIND" 37 | "PROPPATCH" 38 | "REBIND" 39 | "REPORT" 40 | "SEARCH" 41 | "UNBIND" 42 | "UNCHECKOUT" 43 | "UNLINK" 44 | "UNLOCK" 45 | "UPDATE" 46 | "UPDATEREDIRECTREF" 47 | "VERSION-CONTROL" 48 | 49 | 50 | # Fields 51 | "A-IM" 52 | "Accept" 53 | "Accept-Charset" 54 | "Accept-Datetime" 55 | "Accept-Encoding" 56 | "Accept-Language" 57 | "Accept-Patch" 58 | "Accept-Ranges" 59 | "Access-Control-Allow-Credentials" 60 | "Access-Control-Allow-Headers" 61 | "Access-Control-Allow-Methods" 62 | "Access-Control-Allow-Origin" 63 | "Access-Control-Expose-Headers" 64 | "Access-Control-Max-Age" 65 | "Access-Control-Request-Headers" 66 | "Access-Control-Request-Method" 67 | "Age" 68 | "Allow" 69 | "Alt-Svc" 70 | "Authorization" 71 | "Cache-Control" 72 | "Connection" 73 | "Connection:" 74 | "Content-Disposition" 75 | "Content-Encoding" 76 | "Content-Language" 77 | "Content-Length" 78 | "Content-Location" 79 | "Content-MD5" 80 | "Content-Range" 81 | "Content-Security-Policy" 82 | "Content-Type" 83 | "Cookie" 84 | "DNT" 85 | "Date" 86 | "Delta-Base" 87 | "ETag" 88 | "Expect" 89 | "Expires" 90 | "Forwarded" 91 | "From" 92 | "Front-End-Https" 93 | "HTTP2-Settings" 94 | "Host" 95 | "IM" 96 | "If-Match" 97 | "If-Modified-Since" 98 | "If-None-Match" 99 | "If-Range" 100 | "If-Unmodified-Since" 101 | "Last-Modified" 102 | "Link" 103 | "Location" 104 | "Max-Forwards" 105 | "Origin" 106 | "P3P" 107 | "Pragma" 108 | "Proxy-Authenticate" 109 | "Proxy-Authorization" 110 | "Proxy-Connection" 111 | "Public-Key-Pins" 112 | "Range" 113 | "Referer" 114 | "Refresh" 115 | "Retry-After" 116 | "Save-Data" 117 | "Server" 118 | "Set-Cookie" 119 | "Status" 120 | "Strict-Transport-Security" 121 | "TE" 122 | "Timing-Allow-Origin" 123 | "Tk" 124 | "Trailer" 125 | "Transfer-Encoding" 126 | "Upgrade" 127 | "Upgrade-Insecure-Requests" 128 | "User-Agent" 129 | "Vary" 130 | "Via" 131 | "WWW-Authenticate" 132 | "Warning" 133 | "X-ATT-DeviceId" 134 | "X-Content-Duration" 135 | "X-Content-Security-Policy" 136 | "X-Content-Type-Options" 137 | "X-Correlation-ID" 138 | "X-Csrf-Token" 139 | "X-Forwarded-For" 140 | "X-Forwarded-Host" 141 | "X-Forwarded-Proto" 142 | "X-Frame-Options" 143 | "X-Http-Method-Override" 144 | "X-Powered-By" 145 | "X-Request-ID" 146 | "X-Requested-With" 147 | "X-UA-Compatible" 148 | "X-UIDH" 149 | "X-Wap-Profile" 150 | "X-WebKit-CSP" 151 | "X-XSS-Protection" 152 | 153 | #Others 154 | "keep-alive" 155 | "nokeepalive" 156 | "127.0.0.1" 157 | "http" 158 | "https" 159 | "html" 160 | 161 | #Mod_negotiation 162 | "Negotiate" 163 | "trans" 164 | "Lynx" 165 | "1.0" 166 | 167 | #2bytes words 168 | "" 235 | "" 236 | "xmlns" 237 | "test" 238 | 239 | 240 | 241 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test.txt: -------------------------------------------------------------------------------- 1 | GET /test/ethereal.html HTTP/1.1 2 | Host: 127.0.0.1 3 | User-Agent: Mozilla/5.0 (X11; U; Linux ppc; rv:1.7.3) Gecko/20041004 Firefox/0.10.1 4 | Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 5 | Accept-Language: en-us,en;q=0.5 6 | Accept-Encoding: gzip,deflate 7 | Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 8 | Keep-Alive: 300 9 | Connection: keep-alive 10 | Cookie: A=05c04axp1yaqynldtcdiwis0ag1 11 | 12 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test1.txt: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT) 3 | Host: 127.0.0.1 4 | Accept-Language: en-us 5 | Accept-Encoding: gzip, deflate 6 | Connection: Keep-Alive 7 | 8 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test10.txt: -------------------------------------------------------------------------------- 1 | GET /b/c/d?q&path=g?y HTTP/1.1 2 | Host: 127.0.0.1 3 | User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:59.0) Gecko/20100101 Firefox/59.0 4 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 5 | Accept-Language: en-US,en;q=0.5 6 | Accept-Encoding: gzip, deflate 7 | Connection: keep-alive 8 | Upgrade-Insecure-Requests: 1 9 | 10 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test11.txt: -------------------------------------------------------------------------------- 1 | GET /images/layout/logo.png HTTP/1.0 2 | User-Agent: Wget/1.12 (linux-gnu) 3 | Accept: */* 4 | Host: packetlife.net 5 | If-Match: "f6-5b1b7cc85b700" 6 | Connection: Keep-Alive 7 | 8 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test12.txt: -------------------------------------------------------------------------------- 1 | POST /foo HTTP/1.1 2 | Content-Length: 68137 3 | Content-Type: multipart/form-data; boundary=---------------------------974767299852498929531610575 4 | 5 | -----------------------------974767299852498929531610575 6 | Content-Disposition: form-data; name="description" 7 | 8 | some text 9 | -----------------------------974767299852498929531610575 10 | Content-Disposition: form-data; name="myFile"; filename="foo.txt" 11 | Content-Type: text/plain 12 | 13 | (content of the uploaded file foo.txt) 14 | -----------------------------974767299852498929531610575-- 15 | 16 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test13.txt: -------------------------------------------------------------------------------- 1 | POST / HTTP/1.1 2 | Host: example.com 3 | Content-Type: multipart/form-data; boundary="578de3b0e3c46.2334ba3" 4 | 5 | --578de3b0e3c46.2334ba3 6 | Content-Disposition: form-data; name="foo" 7 | Content-Length: 15 8 | 9 | A normal stream 10 | --578de3b0e3c46.2334ba3 11 | Content-Disposition: form-data; name="bar"; filename="bar.png" 12 | Content-Length: 71 13 | Content-Type: image/png 14 | 15 | ?PNG 16 |  17 | ??? 18 | IHDR??? ??? ?????? ???? IDATxc???51?)?:??????IEND?B`? 19 | --578de3b0e3c46.2334ba3 20 | Content-Type: text/plain 21 | Content-Disposition: form-data; name="baz" 22 | Content-Length: 6 23 | 24 | string 25 | --578de3b0e3c46.2334ba3-- 26 | 27 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test14.txt: -------------------------------------------------------------------------------- 1 | GET http://username:password@[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/ HTTP/1.1 2 | User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT) 3 | Host: 127.0.0.1 4 | Accept-Language: en-us 5 | Accept-Encoding: gzip, deflate 6 | Connection: Keep-Alive 7 | 8 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test15.txt: -------------------------------------------------------------------------------- 1 | CONNECT [2001:0db8:85a3:0000:0000:8a2e:0370:7334]:80 HTTP/1.1 2 | Host: server.example.com:80 3 | Proxy-Authorization: basic aGVsbG86d29ybGQ= 4 | 5 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test16.txt: -------------------------------------------------------------------------------- 1 | OPTIONS /foo HTTP/1.1 2 | Host: bar.example 3 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 4 | Accept-Language: en-us,en;q=0.5 5 | Accept-Encoding: gzip,deflate 6 | Connection: keep-alive 7 | Origin: https://foo.example 8 | Access-Control-Request-Method: POST 9 | Access-Control-Request-Headers: X-PINGOTHER, Content-Type 10 | 11 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test17.txt: -------------------------------------------------------------------------------- 1 | OPTIONS * HTTP/1.1 2 | Host: bar.example 3 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 4 | Accept-Language: en-us,en;q=0.5 5 | Accept-Encoding: gzip,deflate 6 | Connection: keep-alive 7 | Origin: https://foo.example 8 | Access-Control-Request-Method: POST 9 | Access-Control-Request-Headers: X-PINGOTHER, Content-Type 10 | 11 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test18.txt: -------------------------------------------------------------------------------- 1 | GET /images/layout/logo.png HTTP/1.0 2 | User-Agent: Wget/1.12 (linux-gnu) 3 | Accept: */* 4 | Host: packetlife.net 5 | If-Match: * 6 | If-Unmodified-Since: Wed, 21 Oct 2015 07:28:00 GMT 7 | Connection: Keep-Alive 8 | 9 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test19.txt: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.11 [en] 3 | Host: 10.1.1.1 4 | Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,text/css,*/*;q=0.1 5 | Accept-Language: en 6 | Accept-Charset: windows-1252, utf-8, utf-16, iso-8859-1;q=0.6, *;q=0.1 7 | Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0 8 | If-None-Match: * 9 | Connection: Keep-Alive 10 | 11 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test2.txt: -------------------------------------------------------------------------------- 1 | GET http://127.0.0.1:8080/foo HTTP/1.1 2 | Host: www.wireshark.org:8080 3 | User-Agent: curl/7.46.0 4 | Accept: */* 5 | Connection: close 6 | Accept-Encoding: chunked, gzip 7 | 8 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test20.txt: -------------------------------------------------------------------------------- 1 | GET /images/layout/logo.png HTTP/1.1 2 | Host: 127.0.0.1 3 | User-Agent: Mozilla/5.0 (X11; U; Linux ppc; rv:1.7.3) Gecko/20041004 Firefox/0.10.1 4 | Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 5 | Accept-Language: en-us,en;q=0.5 6 | Accept-Encoding: gzip,deflate 7 | Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 8 | Keep-Alive: 300 9 | Range: bytes=5-10, 20-65 10 | Connection: keep-alive 11 | Cookie: A=05c04axp1yaqynldtcdiwis0ag1 12 | 13 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test21.txt: -------------------------------------------------------------------------------- 1 | GET /index.html HTTP/1.1 2 | Host: www.example.com 3 | Connection: upgrade 4 | Upgrade: http1.1, foo2 5 | 6 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test22.txt: -------------------------------------------------------------------------------- 1 | OPTIONS / HTTP/1.1 2 | Host: bar.example 3 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 4 | Accept-Language: en-us,en;q=0.5 5 | Accept-Encoding: gzip,deflate 6 | Connection: keep-alive 7 | Origin: https://foo.example 8 | Access-Control-Request-Method: POST 9 | Access-Control-Request-Headers: X-PINGOTHER, Content-Type 10 | 11 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test23.txt: -------------------------------------------------------------------------------- 1 | PUT /new.html HTTP/1.1 2 | Host: example.com 3 | Content-type: text/html 4 | Content-length: 16 5 | 6 |

New File

7 | 8 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test24.txt: -------------------------------------------------------------------------------- 1 | GET /red HTTP/1.1 2 | Host: 127.0.0.1 3 | User-Agent: Mozilla/5.0 (X11; U; Linux ppc; rv:1.7.3) Gecko/20041004 Firefox/0.10.1 4 | Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 5 | Accept-Language: en-us,en;q=0.5 6 | Accept-Encoding: gzip,deflate 7 | Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 8 | Keep-Alive: 300 9 | Connection: keep-alive 10 | Cookie: A=05c04axp1yaqynldtcdiwis0ag1 11 | 12 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test25.txt: -------------------------------------------------------------------------------- 1 | GET /d.var HTTP/1.1 2 | Host: 127.0.0.1 3 | User-Agent: Firefox/0.10.1 4 | Accept: image/png,*;q=0.5 5 | Accept-Language: en-us;q=0.5 6 | Accept-Encoding: gzip,deflate 7 | Accept-Charset: utf-8;q=0.0;q=0.0 8 | Keep-Alive: 300 9 | Connection: keep-alive 10 | 11 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test3.txt: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.11 [en] 3 | Host: 10.1.1.1 4 | Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,text/css,*/*;q=0.1 5 | Accept-Language: en 6 | Accept-Charset: windows-1252, utf-8, utf-16, iso-8859-1;q=0.6, *;q=0.1 7 | Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0 8 | If-None-Match: "bf-5b1b7cc85b700" 9 | Connection: Keep-Alive 10 | 11 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test4.txt: -------------------------------------------------------------------------------- 1 | POST /scripts/cms/xcms.asp HTTP/1.1 2 | User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.11 [en] 3 | Host: ins1.opera.com 4 | Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,text/css,*/*;q=0.1 5 | Accept-Language: en 6 | Accept-Charset: windows-1252, utf-8, utf-16, iso-8859-1;q=0.6, *;q=0.1 7 | Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0 8 | Connection: Keep-Alive 9 | Content-length: 433 10 | Content-Type: application/vnd.xacp 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test5.txt: -------------------------------------------------------------------------------- 1 | GET /Websidan/index.html HTTP/1.1 2 | User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0) Opera 7.11 [en] 3 | Host: 10.1.1.1 4 | Accept: application/x-shockwave-flash,text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,text/css,*/*;q=0.1 5 | Accept-Language: en 6 | Accept-Charset: windows-1252, utf-8, utf-16, iso-8859-1;q=0.6, *;q=0.1 7 | Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0 8 | Referer: http://10.1.1.1/ 9 | If-Range: Wed, 21 Oct 2015 07:28:00 GMT 10 | Range: bytes=200-1000, 2000-6576, 19000- 11 | Connection: Keep-Alive, TE 12 | TE: deflate, gzip, chunked, identity, trailers 13 | 14 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test6.txt: -------------------------------------------------------------------------------- 1 | POST /ethereal-labs/lab3-1-reply.htm HTTP/1.1 2 | Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */* 3 | Referer: http://gaia.cs.umass.edu/ethereal-labs/TCP-ethereal-file1.html 4 | Accept-Language: en-us 5 | Content-Type: multipart/form-data; boundary=---------------------------7d537442b03aa 6 | Accept-Encoding: gzip, deflate 7 | User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322) 8 | Host: gaia.cs.umass.edu 9 | Content-Length: 152372 10 | Connection: Keep-Alive 11 | Cache-Control: no-cache 12 | 13 | ---------------------------7d537442b03aa 14 | Content-Disposition: form-data; name="description" 15 | 16 | some text 17 | ---------------------------7d537442b03aa 18 | Content-Disposition: form-data; name="myFile"; filename="foo.txt" 19 | Content-Type: text/plain 20 | 21 | 22 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test7.txt: -------------------------------------------------------------------------------- 1 | GET /show-tech HTTP/1.1 2 | User-Agent: cisco-IOS 3 | Host: 1.1.12.1 4 | Authorization: Basic YWRtaW46Y2lzY28= 5 | Date: Fri, 01 Mar 2002 00:30:47 GMT 6 | Connection: close 7 | 8 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test8.txt: -------------------------------------------------------------------------------- 1 | GET / HTTP/1.1 2 | Host: 127.0.0.1 3 | User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:59.0) Gecko/20100101 Firefox/59.0 4 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 5 | Accept-Language: en-US,en;q=0.5 6 | Accept-Encoding: gzip, deflate 7 | Connection: keep-alive 8 | Upgrade-Insecure-Requests: 1 9 | 10 | -------------------------------------------------------------------------------- /fuzzer-dir/input-cases/test9.txt: -------------------------------------------------------------------------------- 1 | GET /?path=foo HTTP/1.1 2 | Host: 127.0.0.1 3 | User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:59.0) Gecko/20100101 Firefox/59.0 4 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 5 | Accept-Language: en-US,en;q=0.5 6 | Accept-Encoding: gzip, deflate 7 | Connection: keep-alive 8 | Upgrade-Insecure-Requests: 1 9 | 10 | -------------------------------------------------------------------------------- /fuzzer-dir/out-dir/.gitignore: -------------------------------------------------------------------------------- 1 | */** -------------------------------------------------------------------------------- /insert-fuzz.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Purpose 4 | # ---------- 5 | # .patch files with `diff` syntax are not always reliable, because the line-numbers might changes from version 6 | # to version, which requires us to create a dedicated .patch file for every version of apache. 7 | # This approach makes the whole process too tedious / version-specific. Which is why I preferred dedicating 8 | # this py file for hot-patching purposes in a 'universal way'(pseudo-regex approach) since our goal is to support 9 | # as many Apache versions as we can without breaking stuff in the process. 10 | 11 | 12 | # hot-patch #1: Enable fuzzing via stdin 13 | needle = 'int main(int argc, const char * const argv[])\n{' 14 | with open('./server/main.c', 'r') as f: 15 | haystack = f.read() 16 | 17 | with open('../fuzz.patch.c', 'r') as f: 18 | fuzzable = f.read() 19 | 20 | 21 | result = haystack.replace(needle, fuzzable) 22 | 23 | with open('./server/main.c', 'w') as f: 24 | f.write(result) 25 | 26 | print('[+] ./server/main.c is patched :^) \n') 27 | 28 | 29 | # hot-patch #2: Disable randomness to improve stability 30 | with open('./server/core.c', 'r') as f: 31 | haystack = f.read() 32 | 33 | with open('../fuzz.patch.c', 'r') as f: 34 | fuzzable = f.read() 35 | 36 | 37 | needle = 'rv = apr_generate_random_bytes(seed, sizeof(seed));' 38 | disable_random = ''' 39 | // ---- PATCH ----- 40 | // rv = apr_generate_random_bytes(seed, sizeof(seed)); 41 | char constant_seed[] = {0x78,0xAB,0xF5,0xDB,0xE2,0x7F,0xD2,0x8A}; 42 | memcpy(seed, constant_seed, sizeof(seed)); 43 | rv = APR_SUCCESS; 44 | //------------------------------------------------- 45 | 46 | ''' 47 | result = haystack.replace(needle, disable_random) 48 | 49 | with open('./server/core.c', 'w') as f: 50 | f.write(result) 51 | 52 | print('[+] ./server/core.c is patched :^) \n') --------------------------------------------------------------------------------