Skip to content

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

Closed
@fast-reflexes

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

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