Forum Discussion

Maxim_Taskov's avatar
Maxim_Taskov
Icon for Nimbostratus rankNimbostratus
Feb 09, 2026
Solved

Question/Advice on iRule Remediating the Telerik (Unsafe Reflection Vulnerability (CVE-2025-3600)

Hi, I have the below iRule that is supposed to remediate the Telerik UI library vulnerability mentioned in the title above. The iRule is built based on their IIS URL Rewrite recommendation. I understand its logic in general but I am not a developer and I am not sure that what I am seeing is OK or not. If I test the iRule with a malicious request using Postman or curl, it works as expected, the request is blocked every time. If I test using a browser, any browser, the first request is blocked and the next one is allowed, which is not what I would expect. Below is the iRule and any help/advice would be much appreciated. I am running BIGIP LTM 17.5.1.3. Thank you

 

when HTTP_REQUEST {

# Case-insensitive match on path for Telerik.Web.UI.WebResource.axd

set path_lc [string tolower [HTTP::path]]

if { [string match "*telerik.web.ui.webresource.axd" $path_lc] } {

# Normalize method

set method [string toupper [HTTP::method]]

# Decode query string (may be empty)

set raw_q [HTTP::query]

if { $raw_q eq "" } {

set dec_q ""

} else {

set dec_q [URI::decode $raw_q]

}

# Decode Cookie header (if present)

set raw_cookie ""

if { [HTTP::header exists "Cookie"] } {

set raw_cookie [HTTP::header value "Cookie"]

}

set dec_cookie [URI::decode $raw_cookie]

# -------------------------

# Rule 1 (ALLOW): Allow RadAsyncUpload/RadCloudUpload POSTs

# IIS: UrlDecode(QUERY_STRING) must match ^type=(rau|rcu)$ and method == POST

# -------------------------

set allow_post_rau_rcu 0

if { $method eq "POST" } {

if { [regexp -nocase {^type=(rau|rcu)$} $dec_q] } {

set allow_post_rau_rcu 1

}

}

if { $allow_post_rau_rcu } {

# Stop further processing (equivalent to stopProcessing="true")

return

}

# -------------------------

# Rule 2 (BLOCK): Block all GET requests containing Content-Type header

# IIS: method == GET AND HTTP_CONTENT_TYPE matches ".+"

# -------------------------

if { $method eq "GET" } {

if { [HTTP::header exists "Content-Type"] && [string length [HTTP::header "Content-Type"]] > 0 } {

HTTP::respond 403 content {Request blocked 2}

event disable

return

}

}

# -------------------------

# Rule 3 (BLOCK): Block PRType and encoded attacks; also block non-GET

# IIS: MatchAny of:

# - UrlDecode(QUERY_STRING) contains "prtype="

# - UrlDecode(HTTP_COOKIE) contains "prtype="

# - REQUEST_METHOD != GET

# Note: The allowed POSTs above have already returned.

# -------------------------

if { [regexp -nocase {prtype=} $dec_q]

|| [regexp -nocase {prtype=} $dec_cookie]

|| $method ne "GET" } {

HTTP::respond 403 content {Request blocked 3}

event disable

return

}

# If none of the block conditions match, allow the request.

}

}

  • HI Maxim_Taskov​    We have this really cool AI iRules assistant   F5 AI Assistant Expands with iRules Code Generation for BIG-IP Programmability | F5  that can help write and analyze irules... I put your irule in and here is what came back...  

     

    1. Objective
      • This iRule targets requests for “Telerik.Web.UI.WebResource.axd” and applies three security controls.
      • It first allows only specific POST uploads (type=rau or rcu).
      • It then blocks any GET with a Content-Type header.
      • Finally, it blocks requests containing “prtype=” in the decoded query or cookie, or any non-GET not already allowed.
    2. Execution Flow
      • Event: when HTTP_REQUEST (docs: valid event for HTTP::path, HTTP::query, HTTP::method, etc.)
      1. Retrieve the request path via HTTP::path, lowercase it (string tolower).
      2. If the lowercase path matches *telerik.web.ui.webresource.axd, proceed; else do nothing.
      3. Normalize the method: set method [string toupper [HTTP::method]].
      4. Read raw query: set raw_q [HTTP::query]; decode if non-empty (URI::decode), else set dec_q "".
      5. If a “Cookie” header exists (HTTP::header exists "Cookie"), read and decode it into dec_cookie; else dec_cookie is empty.
      6. Rule 1 (ALLOW):
        – If method == "POST" and dec_q matches ^type=(rau|rcu)$ (case-insensitive), then return (stop this event).
      7. Rule 2 (BLOCK):
        – If method == "GET" and a non-empty “Content-Type” header exists, then respond with 403 “Request blocked 2”, disable the event, and return.
      8. Rule 3 (BLOCK):
        – If dec_q or dec_cookie contains prtype= (case-insensitive) OR method != "GET", then respond with 403 “Request blocked 3”, disable the event, and return.
      9. If none of the above rules fired, the request is allowed to proceed.
    3. Potential Logic Concerns
      • The calls to event disable omit the required event name (e.g., event HTTP_REQUEST disable), so they will not actually disable further evaluations as intended. (high confidence)

    Overall, the iRule correctly sequences allow-then-block checks for the targeted resource, but the malformed event disable commands mean blocked requests may still trigger later events.

     

    So it seems there may be an issue with the event disable.  

    Looks like the request  matches a blocking condition, the iRule issues HTTP::respond 403 to reject it, followed by event disable and return.

    Event disable disables the HTTP_REQUEST event for the entire current TCP connection. This is a global effect on the connection, not just the current HTTP request.

    Have you considered using "reject" which will send a TCP RST, closing the connection immediately.  

     

    this part of the code you can try 

    if { [regexp -nocase {prtype=} $dec_q]
                 || [regexp -nocase {prtype=} $dec_cookie]
                 || $method ne "GET" } {
                HTTP::respond 403 content {Request blocked 3}
                reject  ;# Close connection to prevent reuse
                return
            }

     

     

2 Replies

  • HI Maxim_Taskov​    We have this really cool AI iRules assistant   F5 AI Assistant Expands with iRules Code Generation for BIG-IP Programmability | F5  that can help write and analyze irules... I put your irule in and here is what came back...  

     

    1. Objective
      • This iRule targets requests for “Telerik.Web.UI.WebResource.axd” and applies three security controls.
      • It first allows only specific POST uploads (type=rau or rcu).
      • It then blocks any GET with a Content-Type header.
      • Finally, it blocks requests containing “prtype=” in the decoded query or cookie, or any non-GET not already allowed.
    2. Execution Flow
      • Event: when HTTP_REQUEST (docs: valid event for HTTP::path, HTTP::query, HTTP::method, etc.)
      1. Retrieve the request path via HTTP::path, lowercase it (string tolower).
      2. If the lowercase path matches *telerik.web.ui.webresource.axd, proceed; else do nothing.
      3. Normalize the method: set method [string toupper [HTTP::method]].
      4. Read raw query: set raw_q [HTTP::query]; decode if non-empty (URI::decode), else set dec_q "".
      5. If a “Cookie” header exists (HTTP::header exists "Cookie"), read and decode it into dec_cookie; else dec_cookie is empty.
      6. Rule 1 (ALLOW):
        – If method == "POST" and dec_q matches ^type=(rau|rcu)$ (case-insensitive), then return (stop this event).
      7. Rule 2 (BLOCK):
        – If method == "GET" and a non-empty “Content-Type” header exists, then respond with 403 “Request blocked 2”, disable the event, and return.
      8. Rule 3 (BLOCK):
        – If dec_q or dec_cookie contains prtype= (case-insensitive) OR method != "GET", then respond with 403 “Request blocked 3”, disable the event, and return.
      9. If none of the above rules fired, the request is allowed to proceed.
    3. Potential Logic Concerns
      • The calls to event disable omit the required event name (e.g., event HTTP_REQUEST disable), so they will not actually disable further evaluations as intended. (high confidence)

    Overall, the iRule correctly sequences allow-then-block checks for the targeted resource, but the malformed event disable commands mean blocked requests may still trigger later events.

     

    So it seems there may be an issue with the event disable.  

    Looks like the request  matches a blocking condition, the iRule issues HTTP::respond 403 to reject it, followed by event disable and return.

    Event disable disables the HTTP_REQUEST event for the entire current TCP connection. This is a global effect on the connection, not just the current HTTP request.

    Have you considered using "reject" which will send a TCP RST, closing the connection immediately.  

     

    this part of the code you can try 

    if { [regexp -nocase {prtype=} $dec_q]
                 || [regexp -nocase {prtype=} $dec_cookie]
                 || $method ne "GET" } {
                HTTP::respond 403 content {Request blocked 3}
                reject  ;# Close connection to prevent reuse
                return
            }

     

     

    • Maxim_Taskov's avatar
      Maxim_Taskov
      Icon for Nimbostratus rankNimbostratus

      Thank you Jeff_Granieri​ . Good point and obvious miss on my part. Seems to block the connection consistently but it now entirely skips the below and doesn't return 403, which is fine for now. And notes, I will use the AI editor to try to polish this one further.