2016-06-28 2 views
2

Ich muss sichere Weiterleitungen nur innerhalb der gemeinsamen Domäne example.local machen. So zum Beispiel die folgenden gelten: http://blog.example.local, http://www.example.local/dashboard während die folgenden nicht: http://blog.example.localhttp://blog.example.local.fake.comIst es sicher, url.parse zu verwenden, um zu überprüfen, ob redirectURL nur in der Domäne vorhanden ist?

var url = require('url'); 

app.post('/login', function (req, res, next) { 
    var redirect = req.query.redirect, 
     targetUrl = url.parse(redirect); 

    if (targetUrl.host !== 'example.local') { 
     return next(new Error('Open redirect attack detected')); 
    } 

    return res.redirect(redirect); 
}); 

Ist es sicher genug, um in der Produktion zu verwenden, oder sollte ich etwas reparieren?

+0

Sorry, irritierend zu klingen, aber wie unterscheidet sich das von deiner [vorherigen Frage mit dem gleichen Code] (http://stackoverflow.com/questions/37668514/is-preventing-open-redirects-attack-in- nodejs-secure) das schon beantwortet wurde? Anders als der hartcodierte Host – cviejo

+0

möchte ich in dieser Lösung sicher sein, weil es sehr kritisch Sache ist – Erik

+0

Nun, die akzeptierte Lösung in dem anderen Beitrag nutzt eine Whitelist. Was Sie hier vorschlagen, ist im Wesentlichen eine Whitelist mit nur einem Element, also sind sie technisch gleichwertig. Ich verstehe nicht, warum die Antworten von den vorherigen abweichen sollten, aber vielleicht bekommst du neue Informationen, klar ... – cviejo

Antwort

1

aus dem Code, wenn targetUrl = 'http://blog.example.local', wird Ihre App zurückkehren Fehler ‚Open-Angriff erkannt umleiten‘, weil targetUrl.host ‚blog.example.local‘

wird

Bitte ändern Sie Ihren Code ein wenig zu

var expectedHost = [ 
    'blog.example.local', 
    'example.local' 
]; 

if (expectedHost.indexOf(targetUrl.host) === -1) { 
    return next(new Error('Open redirect attack detected')); 
} 

dann wird alles in Ordnung sein.

1

Ich würde irgendwo in der Datenbank oder in einer configuration.json eine Liste zulässiger Domänen erstellen und die Rückgabe-URL validieren, die RegExp dagegen verwendet.

1

Sieht aus wie Ihre Entscheidung Subdomains überspringen wird. Ich lief den Code in repl:

23:06 $ node 
> var url = require('url') 
undefined 
> url.parse('http://blog.example.local.fake.com') 
{ protocol: 'http:', 
    slashes: true, 
    auth: null, 
    host: 'blog.example.local.fake.com', 
    port: null, 
    hostname: 'blog.example.local.fake.com', 
    hash: null, 
    search: null, 
    query: null, 
    pathname: '/', 
    path: '/', 
    href: 'http://blog.example.local.fake.com/' } 
> url.parse('http://blog.example.local') 
{ protocol: 'http:', 
    slashes: true, 
    auth: null, 
    host: 'blog.example.local', 
    port: null, 
    hostname: 'blog.example.local', 
    hash: null, 
    search: null, 
    query: null, 
    pathname: '/', 
    path: '/', 
    href: 'http://blog.example.local/' } 

Ich denke, es ist sicher für die universelle Entscheidung einfachen Regex zu verwenden, ohne alle Subdomains Auflistung:

isValidHost = function(host) { 
    return /^([^.]+\.)*example.local$/.test(host); 
} 

Vielleicht besser strengen regex zu verwenden:

/^([a-zA-Z0-9-_]+\.)*example.local$/ 

ich habe versucht, auf der Konsole:

/^([a-zA-Z0-9-_]+\.)*example.com$/.test('xxx..blog.example.com') 
false 
/^([^.]+\.)*example.com$/.test('xxx..blog.example.com') 
false 
/^([^.]*\.)*example.com$/.test('xxx.blog.example.com') 
true 
/^([a-zA-Z0-9-_]+\.)*example.com$/.test('xxxexample.com') 
false 
/^([a-zA-Z0-9-_]+\.)*example.com$/.test('example.com') 
true 
0

Im Folgenden finden Sie den gesamten Code zum Verhindern eines Angriffs durch eine offene Umleitung. Er prüft Ihre URL und überprüft, ob sie sich in derselben Domain befindet oder nicht.

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <title></title> 
    <script> 
       function LaunchHelp() { 
      try { 

       var surl = "http://www.google.com"; 
       if (validateURL(surl)) 
        window.open(surl, '_blank', 'toolbar=no,menubar=no,status=yes'); 
       else { 
        throw new InvalidURLException(); 
       } 
      } catch (e) { 
       if (e instanceof InvalidURLException) 
        alert(e.message); 
      } 
     } 

     function InvalidURLException() { 
      this.message = "An attempt was made to open a webpage of foreign domain. No allowed."; 
      this.toString = function() { 
       return this.message 
      }; 
     } 

     function validateURL(surl) { 
      var url = parseURL(surl); 
      var urlHostname = url.hostname.trim(); 

      if (urlHostname == '') { 
       return true; 
      } 
      else { 
       if (urlHostname.toUpperCase() == location.hostname.trim().toUpperCase()) { 
        return true; 
       } 
       else 
        return false; 
      } 
     } 

     function parseURL(url) { 
      var a = document.createElement('a'); 
      a.href = url; 
      return { 
       source: url, 
       protocol: a.protocol.replace(':', ''), 
       hostname: a.hostname, 
       host: a.host, 
       port: a.port, 
       query: a.search, 
       params: (function() { 
        var ret = {}, 
         seg = a.search.replace(/^\?/, '').split('&'), 
         len = seg.length, i = 0, s; 
        for (; i < len; i++) { 
         if (!seg[i]) { continue; } 
         s = seg[i].split('='); 
         ret[s[0]] = s[1]; 
        } 
        return ret; 
       })(), 
       file: (a.pathname.match(/\/([^\/?#]+)$/i) || [, ''])[1], 
       hash: a.hash.replace('#', ''), 
       path: a.pathname.replace(/^([^\/])/, '/$1'), 
       relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [, ''])[1], 
       segments: a.pathname.replace(/^\//, '').split('/') 
      }; 
     } 



    </script> 
</head> 
<body> 
    <h1>This is Test 1 Page.</h1> 
    <button id="btnRedirect" name="btnRedirect" onclick="LaunchHelp()">Redirect</button> 
</body> 
</html> 

Sie können Ihre URL anstelle dieser Codezeile ersetzen.

var surl = "http://www.google.com"; 

Hoffe, das wird Ihnen helfen. danke

Verwandte Themen