Skip to content

Commit

Permalink
Valide les urls de redirection (#1229)
Browse files Browse the repository at this point in the history
  • Loading branch information
niladic authored Nov 11, 2021
1 parent 2536d11 commit 03fc904
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 7 deletions.
14 changes: 11 additions & 3 deletions app/controllers/LoginController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ import helper.{StringHelper, Time}
import java.time.ZoneId
import javax.inject.{Inject, Singleton}
import models.EventType.{GenerateToken, UnknownEmail}
import models.{Authorization, LoginToken, User}
import models.{Authorization, EventType, LoginToken, User}
import org.webjars.play.WebJarsUtil
import play.api.Configuration
import play.api.mvc.{Action, AnyContent, InjectedController, Request}
import serializers.Keys
import services.{EventService, NotificationService, SignupService, TokenService, UserService}
import views.home.LoginPanel

import scala.concurrent.{ExecutionContext, Future}

@Singleton
Expand Down Expand Up @@ -159,7 +158,16 @@ class LoginController @Inject() (
request.getQueryString(Keys.QueryParam.token),
request.getQueryString(Keys.QueryParam.path)
) match {
case (Some(token), Some(path)) =>
case (Some(token), Some(uncheckedPath)) =>
val path =
if (PathValidator.isValidPath(uncheckedPath)) uncheckedPath
else {
eventService.logSystem(
EventType.LoginInvalidPath,
s"Redirection invalide après le login '$uncheckedPath'"
)
routes.HomeController.index.url
}
Ok(
views.html.magicLinkAntiConsumptionPage(
token = token,
Expand Down
56 changes: 56 additions & 0 deletions app/controllers/PathValidator.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package controllers

import java.util.UUID
import models.EventType
import play.api.mvc.Call
import scala.util.Try
import scala.util.matching.Regex

object PathValidator {

// We put in the whitelist paths used in emails and
// paths that might be used as bookmarks.
//
// Note that we cannot use Play's router to validate an url, hence the regexes.
private val pathWhitelist: List[Regex] = {
val placeholder = "00000000-0000-0000-0000-000000000000"
val placeholderUUID = UUID.fromString(placeholder)
val calls: List[Call] = List(
routes.HomeController.index,
routes.HomeController.help,
routes.HomeController.welcome,
routes.ApplicationController.create,
routes.ApplicationController.myApplications,
routes.ApplicationController.show(placeholderUUID),
routes.MandatController.mandat(placeholderUUID),
routes.ApplicationController.stats,
routes.UserController.showEditProfile,
routes.UserController.home,
routes.UserController.editUser(placeholderUUID),
routes.GroupController.showEditMyGroups,
routes.GroupController.editGroup(placeholderUUID),
routes.UserController.add(placeholderUUID),
routes.UserController.showValidateAccount,
routes.AreaController.all,
routes.AreaController.deploymentDashboard,
routes.AreaController.franceServiceDeploymentDashboard,
routes.ApplicationController.all(placeholderUUID),
routes.UserController.all(placeholderUUID),
)
val uuidRegex = "([a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12})"
calls.map(call =>
// this compiles the regex
new Regex("^" + call.path().replace(placeholder, uuidRegex) + "$")
)
}

def isValidPath(path: String): Boolean =
pathWhitelist.exists { pathRegex =>
path match {
case pathRegex(uuids @ _*) =>
uuids.forall(uuid => Try(UUID.fromString(uuid)).isSuccess)
case _ => false
}
}

}
21 changes: 17 additions & 4 deletions app/controllers/UserController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,17 @@ case class UserController @Inject() (
def validateAccount: Action[AnyContent] =
loginAction.async { implicit request =>
val user = request.currentUser

def validateRedirect(uncheckedRedirect: String): String =
if (PathValidator.isValidPath(uncheckedRedirect)) uncheckedRedirect
else {
eventService.log(
EventType.CGUInvalidRedirect,
s"URL de redirection après les CGU invalide '$uncheckedRedirect'"
)
routes.HomeController.index.url
}

ValidateSubscriptionForm
.validate(user)
.bindFromRequest()
Expand All @@ -747,13 +758,14 @@ case class UserController @Inject() (
},
{
case ValidateSubscriptionForm(
Some(redirect),
Some(uncheckedRedirect),
true,
firstName,
lastName,
qualite,
phoneNumber
) if redirect =!= routes.ApplicationController.myApplications.url =>
) if uncheckedRedirect =!= routes.ApplicationController.myApplications.url =>
val redirect = validateRedirect(uncheckedRedirect)
validateAndUpdateUser(request.currentUser)(firstName, lastName, qualite, phoneNumber)
.map { updatedUser =>
val logMessage =
Expand All @@ -771,8 +783,9 @@ case class UserController @Inject() (
Redirect(routes.HomeController.welcome)
.flashing("success" -> "Merci d’avoir accepté les CGU")
}
case ValidateSubscriptionForm(Some(redirect), false, _, _, _, _)
if redirect =!= routes.ApplicationController.myApplications.url =>
case ValidateSubscriptionForm(Some(uncheckedRedirect), false, _, _, _, _)
if uncheckedRedirect =!= routes.ApplicationController.myApplications.url =>
val redirect = validateRedirect(uncheckedRedirect)
Future(Redirect(Call("GET", redirect)))
case ValidateSubscriptionForm(_, false, _, _, _, _) =>
Future(Redirect(routes.HomeController.welcome))
Expand Down
2 changes: 2 additions & 0 deletions app/models/EventType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ object EventType {
object CGUShowed extends Info
object CGUValidated extends Info
object CGUValidationError extends Error
object CGUInvalidRedirect extends Warn
object ChangeAreaUnauthorized extends Warn
object DeleteUserUnauthorized extends Warn
object DeploymentDashboardUnauthorized extends Warn
Expand Down Expand Up @@ -142,6 +143,7 @@ object EventType {
object StatsIncorrectSetup extends Warn
object TryLoginByKey extends Info
object UnknownEmail extends Warn
object LoginInvalidPath extends Warn

object UserProfileShowed extends Info
object UserProfileShowedError extends Error
Expand Down

0 comments on commit 03fc904

Please sign in to comment.