js 使用白名单方式过滤 dom-based xss 的方法

学习笔记 github 用户 2017-06-21 21:57:54 127 0

【摘要】前两天学习了 dom-based xss 的实例,今天想看看如何过滤 dom-based xss 的方法,于是乎我就在 github 上面搜索相关的代码,若不其然,找到了一个非常不错的开源代码,代码使用 js 白名单过滤方式来过滤 dom-based xss。所以本文记录一下他给的源代码以及使用方法。

首先是一个 index.html 文件:

  1. <!DOCTYPE html>
  2. <html>
  3.   <head>
  4.     <meta charset="utf-8">
  5.     <title>JSDXss 前端XSS过滤组件</title>
  6.     <script type="text/javascript" src="jsdxss.js"></script>
  7.   </head>
  8.   <body>
  9.     <label for="allows">白名单:</label><br>
  10.     <textarea id="allows" style="width:90%;height:10em">
  11.     {
  12.     "a" : [ "title", "ping", "href", "class" ],
  13.     "b" : [ "class" ],
  14.     "s" : [ "class" ],
  15.     "img" : [ "src", "class" ],
  16.     "div" : [ "class" ]
  17.     }
  18.     </textarea><br>
  19.     <label for="html">HTML:</label><br>
  20.     <textarea id="html" style="width:95%;height:10em;">
  21.     <div><b><a href="javascript:alert(1)">Hello, Sanitize</a></b></div><img src=# onerror=alert(1)>
  22.     </textarea><br>
  23.     <input type="button" id="filter" value="sanitize">
  24.     <br>
  25.     <div id="target" style="margin:0.5em;padding:0.5em;boder:solid 1px silver; background-color:#fffff0" ></div>
  26.     <script type="text/javascript">
  27.       filter.onclick = function(){
  28.         var j = JSON.parse(allows.value.replace(/^\s\s*/, '').replace(/\s\s*$/, ''));
  29.         var h = html.value;
  30.         new Jsdxss(j).filter(h, "target");
  31.       };
  32.     </script>
  33.   </body>
  34. </html>

然后是 js 过滤函数, jsdxss.js 文件:

  1. function Jsdxss(allows){
  2. 	this.allows = allows || {
  3. 	  "a" : [ "title", "ping", "href", "class", "target", "style" ],
  4. 	  "b" : [ "class", "style" ],
  5. 	  "img" : [ "src", "class", "style" ],
  6. 	  "div" : [ "class", "style"],
  7. 	  "p" : ["class", "style"]
  8. 	}
  9. 	var buildNodes = function( node ){
  10. 		var i, newNode, attributes, child;
  11. 		switch( node.nodeType ){
  12. 		case 1: // ELEMENT_NODE
  13. 			attributes = allows[ node.tagName.toLowerCase() ];
  14. 			if( attributes === undefined ) return undefined;
  15. 			newNode = document.createElement( node.tagName );
  16. 			for( i = 0; i < node.attributes.length; i++ ){
  17. 				if( attributes.indexOf( node.attributes[ i ].name ) != -1 ){
  18. 					switch(node.attributes[ i ].name){
  19. 						case "href": node.attributes[ i ] = _deal_href(node.attributes[ i ]);break;
  20. 						case "style": node.attributes[ i ] = _deal_style(node.attributes[ i ]);break;
  21. 					}
  22. 					newNode.setAttribute( node.attributes[ i ].name, node.attributes[ i ].value );
  23. 				}
  24. 			}
  25. 			for( i = 0; i < node.childNodes.length; i++ ){
  26. 				child = buildNodes( node.childNodes[ i ] );
  27. 				if( child !== undefined ){
  28. 					newNode.appendChild( child );
  29. 				}
  30. 			}
  31. 			return newNode;
  32. 		case 3: // TEXT_NODE
  33. 			return document.createTextNode( node.textContent );
  34. 		default:
  35. 			return undefined;
  36. 		}
  37. 	}
  38. 	var _deal_href = function(attr){
  39. 		var href = attr.value;
  40. 		if (href.indexOf("http://") === 0 || href.indexOf("http://") === 0) {
  41. 			attr.value = href;
  42. 		}else{
  43. 			attr.value = "http://" + href;
  44. 		}
  45. 		return attr;
  46. 	}
  47. 	var _deal_style = function(attr){
  48. 		var style = attr.value;
  49. 		var re = /expression/gim
  50. 		style = style.replace(/\\/g, ' ').replace(/&#/g, ' ').replace(/\/\*/g, ' ').replace(/\*\//g, ' ');
  51. 		attr.value = style.replace(re, ' ');
  52. 		return attr;
  53. 	}
  54. 	this.filter = function(html, target){
  55. 		try{
  56. 			var parser = new DOMParser();
  57. 			var newDoc = parser.parseFromString( html, "text/html" );
  58. 		}catch(e){
  59. 			var doc = new ActiveXObject ("MSXML2.DOMDocument");
  60. 			var newDoc = doc.loadXML(html);
  61. 		}
  62. 	    
  63. 	    var newBody = newDoc.body;
  64. 	    var target = document.getElementById( target );
  65. 	    var i, childeNode;
  66. 	  
  67. 		target.innerHTML = "";
  68. 		for( i = 0; i < newBody.childNodes.length; i++ ){
  69. 			childNode = buildNodes( newBody.childNodes[ i ] );
  70. 			if( childNode !== undefined ){
  71. 				target.appendChild( childNode );
  72. 			}
  73. 		}
  74. 	}
  75. }

代码很简洁,但是实现的功能特别的强大,将这两部分代码复制到文件后,打开执行,即进入如下:

请输入图片名称

点击 sanitize 按钮,会将 HTML 这个里面的输入的内容在,下面显示出来,如图所示:

请输入图片名称

从图中可以看出,并没有弹出窗口,即 alert(1) 被过滤掉了。

接着,我们在 HTML 输入框中输入:

  1. <strong> this is a strog tag</strong>

并且点击 sanitize 按钮,截图如下:

请输入图片名称

但是下方并没有输出这个内容,原因是白名单里面没有 strong 标签,因此被过滤掉了。接着我们在白名单里面添加如下信息:

  1. "strong":[]

然后点击按钮,执行截图如下:

请输入图片名称

说明这个 dom-based xss 过滤函数是采用白名单式方法来过滤的,具有一定的功能,值得借鉴。

版权归 马富天PHP博客 所有

本文标题:《js 使用白名单方式过滤 dom-based xss 的方法》

本文链接地址:http://www.mafutian.net/272.html

转载请务必注明出处,小生将不胜感激,谢谢! 喜欢本文或觉得本文对您有帮助,请分享给您的朋友 ^_^

0

0

上一篇《 PHP 判断用户访问页面是通过手机移动端访问还是 PC 端 》 下一篇《 SQL server 数据库修改服务器地址,将本机地址改成 IP 地址 》
分享到:

暂无评论

评论审核未开启
表情 表情 表情 表情 表情 表情 表情 表情 表情 表情 表情 表情 表情 表情 表情 表情 表情 表情 表情 表情 表情 表情 表情 表情
验证码