Skip to content

Configuration for disabling aliases #1093

@d-lozanov

Description

@d-lozanov

Hi team,
As per this article, alias overloading could be used for DoS attacks. There are a few options for preventing these attacks like limiting the request body, limiting the number of aliases and disabling them. I couldn't find any configuration for disabling aliases and I had to implement a filter in my application.
Do you plan to provide some kind of configuration for disabling aliases( for example, application property ), so that people could use it out of the box, as it is a general problem?

I paste the solution with filter for a reference:

@WebFilter("/graphql")
public class AliasRejectionFilter extends OncePerRequestFilter {

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        if (!(request instanceof CachedBodyHttpServletRequest)) {
            request = new CachedBodyHttpServletRequest(request);
        }

        String body = ((CachedBodyHttpServletRequest) request).getCachedBody();
        String query = extractQueryFromBody(body);

        if (query == null || query.isEmpty()) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            response.getWriter()
                    .write("{\"error\": \"Invalid GraphQL query.\"}");
            return;
        }

        if (containsAliases(query)) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            response.getWriter()
                    .write("{\"error\": \"Aliases are not allowed in this query.\"}");
            return;
        }

        filterChain.doFilter(request, response);
    }

    private String extractQueryFromBody(String body) {
        try {
            JsonNode jsonNode = objectMapper.readTree(body);
            return jsonNode.get("query")
                    .asText();
        } catch (Exception e) {
            System.err.println("Failed to extract query from body: " + e.getMessage());
            return null;
        }
    }

    private boolean containsAliases(String query) {
        try {
            Document document = Parser.parse(query);

            List<OperationDefinition> operationDefinitions = document.getDefinitionsOfType(OperationDefinition.class);
            for (OperationDefinition opDef : operationDefinitions) {
                List<Selection> selections = opDef.getSelectionSet()
                        .getSelections();
                for (Selection selection : selections) {
                    if (selection instanceof Field) {
                        Field field = (Field) selection;
                        if (field.getAlias() != null) {
                            return true;
                        }
                    }
                }
            }
        } catch (Exception e) {
            return false;
        }
        return false;
    }

}

where CachedBodyHttpServletRequest is just a wrapper for the request.

Best regards,
Denis.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions