[Opalvoip-svn] SF.net SVN: opalvoip:[34640] ptlib/branches/v2_16
Brought to you by:
csoutheren,
rjongbloed
From: <rjo...@us...> - 2016-02-21 12:41:53
|
Revision: 34640 http://sourceforge.net/p/opalvoip/code/34640 Author: rjongbloed Date: 2016-02-21 12:41:51 +0000 (Sun, 21 Feb 2016) Log Message: ----------- Disable all XML entity expansion, unless re-enabled via PCML::Option, to finally protect against "billion laughs" attack. The previous mothod did not protect against expansion within element attributes, only in data. Modified Paths: -------------- ptlib/branches/v2_16/include/ptclib/pxml.h ptlib/branches/v2_16/src/ptclib/pxml.cxx Modified: ptlib/branches/v2_16/include/ptclib/pxml.h =================================================================== --- ptlib/branches/v2_16/include/ptclib/pxml.h 2016-02-19 12:26:00 UTC (rev 34639) +++ ptlib/branches/v2_16/include/ptclib/pxml.h 2016-02-21 12:41:51 UTC (rev 34640) @@ -54,12 +54,12 @@ PCLASSINFO(PXMLBase, PObject); public: enum { - DEFAULT_MAX_ENTITY_LENGTH = 4096 + DEFAULT_MAX_ENTITY_LENGTH = 65536 }; P_DECLARE_BITWISE_ENUM_EX( Options, - 7, + 8, ( NoOptions, Indent, @@ -68,9 +68,10 @@ NoIgnoreWhiteSpace, CloseExtended, WithNS, - FragmentOnly + FragmentOnly, + ExpandEntities ), - AllOptions = (1<<(6+1))-1 + AllOptions = (1<<8)-1 ); enum StandAloneType { @@ -499,7 +500,7 @@ class PXMLParserBase { protected: - PXMLParserBase(bool withNS); + PXMLParserBase(PXMLBase::Options options); public: ~PXMLParserBase(); @@ -515,6 +516,14 @@ virtual void StartElement(const char * name, const char **attrs) = 0; virtual void EndElement(const char * name) = 0; virtual void AddCharacterData(const char * data, int len) = 0; + virtual void Entity(const char *entityName, + int is_parameter_entity, + const char *value, + int value_length, + const char *base, + const char *systemId, + const char *publicId, + const char *notationName); virtual bool Progress() { return true; } @@ -530,6 +539,7 @@ off_t m_consumed; unsigned m_percent; bool m_userAborted; + bool m_expandEntities; }; Modified: ptlib/branches/v2_16/src/ptclib/pxml.cxx =================================================================== --- ptlib/branches/v2_16/src/ptclib/pxml.cxx 2016-02-19 12:26:00 UTC (rev 34639) +++ ptlib/branches/v2_16/src/ptclib/pxml.cxx 2016-02-21 12:41:51 UTC (rev 34640) @@ -122,14 +122,29 @@ } -PXMLParserBase::PXMLParserBase(bool withNS) +static void PXML_EntityDeclHandler(void *userData, + const XML_Char *entityName, + int is_parameter_entity, + const XML_Char *value, + int value_length, + const XML_Char *base, + const XML_Char *systemId, + const XML_Char *publicId, + const XML_Char *notationName) +{ + ((PXMLParserBase *)userData)->Entity(entityName, is_parameter_entity, value, value_length, base, systemId, publicId, notationName); +} + + +PXMLParserBase::PXMLParserBase(PXMLBase::Options options) : m_parsing(true) , m_total(0) , m_consumed(0) , m_percent(0) , m_userAborted(false) + , m_expandEntities(options & PXMLBase::ExpandEntities) { - if (withNS) + if (options & PXMLBase::WithNS) m_context = XML_ParserCreateNS(NULL, '|'); else m_context = XML_ParserCreate(NULL); @@ -141,6 +156,7 @@ XML_SetXmlDeclHandler (MY_CONTEXT, PXML_XmlDeclHandler); XML_SetDoctypeDeclHandler (MY_CONTEXT, PXML_StartDocTypeDecl, PXML_EndDocTypeDecl); XML_SetNamespaceDeclHandler(MY_CONTEXT, PXML_StartNamespaceDeclHandler, PXML_EndNamespaceDeclHandler); + XML_SetEntityDeclHandler (MY_CONTEXT, PXML_EntityDeclHandler); } @@ -238,7 +254,7 @@ PXMLParser::PXMLParser(PXML & doc, Options options, off_t progressTotal) : PXMLBase(options) - , PXMLParserBase(options & WithNS) + , PXMLParserBase(options) , m_document(doc) , m_currentElement(NULL) , m_lastData(NULL) @@ -335,7 +351,7 @@ unsigned checkLen = len + ((m_lastData != NULL) ? m_lastData->GetString().GetLength() : 0); if (checkLen >= m_maxEntityLength) { PTRACE(2, "PXML\tAborting XML parse at size " << m_maxEntityLength << " - possible 'billion laugh' attack"); - XML_StopParser((XML_Parser)m_context, XML_FALSE); + XML_StopParser(MY_CONTEXT, XML_FALSE); return; } @@ -365,6 +381,24 @@ } +void PXMLParserBase::Entity(const char * /*entityName*/, + int /*is_parameter_entity*/, + const char * /*value*/, + int /*value_length*/, + const char * /*base*/, + const char * /*systemId*/, + const char * /*publicId*/, + const char * /*notationName*/) +{ + if (m_expandEntities) + return; + + // Disable entity expansion completely to prevent billion laughs attack + PTRACE(2, "PXML\tAborting XML parse at when expanding entity - possible 'billion laughs' attack"); + XML_StopParser(MY_CONTEXT, XML_FALSE); +} + + /////////////////////////////////////////////////////////////////////////////////////////////// PXML::PXML(Options options, const char * noIndentElementsParam) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |