FortiGate
FortiGate Next Generation Firewall utilizes purpose-built security processors and threat intelligence security services from FortiGuard labs to deliver top-rated protection and high performance, including encrypted traffic.
heljag
Staff
Staff
Article Id 332380
Description This article describes how to troubleshoot WAF, collect debug logs and match Event IDs from logs to signatures (main-class).
Scope FortiGate.

Solution

 

In order to use a WAF profile, the related policies should be in proxy mode. That way, the daemon/process responsible for handling this type is WAD.

 

Example:

 

Consider an example with a WAF profile configured with the following signatures.

 

signatures.PNG

 

This WAF profile will be used to protect a web server behind FortiGate on the following policy:

 

policyWAF.PNG

 

To test WAF, a simple SQL Injection attempt will be made using the following URL:

 

https://site.example.com/index.php?username=1'%20or%20'1'%20=%20'1&password=1'%20or%20'1'%20=%20'1,

 

On the machine being tested, the following error will appear:

 

policyWAF_machine.PNG

 

Checking the logs from the FortiGate side will show the following:

 

policyWAF_FGT.PNG

 

If traffic was blocked as seen from the client side, it may seem strange to see a different Event ID on the FortiGate side and with Action passthrough.

 

First, it is necessary to understand how the signatures are grouped.

Checking the 'default' WAF profile on the CLI will show the following:

 

config waf profile
    edit "default"
        config signature
            config main-class 100000000
                set action block
                set log disable
                set severity high
            end
            config main-class 20000000
                set status enable
                set action block
            end
            config main-class 30000000
                set status enable
                set action block
                set log disable
                set severity high
                end
            config main-class 40000000
                set status enable
            end

                          ...

 

Based on this, it is possible to conclude that the event we saw on the FortiGate (40000163) belongs to main-class 40000000 but the event from the client machine (30000040) belongs to main-class 30000000.

 

The association between 30000040 and the main-class 30000000 and what the main-class represents:

 

The 3000040 is a signature that belongs to the main-class 30000000. Regard the main-class as a group.

 

How to know what signature is 30000040 and if I the right one is being blocked:

 

Hovering the mouse over one of the signatures in the GUI will show the main-class.

 

Figure 5:

 

waf_sql_injection.png

 

Figure 6:

 

waf_sql_injection_extended.png

 

Here, 30000040 belongs to the SQL Injection main-class and 40000163 belongs to SQL Injection (Extended).

 

If more detail is needed from these signatures, check in the CLI:

 

diagnose waf dump | grep 30000040
30000040 - This signature prevents attackers from getting database sensitive information through "bOOL" operation. This injection can be achieved in HTTP request URL and arguments.

 

diagnose waf dump | grep 40000163
40000163 - This signature prevents attackers from probing SQL injection vulnerability in accessed page.

 

Now that the association between the Event ID, signatures, and main-class is known, perform debugging to see why different Event IDs are observed from the client machine and FortiGate.

As mentioned in the start of this article, WAD is the daemon/process that must be debugged to capture the necessary debug logs.

 

diagnose debug console timestamp en
diagnose wad debug enable level verbose
diagnose wad debug enable category all
diagnose debug enable

 

Below is an example collected from the WAD.

 

[I]2024-08-12 19:25:42.689695 [p:244][s:92681][r:1] wad_dump_http_request :2569 hreq=0x7ff5cfa0f500 Received request from client: 20.20.20.43:56313

GET /index.php?username=1%27%20or%20%271%27%20=%20%271&password=1%27%20or%20%271%27%20=%20%20%271, HTTP/1.1
Host: site.example.com
Connection: keep-alive
sec-ch-ua: "Chromium";v="122", "Not(A:Brand";v="24", "Microsoft Edge";v="122"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9

[V]2024-08-12 19:25:42.689703 [p:244][s:92681][r:1] wad_http_marker_uri :1260 path=/index.php len=10
[V]2024-08-12 19:25:42.689709 [p:244][s:92681][r:1] wad_http_parse_host :1635 host_len=16
[I]2024-08-12 19:25:42.689711 [p:244][s:92681][r:1] wad_http_parse_host :1667 host=[16]site.example.com
[I]2024-08-12 19:25:42.689715 [p:244][s:92681][r:1] wad_http_str_canonicalize :2182 enc=0 path=/index.php len=10 changes=0
[I]2024-08-12 19:25:42.689718 [p:244][s:92681][r:1] wad_http_str_canonicalize :2184 end=4 path=username=1%27%20or%20%271%27%20=%20%271&password=1%27%20or%20%271%27%20=%20%20%271, len=83 changes=0

...

