C#如何安全地解析XML以防止XXE注入
技术百科
月夜之吻
发布时间:2025-12-26
浏览: 次 默认XmlDocument和XmlReader触发XXE因.NET默认启用DTD解析,需同时设DtdProcessing.Prohibit和XmlResolver=null;XmlSerializer也需用加固XmlReader;还需限制MaxDepth、MaxCharactersInDocument等防DoS。
为什么默认的 XmlDocument 和 XmlReader 会触发XXE
因为 .NET 默认启用 DTD 解析(XmlResolver 非空),当 XML 包含 ]> 这类声明时,XmlDocument.Load() 或 XmlReader.Create() 会尝试解析并加载外部实体,导致文件读取、网络请求甚至 SSRF。
禁用 DTD 解析的两种可靠方式
核心是让解析器完全忽略 DOCTYPE 声明,不执行任何外部实体解析。推荐以下任一做法:
- 使用
XmlReaderSettings显式关闭:var settings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Prohibit, // 关键:禁止 DTD 处理 XmlResolver = null // 关键:移除解析器 }; using var reader = XmlReader.Create(stream, settings); var doc = new XmlDocument(); doc.Load(reader); - 对
XmlDocument直接设置:var doc = new XmlDocument(); doc.XmlResolver = null; // 必须在 Load 前设置 doc.Load(xmlStream);
注意:此方式仅在 .NET Framework 4.5.2+ 和 .NET Core 2.0+ 有效;旧版需配合ProhibitDtd = true(但该属性已过时)
别踩 XmlSerializer 的坑
XmlSerializer 默认不解析 DTD,看似安全,但它会隐式使用 XmlReader,若你传入的是未加固的 XmlReader 实例,风险仍在。安全做法是始终用加固后的 XmlReader 构造:
var settings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Prohibit, XmlResolver = null };
using var reader = XmlReader.Create(stream, settings);
var serializer = new XmlSerializer(typeof(MyClass));
var obj = serializer.Deserialize(reader);不要直接传 stream 给 Deserialize() —— 它会内部创建不设防的 reader。
额外加固:限制解析深度与大小
防止恶意构造的超深嵌套或超大文本耗尽内存:
-
MaxDepth = 10(默认 64,建议压到 8–12) -
MaxCharactersInDocument = 10 * 1024 * 10(如限制 10MB)
24 -
MaxCharactersFromEntities = 10240(防实体膨胀攻击)
这些都应在 XmlReaderSettings 中一并配置,否则单禁 DTD 仍可能被 DoS。
XXE 防御不是“关一个开关”就完事;DtdProcessing.Prohibit 和 XmlResolver = null 必须同时生效,且所有入口(XmlDocument、XmlReader、XmlSerializer)都要走同一套加固逻辑。漏掉任意一种路径,攻击面就还在。
# 的是
# 这类
# 还在
# 它会
# 移除
# 两种
# 还需
# 旧版
# stream
# c#
# xml
# .net
# 为什么
# NULL
# 要走
# 应在
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- 如何有效拦截拼接式恶意域名的垃圾信息
- 如何减少Golang内存碎片化_Golang内存分
- Win11怎样安装搜狗输入法_Win11安装搜狗输
- C++ static_cast和dynamic_c
- c# 如何用c#实现一个支持优先级的任务队列
- 如何在Golang中实现邮件发送功能_Golang
- Python性能剖析高级教程_cProfileLi
- Win11怎么忘记WiFi网络_Win11删除已保
- Win10怎么关闭自动更新错误弹窗_Win10策略
- C++中的std::shared_from_thi
- Win10怎么卸载迅雷_Win10彻底卸载迅雷方法
- C++如何编写函数模板?(泛型编程入门)
- 如何在JavaScript中动态拼接PHP的bas
- Win11任务栏天气怎么关闭 Win11隐藏天气小
- Win11怎么压缩文件 Win11自带压缩解压功能
- Mac的“调度中心”与“空间”怎么用_Mac多桌面
- Win11怎么开启上帝模式_创建Windows 1
- Win11怎么设置闹钟_Windows 11时钟应
- Windows10如何查看保存的WiFi密码_Wi
- Windows音频驱动无声音原因解析_声卡驱动错误
- Linux如何挂载新硬盘_Linux磁盘分区格式化
- 如何在Golang中使用内置函数_Golangle
- Win11文件扩展名怎么显示_Win11查看文件后
- c++如何实现多态性_c++ 虚函数表原理与动态绑
- Win11怎么清理C盘OneDrive缓存_Win
- Win11怎么设置默认邮件应用_Windows11
- Win10任务栏天气和资讯怎么关闭 Win10禁用
- Win11怎么设置单手模式_Win11触控键盘布局
- Python实现图数据库操作_Neo4j核心CRU
- 如何在 Django 中修改用户密码后保持会话不丢
- Windows蓝屏错误0x00000018怎么处理
- 如何使用Golang实现负载均衡_分发请求到多个服
- windows如何禁用驱动程序强制签名_windo
- Windows系统文件被保护机制阻止怎么办_权限不
- C++中引用和指针有什么区别?(代码说明)
- Windows 10怎么录屏_Windows 10
- php做exe支持多线程吗_并发处理实现方式【详解
- Win11截图快捷键是什么_Win11自带截图工具
- Win11怎么设置默认邮件客户端 Win11修改M
- Win11关机界面怎么改_Win11自定义关机画面
- php485在php5.6下能用吗_php485旧
- c++ namespace命名空间用法_c++避免
- Win10怎么设置开机密码_Windows10账户
- Python文件管理规范_工程实践说明【指导】
- 如何用正则与预处理结合精准拦截拼接式垃圾域名
- Win11怎么关闭系统推荐内容_Windows11
- Windows10如何更改系统字体大小_Win10
- Windows如何使用注册表查找和删除项?(reg
- c++中如何使用auto关键字_c++11类型推导
- php订单日志怎么记录评价_php记录订单评价日志

24
QQ客服