codecamp

Node.js URL跳转

1.12.1【必须】限定跳转目标地址

  • 适用场景包括:

  1. 使用30x返回码并在Header中设置Location进行跳转
  2. 在返回页面中打印<script>location.href=__Redirection_URL__</script>

  • 使用白名单,限定重定向地址的协议前缀(默认只允许HTTP、HTTPS)、域名(默认只允许公司根域),或指定为固定值;

// 使用express实现的登录成功后的回调跳转页面


// bad: 未校验页面重定向地址
app.get("/login", (req, res) => {
    // 若未登录用户访问其他页面,则让用户导向到该处理函数进行登录
  // 使用参数loginCallbackUrl记录先前尝试访问的url,在登录成功后跳转回loginCallbackUrl:
    const { loginCallbackUrl } = req.query;
    if (loginCallbackUrl) {
        res.redirect(loginCallbackUrl);
    }
});


// good: 白名单限定重定向地址
function isValidURL(sUrl) {
    return !!((/^(https?:\/\/)?[\w\-.]+\.(qq|tencent)\.com($|\/|\\)/i).test(sUrl) || (/^[\w][\w/.\-_%]+$/i).test(sUrl) || (/^[/\\][^/\\]/i).test(sUrl));
}
app.get("/login", (req, res) => {
    // 若未登录用户访问其他页面,则让用户导向到该处理函数进行登录
  // 使用参数loginCallbackUrl记录先前尝试访问的url,在登录成功后跳转回loginCallbackUrl:
    const { loginCallbackUrl } = req.query;
    if (loginCallbackUrl && isValidUrl(loginCallbackUrl)) {
        res.redirect(loginCallbackUrl);
    }
});


// good: 白名单限定重定向地址,通过返回html实现
function isValidURL(sUrl) {
    return !!((/^(https?:\/\/)?[\w\-.]+\.(qq|tencent)\.com($|\/|\\)/i).test(sUrl) || (/^[\w][\w/.\-_%]+$/i).test(sUrl) || (/^[/\\][^/\\]/i).test(sUrl));
}
app.get("/login", (req, res) => {
    // 若未登录用户访问其他页面,则让用户导向到该处理函数进行登录
  // 使用参数loginCallbackUrl记录先前尝试访问的url,在登录成功后跳转回loginCallbackUrl:
    const { loginCallbackUrl } = req.query;
    if (loginCallbackUrl && isValidUrl(loginCallbackUrl)) {
        // 使用encodeURI,过滤左右尖括号与双引号,防止逃逸出包裹的双引号
        const redirectHtml = `<script>location.href = "${encodeURI(loginCallbackUrl)}";</script>`;
        res.end(redirectHtml);
    }
});

关联漏洞:中风险 - 任意URL跳转漏洞

Node.js 服务器端渲染(SSR)
Node.js Cookie与登录态
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }