Remove unplanned path traversal feature
This commit is contained in:
@@ -52,6 +52,10 @@ public class FilePrivateAPI {
|
|||||||
@Path("/{names: .+}")
|
@Path("/{names: .+}")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Response getFileInfo(List<PathSegment> names) {
|
public Response getFileInfo(List<PathSegment> names) {
|
||||||
|
if (roleAccessService.hasEncodedPathSeparator(names)) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST).build();
|
||||||
|
}
|
||||||
|
|
||||||
if (!roleAccessService.checkRouteAccess(securityIdentity.getRoles(), names)
|
if (!roleAccessService.checkRouteAccess(securityIdentity.getRoles(), names)
|
||||||
|| !adventAccessService.checkEventAccess(names)) {
|
|| !adventAccessService.checkEventAccess(names)) {
|
||||||
return Response.status(Response.Status.FORBIDDEN).build();
|
return Response.status(Response.Status.FORBIDDEN).build();
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package sh.rhiobet.lalafin.api.internal;
|
package sh.rhiobet.lalafin.api.internal;
|
||||||
|
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -15,6 +17,18 @@ public class RoleAccessService {
|
|||||||
@Inject
|
@Inject
|
||||||
FileApiConfiguration fileApiConfiguration;
|
FileApiConfiguration fileApiConfiguration;
|
||||||
|
|
||||||
|
public boolean hasEncodedPathSeparator(final List<PathSegment> names) {
|
||||||
|
return names.stream().anyMatch(s -> {
|
||||||
|
String current = s.getPath();
|
||||||
|
while (true) {
|
||||||
|
String decoded = URLDecoder.decode(current, StandardCharsets.UTF_8);
|
||||||
|
if (decoded.equals(current)) break;
|
||||||
|
current = decoded;
|
||||||
|
}
|
||||||
|
return current.contains("/") || current.contains("\0") || current.equals("..") || current.equals(".");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public boolean checkRouteAccess(final Set<String> userRoles, final List<PathSegment> names) {
|
public boolean checkRouteAccess(final Set<String> userRoles, final List<PathSegment> names) {
|
||||||
List<Route> matchingRoutes = new ArrayList<>();
|
List<Route> matchingRoutes = new ArrayList<>();
|
||||||
for (Route route : fileApiConfiguration.routes()) {
|
for (Route route : fileApiConfiguration.routes()) {
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ public class FileResource {
|
|||||||
@GET
|
@GET
|
||||||
@Path("/{names: .+}")
|
@Path("/{names: .+}")
|
||||||
public Response serve(List<PathSegment> names, @HeaderParam("Range") String range) {
|
public Response serve(List<PathSegment> names, @HeaderParam("Range") String range) {
|
||||||
|
if (roleAccessService.hasEncodedPathSeparator(names)) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST).build();
|
||||||
|
}
|
||||||
|
|
||||||
if (!roleAccessService.checkRouteAccess(securityIdentity.getRoles(), names)
|
if (!roleAccessService.checkRouteAccess(securityIdentity.getRoles(), names)
|
||||||
|| !adventAccessService.checkEventAccess(names)) {
|
|| !adventAccessService.checkEventAccess(names)) {
|
||||||
return Response.status(Response.Status.FORBIDDEN).build();
|
return Response.status(Response.Status.FORBIDDEN).build();
|
||||||
|
|||||||
@@ -45,6 +45,10 @@ public class ViewerResource {
|
|||||||
@GET
|
@GET
|
||||||
@Path("/{names: .+}/{page}")
|
@Path("/{names: .+}/{page}")
|
||||||
public Response view(List<PathSegment> names, int page) {
|
public Response view(List<PathSegment> names, int page) {
|
||||||
|
if (roleAccessService.hasEncodedPathSeparator(names)) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST).build();
|
||||||
|
}
|
||||||
|
|
||||||
if (!roleAccessService.checkRouteAccess(securityIdentity.getRoles(), names)
|
if (!roleAccessService.checkRouteAccess(securityIdentity.getRoles(), names)
|
||||||
|| !adventAccessService.checkEventAccess(names)) {
|
|| !adventAccessService.checkEventAccess(names)) {
|
||||||
return Response.status(Response.Status.FORBIDDEN).build();
|
return Response.status(Response.Status.FORBIDDEN).build();
|
||||||
|
|||||||
Reference in New Issue
Block a user