gpt4 book ai didi

c - 如何在 libxml2in C 中禁用 XXE?

转载 作者:太空狗 更新时间:2023-10-29 15:38:34 26 4
gpt4 key购买 nike

要求:当我将以下请求传递给我的应用程序时,

1)如何对这种存在风险的输入xml进行XML验证

2) 如何在 libxml2 中禁用 XXE,即不应该解析 ENTITY 字段

<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY foo SYSTEM "file:///etc/issue">
]><TRANSACTION>
<FUNCTION_TYPE>LINE_ITEM</FUNCTION_TYPE>
<COMMAND>ADD</COMMAND>
<COUNTER>3</COUNTER>
<MAC>qof2EtycqT9YMcmOfKowpyXVbRpgM/7rncS3liK4JOs=</MAC>
<MAC_LABEL>P_206</MAC_LABEL>
<RUNNING_TAX_AMOUNT>0.00</RUNNING_TAX_AMOUNT>
<RUNNING_TRANS_AMOUNT>1.00</RUNNING_TRANS_AMOUNT>
<LINE_ITEMS>
<MERCHANDISE>
<LINE_ITEM_ID>1</LINE_ITEM_ID>
<DESCRIPTION>&foo;</DESCRIPTION>
<QUANTITY>1</QUANTITY>
<UNIT_PRICE>5.00</UNIT_PRICE>
<EXTENDED_PRICE>5.00</EXTENDED_PRICE>
</MERCHANDISE>
</LINE_ITEMS>
</TRANSACTION>

据我所知,从 libxml2 2.9 版开始,XXE 已默认禁用。但我们目前使用的是 2.7.7 版本。

根据此链接XML_ENTITY_PROCESSING

Enum xmlParserOption 不应在 libxml2 中定义以下选项:

XML_PARSE_NOENT:扩展实体并用替换文本替换它们XML_PARSE_DTDLOAD:加载外部DTD

直到现在,我一直在使用 xmlParseMemory 函数来解析内存中的 XML block 并构建树。此函数不采用任何参数来设置 xmlParserOption。

然后我更改为 xmlReadMemory 函数,它也与 xmlParseMemory 函数做同样的事情,但采用不同的参数。

docPtr = xmlReadMemory(szXMLMsg, iLen, "noname.xml", NULL, XML_PARSE_RECOVER);

我仍然观察到 ENTITY 字段正在被解析。谁能帮帮我?如果您需要更多信息,请告诉我。

感谢您的宝贵时间。

问候

普拉文

最佳答案

如果您指定XML_PARSE_NOENTENTITY 声明仍会被解析,但实体不会被替换。此外,文件 /etc/issue 不会打开,您可以使用 strace 进行验证。因此,为了防止 XXE,您只需不传递 XML_PARSE_NOENT 解析器选项即可。

选项的名称有点误导,XML_PARSE_NOENT 表示不应在已解析的文档中创建任何实体节点。因此,每个实体都被扩展了。更好的名称应类似于 XML_PARSE_EXPAND_ENTITIES

如果你真的想确定或者你想扩展实体来细粒度地控制要加载的 URL,你可以使用 xmlSetExternalEntityLoader 安装你自己的外部实体加载器。 .如果您的处理程序总是返回 NULL,那么您就安全了。但请注意,外部实体加载器用于加载各种外部资源,因此完全禁用它可能会破坏其他内容(例如 XIncludes 或 XSLT 样式表)。

编辑: 我不知道为什么在您的案例中实体被替换了。这是一个测试程序:

#include <stdio.h>
#include <stdlib.h>
#include <libxml/parser.h>
#include <libxml/tree.h>

static xmlNodePtr
find_node(xmlNodePtr parent, const char *name) {
for (xmlNodePtr cur = parent->children; cur != NULL; cur = cur->next) {
if (cur->type == XML_ELEMENT_NODE
&& xmlStrcmp(cur->name, (const xmlChar*)name) == 0
) {
return cur;
}
}

fprintf(stderr, "Element '%s' not found\n", name);
abort();

return NULL;
}

int
main(int argc, char **argv) {
static const char buf[] =
"<?xml version=\"1.0\"?>\n"
"<!DOCTYPE foo [\n"
"<!ENTITY foo SYSTEM \"file:///etc/issue\">\n"
"]><TRANSACTION>\n"
"<FUNCTION_TYPE>LINE_ITEM</FUNCTION_TYPE>\n"
"<COMMAND>ADD</COMMAND>\n"
"<COUNTER>3</COUNTER>\n"
"<MAC>qof2EtycqT9YMcmOfKowpyXVbRpgM/7rncS3liK4JOs=</MAC>\n"
"<MAC_LABEL>P_206</MAC_LABEL>\n"
"<RUNNING_TAX_AMOUNT>0.00</RUNNING_TAX_AMOUNT>\n"
"<RUNNING_TRANS_AMOUNT>1.00</RUNNING_TRANS_AMOUNT>\n"
"<LINE_ITEMS>\n"
"<MERCHANDISE>\n"
"<LINE_ITEM_ID>1</LINE_ITEM_ID>\n"
"<DESCRIPTION>&foo;</DESCRIPTION>\n"
"<QUANTITY>1</QUANTITY>\n"
"<UNIT_PRICE>5.00</UNIT_PRICE>\n"
"<EXTENDED_PRICE>5.00</EXTENDED_PRICE>\n"
"</MERCHANDISE>\n"
"</LINE_ITEMS>\n"
"</TRANSACTION>\n";

xmlDocPtr doc = xmlReadMemory(buf, sizeof(buf), "noname.xml", NULL,
XML_PARSE_RECOVER);

xmlNodePtr trans = find_node((xmlNodePtr)doc, "TRANSACTION");
xmlNodePtr items = find_node(trans, "LINE_ITEMS");
xmlNodePtr merch = find_node(items, "MERCHANDISE");
xmlNodePtr desc = find_node(merch, "DESCRIPTION");

for (xmlNodePtr cur = desc->children; cur != NULL; cur = cur->next) {
if (cur->type == XML_ENTITY_REF_NODE) {
printf("entity ref node\n");
}
else {
printf("other node of type: %d\n", cur->type);
}
}

xmlFreeDoc(doc);

return 0;
}

如果我编译

gcc -std=c99 -O2 -I/usr/include/libxml2 so.c -lxml2 -o so

然后运行,结果是

entity ref node

关于c - 如何在 libxml2in C 中禁用 XXE?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22930043/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com