mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2025-10-16 15:41:13 +02:00
2023-05-17 Fred Gleason <fredg@paravelsystems.com>
* Fixed a vulnerabilities in 'RDFormPost' that could allow maximum post length restrictions to be bypassed by use of a maliciously crafted HTTP transaction. Signed-off-by: Fred Gleason <fredg@paravelsystems.com>
This commit is contained in:
@@ -24124,3 +24124,7 @@
|
|||||||
2023-05-17 Fred Gleason <fredg@paravelsystems.com>
|
2023-05-17 Fred Gleason <fredg@paravelsystems.com>
|
||||||
* Fixed a regression in the WebAPI that caused imports to bypass the
|
* Fixed a regression in the WebAPI that caused imports to bypass the
|
||||||
maximum file size limitation set the 'System Settings' in rdadmin(1).
|
maximum file size limitation set the 'System Settings' in rdadmin(1).
|
||||||
|
2023-05-17 Fred Gleason <fredg@paravelsystems.com>
|
||||||
|
* Fixed a vulnerabilities in 'RDFormPost' that could allow maximum
|
||||||
|
post length restrictions to be bypassed by use of a maliciously
|
||||||
|
crafted HTTP transaction.
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
//
|
//
|
||||||
// Handle data from an HTML form.
|
// Handle data from an HTML form.
|
||||||
//
|
//
|
||||||
// (C) Copyright 2009-2021 Fred Gleason <fredg@paravelsystems.com>
|
// (C) Copyright 2009-2023 Fred Gleason <fredg@paravelsystems.com>
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or modify
|
// This program is free software; you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License version 2 as
|
// it under the terms of the GNU General Public License version 2 as
|
||||||
@@ -43,6 +43,7 @@ RDFormPost::RDFormPost(RDFormPost::Encoding encoding,int64_t maxsize,
|
|||||||
post_auto_delete=auto_delete;
|
post_auto_delete=auto_delete;
|
||||||
post_data=NULL;
|
post_data=NULL;
|
||||||
post_tempdir=NULL;
|
post_tempdir=NULL;
|
||||||
|
post_bytes_downloaded=0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Client Info
|
// Client Info
|
||||||
@@ -101,7 +102,13 @@ RDFormPost::RDFormPost(RDFormPost::Encoding encoding,int64_t maxsize,
|
|||||||
// (Perhaps) autodetect the encoding type
|
// (Perhaps) autodetect the encoding type
|
||||||
//
|
//
|
||||||
char first[2];
|
char first[2];
|
||||||
RDCheckExitCode("RDFormPost::RDFormPost read",read(0,first,1));
|
ssize_t s;
|
||||||
|
|
||||||
|
if((s=read(0,first,1))<=0) {
|
||||||
|
post_error=RDFormPost::ErrorMalformedData;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
post_bytes_downloaded+=1;
|
||||||
if(post_encoding==RDFormPost::AutoEncoded) {
|
if(post_encoding==RDFormPost::AutoEncoded) {
|
||||||
if(first[0]=='-') {
|
if(first[0]=='-') {
|
||||||
post_encoding=RDFormPost::MultipartEncoded;
|
post_encoding=RDFormPost::MultipartEncoded;
|
||||||
@@ -138,9 +145,11 @@ RDFormPost::~RDFormPost()
|
|||||||
if(post_tempdir!=NULL) {
|
if(post_tempdir!=NULL) {
|
||||||
delete post_tempdir;
|
delete post_tempdir;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if(post_data!=NULL) {
|
if(post_data!=NULL) {
|
||||||
delete post_data;
|
delete post_data;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,12 +572,13 @@ void RDFormPost::LoadUrlEncoding(char first)
|
|||||||
post_error=RDFormPost::ErrorMalformedData;
|
post_error=RDFormPost::ErrorMalformedData;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
post_bytes_downloaded+=n;
|
||||||
total_read+=n;
|
total_read+=n;
|
||||||
}
|
}
|
||||||
|
|
||||||
// post_data[post_content_length]=0;
|
|
||||||
post_data[total_read]=0;
|
post_data[total_read]=0;
|
||||||
lines=QString(post_data).split("&");
|
lines=QString(post_data).split("&");
|
||||||
|
|
||||||
for(int i=0;i<lines.size();i++) {
|
for(int i=0;i<lines.size();i++) {
|
||||||
line=lines[i].split("=",QString::KeepEmptyParts);
|
line=lines[i].split("=",QString::KeepEmptyParts);
|
||||||
for(int j=2;j<line.size();j++) {
|
for(int j=2;j<line.size();j++) {
|
||||||
@@ -596,6 +606,8 @@ void RDFormPost::LoadUrlEncoding(char first)
|
|||||||
|
|
||||||
void RDFormPost::LoadMultipartEncoding(char first)
|
void RDFormPost::LoadMultipartEncoding(char first)
|
||||||
{
|
{
|
||||||
|
bool ok=false;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Create Stream Reader
|
// Create Stream Reader
|
||||||
//
|
//
|
||||||
@@ -627,7 +639,11 @@ void RDFormPost::LoadMultipartEncoding(char first)
|
|||||||
//
|
//
|
||||||
// Get Separator Line
|
// Get Separator Line
|
||||||
//
|
//
|
||||||
post_separator=first+QString::fromUtf8(GetLine()).trimmed();
|
post_separator=first+QString::fromUtf8(GetLine(&ok)).trimmed();
|
||||||
|
if(!ok) {
|
||||||
|
post_error=RDFormPost::ErrorMalformedData;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Read Mime Parts
|
// Read Mime Parts
|
||||||
@@ -638,7 +654,11 @@ void RDFormPost::LoadMultipartEncoding(char first)
|
|||||||
bool again=false;
|
bool again=false;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
again=GetMimePart(&name,&value,&is_file);
|
again=GetMimePart(&name,&value,&is_file,&ok);
|
||||||
|
if(!ok) {
|
||||||
|
post_error=RDFormPost::ErrorMalformedData;
|
||||||
|
return;
|
||||||
|
}
|
||||||
post_values[name]=value;
|
post_values[name]=value;
|
||||||
post_filenames[name]=is_file;
|
post_filenames[name]=is_file;
|
||||||
} while(again);
|
} while(again);
|
||||||
@@ -646,7 +666,8 @@ void RDFormPost::LoadMultipartEncoding(char first)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool RDFormPost::GetMimePart(QString *name,QString *value,bool *is_file)
|
bool RDFormPost::GetMimePart(QString *name,QString *value,bool *is_file,
|
||||||
|
bool *ok)
|
||||||
{
|
{
|
||||||
QString line;
|
QString line;
|
||||||
int fd=-1;
|
int fd=-1;
|
||||||
@@ -659,7 +680,10 @@ bool RDFormPost::GetMimePart(QString *name,QString *value,bool *is_file)
|
|||||||
// Headers
|
// Headers
|
||||||
//
|
//
|
||||||
do {
|
do {
|
||||||
line=QString::fromUtf8(GetLine());
|
line=QString::fromUtf8(GetLine(ok));
|
||||||
|
if(!ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
QStringList f0=line.split(":");
|
QStringList f0=line.split(":");
|
||||||
if(f0.size()==2) {
|
if(f0.size()==2) {
|
||||||
if(f0[0].toLower()=="content-disposition") {
|
if(f0[0].toLower()=="content-disposition") {
|
||||||
@@ -692,20 +716,32 @@ bool RDFormPost::GetMimePart(QString *name,QString *value,bool *is_file)
|
|||||||
//
|
//
|
||||||
if(*is_file) {
|
if(*is_file) {
|
||||||
QByteArray data;
|
QByteArray data;
|
||||||
data=GetLine();
|
data=GetLine(ok);
|
||||||
|
if(!ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
line=QString::fromUtf8(data).trimmed();
|
line=QString::fromUtf8(data).trimmed();
|
||||||
while(!line.contains(post_separator)) {
|
while(!line.contains(post_separator)) {
|
||||||
RDCheckExitCode("RDFormPost::GetMimePart write",
|
RDCheckExitCode("RDFormPost::GetMimePart write",
|
||||||
write(fd,data,data.length()));
|
write(fd,data,data.length()));
|
||||||
data=GetLine();
|
data=GetLine(ok);
|
||||||
|
if(!ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
line=QString::fromUtf8(data).trimmed();
|
line=QString::fromUtf8(data).trimmed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
line=QString::fromUtf8(GetLine());
|
line=QString::fromUtf8(GetLine(ok));
|
||||||
|
if(!ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
while((!line.isEmpty())&&(!line.contains(post_separator))) {
|
while((!line.isEmpty())&&(!line.contains(post_separator))) {
|
||||||
*value+=line;
|
*value+=line;
|
||||||
line=QString::fromUtf8(GetLine());
|
line=QString::fromUtf8(GetLine(ok));
|
||||||
|
if(!ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*value=value->trimmed();
|
*value=value->trimmed();
|
||||||
}
|
}
|
||||||
@@ -721,13 +757,18 @@ bool RDFormPost::GetMimePart(QString *name,QString *value,bool *is_file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QByteArray RDFormPost::GetLine() const
|
QByteArray RDFormPost::GetLine(bool *ok)
|
||||||
{
|
{
|
||||||
char *data=NULL;
|
char *data=NULL;
|
||||||
size_t n=0;
|
size_t n=0;
|
||||||
|
|
||||||
n=getline(&data,&n,post_stream);
|
if((n=getline(&data,&n,post_stream))<0) {
|
||||||
|
*ok=false;
|
||||||
|
}
|
||||||
|
post_bytes_downloaded+=n;
|
||||||
QByteArray ret(data,n);
|
QByteArray ret(data,n);
|
||||||
free(data);
|
free(data);
|
||||||
|
*ok=true;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
//
|
//
|
||||||
// Handle POST data from an HTML form.
|
// Handle POST data from an HTML form.
|
||||||
//
|
//
|
||||||
// (C) Copyright 2009-2020 Fred Gleason <fredg@paravelsystems.com>
|
// (C) Copyright 2009-2023 Fred Gleason <fredg@paravelsystems.com>
|
||||||
//
|
//
|
||||||
// This program is free software; you can redistribute it and/or modify
|
// This program is free software; you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License version 2 as
|
// it under the terms of the GNU General Public License version 2 as
|
||||||
@@ -67,8 +67,8 @@ class RDFormPost
|
|||||||
private:
|
private:
|
||||||
void LoadUrlEncoding(char first);
|
void LoadUrlEncoding(char first);
|
||||||
void LoadMultipartEncoding(char first);
|
void LoadMultipartEncoding(char first);
|
||||||
bool GetMimePart(QString *name,QString *value,bool *is_file);
|
bool GetMimePart(QString *name,QString *value,bool *is_file,bool *ok);
|
||||||
QByteArray GetLine() const;
|
QByteArray GetLine(bool *ok);
|
||||||
QHostAddress post_client_address;
|
QHostAddress post_client_address;
|
||||||
RDFormPost::Encoding post_encoding;
|
RDFormPost::Encoding post_encoding;
|
||||||
RDFormPost::Error post_error;
|
RDFormPost::Error post_error;
|
||||||
@@ -79,6 +79,7 @@ class RDFormPost
|
|||||||
int64_t post_content_length;
|
int64_t post_content_length;
|
||||||
QString post_content_type;
|
QString post_content_type;
|
||||||
char *post_data;
|
char *post_data;
|
||||||
|
int64_t post_bytes_downloaded;
|
||||||
QString post_separator;
|
QString post_separator;
|
||||||
FILE *post_stream;
|
FILE *post_stream;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user