fix a potential DoS (through memory exhaustion) by restricting HTML form field name and value sizes

This commit is contained in:
Guenter Obiltschnig 2017-01-24 13:14:05 +01:00
parent 11845334dc
commit 3eda8f40bb
2 changed files with 47 additions and 8 deletions

View File

@ -184,11 +184,19 @@ public:
/// Specify 0 for unlimited (not recommended). /// Specify 0 for unlimited (not recommended).
/// ///
/// The default limit is 100. /// The default limit is 100.
void setValueLengthLimit(int limit);
/// Sets the maximum size for form field values
/// stored as strings.
int getValueLengthLimit() const;
/// Returns the maximum size for form field values
/// stored as strings.
static const std::string ENCODING_URL; /// "application/x-www-form-urlencoded" static const std::string ENCODING_URL; /// "application/x-www-form-urlencoded"
static const std::string ENCODING_MULTIPART; /// "multipart/form-data" static const std::string ENCODING_MULTIPART; /// "multipart/form-data"
static const int UNKNOWN_CONTENT_LENGTH; static const int UNKNOWN_CONTENT_LENGTH;
protected: protected:
void readUrl(std::istream& istr); void readUrl(std::istream& istr);
void readMultipart(std::istream& istr, PartHandler& handler); void readMultipart(std::istream& istr, PartHandler& handler);
@ -201,7 +209,9 @@ private:
enum Limits enum Limits
{ {
DFL_FIELD_LIMIT = 100 DFL_FIELD_LIMIT = 100,
MAX_NAME_LENGTH = 1024,
DFL_MAX_VALUE_LENGTH = 256*1024
}; };
struct Part struct Part
@ -213,6 +223,7 @@ private:
typedef std::vector<Part> PartVec; typedef std::vector<Part> PartVec;
int _fieldLimit; int _fieldLimit;
int _valueLengthLimit;
std::string _encoding; std::string _encoding;
std::string _boundary; std::string _boundary;
PartVec _parts; PartVec _parts;
@ -240,6 +251,12 @@ inline int HTMLForm::getFieldLimit() const
} }
inline int HTMLForm::getValueLengthLimit() const
{
return _valueLengthLimit;
}
} } // namespace Poco::Net } } // namespace Poco::Net

View File

@ -73,6 +73,7 @@ private:
HTMLForm::HTMLForm(): HTMLForm::HTMLForm():
_fieldLimit(DFL_FIELD_LIMIT), _fieldLimit(DFL_FIELD_LIMIT),
_valueLengthLimit(DFL_MAX_VALUE_LENGTH),
_encoding(ENCODING_URL) _encoding(ENCODING_URL)
{ {
} }
@ -80,27 +81,31 @@ HTMLForm::HTMLForm():
HTMLForm::HTMLForm(const std::string& encoding): HTMLForm::HTMLForm(const std::string& encoding):
_fieldLimit(DFL_FIELD_LIMIT), _fieldLimit(DFL_FIELD_LIMIT),
_valueLengthLimit(DFL_MAX_VALUE_LENGTH),
_encoding(encoding) _encoding(encoding)
{ {
} }
HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler): HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler):
_fieldLimit(DFL_FIELD_LIMIT) _fieldLimit(DFL_FIELD_LIMIT),
_valueLengthLimit(DFL_MAX_VALUE_LENGTH)
{ {
load(request, requestBody, handler); load(request, requestBody, handler);
} }
HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody): HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody):
_fieldLimit(DFL_FIELD_LIMIT) _fieldLimit(DFL_FIELD_LIMIT),
_valueLengthLimit(DFL_MAX_VALUE_LENGTH)
{ {
load(request, requestBody); load(request, requestBody);
} }
HTMLForm::HTMLForm(const HTTPRequest& request): HTMLForm::HTMLForm(const HTTPRequest& request):
_fieldLimit(DFL_FIELD_LIMIT) _fieldLimit(DFL_FIELD_LIMIT),
_valueLengthLimit(DFL_MAX_VALUE_LENGTH)
{ {
load(request); load(request);
} }
@ -300,7 +305,10 @@ void HTMLForm::readUrl(std::istream& istr)
while (ch != eof && ch != '=' && ch != '&') while (ch != eof && ch != '=' && ch != '&')
{ {
if (ch == '+') ch = ' '; if (ch == '+') ch = ' ';
name += (char) ch; if (name.size() < MAX_NAME_LENGTH)
name += (char) ch;
else
throw HTMLFormException("Field name too long");
ch = istr.get(); ch = istr.get();
} }
if (ch == '=') if (ch == '=')
@ -309,7 +317,10 @@ void HTMLForm::readUrl(std::istream& istr)
while (ch != eof && ch != '&') while (ch != eof && ch != '&')
{ {
if (ch == '+') ch = ' '; if (ch == '+') ch = ' ';
value += (char) ch; if (value.size() < _valueLengthLimit)
value += (char) ch;
else
throw HTMLFormException("Field value too long");
ch = istr.get(); ch = istr.get();
} }
} }
@ -363,7 +374,10 @@ void HTMLForm::readMultipart(std::istream& istr, PartHandler& handler)
int ch = istr.get(); int ch = istr.get();
while (ch != eof) while (ch != eof)
{ {
value += (char) ch; if (value.size() < _valueLengthLimit)
value += (char) ch;
else
throw HTMLFormException("Field value too long");
ch = istr.get(); ch = istr.get();
} }
add(name, value); add(name, value);
@ -445,4 +459,12 @@ void HTMLForm::setFieldLimit(int limit)
} }
void HTMLForm::setValueLengthLimit(int limit)
{
poco_assert (limit >= 0);
_valueLengthLimit = limit;
}
} } // namespace Poco::Net } } // namespace Poco::Net