xercesc::DOMLSParserImpl::doctypeDecl 从 xercesc 接收到内部和外部实体的错误输入

问题描述 投票:0回答:0

实际上,它接收内部和外部实体切换的参数。方法签名:

virtual void doctypeDecl (const xercesc::DTDElementDecl& root,
               const XMLCh* const             public_id,
               const XMLCh* const             system_id,
               const bool                     has_internal,
               const bool                     has_external)

对于具有外部实体的文件,它得到

has_internal = true and has_external = false
,

以及具有内部实体的文档

has_internal = false and has_external = true
.

如何检测到

在我们的项目中,我们使用的是 libxsd-3.3.0,它使用 xercesc-3.4.1.

为了修补 libxsd 中的 XXE 漏洞,我们应用了以下解决方案https://www.codesynthesis.com/pipermail/xsd-users/2015-September/004689.html。简而言之,解决方案建议将 xercesc::DOMLSParserImpl 子类化并重新实现 doctypeDecl 方法。如果文档具有外部(或内部)实体,我们应该在其中通过 bool 参数得到通知,并且能够根据需要做出反应,例如:

void SecureDOMParser::doctypeDecl (const DTDElementDecl& e, 
             const XMLCh* const    pub_id,
             const XMLCh* const    sys_id,
             const bool            hasi,
             const bool            hase)
{
  if (hasi || hase)
    ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager);

  DOMLSParserImpl::doctypeDecl (e, pub_id, sys_id, hasi, hase);
}

上面链接提供的解决方案,包含内部和外部实体的示例,我们在测试 XML 中重复使用了这些示例。

原始示例按预期工作,但是,由于我们只需要避免外部实体,解决方案按以下方式调整:

void SecureDOMParser::doctypeDecl (const DTDElementDecl& e,
             const XMLCh* const    pub_id,
             const XMLCh* const    sys_id,
             const bool            hasi,
             const bool            hase)
{
  if (hase)   // modified here
    ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager);

  DOMLSParserImpl::doctypeDecl (e, pub_id, sys_id, hasi, hase);
}

在这种形式下,它不会抛出具有外部实体的文档。如果用

if (hasi)
代替它确实会抛出。

在 if 子句中添加额外的登录后得到确认,例如:

void SecureDOMParser::doctypeDecl (const DTDElementDecl& e,
             const XMLCh* const    pub_id,
             const XMLCh* const    sys_id,
             const bool            hasi,
             const bool            hase)
{
  if (hasi || hase)
  {
    // added logging
    std::cout << "has external: " << hase << " has internal: " << hasi;
        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager);                      
  }

  DOMLSParserImpl::doctypeDecl (e, pub_id, sys_id, hasi, hase);
}

此日志记录的输出将如开头所述 - 反之亦然。

还有其他人遇到过这个吗?这是已知的错误吗?

c++ xsd xerces xerces-c
© www.soinside.com 2019 - 2024. All rights reserved.