Exploiting CVE-2002-0082
In this post we explore CVE-2002-0082 and try to exploit it. To do so we use the vulnerable virtual machine created for the Kioptrix 1 challenge.
Here is the summary for CVE-2002-0082 :
The dbm and shm session cache code in mod_ssl before 2.8.7-1.3.23, and Apache-SSL before 1.3.22+1.46, does not properly initialize memory using the i2d_SSL_SESSION function, which allows remote attackers to use a buffer overflow to execute arbitrary code via a large client certificate that is signed by a trusted Certificate Authority (CA), which produces a large serialized session.
Finding the error
By looking for CVE-2002-0082 we find an apacheweek security issue indicating that :
A buffer overflow has been found in mod_ssl in all versions prior to 2.8.7-1.3.23 (February 23rd 2002)
So we download versions 2.8.6-1.3.23 and 2.8.7-1.3.23 from the
modssl website.
In the CHANGES
file in version 2.8.7-1.3.23 we find the following indication
related to the security fix :
Fixed potential buffer overflow in DBM and SHMHT session cache if very very large certificate chains are used.
If we do a diff between the two versions we find that the files
pkg.sslmod/ssl_scache_dbm.c
and pkg.sslmod/ssl_scache_shmht.c
have been modified.
diff --git a/pkg.sslmod/ssl_scache_dbm.c b/pkg.sslmod/ssl_scache_dbm.
c
index 323c612..669658f 100644
--- a/pkg.sslmod/ssl_scache_dbm.c
+++ b/pkg.sslmod/ssl_scache_dbm.c
@@ -143,8 +143,10 @@ BOOL ssl_scache_dbm_store(server_rec *s, UCHAR *
id, int idlen, time_t expiry, SS
UCHAR *ucp;
/* streamline session data */
+ if ((nData = i2d_SSL_SESSION(sess, NULL)) > sizeof(ucaData))
+ return FALSE;
ucp = ucaData;
- nData = i2d_SSL_SESSION(sess, &ucp);
+ i2d_SSL_SESSION(sess, &ucp);
/* be careful: do not try to store too much bytes in a DBM file! */
diff --git a/pkg.sslmod/ssl_scache_shmht.c b/pkg.sslmod/ssl_scache_shmht.c
index 18e688a..fad41e0 100644
--- a/pkg.sslmod/ssl_scache_shmht.c
+++ b/pkg.sslmod/ssl_scache_shmht.c
@@ -175,8 +175,10 @@ BOOL ssl_scache_shmht_store(server_rec *s, UCHAR *id, int idlen, time_t expiry,
UCHAR *ucp;
/* streamline session data */
+ if ((nData = i2d_SSL_SESSION(sess, NULL)) > sizeof(ucaData))
+ return FALSE;
ucp = ucaData;
- nData = i2d_SSL_SESSION(sess, &ucp);
+ i2d_SSL_SESSION(sess, &ucp);
i2d_SSL_SESSION description
We download the OpenSSL code.
If we look at the CHANGES
file in version 2.8.7-1.3.23 we find that the changes
were made between the 01-Feb-2002 and 23-Feb-2002.
We revert the state of the code to a date prior to 01-Feb-2002 (let’s say 23-Jan-2002).
We picked the commit 9b2f486c9e95c79ab9a0f10a9f61a8792ed2a18d
:
git checkout 9b2f486c9e95c79ab9a0f10a9f61a8792ed2a18d
The code of the i2d_SSL_SESSION
function can be found in ssl_asn1.c
.
Click on the file name below if you want to see the whole function.
Here is what the documentation has to say about this function :
Description
i2d_SSL_SESSION() transforms the SSL_SESSION object in into the ASN1 representation and stores it into the memory location pointed to by pp. The length of the resulting ASN1 representation is returned. If pp is the NULL pointer, only the length is calculated and returned.
Notes
When using i2d_SSL_SESSION(), the memory location pointed to by pp must be large enough to hold the binary representation of the session. There is no known limit on the size of the created ASN1 representation, so the necessary amount of space should be obtained by first calling i2d_SSL_SESSION() with pp=NULL , and obtain the size needed, then allocate the memory and call i2d_SSL_SESSION() again.
Return values
i2d_SSL_SESSION() returns the size of the ASN1 representation in bytes. When the session is not valid, 0 is returned and no operation is performed.
Understanding the vulnerability in mod_ssl
What i2d_SSL_SESSION
does is convert an object into another and store it in pp.
The information was in the i2d_SSL_SESSION
notes.
The memory location pointed to by pp must be large enough to hold the binary
representation of the session.
The fact that the mod_ssl code did not verify the amount of space needed first
was the problem :
BOOL ssl_scache_dbm_store(server_rec *s, UCHAR *id, int idlen, time_t expiry, SSL_SESSION *sess)
{
SSLModConfigRec *mc = myModConfig();
DBM *dbm;
datum dbmkey;
datum dbmval;
UCHAR ucaData[SSL_SESSION_MAX_DER];
int nData;
UCHAR *ucp;
/* streamline session data */
ucp = ucaData;
nData = i2d_SSL_SESSION(sess, &ucp);
/* be careful: do not try to store too much bytes in a DBM file! \*/
...
}
In the code above we can see that the sess
object is converted and stored in
ucp
but no verification is done to verify that the converted session does not
overflow the bounds of ucp
.