[I]2024-08-12 19:25:42.690110 [p:244][s:92681][r:1] wad_waf_sig_match_request :414 WAF sig=40000040 sig_flags=0x3 kw_sig_flags=0x403 check_body_args=0
WAF data=1' or '1' = '1 ret=1/3/11
[I]2024-08-12 19:25:42.690114 [p:244][s:92681][r:1] wad_waf_match_signatures :729 WAF sig=40000040 matched action=0 severity=2
[I]2024-08-12 19:25:42.690128 [p:244][s:92681][r:1] wad_waf_sig_match_request :414 WAF sig=40000108 sig_flags=0xc3 kw_sig_flags=0x4c3 check_body_args=0
WAF data=1' or '1' = '1 ret=1/1/14
[I]2024-08-12 19:25:42.690133 [p:244][s:92681][r:1] wad_waf_match_signatures :729 WAF sig=40000108 matched action=0 severity=2

...

[I]2024-08-12 19:25:42.690168 [p:244][s:92681][r:1] wad_waf_sig_match_request :414 WAF sig=40000163 sig_flags=0x3 kw_sig_flags=0x403 check_body_args=0
WAF data=1' or '1' = '1 ret=1/1/7
[I]2024-08-12 19:25:42.690171 [p:244][s:92681][r:1] wad_waf_match_signatures :729 WAF sig=40000163 matched action=0 severity=2
[I]2024-08-12 19:25:42.690175 [p:244][s:92681][r:1] wad_waf_sig_match_request :414 WAF sig=30000040 sig_flags=0x3 kw_sig_flags=0x403 check_body_args=0
WAF data=1' or '1' = '1 ret=1/3/11
[I]2024-08-12 19:25:42.690178 [p:244][s:92681][r:1] wad_waf_match_signatures :729 WAF sig=30000040 matched action=1 severity=1
[I]2024-08-12 19:25:42.690180 [p:244][s:92681][r:1] wad_http_waf_check_signature :1144 WAF signature-based attack detected msg=0x7ff5cfa0f500
[I]2024-08-12 19:25:42.690183 [p:244][s:92681][r:1] __wad_http_build_replmsg_resp :632 Generating replacement message. WAF attack detected repmsg_id 54
[V]2024-08-12 19:25:42.690186 [p:244][s:92681][r:1] wad_mem_c_malloc :138 size 32770 exceeds max_elm_size (18396); not using bucket
[V]2024-08-12 19:25:42.690298 [p:244][s:92681][r:1] wad_http_msg_start_setup_proc :2100 msg(0x7ff5cfa0f500) proc-setup started from: req_resp_ready.
[V]2024-08-12 19:25:42.690303 [p:244][s:92681][r:1] wad_http_def_proc_msg_plan :2062 msg(0x7ff5cfa0f500) setting up processor(req_resp_ready)
[V]2024-08-12 19:25:42.690305 [p:244][s:92681][r:1] wad_http_msg_start_setup_proc :2100 msg(0x7ff5cffe31f0) proc-setup started from: resp_forward.
[V]2024-08-12 19:25:42.690307 [p:244][s:92681][r:1] wad_http_def_proc_msg_plan :2062 msg(0x7ff5cffe31f0) setting up processor(resp_forward)
[I]2024-08-12 19:25:42.690309 [p:244][s:92681][r:1] wad_dump_fwd_http_resp :2585 hreq=0x7ff5cfa0f500 Forward response from Internal:

 

With this sample we can see that multiple signatures are matched. 40000040, 40000108, 40000163 and 30000040.

We can see also that action and severity is using different numbers.

 

  • action = 0 (monitor or allow)
  • action = 1 (block)
  • severity = 1 (high)
  • severity = 2 (medium)
  • severity = 3 (low)

 

Based on this, it is possible to see that the only signature that was blocked was the one with Event ID 30000040, as seen on the client machine.

Notably, the others were not blocked (40000040, 40000108 and 40000163) and the blocked signature (30000040) did not show up in the logs.

 

Checking the image from Figure 5 or Figure 6 will show that SQL Injection (Extended) - main-class 40000000 - is set to monitor.

This explains why signatures from main-class 4000000 were not blocked

 

As for the log, checking the 'default' WAF profile again will reveal the following:

 

config waf profile
    edit "default"
        config signature
            config main-class 100000000
                set action block
                set log disable
                set severity high
            end
            config main-class 20000000
                set status enable
                set action block
            end
            config main-class 30000000
                set status enable
                set action block
                set log disable <- Here, logging is disabled.
                set severity high
            end
            config main-class 40000000
                set status enable
            end

                          ...

 

Adjusting the log setting (to enable) will show the block on FortiGate for SQL Injection main-class 30000000.

 

waf_last.png

 

Contributors