Uploaded image for project: 'WildFly WIP'
  1. WildFly WIP
  2. WFWIP-687

[WFCORE-7192] Brute Force Authentication Attack: SASL/HTTP inconsistency when attempting valid disabled authentication

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Critical Critical
    • Security
    • None
    • Hide

      Prepare logging:

      bin/jboss-cli.sh
      embed-server --admin-only
      /subsystem=logging/logger=org.wildfly.security:add(level=TRACE)
      /subsystem=logging/logger=org.wildfly.extension.elytron:add(level=TRACE)
      exit
      

      Add users:

      bin/add-user.sh -u testOne -p passwordOne
      bin/add-user.sh -u testTwo -p passwordTwo
      

      Start server adjusting max failed attempts and lockout interval:

      bin/standalone.sh -Dwildfly.elytron.realm.ManagementRealm.brute-force.max-failed-attempts=2 -Dwildfly.elytron.realm.ManagementRealm.brute-force.lockout-interval=1
      

      Try SASL through jboss-cli. Any attempts should prolong the lockout once max failed attempts exceeded (expected):

      bin/jboss-cli.sh --connect \
       --user=testOne \
       --password=passwordOne \
       --no-local-auth \
       --command=":read-attribute(name=name)"
      
      bin/jboss-cli.sh --connect \
       --user=testOne \
       --password=badPassword \
       --no-local-auth \
       --command=":read-attribute(name=name)"
      

      Try HTTP using curl. Any attempts have no effect on the lockout interval once max failed attempts exceeded (not expected):

      curl --digest -L -D - http://localhost:9990/management --header "Content-Type: application/json" -d '{"operation":"read-attribute","name":"server-state","json.pretty":1}' -u testOne:passwordOne
      
      curl --digest -L -D - http://localhost:9990/management --header "Content-Type: application/json" -d '{"operation":"read-attribute","name":"server-state","json.pretty":1}' -u testOne:badPassword
      
      Show
      Prepare logging: bin/jboss-cli.sh embed-server --admin-only /subsystem=logging/logger=org.wildfly.security:add(level=TRACE) /subsystem=logging/logger=org.wildfly.extension.elytron:add(level=TRACE) exit Add users: bin/add-user.sh -u testOne -p passwordOne bin/add-user.sh -u testTwo -p passwordTwo Start server adjusting max failed attempts and lockout interval: bin/standalone.sh -Dwildfly.elytron.realm.ManagementRealm.brute-force.max-failed-attempts=2 -Dwildfly.elytron.realm.ManagementRealm.brute-force.lockout-interval=1 Try SASL through jboss-cli. Any attempts should prolong the lockout once max failed attempts exceeded (expected): bin/jboss-cli.sh --connect \ --user=testOne \ --password=passwordOne \ --no-local-auth \ --command=":read-attribute(name=name)" bin/jboss-cli.sh --connect \ --user=testOne \ --password=badPassword \ --no-local-auth \ --command=":read-attribute(name=name)" Try HTTP using curl. Any attempts have no effect on the lockout interval once max failed attempts exceeded (not expected): curl --digest -L -D - http://localhost:9990/management --header "Content-Type: application/json" -d '{"operation":"read-attribute","name":"server-state","json.pretty":1}' -u testOne:passwordOne curl --digest -L -D - http://localhost:9990/management --header "Content-Type: application/json" -d '{"operation":"read-attribute","name":"server-state","json.pretty":1}' -u testOne:badPassword

      After the number of bad authentication attempts has been exceeded the authentication is disabled for the given username. Any subsequent valid authentication attempts are unsuccessful (which is intended behaviour).

      However, there is inconsistent behavior for SASL vs HTTP when attempting to authenticate with good password while authentication is disabled:

      • For SASL, the lockout timeout is prolonged with such attempts ("Disabling authentication for ..." is logged).
      • for HTTP the lockout timeout is driven by the last unsuccessful authentication attempt exceeding the max-failed-attempts ("Disabling authentication for ..." is not logged in this case). The following is logged:

       

      2026-01-15 12:39:12,261 TRACE [org.wildfly.security] (management task-2) Created HttpServerAuthenticationMechanism [org.wildfly.security.auth.server.SecurityIdentityServerMechanismFactory$1@5b9620f2] for mechanism [DIGEST]
      2026-01-15 12:39:12,262 TRACE [org.wildfly.security] (management task-2) Handling SocketAddressCallback
      2026-01-15 12:39:12,262 TRACE [org.wildfly.security] (management task-2) Handling MechanismInformationCallback type='HTTP' name='DIGEST' host-name='localhost' protocol='http'
      2026-01-15 12:39:12,262 TRACE [org.wildfly.security] (management task-2) Handling AvailableRealmsCallback: realms = [ManagementRealm]
      2026-01-15 12:39:12,262 TRACE [org.wildfly.security.http.digest] (management task-2) New nonce generated AAAAFQAAqN8XdPt7txbq1f3gp01sxZ7ks28eWY4MVIPWR+vG6jBLmrKJFE8=, using seed 4d616e6167656d656e745265616c6d
      2026-01-15 12:39:12,265 TRACE [org.wildfly.security] (management task-2) Created HttpServerAuthenticationMechanism [org.wildfly.security.auth.server.SecurityIdentityServerMechanismFactory$1@4e183644] for mechanism [DIGEST]
      2026-01-15 12:39:12,265 TRACE [org.wildfly.security] (management task-2) Handling SocketAddressCallback
      2026-01-15 12:39:12,265 TRACE [org.wildfly.security] (management task-2) Handling MechanismInformationCallback type='HTTP' name='DIGEST' host-name='localhost' protocol='http'
      2026-01-15 12:39:12,266 TRACE [org.wildfly.security.http.digest] (management task-2) Currently 13 nonces being tracked
      2026-01-15 12:39:12,266 TRACE [org.wildfly.security] (management task-2) Handling AvailableRealmsCallback: realms = [ManagementRealm]
      2026-01-15 12:39:12,266 TRACE [org.wildfly.security] (management task-2) Handling AvailableRealmsCallback: realms = [ManagementRealm]
      2026-01-15 12:39:12,266 TRACE [org.wildfly.security] (management task-2) Handling RealmCallback: selected = [ManagementRealm]
      2026-01-15 12:39:12,266 TRACE [org.wildfly.security] (management task-2) Handling NameCallback: authenticationName = testOne
      2026-01-15 12:39:12,266 TRACE [org.wildfly.security] (management task-2) Principal assigning: [testOne], pre-realm rewritten: [testOne], realm name: [ManagementRealm], post-realm rewritten: [testOne], realm rewritten: [testOne]
      2026-01-15 12:39:12,266 TRACE [org.wildfly.security] (management task-2) Handling CredentialCallback: failed to obtain credential
      2026-01-15 12:39:12,266 TRACE [org.wildfly.security] (management task-2) Handling RealmCallback: selected = [ManagementRealm]
      2026-01-15 12:39:12,266 TRACE [org.wildfly.security] (management task-2) Handling NameCallback: authenticationName = testOne
      2026-01-15 12:39:12,266 TRACE [org.wildfly.security] (management task-2) Handling CredentialCallback: failed to obtain credential
      2026-01-15 12:39:12,266 TRACE [org.wildfly.security] (management task-2) Handling RealmCallback: selected = [ManagementRealm]
      2026-01-15 12:39:12,266 TRACE [org.wildfly.security] (management task-2) Handling NameCallback: authenticationName = testOne
      2026-01-15 12:39:12,266 TRACE [org.wildfly.security] (management task-2) Handling PasswordCallback: PasswordCredential may not be supported
      2026-01-15 12:39:12,266 TRACE [org.wildfly.security.http.digest] (management task-2) Failed to parse or validate the response: org.wildfly.security.mechanism.AuthenticationMechanismException: ELY05051: Callback handler does not support credential acquisition
      	at org.wildfly.security.elytron-base@2.8.0.CR1-SNAPSHOT//org.wildfly.security.mechanism.digest.PasswordDigestObtainer.getSaltedPasswordFromPasswordCallback(PasswordDigestObtainer.java:344)
      	at org.wildfly.security.elytron-base@2.8.0.CR1-SNAPSHOT//org.wildfly.security.mechanism.digest.PasswordDigestObtainer.handleUserRealmPasswordCallbacks(PasswordDigestObtainer.java:143)
      	at org.wildfly.security.elytron-base@2.8.0.CR1-SNAPSHOT//org.wildfly.security.http.digest.DigestAuthenticationMechanism.getH_A1(DigestAuthenticationMechanism.java:332)
      	at org.wildfly.security.elytron-base@2.8.0.CR1-SNAPSHOT//org.wildfly.security.http.digest.DigestAuthenticationMechanism.validateResponse(DigestAuthenticationMechanism.java:220)
      	at org.wildfly.security.elytron-base@2.8.0.CR1-SNAPSHOT//org.wildfly.security.http.digest.DigestAuthenticationMechanism.evaluateRequest(DigestAuthenticationMechanism.java:127)
      	at org.wildfly.security.elytron-base@2.8.0.CR1-SNAPSHOT//org.wildfly.security.http.util.SetMechanismInformationMechanismFactory$1.evaluateRequest(SetMechanismInformationMechanismFactory.java:119)
      	at org.wildfly.security.elytron-base@2.8.0.CR1-SNAPSHOT//org.wildfly.security.http.util.SocketAddressCallbackServerMechanismFactory$1.evaluateRequest(SocketAddressCallbackServerMechanismFactory.java:82)
      	at org.wildfly.security.elytron-base@2.8.0.CR1-SNAPSHOT//org.wildfly.security.http.util.SetRequestInformationCallbackMechanismFactory$1.evaluateRequest(SetRequestInformationCallbackMechanismFactory.java:84)
      	at org.wildfly.security.elytron-base@2.8.0.CR1-SNAPSHOT//org.wildfly.security.auth.server.SecurityIdentityServerMechanismFactory$1.evaluateRequest(SecurityIdentityServerMechanismFactory.java:86)
      	at org.wildfly.security.elytron-base@2.8.0.CR1-SNAPSHOT//org.wildfly.security.http.HttpAuthenticator$AuthenticationExchange.authenticate(HttpAuthenticator.java:331)
      	at org.wildfly.security.elytron-base@2.8.0.CR1-SNAPSHOT//org.wildfly.security.http.HttpAuthenticator.authenticate(HttpAuthenticator.java:93)
      	at org.wildfly.security.elytron-web.undertow-server@4.1.2.Final//org.wildfly.elytron.web.undertow.server.SecurityContextImpl.authenticate(SecurityContextImpl.java:107)
      	at io.undertow.core@2.3.20.Final//io.undertow.security.handlers.AuthenticationCallHandler.handleRequest(AuthenticationCallHandler.java:50)
      	at io.undertow.core@2.3.20.Final//io.undertow.server.Connectors.executeRootHandler(Connectors.java:395)
      	at io.undertow.core@2.3.20.Final//io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:900)
      	at org.jboss.threads@3.9.2//org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
      	at org.jboss.threads@3.9.2//org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2651)
      	at org.jboss.threads@3.9.2//org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2630)
      	at org.jboss.threads@3.9.2//org.jboss.threads.EnhancedQueueExecutor.runThreadBody(EnhancedQueueExecutor.java:1622)
      	at org.jboss.threads@3.9.2//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1589)
      	at org.jboss.xnio@3.8.16.Final//org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1282)
      	at java.base/java.lang.Thread.run(Thread.java:1583)
      Caused by: org.wildfly.security.auth.callback.FastUnsupportedCallbackException: javax.security.auth.callback.PasswordCallback@32006e18
      
      2026-01-15 12:39:12,267 TRACE [org.wildfly.security] (management task-2) Handling AvailableRealmsCallback: realms = [ManagementRealm]
      2026-01-15 12:39:12,267 TRACE [org.wildfly.security.http.digest] (management task-2) New nonce generated AAAAFgAAqN8XtyzYXVuCPZaFGXTkYhmmqn0l1Do+ylgW+0Uhhp0Gi5DG1yI=, using seed 4d616e6167656d656e745265616c6d
      

              darran.lofthouse@redhat.com Darran Lofthouse
              okotek@redhat.com Ondrej Kotek
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated: