Skip to content

DefaultWebInvocationPrivilegeEvaluator can't handle rules based on remote address #10664

Closed

Description

@fast-reflexes

Describe the bug
When the ErrorPageSecurityFilter kicks in, it uses the DefaultWebInvocationPrivilegeEvaluator to determine if some error pages should be shown or if just a status code should be sent. If the pattern controlling access to error pages contain patterns based on remote address, the invocation fails with an exception:

java.lang.UnsupportedOperationException: public abstract java.lang.String javax.servlet.ServletRequest.getRemoteAddr() is not supported
    at org.springframework.security.web.FilterInvocation$UnsupportedOperationExceptionInvocationHandler.invoke(FilterInvocation.java:326) ~[spring-security-web-5.6.1.jar:5.6.1]
    at com.sun.proxy.$Proxy68.getRemoteAddr(Unknown Source) ~[na:na]
    at javax.servlet.ServletRequestWrapper.getRemoteAddr(ServletRequestWrapper.java:241) ~[tomcat-embed-core-9.0.56.jar:4.0.FR]
    at org.springframework.security.web.util.matcher.IpAddressMatcher.matches(IpAddressMatcher.java:65) ~[spring-security-web-5.6.1.jar:5.6.1]
    at org.springframework.security.web.access.expression.WebSecurityExpressionRoot.hasIpAddress(WebSecurityExpressionRoot.java:51) ~[spring-security-web-5.6.1.jar:5.6.1]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
    at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:129) ~[spring-expression-5.3.14.jar:5.3.14]
    at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:139) ~[spring-expression-5.3.14.jar:5.3.14]
    at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:95) ~[spring-expression-5.3.14.jar:5.3.14]
    at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:117) ~[spring-expression-5.3.14.jar:5.3.14]
    at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:308) ~[spring-expression-5.3.14.jar:5.3.14]
    at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:30) ~[spring-security-core-5.6.1.jar:5.6.1]
    at org.springframework.security.web.access.expression.WebExpressionVoter.vote(WebExpressionVoter.java:59) ~[spring-security-web-5.6.1.jar:5.6.1]
    at org.springframework.security.web.access.expression.WebExpressionVoter.vote(WebExpressionVoter.java:39) ~[spring-security-web-5.6.1.jar:5.6.1]
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:60) ~[spring-security-core-5.6.1.jar:5.6.1]
    at org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator.isAllowed(DefaultWebInvocationPrivilegeEvaluator.java:100) ~[spring-security-web-5.6.1.jar:5.6.1]
    at org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator.isAllowed(DefaultWebInvocationPrivilegeEvaluator.java:67) ~[spring-security-web-5.6.1.jar:5.6.1]
    at org.springframework.boot.web.servlet.filter.ErrorPageSecurityFilter.isAllowed(ErrorPageSecurityFilter.java:84) ~[spring-boot-2.6.2.jar:2.6.2]
    at org.springframework.boot.web.servlet.filter.ErrorPageSecurityFilter.doFilter(ErrorPageSecurityFilter.java:72) ~[spring-boot-2.6.2.jar:2.6.2]
    ....

To Reproduce

  1. Download project https://github.com/fast-reflexes/spring-boot-bug/tree/getRemoteAddrNotImplemented
    It is a project with the following security config:

    override fun configure(http: HttpSecurity) {
        http
            .authorizeRequests()
            .antMatchers("/error/**").hasIpAddress("127.0.0.1")
            .antMatchers("/non-existing/**").denyAll()
            .antMatchers("/test/**", "/favicon.ico").permitAll()
            .anyRequest().denyAll()
    }
    
  2. Start the app with ./gradlew bootRun

  3. Access localhost:8080/non-existing

  4. Check exception in console

Expected behavior
Expected behaviour is to either allow access to the Spring error page or to just send a status code, depending on the remote address pattern and remote address itself. Definitely not an exception and downgrading to the Tomcat error page.

Sample

See above

Activity

  1. added
    in: webAn issue in web modules (web, webmvc)
    and removed on Dec 24, 2021
  2. marcusdacoregio commented on Apr 13, 2022

    @marcusdacoregio
    Contributor

    Hi @fast-reflexes, we are investigating alternatives to the ErrorPageSecurityFilter here #10919.

    I recommend you to take a look at #11055 (comment) where I provided some workaround.

    I'm closing this so we can centralize the comments and effort in just one ticket. Thank you very much for the report and stay tuned to the other tickets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

in: webAn issue in web modules (web, webmvc)status: duplicateA duplicate of another issue

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions