Skip to main content
  1. Posts/

Access Fortigate REST API with enabled Post-Login-Banner

Table of Contents

Problem #

During my daily work I stumbled upon a problem with the REST API of a Fortigate firewall when using session-based authentication (login with username and password instead of an API token). The issue occurs when the post-login-banner option is enabled in the config system global section:

FGT-VM # show system global
config system global
    set hostname "Vladilena"
    set post-login-banner enable
    [...]
end

While the initial login works and the Fortigate returns seemingly correct cookies, all subsequent API calls return a 403 Forbidden error instead of the requested data. See the following example that uses curl to send the requests:

$ curl -k -X POST "https://172.25.86.20/logincheck" \
  -d "username=admin&secretkey=12345" -c cookies.txt
[...]
$ curl -k -b cookies.txt \
  "https://172.25.86.20/api/v2/monitor/system/status"
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head>
[...]

Depending on the FortiOS version, the firewall may respond with a 401 Unauthorized error instead of a 403 Forbidden. Nevertheless, the general problem remains the same.

Note

Token based authentication is not affected by this problem and works just fine even if the Fortigate is configured to display a login banner.

Fortinet released a KB Article describing this issue in which they state that the observed behavior is intended. To solve the problem Fortinet suggests to disable the post-login-banner option. While this solution indeed works it isn’t feasible to implement in my work environment. Luckily I found a workaround that allows you to use session-based authentication even if the post-login-banner is enabled.

Solution #

After the initial login against the /logincheck page an additional POST request must be sent to the /logindisclaimer endpoint. This second API call must contain the payload confirm=1.

Because of this additional requirement, each API login is now a two-step process. It can be seen in the following example that uses curl. Make sure to adjust the IP address of the firewall as well as the login credentials to your environment.

$ curl -k -X POST "https://172.25.86.20/logincheck" \
  -d "username=admin&secretkey=12345" -c cookies.txt
<script language="javascript">
document.location="/logindisclaimer?viewOnly&redir=%2F";
</script>

$ curl -k -b cookies.txt -c cookies.txt -X POST \
  "https://172.25.86.20/logindisclaimer" -d "confirm=1"
<script language="javascript">
document.location="/prompt?viewOnly&redir=%2F";
</script>

Note

A successful call to the /logindisclaimer page returns a new set of cookies that must be sent with all subsequent API requests.

That’s why both the -b and -c parameters are used in the second command.

Once both commands have been executed the API can be accessed normally and the Fortigate responds with the requested information:

$ curl -k -b cookies.txt \
  "https://172.25.86.20/api/v2/monitor/system/status"
{
  "http_method":"GET",
  "results":{
    "model_name":"FortiGate",
    "model_number":"VM64-HV",
    "model":"FGVMH6",
    "hostname":"Vladilena",
    "log_disk_status":"not_available"
  },
  "vdom":"root",
  "path":"system",
  "name":"status",
  "action":"",
  "status":"success",
  "serial":"...",
  "version":"v7.2.4",
  "build":1396
}