curl_easy_duphandle: CURLOPT_COPYPOSTFIELDS read out of bounds

When duplicating a handle, the data to post was duplicated using
strdup() when it could be binary and contain zeroes and it was not even
zero terminated! This caused read out of bounds crashes/segfaults.

Since the lib/strdup.c file no longer is easily shared with the curl
tool with this change, it now uses its own version instead.

Bug: http://curl.haxx.se/docs/adv_20141105.html
CVE: CVE-2014-3707
Reported-By: Symeon Paraschoudis
This commit is contained in:
Daniel Stenberg
2014-10-17 12:59:32 +02:00
parent d997c8b2f6
commit b387560692
9 changed files with 145 additions and 61 deletions

View File

@@ -125,6 +125,7 @@ int curl_win32_idn_to_ascii(const char *in, char **out);
#include "multihandle.h"
#include "pipeline.h"
#include "dotdot.h"
#include "strdup.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@@ -270,8 +271,9 @@ void Curl_freeset(struct SessionHandle *data)
{
/* Free all dynamic strings stored in the data->set substructure. */
enum dupstring i;
for(i=(enum dupstring)0; i < STRING_LAST; i++)
for(i=(enum dupstring)0; i < STRING_LAST; i++) {
Curl_safefree(data->set.str[i]);
}
if(data->change.referer_alloc) {
Curl_safefree(data->change.referer);
@@ -356,14 +358,24 @@ CURLcode Curl_dupset(struct SessionHandle *dst, struct SessionHandle *src)
memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
/* duplicate all strings */
for(i=(enum dupstring)0; i< STRING_LAST; i++) {
for(i=(enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
result = setstropt(&dst->set.str[i], src->set.str[i]);
if(result)
break;
return result;
}
/* If a failure occurred, freeing has to be performed externally. */
return result;
/* duplicate memory areas pointed to */
i = STRING_COPYPOSTFIELDS;
if(src->set.postfieldsize && src->set.str[i]) {
/* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
dst->set.str[i] = Curl_memdup(src->set.str[i], src->set.postfieldsize);
if(!dst->set.str[i])
return CURLE_OUT_OF_MEMORY;
/* point to the new copy */
dst->set.postfields = dst->set.str[i];
}
return CURLE_OK;
}
/*