Modify rule S5146 - Support Location header (#315)
This commit is contained in:
parent
b1bebf13ec
commit
2378417fdd
@ -5,21 +5,18 @@ include::../description.adoc[]
|
||||
----
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace WebApplicationDotNetCore.Controllers
|
||||
public class HomeController : Controller
|
||||
{
|
||||
public class RSPEC5146OpenRedirectNoncompliantController : Controller
|
||||
|
||||
public IActionResult RedirectMe(string url)
|
||||
{
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
return Redirect(url);
|
||||
}
|
||||
|
||||
private readonly string[] whiteList = { "https://www.sonarsource.com" };
|
||||
|
||||
public IActionResult RedirectMe(string url)
|
||||
{
|
||||
return Redirect(url);
|
||||
}
|
||||
public IActionResult SetLocationHeader(string url)
|
||||
{
|
||||
Response.Headers["Location"] = url; // Noncompliant
|
||||
return StatusCode(302);
|
||||
}
|
||||
}
|
||||
----
|
||||
@ -27,30 +24,21 @@ namespace WebApplicationDotNetCore.Controllers
|
||||
== Compliant Solution
|
||||
|
||||
----
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace WebApplicationDotNetCore.Controllers
|
||||
public class HomeController : Controller
|
||||
{
|
||||
public class RSPEC5146OpenRedirectCompliantController : Controller
|
||||
private readonly string[] whiteList = { "/", "/login", "/logout" };
|
||||
|
||||
public IActionResult RedirectMe(string url)
|
||||
{
|
||||
public IActionResult Index()
|
||||
// Match the incoming URL against a whitelist
|
||||
if (!whiteList.Contains(url))
|
||||
{
|
||||
return View();
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
private readonly string[] whiteList = { "https://www.sonarsource.com" };
|
||||
|
||||
public IActionResult RedirectMe(string url)
|
||||
{
|
||||
// Match the incoming URL against a whitelist
|
||||
if (!whiteList.Contains(url))
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
return Redirect(url);
|
||||
}
|
||||
return Redirect(url);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
@ -8,6 +8,13 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IO
|
||||
resp.sendRedirect(location); // Noncompliant
|
||||
}
|
||||
----
|
||||
----
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String location = req.getParameter("url");
|
||||
resp.setStatus(302);
|
||||
resp.setHeader("Location", location); // Noncompliant
|
||||
}
|
||||
----
|
||||
|
||||
== Compliant Solution
|
||||
|
||||
|
@ -3,11 +3,18 @@ include::../description.adoc[]
|
||||
== Noncompliant Code Example
|
||||
|
||||
----
|
||||
function (req, res) {
|
||||
function redirect(req, res) {
|
||||
const url = req.query.url; // user controlled input
|
||||
|
||||
res.redirect(url); // Noncompliant
|
||||
}
|
||||
|
||||
function setLocationHeader(req, res) {
|
||||
const url = req.query.url; // user controlled input
|
||||
|
||||
res.location(url); // Noncompliant
|
||||
res.sendStatus(302);
|
||||
}
|
||||
----
|
||||
|
||||
== Compliant Solution
|
||||
@ -23,7 +30,7 @@ function isValidUrl(url) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function (req, res) {
|
||||
function redirect(req, res) {
|
||||
const url = req.query.url; // user controlled input
|
||||
|
||||
if(isValidUrl(url)) {
|
||||
|
@ -8,22 +8,70 @@ This problem could be mitigated in any of the following ways:
|
||||
|
||||
== Noncompliant Code Example
|
||||
|
||||
Symfony
|
||||
|
||||
----
|
||||
$url = $this->request->getQuery("url");
|
||||
return $this->redirect($url); // Noncompliant
|
||||
public function redirect(Request $request)
|
||||
{
|
||||
$url = $request->query->get('url');
|
||||
return $this->redirect($url); // Noncompliant
|
||||
}
|
||||
|
||||
public function setLocatioHeader(Request $request)
|
||||
{
|
||||
$url = $request->query->get('url');
|
||||
$response = new Response('Redirecting...', 302);
|
||||
$response->headers->set('Location', $url); // Noncompliant
|
||||
return $response;
|
||||
}
|
||||
----
|
||||
|
||||
Laravel
|
||||
----
|
||||
public function redirect(Request $request)
|
||||
{
|
||||
$url = $request->input('url');
|
||||
return $this->redirect($url); // Noncompliant
|
||||
}
|
||||
|
||||
public function setLocatioHeader(Request $request)
|
||||
{
|
||||
$url = $request->input('url');
|
||||
return response("", 302)
|
||||
->header('Location', $url) // Noncompliant
|
||||
}
|
||||
----
|
||||
|
||||
== Compliant Solution
|
||||
|
||||
Symfony
|
||||
|
||||
----
|
||||
$whitelist = array(
|
||||
"https://www.sonarsource.com/"
|
||||
);
|
||||
$url = $this->request->getQuery("url");
|
||||
if (in_array($url, $whitelist)) {
|
||||
return $this->redirect($url);
|
||||
} else {
|
||||
throw new ForbiddenException();
|
||||
public function redirect(Request $request)
|
||||
{
|
||||
$url = $request->query->get('url');
|
||||
$allowedUrls = ["/index", "/login", "/logout"];
|
||||
|
||||
if (in_array($url, $allowedUrls, true)) {
|
||||
return $this->redirect($url);
|
||||
} else {
|
||||
$this->redirect("/");
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Laravel
|
||||
----
|
||||
public function redirect(Request $request)
|
||||
{
|
||||
$url = $request->input('url');
|
||||
$allowedUrls = ["/index", "/login", "/logout"];
|
||||
|
||||
if (in_array($url, $allowedUrls, true)) {
|
||||
return $this->redirect($url);
|
||||
} else {
|
||||
return redirect("/");
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
|
@ -5,12 +5,19 @@ include::../description.adoc[]
|
||||
Flask
|
||||
|
||||
----
|
||||
from flask import request, redirect
|
||||
from flask import request, redirect, Response
|
||||
|
||||
@app.route('move')
|
||||
def move():
|
||||
@app.route('flask_redirect')
|
||||
def flask_redirect():
|
||||
url = request.args["next"]
|
||||
return redirect(url) # Noncompliant
|
||||
return redirect(url) # Noncompliant
|
||||
|
||||
@app.route('set_location_header')
|
||||
def set_location_header():
|
||||
url = request.args["next"]
|
||||
response = Response("redirecting...", 302)
|
||||
response.headers['Location'] = url # Noncompliant
|
||||
return response
|
||||
----
|
||||
|
||||
Django
|
||||
@ -18,9 +25,15 @@ Django
|
||||
----
|
||||
from django.http import HttpResponseRedirect
|
||||
|
||||
def move(request):
|
||||
def http_responser_redirect(request):
|
||||
url = request.GET.get("next", "/")
|
||||
return HttpResponseRedirect(url) # Noncompliant
|
||||
return HttpResponseRedirect(url) # Noncompliant
|
||||
|
||||
def set_location_header(request):
|
||||
url = request.GET.get("next", "/")
|
||||
response = HttpResponse(status=302)
|
||||
response['Location'] = url # Noncompliant
|
||||
return response
|
||||
----
|
||||
|
||||
== Compliant Solution
|
||||
@ -28,12 +41,12 @@ def move(request):
|
||||
Flask
|
||||
|
||||
----
|
||||
from flask import request, redirect, url_for
|
||||
from flask import request, redirect, Response, url_for
|
||||
|
||||
@app.route('move')
|
||||
def move():
|
||||
@app.route('flask_redirect')
|
||||
def flask_redirect():
|
||||
endpoint = request.args["next"]
|
||||
return redirect(url_for(endpoint)) # Compliant
|
||||
return redirect(url_for(endpoint)) # Compliant
|
||||
----
|
||||
|
||||
Django
|
||||
@ -44,11 +57,11 @@ from urllib.parse import urlparse
|
||||
|
||||
DOMAINS_WHITELIST = ['www.example.com', 'example.com']
|
||||
|
||||
def move(request):
|
||||
def http_responser_redirect(request):
|
||||
url = request.GET.get("next", "/")
|
||||
parsed_uri = urlparse(url)
|
||||
if parsed_uri.netloc in DOMAINS_WHITELIST:
|
||||
return HttpResponseRedirect(url) # Compliant
|
||||
return HttpResponseRedirect(url) # Compliant
|
||||
return HttpResponseRedirect("/")
|
||||
----
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user