Merge branch 'owasp-headers' into 'master'

Owasp headers

See merge request openconnect/ocserv!263
This commit is contained in:
Nikos Mavrogiannopoulos
2021-05-14 17:41:14 +00:00
8 changed files with 164 additions and 0 deletions

View File

@@ -438,6 +438,12 @@ int get_auth_handler2(worker_st * ws, unsigned http_ver, const char *pmsg, unsig
goto cleanup;
}
ret = add_owasp_headers(ws);
if (ret < 0) {
ret = -1;
goto cleanup;
}
ret = cstp_puts(ws, "\r\n");
if (ret < 0) {
ret = -1;
@@ -1089,6 +1095,12 @@ int post_common_handler(worker_st * ws, unsigned http_ver, const char *imsg)
if (ret < 0)
goto fail;
ret =
add_owasp_headers(ws);
if (ret < 0)
goto fail;
#ifdef ANYCONNECT_CLIENT_COMPAT
if (WSCONFIG(ws)->xml_config_file) {
ret =

View File

@@ -58,6 +58,7 @@ static int send_headers(worker_st *ws, unsigned http_ver, const char *content_ty
cstp_printf(ws, "Content-Type: %s\r\n", content_type) < 0 ||
cstp_puts (ws, "X-Transcend-Version: 1\r\n") < 0 ||
cstp_printf(ws, "Content-Length: %u\r\n", content_length) < 0 ||
add_owasp_headers(ws) < 0 ||
cstp_puts (ws, "\r\n") < 0)
return -1;
return 0;

View File

@@ -863,3 +863,28 @@ void http_req_deinit(worker_st * ws)
ws->req.body = NULL;
}
/* add_owasp_headers:
* @ws: an initialized worker structure
*
* This function adds the OWASP default headers
* There are security tools that flag the server as a security risk.
* These are added to help users comply with security best practices.
*/
int add_owasp_headers(worker_st * ws)
{
if (cstp_puts(ws, "Strict-Transport-Security: max-age=31536000 ; includeSubDomains\r\n") < 0 ||
cstp_puts(ws, "X-Frame-Options: deny\r\n") < 0 ||
cstp_puts(ws, "X-Content-Type-Options: nosniff\r\n") < 0 ||
cstp_puts(ws, "Content-Security-Policy: default-src \'none\'\r\n") < 0 ||
cstp_puts(ws, "X-Permitted-Cross-Domain-Policies: none\r\n") < 0 ||
cstp_puts(ws, "Referrer-Policy: no-referrer\r\n") < 0 ||
cstp_puts(ws, "Clear-Site-Data: \"cache\",\"cookies\",\"storage\"\r\n") < 0 ||
cstp_puts(ws, "Cross-Origin-Embedder-Policy: require-corp\r\n") < 0 ||
cstp_puts(ws, "Cross-Origin-Opener-Policy: same-origin\r\n") < 0 ||
cstp_puts(ws, "Cross-Origin-Resource-Policy: same-origin\r\n") < 0 ||
cstp_puts(ws, "X-XSS-Protection: 0\r\n") < 0)
{
return -1;
}
return 0;
}

View File

@@ -273,6 +273,11 @@ int post_kkdcp_handler(worker_st *ws, unsigned http_ver)
goto fail;
}
ret = add_owasp_headers(ws);
if (ret < 0) {
goto fail;
}
ret = cstp_puts(ws, "\r\n");
if (ret < 0) {
goto fail;

View File

@@ -1931,6 +1931,9 @@ static int connect_handler(worker_st * ws)
ret = cstp_puts(ws, "HTTP/1.1 200 CONNECTED\r\n");
SEND_ERR(ret);
ret = add_owasp_headers(ws);
SEND_ERR(ret);
ret = cstp_puts(ws, "X-CSTP-Version: 1\r\n");
SEND_ERR(ret);

View File

@@ -422,6 +422,8 @@ int parse_proxy_proto_header(struct worker_st *ws, int fd);
void cookie_authenticate_or_exit(worker_st *ws);
int add_owasp_headers(worker_st * ws);
/* after that time (secs) of inactivity in the UDP part, connection switches to
* TCP (if activity occurs there).
*/

View File

@@ -180,6 +180,7 @@ check_PROGRAMS += gen_oidc_test_data
dist_check_SCRIPTS += test-oidc
endif
dist_check_SCRIPTS += test-owasp-headers
dist_check_SCRIPTS += test-replay

115
tests/test-owasp-headers Executable file
View File

@@ -0,0 +1,115 @@
#!/bin/bash
#
# Copyright (C) 2021 Microsoft Corporation
#
# This file is part of ocserv.
#
# ocserv is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at
# your option) any later version.
#
# ocserv is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GnuTLS; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
SERV="${SERV:-../src/ocserv}"
srcdir=${srcdir:-.}
NO_NEED_ROOT=1
. `dirname $0`/common.sh
eval "${GETPORT}"
echo "Testing ocserv owasp headers... "
update_config test-user-cert.config
launch_simple_sr_server -d 1 -f -c ${CONFIG}
PID=$!
wait_server $PID
function CheckHeaders
{
[[ "$1" =~ .*"Strict-Transport-Security".* ]] || fail $PID "Missing HTTP header (Strict-Transport-Security)"
[[ "$1" =~ .*"X-Frame-Options".* ]] || fail $PID "Missing HTTP header (X-Frame-Options)"
[[ "$1" =~ .*"X-Content-Type-Options".* ]] || fail $PID "Missing HTTP header (X-Content-Type-Options)"
[[ "$1" =~ .*"Content-Security-Policy".* ]] || fail $PID "Missing HTTP header (Content-Security-Policy)"
[[ "$1" =~ .*"X-Permitted-Cross-Domain-Policies".* ]] || fail $PID "Missing HTTP header (X-Permitted-Cross-Domain-Policies)"
[[ "$1" =~ .*"Referrer-Policy".* ]] || fail $PID "Missing HTTP header (Referrer-Policy)"
[[ "$1" =~ .*"Clear-Site-Data".* ]] || fail $PID "Missing HTTP header (Clear-Site-Data)"
[[ "$1" =~ .*"Cross-Origin-Embedder-Policy".* ]] || fail $PID "Missing HTTP header (Cross-Origin-Embedder-Policy)"
[[ "$1" =~ .*"Cross-Origin-Opener-Policy".* ]] || fail $PID "Missing HTTP header (Cross-Origin-Opener-Policy)"
[[ "$1" =~ .*"Cross-Origin-Resource-Policy".* ]] || fail $PID "Missing HTTP header (Cross-Origin-Resource-Policy)"
[[ "$1" =~ .*"X-XSS-Protection".* ]] || fail $PID "Missing HTTP header (X-XSS-Protection)"
while IFS=':' read name value; do
case "$name" in
Strict-Transport-Security)
[[ "$value" =~ "max-age=31536000 ; includeSubDomains" ]] || fail $PID "Unexpected HTTP header value ($name: $value)";;
X-Frame-Options)
[[ "$value" =~ "deny" ]] || fail $PID "Unexpected HTTP header value ($name: $value)";;
X-Content-Type-Options)
[[ "$value" =~ "nosniff" ]] || fail $PID "Unexpected HTTP header value ($name: $value)";;
Content-Security-Policy)
[[ "$value" =~ "default-src 'none'" ]] || fail $PID "Unexpected HTTP header value ($name: $value)";;
X-Permitted-Cross-Domain-Policies)
[[ "$value" =~ "none" ]] || fail $PID "Unexpected HTTP header value ($name: $value)";;
Referrer-Policy)
[[ "$value" =~ "no-referrer" ]] || fail $PID "Unexpected HTTP header value ($name: $value)";;
Clear-Site-Data)
[[ "$value" =~ "\"cache\",\"cookies\",\"storage\"" ]] || fail $PID "Unexpected HTTP header value ($name: $value)";;
Cross-Origin-Embedder-Policy)
[[ "$value" =~ "require-corp" ]] || fail $PID "Unexpected HTTP header value ($name: $value)";;
Cross-Origin-Opener-Policy)
[[ "$value" =~ "same-origin" ]] || fail $PID "Unexpected HTTP header value ($name: $value)";;
Cross-Origin-Resource-Policy)
[[ "$value" =~ "same-origin" ]] || fail $PID "Unexpected HTTP header value ($name: $value)";;
X-XSS-Protection)
[[ "$value" =~ "0" ]] || fail $PID "Unexpected HTTP header value ($name: $value)";;
esac
done < <(echo "$1")
}
echo -n "Testing / ... "
results=$(LD_PRELOAD=libsocket_wrapper.so curl -I -X GET -s https://$ADDRESS:$PORT/ --insecure)
CheckHeaders "$results"
echo -n "Testing /auth ... "
results=$(LD_PRELOAD=libsocket_wrapper.so curl -I -X GET -s https://$ADDRESS:$PORT/auth --insecure)
CheckHeaders "$results"
echo -n "Testing /VPN ... "
results=$(LD_PRELOAD=libsocket_wrapper.so curl -I -X GET -s https://$ADDRESS:$PORT/VPN --insecure)
CheckHeaders "$results"
echo "ok"
echo -n "Testing /cert.pem ... "
results=$(LD_PRELOAD=libsocket_wrapper.so curl -I -X GET -s https://$ADDRESS:$PORT/cert.pem --insecure)
CheckHeaders "$results"
echo "ok"
echo -n "Testing /cert.cer ... "
results=$(LD_PRELOAD=libsocket_wrapper.so curl -I -X GET -s https://$ADDRESS:$PORT/cert.cer --insecure)
CheckHeaders "$results"
echo "ok"
echo -n "Testing /ca.pem ... "
results=$(LD_PRELOAD=libsocket_wrapper.so curl -I -X GET -s https://$ADDRESS:$PORT/ca.pem --insecure)
CheckHeaders "$results"
echo "ok"
echo -n "Testing /ca.cer ... "
results=$(LD_PRELOAD=libsocket_wrapper.so curl -I -X GET -s https://$ADDRESS:$PORT/ca.cer --insecure)
CheckHeaders "$results"
echo "ok"
cleanup
exit 0