From f193e294d15d962d2837a47eadaabf316caf66bf Mon Sep 17 00:00:00 2001
From: Aiden Xu <aiden.xu@yoho.cn>
Date: Wed, 31 Aug 2016 18:02:26 +0800
Subject: [PATCH] 登录处存在URL跳转漏洞。 注册成功后反馈的跳转页面存在URL跳转漏洞。

---
 app.js                               |  3 ++-
 apps/passport/controllers/login.js   |  3 ++-
 apps/passport/controllers/reg.js     |  5 +++--
 config/safe-domain.js                | 10 ++++++++++
 doraemon/middleware/safe-redirect.js | 45 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 62 insertions(+), 4 deletions(-)
 create mode 100644 config/safe-domain.js
 create mode 100644 doraemon/middleware/safe-redirect.js

diff --git a/app.js b/app.js
index 1e14db8..53a6e59 100644
--- a/app.js
+++ b/app.js
@@ -22,7 +22,6 @@ const memcached = require('connect-memcached');
 const hbs = require('express-handlebars');
 const multer = require('connect-multiparty');
 const pkg = require('./package.json');
-
 const yohoLib = require('yoho-node-lib');
 
 const app = express();
@@ -91,10 +90,12 @@ try {
     const errorHanlder = require(`${global.middleware}/error-handler`);
     const setPageInfo = require(`${global.middleware}/set-pageinfo`);
     const display = require(`${global.middleware}/display`);
+    const safeRedirect = require(`${global.middleware}/safe-redirect`).middleware;
 
     // YOHO 前置中间件
     app.use(mobileCheck());
     app.use(setYohoData());
+    app.use(safeRedirect());
     app.use(user());
     app.use(seo());
     app.use(setPageInfo());
diff --git a/apps/passport/controllers/login.js b/apps/passport/controllers/login.js
index d368b14..5e78a29 100644
--- a/apps/passport/controllers/login.js
+++ b/apps/passport/controllers/login.js
@@ -19,6 +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 loginPageURL = `${config.siteUrl}/passport/login`;
 const BlockRedirectFilter = /sign|login|passport/;
@@ -176,7 +177,7 @@ const local = {
                         res.json({
                             code: 200,
                             data: {
-                                refer: refer
+                                refer: safeRedirectFilter(refer)
                             }
                         });
                     });
diff --git a/apps/passport/controllers/reg.js b/apps/passport/controllers/reg.js
index 29cbef5..ee43a12 100644
--- a/apps/passport/controllers/reg.js
+++ b/apps/passport/controllers/reg.js
@@ -9,6 +9,7 @@ const RegService = require('../models/reg-service');
 const UserService = require('../models/user-service');
 const LoginService = require('../models/login-service');
 const config = require('../../../config/common');
+const safeRedirect = require('../../../doraemon/middleware/safe-redirect').safeRedirect;
 
 let helpers = global.yoho.helpers;
 let cache = global.yoho.cache;
@@ -252,10 +253,10 @@ let mobileRegister = (req, res, next) => {
                 code: 200,
                 message: '注册成功',
                 data: {
-                    href: helpers.urlFormat('/passport/reg/success', {
+                    href: safeRedirect(helpers.urlFormat('/passport/reg/success', {
                         next: cookie.getRefer(req, '/?go=1'),
                         goShoppingUrl: config.siteUrl
-                    })
+                    }))
                 }
             });
         });
diff --git a/config/safe-domain.js b/config/safe-domain.js
new file mode 100644
index 0000000..d57bc58
--- /dev/null
+++ b/config/safe-domain.js
@@ -0,0 +1,10 @@
+module.exports = {
+    domains: [
+        'www.yohoblk.com',
+        'm.yohoblk.com',
+        'www.yohobuy.com',
+        'm.yohobuy.com',
+        'www.yohoshow.com',
+        'www.yohood.cn'
+    ]
+};
diff --git a/doraemon/middleware/safe-redirect.js b/doraemon/middleware/safe-redirect.js
new file mode 100644
index 0000000..a88f64d
--- /dev/null
+++ b/doraemon/middleware/safe-redirect.js
@@ -0,0 +1,45 @@
+/**
+ * 安全重定向 301、302跳转只允许白名单中的URL
+ *
+ * @author: Aiden Xu<aiden.xu@yoho.cn>
+ * @date: 2016/6/22
+ */
+
+'use strict';
+
+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;
+    });
+
+    return ret ? uri : '/';
+};
+
+const middleware = () => {
+    return (req, res, next) => {
+        const expressRedirect = res.redirect;
+
+        res.redirect = function(uri) {
+            safeRedirect(uri);
+            return expressRedirect.apply(res, arguments);
+        };
+
+        next();
+    };
+};
+
+
+module.exports = {
+    safeRedirect,
+    middleware
+};
--
libgit2 0.24.0