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
}