mirror of
https://github.com/overleaf/overleaf.git
synced 2024-12-04 03:44:02 -05:00
Merge pull request #1499 from sharelatex/ta-open-redirect-fix
Prevent Open Redirects GitOrigin-RevId: 8cd2ead74de60f47b728ac227c21440281b111a5
This commit is contained in:
parent
9b97af8977
commit
b39626751a
2 changed files with 53 additions and 6 deletions
|
@ -15,6 +15,7 @@ NotificationsBuilder = require("../Notifications/NotificationsBuilder")
|
||||||
SudoModeHandler = require '../SudoMode/SudoModeHandler'
|
SudoModeHandler = require '../SudoMode/SudoModeHandler'
|
||||||
V1Api = require "../V1/V1Api"
|
V1Api = require "../V1/V1Api"
|
||||||
{User} = require "../../models/User"
|
{User} = require "../../models/User"
|
||||||
|
{ URL } = require('url')
|
||||||
|
|
||||||
module.exports = AuthenticationController =
|
module.exports = AuthenticationController =
|
||||||
|
|
||||||
|
@ -225,7 +226,8 @@ module.exports = AuthenticationController =
|
||||||
!/^\/(socket.io|js|stylesheets|img)\/.*$/.test(value) &&
|
!/^\/(socket.io|js|stylesheets|img)\/.*$/.test(value) &&
|
||||||
!/^.*\.(png|jpeg|svg)$/.test(value)
|
!/^.*\.(png|jpeg|svg)$/.test(value)
|
||||||
)
|
)
|
||||||
req.session.postLoginRedirect = value
|
safePath = AuthenticationController._getSafeRedirectPath(value)
|
||||||
|
req.session.postLoginRedirect = safePath
|
||||||
|
|
||||||
_redirectToLoginOrRegisterPage: (req, res)->
|
_redirectToLoginOrRegisterPage: (req, res)->
|
||||||
if (req.query.zipUrl? or req.query.project_name? or req.path == '/user/subscription/new')
|
if (req.query.zipUrl? or req.query.project_name? or req.path == '/user/subscription/new')
|
||||||
|
@ -261,8 +263,17 @@ module.exports = AuthenticationController =
|
||||||
callback()
|
callback()
|
||||||
|
|
||||||
_getRedirectFromSession: (req) ->
|
_getRedirectFromSession: (req) ->
|
||||||
return req?.session?.postLoginRedirect || null
|
value = req?.session?.postLoginRedirect
|
||||||
|
safePath = AuthenticationController._getSafeRedirectPath(value) if value
|
||||||
|
return safePath || null
|
||||||
|
|
||||||
_clearRedirectFromSession: (req) ->
|
_clearRedirectFromSession: (req) ->
|
||||||
if req.session?
|
if req.session?
|
||||||
delete req.session.postLoginRedirect
|
delete req.session.postLoginRedirect
|
||||||
|
|
||||||
|
_getSafeRedirectPath: (value) ->
|
||||||
|
baseURL = Settings.siteUrl # base URL is required to construct URL from path
|
||||||
|
url = new URL(value, baseURL)
|
||||||
|
safePath = "#{url.pathname}#{url.search}#{url.hash}"
|
||||||
|
safePath = undefined if safePath == '/'
|
||||||
|
safePath
|
||||||
|
|
|
@ -24,7 +24,7 @@ describe "AuthenticationController", ->
|
||||||
"../User/UserHandler": @UserHandler = {setupLoginData:sinon.stub()}
|
"../User/UserHandler": @UserHandler = {setupLoginData:sinon.stub()}
|
||||||
"../Analytics/AnalyticsManager": @AnalyticsManager = { recordEvent: sinon.stub() }
|
"../Analytics/AnalyticsManager": @AnalyticsManager = { recordEvent: sinon.stub() }
|
||||||
"logger-sharelatex": @logger = { log: sinon.stub(), error: sinon.stub(), err: sinon.stub() }
|
"logger-sharelatex": @logger = { log: sinon.stub(), error: sinon.stub(), err: sinon.stub() }
|
||||||
"settings-sharelatex": {}
|
"settings-sharelatex": { siteUrl: 'http://www.foo.bar' }
|
||||||
"passport": @passport =
|
"passport": @passport =
|
||||||
authenticate: sinon.stub().returns(sinon.stub())
|
authenticate: sinon.stub().returns(sinon.stub())
|
||||||
"../User/UserSessionsManager": @UserSessionsManager =
|
"../User/UserSessionsManager": @UserSessionsManager =
|
||||||
|
@ -654,6 +654,10 @@ describe "AuthenticationController", ->
|
||||||
@AuthenticationController.setRedirectInSession(@req, '/somewhere/specific')
|
@AuthenticationController.setRedirectInSession(@req, '/somewhere/specific')
|
||||||
expect(@req.session.postLoginRedirect).to.equal "/somewhere/specific"
|
expect(@req.session.postLoginRedirect).to.equal "/somewhere/specific"
|
||||||
|
|
||||||
|
it 'should not allow open redirects', ->
|
||||||
|
@AuthenticationController.setRedirectInSession(@req, 'https://evil.com')
|
||||||
|
expect(@req.session.postLoginRedirect).to.be.undefined
|
||||||
|
|
||||||
describe 'with a png', ->
|
describe 'with a png', ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
@req = {session: {}}
|
@req = {session: {}}
|
||||||
|
@ -672,12 +676,44 @@ describe "AuthenticationController", ->
|
||||||
expect(@req.session.postLoginRedirect).to.equal undefined
|
expect(@req.session.postLoginRedirect).to.equal undefined
|
||||||
|
|
||||||
describe '_getRedirectFromSession', ->
|
describe '_getRedirectFromSession', ->
|
||||||
beforeEach ->
|
|
||||||
@req = {session: {postLoginRedirect: "/a?b=c"}}
|
|
||||||
|
|
||||||
it 'should get redirect property from session', ->
|
it 'should get redirect property from session', ->
|
||||||
|
@req = session: { postLoginRedirect: '/a?b=c' }
|
||||||
expect(@AuthenticationController._getRedirectFromSession(@req)).to.equal "/a?b=c"
|
expect(@AuthenticationController._getRedirectFromSession(@req)).to.equal "/a?b=c"
|
||||||
|
|
||||||
|
it 'should not allow open redirects', ->
|
||||||
|
@req = session: { postLoginRedirect: 'https://evil.com' }
|
||||||
|
expect(@AuthenticationController._getRedirectFromSession(@req)).to.be.null
|
||||||
|
|
||||||
|
it 'handle null values', ->
|
||||||
|
@req = session: {}
|
||||||
|
expect(@AuthenticationController._getRedirectFromSession(@req)).to.be.null
|
||||||
|
|
||||||
|
describe '_getSafeRedirectPath', ->
|
||||||
|
it 'sanitize redirect path to prevent open redirects', ->
|
||||||
|
expect(
|
||||||
|
@AuthenticationController._getSafeRedirectPath('https://evil.com')
|
||||||
|
).to.be.undefined
|
||||||
|
|
||||||
|
expect(
|
||||||
|
@AuthenticationController._getSafeRedirectPath('//evil.com')
|
||||||
|
).to.be.undefined
|
||||||
|
|
||||||
|
expect(
|
||||||
|
@AuthenticationController._getSafeRedirectPath('//ol.com/evil')
|
||||||
|
).to.equal '/evil'
|
||||||
|
|
||||||
|
expect(
|
||||||
|
@AuthenticationController._getSafeRedirectPath('////evil.com')
|
||||||
|
).to.be.undefined
|
||||||
|
|
||||||
|
expect(
|
||||||
|
@AuthenticationController._getSafeRedirectPath('%2F%2Fevil.com')
|
||||||
|
).to.equal '/%2F%2Fevil.com'
|
||||||
|
|
||||||
|
expect(
|
||||||
|
@AuthenticationController._getSafeRedirectPath('.evil.com')
|
||||||
|
).to.equal '/.evil.com'
|
||||||
|
|
||||||
describe '_clearRedirectFromSession', ->
|
describe '_clearRedirectFromSession', ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
@req = {session: {postLoginRedirect: "/a?b=c"}}
|
@req = {session: {postLoginRedirect: "/a?b=c"}}
|
||||||
|
|
Loading…
Reference in a new issue