如何修复ASP.NET中ltLinkDoc.Text触发的Veracode CWE 80漏洞
这段代码存在XSS(CWE 80)漏洞的原因及修复方案
漏洞原因
- 编码拼接的安全隐患:虽然代码对参数做了
HttpUtility.JavaScriptStringEncode编码,但通过string.Format拼接生成safeScript后直接插入到<script>标签的HTML内容中,这种方式可能导致编码防护被绕过。JavaScriptStringEncode仅能保证参数在JS字符串上下文的安全,但当整个JS代码作为HTML的一部分被解析时,HTML与JS解析器的逻辑差异可能引发边界绕过问题。 - 布尔值的不当处理:
isDocOrDestCheckedJs在条件不满足时会生成空字符串,编码后仍为空,导致函数参数为""。若相关条件可被攻击者篡改,可能构造出闭合字符串、跳出函数调用的恶意代码,进而注入执行任意JS。 - 动态生成HTML/JS的风险:直接将拼接后的JS代码赋值给服务器控件的
Text属性,属于动态生成页面内容的模式,没有分离数据与代码,大幅提升了注入风险。
修复方案
方案1:分离数据与代码(推荐)
将参数存储在HTML元素的data-*属性中,通过静态JS代码读取参数并执行逻辑,彻底避免动态拼接JS的风险:
Session.Remove("linkdoc"); // 将参数存入控件的data属性 ltLinkDoc.Attributes["data-webdav"] = strWebDav; ltLinkDoc.Attributes["data-generate-dialog"] = (_settingPageInPopup != null ? _settingPageInPopup.GenerateLinkDialog : true).ToString(); ltLinkDoc.Attributes["data-show-status"] = IsShowSuccussfulOrFailed.ToString(); ltLinkDoc.Attributes["data-doc-checked"] = (rdoDocumentInfile.Checked || IsDestinationFileChecked()).ToString(); // 静态JS代码,从data属性读取参数执行 ltLinkDoc.Text = @"<script>$(window).bind('load', function(){ setTimeout(function() { const webdav = document.querySelector('[data-webdav]').dataset.webdav; const generateDialog = document.querySelector('[data-generate-dialog]').dataset.generateDialog === 'true'; const showStatus = document.querySelector('[data-show-status]').dataset.showStatus === 'true'; const docChecked = document.querySelector('[data-doc-checked]').dataset.docChecked === 'true'; CloseAndSendLinkToParent(webdav, generateDialog, showStatus, docChecked); }, 100); });</script>";
方案2:安全动态生成JS代码
如果必须动态生成JS,需确保参数类型正确,并用安全方式拼接:
Session.Remove("linkdoc"); // 直接获取布尔值,避免字符串转换风险 var generateLinkDialog = _settingPageInPopup != null ? _settingPageInPopup.GenerateLinkDialog : true; var isShowSuccussfulOrFailed = IsShowSuccussfulOrFailed; var isDocOrDestChecked = rdoDocumentInfile.Checked || IsDestinationFileChecked(); // 仅对字符串参数做JS编码 var encodedWebDav = HttpUtility.JavaScriptStringEncode(strWebDav); // 使用StringBuilder安全拼接JS代码 var scriptBuilder = new StringBuilder(); scriptBuilder.Append("<script>$(window).bind('load', function(){ setTimeout(function() { "); scriptBuilder.AppendFormat( "CloseAndSendLinkToParent({0}, {1}, {2}, {3});", encodedWebDav, generateLinkDialog.ToString().ToLower(), isShowSuccussfulOrFailed.ToString().ToLower(), isDocOrDestChecked.ToString().ToLower() ); scriptBuilder.Append(" }, 100); });</script>"); ltLinkDoc.Text = scriptBuilder.ToString();
关键修复要点
- 优先采用数据与代码分离的模式,避免直接拼接用户可控数据到JS代码中。
- 字符串参数必须用
HttpUtility.JavaScriptStringEncode编码;布尔值直接传递JS原生布尔类型,无需转字符串编码。 - 禁止用
string.Format拼接含用户数据的代码,改用StringBuilder或安全拼接方式,减少格式注入风险。
内容的提问来源于stack exchange,提问作者Nguyen Xuan Nghia
相关产品推荐
相关产品推荐

