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
}