Forum Discussion

jba3126's avatar
jba3126
Icon for Cirrus rankCirrus
Apr 26, 2023

ASM Bot Defense JS and CSP

Our company has issued a requirement for all applications to enable CSP (Content Security Policy).  The problem is one of the first applications to enable this has Bot Defense enabled.  Part of PBD is to inject a JAVA script inline which causes an issue with the page not loading per the CSP policy.  We opened a support case and F5 level II and the ENE say they can't find a way to make these compatible and this is beyond the scope of Support i.e. engage Professional Services.  I'm a long-time F5 user and so this was frustrating, to say the least.

Part of our CSP is our scripts have a nonce key generated. PBD script is not being delivered from our server (it's directly injected into the response), and it does not contain our nonce key.  This means that the CSP will tell the browser to NOT allow the execution of that script thereby breaking the application.

Part of the CSP Rules

  1. The browser should accept any JS that is delivered as a file from 'self' which means it's delivered from our web server with a relative path
  2. The browser should accept any JS that is delivered to the browser with our nonce key (value in the header)
  3. All other JS should be ignored by the browser!

So, the only question that we really had for F5 is how do we make PBD JS work with a CSP?  The CSP is set up in a basic way and is not customized to our application at all. It seems we either need to have this JS delivered by a file (not directly injected) or the F5 will need to pick up our nonce key and add it to that injection. 

Has anyone come across this and what methods did you employ to resolve it, i.e. iRule or Traffic policy to set the nonce key on the JS, which is not super ideal?
Depending on when ASM/PBD fire, something similar to the following:

when HTTP_RESPONSE {
    # Check if the response header contains a CSP
    if {[HTTP::header exists "Content-Security-Policy"]} {
        # Get the CSP header value
        set csp [HTTP::header value "Content-Security-Policy"]
        # Check if the CSP contains a nonce
        if {[string first "nonce-" $csp] != -1} {
            # Get the nonce value
            set nonce [string range $csp [string first "nonce-" $csp] [string first ";" $csp]]
            # Check if the response body contains a script tag
            if {[string first "<script" [HTTP::payload]] != -1} {
                # Add the nonce to the script tag
                HTTP::payload replace [string first "<script" [HTTP::payload]] [string first ">" [HTTP::payload]] "<script nonce=\"$nonce\""
            }
        }
    }
}

 

  • Has anyone come across this and what methods did you employ to resolve it, i.e. iRule or Traffic policy to set the nonce key on the JS, which is not super ideal?

    I am running into the same issue here.

    Have just tested this but the issue is that ASM sets the script tags in the http payload after the HTTP_RESPONSE_DATA event, this is the last moment we can manipulate the payload. So we are never able to manipulate the script tags ourself to add the nonce value.

    UPDATE:

    I have created an irule that works for me. It uses a HTML profile with a rule that triggers on seeing a script tag in the HTML. When using this profile you get access to the HTML_TAG_MATCHED even in the irule.

    The irule then takes the nonce value from the content security profile an adds it (if missing) to the script tags.

    I shared it on GitHub as well.

    https://github.com/security-by-design-it/F5-Irules/blob/main/set_nonce_js_inject.tcl

    # IRule to get the nonce value of a CSP header and put it in the HTML script tags
    # This is needed for the JavaScript that is injected by an ASM Bot Defence profile
    # Make sure to put a HTML profile on the virtual server that triggers an
    # event when it detects a script-tag in the HTML.
    
    when HTTP_RESPONSE {
        # Check if the response header contains a CSP
        if {[HTTP::header exists "Content-Security-Policy"]} {
            # Get the CSP header value
            set csp [HTTP::header value "Content-Security-Policy"]
            # Check if the CSP contains a nonce
            if {[string first "nonce-" $csp] != -1} {
                # Get the nonce value
                set idx [string first "nonce-" $csp]
                set nonce [string trim [string range $csp $idx end-3] "nonce-"]
            }
        }
    }
    
    # Event if the HTML profile rule is triggered
    when HTML_TAG_MATCHED {
        # Check if nonce value allready exists, if not add it
        if {not [HTML::tag attribute exists "nonce"]} {
            HTML::tag attribute insert "nonce" $nonce
        }
    }

     

    This is the HTML Profile event rule i created, you link this to a HTML profile then you add it in your virtual server config.

     

  • rburch's avatar
    rburch
    Icon for Nimbostratus rankNimbostratus

    Was there any resolution for this issue as I am running into this issue myself?

  • I have faced the same issue...the JS broke the application. Running Bot Defense without features that send ASM proactive cookies (not the ideal solution!).