Bugzilla – Bug 1016712
VUL-1: CVE-2016-0736: apache2: Padding Oracle in Apache mod_session_crypto
Last modified: 2017-08-04 00:54:20 UTC
https://httpd.apache.org/security/vulnerabilities_24.html low: Padding Oracle in Apache mod_session_crypto CVE-2016-0736 Authenticate the session data/cookie presented to mod_session_crypto with a MAC (SipHash) to prevent deciphering or tampering with a padding oracle attack. Acknowledgements: We would like to thank Alexander Neumann of RedTeam Pentesting for reporting this issue. Reported to security team: 20th January 2016 Issue public: 20th December 2016 Update Released: 20th December 2016 Affects: 2.4.23, 2.4.20, 2.4.18, 2.4.17, 2.4.16, 2.4.12, 2.4.10, 2.4.9, 2.4.7, 2.4.6, 2.4.4, 2.4.3, 2.4.2, 2.4.1
https://svn.apache.org/viewvc?view=revision&sortby=date&revision=1772812 I think.
bugbot adjusting priority
2.4 commit http://svn.apache.org/viewvc?view=revision&revision=1772925
Testcase can be found here: http://seclists.org/fulldisclosure/2016/Dec/74 mod_session_crypto is available from 2.3 on, 2.2 is not affected.
(In reply to Petr Gajdos from comment #6) > Testcase can be found here: > http://seclists.org/fulldisclosure/2016/Dec/74 Unfortunately I do not understand fully the test case flow and maybe also not the issue itself. I tried the procedure with 2.4.25 until following paragraph: " This verifies the existence of the Padding Oracle vulnerability. The Python library[1] python-paddingoracle was then used to implement decrypting the session by exploiting the Padding Oracle vulnerability. " and the result seem to be basically the same (see below). The first sentence of paragraph cited evokes that the issue can be seen already by the step right above, but I do not see how. Could you please advise? I understand that the python library can be used then to decrypt the session cookie and encrypt another one, but can be the vulnerability proven without it? The paragraph cited seem to me to claim that it can. So far tried with: ---- httpd.conf ServerName test User pgajdos Group users Listen 60080 PidFile /tmp/apache-rex/mod_session_crypto-oracle-padding/pid ErrorLog /tmp/apache-rex/mod_session_crypto-oracle-padding/error_log LoadModule auth_basic_module /usr/lib64/apache2-prefork/mod_auth_basic.so LoadModule dir_module /usr/lib64/apache2-prefork/mod_dir.so LoadModule authz_host_module /usr/lib64/apache2-prefork/mod_authz_host.so LoadModule session_module /usr/lib64/apache2-prefork/mod_session.so LoadModule session_cookie_module /usr/lib64/apache2-prefork/mod_session_cookie.so LoadModule session_crypto_module /usr/lib64/apache2-prefork/mod_session_crypto.so LoadModule cgi_module /usr/lib64/apache2-prefork/mod_cgi.so LoadModule mime_module /usr/lib64/apache2-prefork/mod_mime.so LoadModule authz_core_module /usr/lib64/apache2-prefork/mod_authz_core.so DocumentRoot /tmp/apache-rex/mod_session_crypto-oracle-padding/htdocs DirectoryIndex index.html ### example configuration # http://seclists.org/fulldisclosure/2016/Dec/74 <Directory "/tmp/apache-rex/mod_session_crypto-oracle-padding/htdocs"> Options +ExecCGI AddHandler cgi-script .sh Session On SessionEnv On SessionCookieName session path=/ SessionHeader X-Replace-Session SessionCryptoPassphrase RedTeam </Directory> ----- #!/bin/bash #echo #echo "HTTP_USER_AGENT: $HTTP_USER_AGENT" echo "Content-type: text/plain" username=$(echo "$HTTP_SESSION" | sed 's:.*username=\([^&]*\)&.*:\1:') if [ -n "$username" ]; then echo echo "your username is $username" else echo "X-Replace-Session: username=guest×tamp=$(date +"%s")" echo echo "not logged in" fi ----- $ curl -i http://localhost:60080/status.sh HTTP/1.1 200 OK Date: Wed, 01 Mar 2017 11:49:25 GMT Server: Apache/2.4.25 (Linux/SUSE) Set-Cookie: session=mjkJBylikPD+zfEKdYxE5rrKCVQhjy5fSnhdlapkjT+y5arRejk8f5noOoSl+tV67U7rodEqMKOTGPNmA69+/SSc3XDpCWUzNyM6nlEvv3RBCFj4t6jRlA==;path=/ Cache-Control: no-cache Set-Cookie: session=mjkJBylikPD+zfEKdYxE5rrKCVQhjy5fSnhdlapkjT+y5arRejk8f5noOoSl+tV67U7rodEqMKOTGPNmA69+/SSc3XDpCWUzNyM6nlEvv3RBCFj4t6jRlA==;path=/ Content-Length: 14 Content-Type: text/plain not logged in $ curl -b 'session=mjkJBylikPD+zfEKdYxE5rrKCVQhjy5fSnhdlapkjT+y5arRejk8f5noOoSl+tV67U7rodEqMKOTGPNmA69+/SSc3XDpCWUzNyM6nlEvv3RBCFj4t6jRlA==;path=/' http://localhost:60080/status.sh your username is guest $ Now change A== to a==. $ curl -b 'session=mjkJBylikPD+zfEKdYxE5rrKCVQhjy5fSnhdlapkjT+y5arRejk8f5noOoSl+tV67U7rodEqMKOTGPNmA69+/SSc3XDpCWUzNyM6nlEvv3RBCFj4t6jRla==;path=/' http://localhost:60080/status.sh not logged in $ Now change A== to A<=. $ curl -b 'session=mjkJBylikPD+zfEKdYxE5rrKCVQhjy5fSnhdlapkjT+y5arRejk8f5noOoSl+tV67U7rodEqMKOTGPNmA69+/SSc3XDpCWUzNyM6nlEvv3RBCFj4t6jRlA<=;path=/' http://localhost:60080/status.sh your username is guest $ What I am missing?
How the error reply already "verifies the existence of the padding oracle" is a bit unclear to me, too. The thing is that when the server responds with a seemingly _correctly_ decrypted session, although we've meddled with the encrypted data, we have the extra knowledge. This is what happens in the python script in the oracle() function. They manipulate single bytes of the encrypted message until the server responds with a valid session. This way they can guess the cleartext byte by byte. You can read up on this here: https://en.wikipedia.org/wiki/Padding_oracle_attack#Example_of_the_attack_on_CBC_encryption I'd just continue with the python script, if it can decrypt the session we have the proof.
Created attachment 716042 [details] joined paddingoracle.py and exploit.py I have not been successful. Running with 2.4.23, I get: $ curl -i http://localhost:60080/status.sh HTTP/1.1 200 OK Date: Thu, 02 Mar 2017 10:55:36 GMT Server: Apache/2.4.23 (Linux/SUSE) Set-Cookie: session=3j1JdPc0GY/cBTGw+7pI+a6QRmKOGUjFG9STlDrFs3N+hGzpSR2fxt6lC7m9wAwS7ZOj7cqRYlwo94XSNGGiD7xES4MDni5rHtb550MmylWwDDfTVTCtXA==;path=/ Cache-Control: no-cache Set-Cookie: session=3j1JdPc0GY/cBTGw+7pI+a6QRmKOGUjFG9STlDrFs3N+hGzpSR2fxt6lC7m9wAwS7ZOj7cqRYlwo94XSNGGiD7xES4MDni5rHtb550MmylWwDDfTVTCtXA==;path=/ Content-Length: 14 Content-Type: text/plain not logged in $ python exploit.py decrypt 3j1JdPc0GY/cBTGw+7pI+a6QRmKOGUjFG9STlDrFs3N+hGzpSR2fxt6lC7m9wAwS7ZOj7cqRYlwo94XSNGGiD7xES4MDni5rHtb550MmylWwDDfTVTCtXA== 56 Traceback (most recent call last): File "exploit.py", line 381, in <module> cookie = padbuster.decrypt(session[32:], block_size=16, iv=session[16:32]) File "exploit.py", line 125, in decrypt "Ciphertext not of block size %d" % (block_size, ) AssertionError: Ciphertext not of block size 16 $ len(ciphertext) is printed before 'Traceback most recent call last):' line. -- The time I had for the poc testing is over, in case none else want to play around, let us leave it as it is now. The patch apply cleanly so far.
(In reply to pgajdos@suse.com from comment #9) > I have not been successful. Running with 2.4.23, I get: > [...] > $ python exploit.py decrypt 3j1JdPc0GY/cBTGw+7pI+a6QRmKOGUjFG9STlDrFs3N+hGzpSR2fxt6lC7m9wAwS7ZOj7cqRYlwo94XSNGGiD7xES4MDni5rHtb550MmylWwDDfTVTCtXA== > [...] > AssertionError: Ciphertext not of block size 16 Well this is strange, somehow your apache is issuing a different kind of session cookie than expected. Is your mod_session_crypto configured correctly? In my setup the PoC is working. On Leap 42.2, using apache 2.4.23-6.1. Did the following: a2enmod session a2enmod session_crypto a2enmod session_cookie <Directory "/srv/www/crypto_oracle"> Session on SessionEnv on SessionCookieName session path=/ SessionHeader X-Replace-Session SessionCryptoPassphrase WhiteTeam Options +ExecCGI AddHandler cgi-script .rb </Directory> Place the `status.rb` script into the served directory. Make sure it gets executed correctly when fetching via curl. I've installed the python paddingoracle module via pip: zypper install python-pip pip2 install paddingoracle --user Then I've obtained the exploit.py script and adjusted the http URL to match my apache configuration. Testing the exploit: $ curl -i http://localhost/status.rb [...] Set-Cookie: session=tk6nw2vYQHOzaoBYHNzMYhhlT7srxWzpehdxJnJKiuewlAjH5ED4QMtP7vyy/YCG1lmxjRFSixPm3c33SAnGQOIyGC8pC8hPHwbLJ9ht9WI=;path=/ [...] $ ./exploit.py decrypt tk6nw2vYQHOzaoBYHNzMYhhlT7srxWzpehdxJnJKiuewlAjH5ED4QMtP7vyy/YCG1lmxjRFSixPm3c33SAnGQOIyGC8pC8hPHwbLJ9ht9WI= (takes some minutes to complete) Decrypted session: bytearray(b'username=guest×tamp=1488456163\r\r\r\r\r\r\r\r\r\r\r\r\r')
(In reply to Matthias Gerstner from comment #11) > $ ./exploit.py decrypt > tk6nw2vYQHOzaoBYHNzMYhhlT7srxWzpehdxJnJKiuewlAjH5ED4QMtP7vyy/ > YCG1lmxjRFSixPm3c33SAnGQOIyGC8pC8hPHwbLJ9ht9WI= > (takes some minutes to complete) > Decrypted session: > bytearray(b'username=guest×tamp=1488456163\r\r\r\r\r\r\r\r\r\r\r\r\r') Still not successful. I run httpd on changeroot and just with httpd.conf provided in comment 7. That could be the problem. Nevermind, now we know how to reproduce, many thanks!
SUSE-SU-2017:0797-1: An update that solves three vulnerabilities and has one errata is now available. Category: security (moderate) Bug References: 1016712,1016714,1016715,1019380 CVE References: CVE-2016-0736,CVE-2016-2161,CVE-2016-8743 Sources used: SUSE Linux Enterprise Software Development Kit 12-SP2 (src): apache2-2.4.23-21.1 SUSE Linux Enterprise Server for Raspberry Pi 12-SP2 (src): apache2-2.4.23-21.1 SUSE Linux Enterprise Server 12-SP2 (src): apache2-2.4.23-21.1
SUSE-SU-2017:0801-1: An update that solves three vulnerabilities and has one errata is now available. Category: security (moderate) Bug References: 1016712,1016714,1016715,980663 CVE References: CVE-2016-0736,CVE-2016-2161,CVE-2016-8743 Sources used: SUSE Linux Enterprise Software Development Kit 12-SP1 (src): apache2-2.4.16-19.1 SUSE Linux Enterprise Server 12-SP1 (src): apache2-2.4.16-19.1
openSUSE-SU-2017:0897-1: An update that solves three vulnerabilities and has one errata is now available. Category: security (moderate) Bug References: 1016712,1016714,1016715,1019380 CVE References: CVE-2016-0736,CVE-2016-2161,CVE-2016-8743 Sources used: openSUSE Leap 42.2 (src): apache2-2.4.23-8.3.1
openSUSE-SU-2017:0903-1: An update that solves three vulnerabilities and has one errata is now available. Category: security (moderate) Bug References: 1016712,1016714,1016715,980663 CVE References: CVE-2016-0736,CVE-2016-2161,CVE-2016-8743 Sources used: openSUSE Leap 42.1 (src): apache2-2.4.16-18.1
released