Authored by 徐炜

URL跳转漏洞。

... ... @@ -19,7 +19,7 @@ const config = global.yoho.config;
const cache = global.yoho.cache;
const LoginService = require('../models/login-service');
const PassportHelper = require('../models/passport-helper');
const safeRedirectFilter = require('../../../doraemon/middleware/safe-redirect').safeRedirectFilter;
const safeRedirect = require('../../../doraemon/middleware/safe-redirect').safeRedirect;
const loginPageURL = `${config.siteUrl}/passport/login`;
const BlockRedirectFilter = /sign|login|passport/;
... ... @@ -184,15 +184,12 @@ const local = {
}
refer = !BlockRedirectFilter.test(decodeURI(refer)) ? decodeURI(refer) : config.siteUrl;
if (!/www\.yohoblk\.com/.test(refer)) {
refer = config.siteUrl;
}
yield LoginService.syncUserSession(user.uid, req, res).then(() => {
res.json({
code: 200,
data: {
refer: safeRedirectFilter(refer)
refer: safeRedirect(refer)
}
});
});
... ...
... ... @@ -11,27 +11,52 @@ const url = require('url');
const domains = require('../../config/safe-domain').domains;
const _ = require('lodash');
/**
* 检查域名安全性
*
* @param uri
*/
const safeRedirect = (uri) => {
let result = url.parse(uri);
const ret = _.some(domains, (item)=> {
return item === result.host;
});
let formalUrl = url.parse(uri); // 匹配标准的URL
let informalUrl = uri.match(/^\/\/(.+)/); // 尝试匹配 '//' 开头的不规范的URL
let matchFunc;
if (formalUrl.protocol) {
// 在白名单中尝试匹配
matchFunc = (item)=> {
return item === formalUrl.host;
};
} else if (informalUrl && informalUrl.length > 0) {
matchFunc = (item)=> {
return item === informalUrl[1];
};
}
return ret ? uri : '/';
return _.some(domains, matchFunc) ? uri : '/';
};
/**
* 安全重定向中间件
*
* @returns {function(*, *=, *)}
*/
const middleware = () => {
return (req, res, next) => {
const expressRedirect = res.redirect;
res.redirect = function(uri) {
safeRedirect(uri);
return expressRedirect.apply(res, arguments);
const safeUri = safeRedirect(uri);
let args = [];
if (arguments.length === 1) {
args[0] = safeUri;
} else if (arguments.length === 2) {
args[1] = safeUri;
}
return expressRedirect.apply(res, args);
};
next();
... ...