Compare commits
66 Commits
5bd7355e8b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81e6fb8aa4 | ||
|
|
ab3cbb9081 | ||
|
|
a6860e338d | ||
|
|
30a9483402 | ||
|
|
bc450ebbb3 | ||
|
|
0992d4a6e0 | ||
|
|
c053a064b2 | ||
|
|
cfa62d8ce0 | ||
|
|
0f3e2044a0 | ||
|
|
e9616a8c7c | ||
|
|
361f34c19f | ||
|
|
1f6bb854c3 | ||
|
|
05cbbfbe18 | ||
|
|
ad84c1ba29 | ||
|
|
53c4898efe | ||
|
|
c7b5f0e436 | ||
|
|
51060422d1 | ||
| e3d7b83059 | |||
| 73c5b1c5d5 | |||
|
|
aa58c0cb1d | ||
|
|
183901ab31 | ||
|
|
3e0237c6f3 | ||
|
|
e90263b3c5 | ||
|
|
f69d1d3b38 | ||
|
|
00f537bc3a | ||
|
|
c528f4844b | ||
|
|
fdc85d9109 | ||
|
|
8136c49f50 | ||
|
|
ded74f1a45 | ||
|
|
a17feb0e1b | ||
|
|
89b17901a9 | ||
|
|
5059041ec7 | ||
|
|
9b38b6385b | ||
|
|
bd0f136ccc | ||
|
|
21c9633755 | ||
|
|
6cd77929f4 | ||
| 2b76e850a5 | |||
|
|
2f44f7327d | ||
|
|
8ee1c901fe | ||
|
|
b4ff1c0018 | ||
|
|
7a5767ef64 | ||
|
|
ddcaf33130 | ||
|
|
a20876fb1e | ||
|
|
e38f655080 | ||
|
|
66534a1648 | ||
|
|
b03a6987f4 | ||
|
|
e0fa8291fe | ||
|
|
3225a90f1e | ||
|
|
553f6ece60 | ||
|
|
0c1bade0f2 | ||
|
|
f8597d72f9 | ||
|
|
c277f65fb5 | ||
|
|
9656c2bee4 | ||
|
|
96c9666a89 | ||
|
|
1de30d80d0 | ||
|
|
288b10550c | ||
|
|
0b337a2117 | ||
|
|
37bb4821e3 | ||
|
|
79d62754a3 | ||
|
|
7cae69b945 | ||
|
|
c175b85239 | ||
|
|
c31c4602f2 | ||
|
|
10e2db0f38 | ||
|
|
53e24aa2ea | ||
|
|
a0fbbe210d | ||
|
|
ddb5ad81ac |
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
*.log
|
||||||
|
*.aux
|
||||||
|
*.synctex.gz
|
||||||
18
CLIENT.sh
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#/bin/bash
|
||||||
|
# CONFIGURACAO DO CLIENTE
|
||||||
|
# (KALI LINUX)
|
||||||
|
|
||||||
|
function instalar() {
|
||||||
|
apt list installed "$1" &>/dev/null && echo "$1 já instalado" || sudo apt install -y "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
IP="20.60.0.2"
|
||||||
|
|
||||||
|
sudo ifconfig eth1 $IP netmask 255.255.255.0
|
||||||
|
sudo route add default gw 20.60.0.1
|
||||||
|
|
||||||
|
sudo apt update
|
||||||
|
instalar zaproxy
|
||||||
|
|
||||||
|
|
||||||
|
# exploits
|
||||||
@@ -1,6 +1 @@
|
|||||||
# Coisas para leres que sao fixes wowowowowowow !!!!! (Assignment 2)
|
kys
|
||||||
- Os slides (duh)
|
|
||||||
- Okay o mais importante é os slides.
|
|
||||||
|
|
||||||
- [X.509 (ssl.com)](https://www.ssl.com/faqs/what-is-an-x-509-certificate/)
|
|
||||||
- [X.509 (youtube)](https://www.youtube.com/watch?v=kAaIYRJoJkc)
|
|
||||||
|
|||||||
66
SERVER.sh
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# SERVIDOR INTERNO
|
||||||
|
# (CentOS 9)
|
||||||
|
alias "s"="sudo systemctl"
|
||||||
|
|
||||||
|
function instalar() {
|
||||||
|
yum list installed "$1" &>/dev/null && echo "$1 já instalado" || sudo yum install -y "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
IP_EXTERNAL="20.60.0.1"
|
||||||
|
IP_INTERNAL="10.60.0.1"
|
||||||
|
|
||||||
|
sudo ifconfig enp0s8 $IP_EXTERNAL netmask 255.255.255.0
|
||||||
|
sudo ifconfig enp0s9 $IP_INTERNAL netmask 255.255.255.0
|
||||||
|
|
||||||
|
# instalar packages
|
||||||
|
if ! command -v node &> /dev/null || [[ "$(node -v)" != v24.* ]]; then
|
||||||
|
echo "Configurando repositório do Node.js 24..."
|
||||||
|
curl -fsSL https://rpm.nodesource.com/setup_24.x | sudo bash -
|
||||||
|
sudo yum remove -y nodejs
|
||||||
|
fi
|
||||||
|
instalar nodejs
|
||||||
|
|
||||||
|
# instalar mod security e apache
|
||||||
|
instalar epel-release
|
||||||
|
instalar httpd
|
||||||
|
instalar mod_security
|
||||||
|
|
||||||
|
instalar iptables-services
|
||||||
|
s stop firewalld
|
||||||
|
s disable firewalld
|
||||||
|
s mask firewalld
|
||||||
|
s enable iptables
|
||||||
|
sudo iptables -F
|
||||||
|
|
||||||
|
# nat
|
||||||
|
sudo sysctl -w net.ipv4.ip_forward=1
|
||||||
|
sudo iptables -t nat -F
|
||||||
|
sudo iptables -A FORWARD -i enp0s9 -o enp0s8 -j ACCEPT
|
||||||
|
sudo iptables -A FORWARD -i enp0s8 -o enp0s9 -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
|
sudo iptables -t nat -A POSTROUTING -o enp0s8 -j MASQUERADE
|
||||||
|
sudo iptables-save > /etc/sysconfig/iptables
|
||||||
|
|
||||||
|
sudo cp conf/httpd.conf /etc/httpd/conf/httpd.conf
|
||||||
|
sudo cp conf/modsecurity.conf /etc/httpd/conf/modsecurity.conf
|
||||||
|
sudo mkdir -p /var/log/modsecurity/
|
||||||
|
sudo rm -f /etc/httpd/conf.d/mod_security.conf
|
||||||
|
sudo rm -f /etc/httpd/modsecurity.d/*.conf
|
||||||
|
|
||||||
|
# instalar juice-shop se nao existir
|
||||||
|
jspath="/var/juice-shop"
|
||||||
|
if [[ ! -f "$jspath/package.json" ]]; then
|
||||||
|
sudo mkdir -p "$jspath"
|
||||||
|
curl -L -o js.tar.gz "https://github.com/juice-shop/juice-shop/releases/download/v20.0.0/juice-shop-20.0.0_node24_linux_x64.tgz"
|
||||||
|
sudo tar -xzvf js.tar.gz -C "$jspath" --strip-components=1
|
||||||
|
rm js.tar.gz
|
||||||
|
sudo chown -R $USER:$USER "$jspath"
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo systemctl stop httpd
|
||||||
|
|
||||||
|
# correr juice shop via npm
|
||||||
|
cd "$jspath"
|
||||||
|
npm start &
|
||||||
|
|
||||||
|
httpd -X
|
||||||
8
TODO.md
@@ -1,8 +0,0 @@
|
|||||||
# Objectivos de acordo com o enunciado
|
|
||||||
|
|
||||||
## Goals
|
|
||||||
- [X] Configure a tunnel in the "road warrior"
|
|
||||||
- [X] Enable two factor authentication with OpenSSL and Apache services
|
|
||||||
- [X] Manage PKI: certification authorities, X.509 certificates, revocation and OCSP.
|
|
||||||
|
|
||||||
|
|
||||||
6
VM_CONFIG.sh → assignment2/VM_CONFIG.sh
Executable file → Normal file
@@ -28,9 +28,3 @@ mkdir -p /etc/openvpn/client
|
|||||||
systemctl stop chronyd
|
systemctl stop chronyd
|
||||||
ntpdate pool.ntp.org
|
ntpdate pool.ntp.org
|
||||||
systemctl start chronyd
|
systemctl start chronyd
|
||||||
|
|
||||||
# NOTE(vasco): o openvpn não consegui aceder ao home e ler os secrets
|
|
||||||
# do google authenticator, por isso fiz isto:
|
|
||||||
mkdir -p /etc/systemd/system/openvpn-server@.service.d
|
|
||||||
echo -e "[Service]\nProtectHome=false" > /etc/systemd/system/openvpn-server@.service.d/override.conf
|
|
||||||
systemctl daemon-reload
|
|
||||||
@@ -4,9 +4,13 @@
|
|||||||
source VM_CONFIG.sh
|
source VM_CONFIG.sh
|
||||||
|
|
||||||
sudo yum install -y epel-release
|
sudo yum install -y epel-release
|
||||||
sudo yum install -y openssl httpd mod_ssl mod_authnz_pam mod_authnz_pam google-authenticator
|
sudo yum install -y openssl httpd mod_ssl mod_authnz_pam google-authenticator
|
||||||
sudo yum install -y mod_session
|
sudo yum install -y mod_session
|
||||||
|
|
||||||
|
# utilizador
|
||||||
|
id -u john &>/dev/null || useradd john
|
||||||
|
echo "password" | passwd --stdin john
|
||||||
|
|
||||||
if_dentro="enp0s8"
|
if_dentro="enp0s8"
|
||||||
ip_dentro="10.60.0.1"
|
ip_dentro="10.60.0.1"
|
||||||
ifconfig $if_dentro $ip_dentro netmask 255.255.255.0
|
ifconfig $if_dentro $ip_dentro netmask 255.255.255.0
|
||||||
@@ -27,20 +31,15 @@ cp ca/dh2048.pem $CA_DIR
|
|||||||
killall openssl 2>/dev/null
|
killall openssl 2>/dev/null
|
||||||
openssl ocsp -index $CA_DIR/index.txt -port 8888 -rsigner $CA_DIR/ca.crt -rkey $CA_DIR/ca.key -CA $CA_DIR/ca.crt -text &
|
openssl ocsp -index $CA_DIR/index.txt -port 8888 -rsigner $CA_DIR/ca.crt -rkey $CA_DIR/ca.key -CA $CA_DIR/ca.crt -text &
|
||||||
|
|
||||||
|
|
||||||
# apache
|
# apache
|
||||||
mkdir -p /etc/httpd/ssl
|
mkdir -p /etc/httpd/ssl
|
||||||
cp ca/ca.crt /etc/httpd/ssl/
|
cp ca/ca.crt /etc/httpd/ssl/
|
||||||
cp ca/apache.crt /etc/httpd/ssl/
|
cp ca/apache.crt /etc/httpd/ssl/
|
||||||
cp ca/apache.key /etc/httpd/ssl/
|
cp ca/apache.key /etc/httpd/ssl/
|
||||||
cp conf/ssl.conf /etc/httpd/conf.d/ssl.conf
|
cp conf/ssl.conf /etc/httpd/conf.d/ssl.conf
|
||||||
|
cp conf/httpd.conf /etc/httpd/conf/httpd.conf
|
||||||
cp conf/httpd-totp /etc/pam.d/httpd-totp
|
cp conf/httpd-totp /etc/pam.d/httpd-totp
|
||||||
|
|
||||||
# NOTA(vasco) é preciso desativar home protection outra vez
|
|
||||||
mkdir -p /etc/systemd/system/httpd.service.d
|
|
||||||
echo -e "[Service]\nProtectHome=false" > /etc/systemd/system/httpd.service.d/override.conf
|
|
||||||
systemctl daemon-reload
|
|
||||||
|
|
||||||
# sim, é preciso fazer isto para carregar serviços
|
# sim, é preciso fazer isto para carregar serviços
|
||||||
echo "LoadModule session_module modules/mod_session.so" > /etc/httpd/conf.modules.d/01-session.conf
|
echo "LoadModule session_module modules/mod_session.so" > /etc/httpd/conf.modules.d/01-session.conf
|
||||||
echo "LoadModule session_cookie_module modules/mod_session_cookie.so" >> /etc/httpd/conf.modules.d/01-session.conf
|
echo "LoadModule session_cookie_module modules/mod_session_cookie.so" >> /etc/httpd/conf.modules.d/01-session.conf
|
||||||
@@ -50,13 +49,4 @@ echo "LoadModule auth_form_module modules/mod_auth_form.so" > /etc/httpd/conf.mo
|
|||||||
cp -r www/* /var/www/html/
|
cp -r www/* /var/www/html/
|
||||||
chown -R apache:apache /var/www/html/
|
chown -R apache:apache /var/www/html/
|
||||||
|
|
||||||
systemctl enable --now httpd
|
httpd -X
|
||||||
|
|
||||||
# acho ?????
|
|
||||||
sudo chgrp apache /etc/shadow
|
|
||||||
sudo chmod o+x /home/john
|
|
||||||
sudo chown apache /home/john/.google_authenticator
|
|
||||||
sudo chmod 400 /home/john/.google_authenticator
|
|
||||||
sudo chmod o+x /home/user
|
|
||||||
sudo chown apache /home/user/.google_authenticator
|
|
||||||
sudo chmod 400 /home/user/.google_authenticator
|
|
||||||
@@ -16,4 +16,5 @@ cp ca/ca.crt $vpn_dir
|
|||||||
cp ca/user.key $vpn_dir
|
cp ca/user.key $vpn_dir
|
||||||
cp ca/user.crt $vpn_dir
|
cp ca/user.crt $vpn_dir
|
||||||
cp conf/client.conf $vpn_dir
|
cp conf/client.conf $vpn_dir
|
||||||
|
|
||||||
openvpn --config "${vpn_dir}/client.conf"
|
openvpn --config "${vpn_dir}/client.conf"
|
||||||
@@ -8,7 +8,6 @@
|
|||||||
source VM_CONFIG.sh
|
source VM_CONFIG.sh
|
||||||
yum install -y google-authenticator qrencode ntpsec
|
yum install -y google-authenticator qrencode ntpsec
|
||||||
|
|
||||||
|
|
||||||
# --- forwarding --- #
|
# --- forwarding --- #
|
||||||
if_fora="enp0s8"
|
if_fora="enp0s8"
|
||||||
ip_fora="193.136.212.1"
|
ip_fora="193.136.212.1"
|
||||||
@@ -23,13 +22,13 @@ ifconfig $if_dentro $ip_dentro netmask 255.255.255.0
|
|||||||
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
|
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
|
||||||
sysctl -p /etc/sysctl.conf
|
sysctl -p /etc/sysctl.conf
|
||||||
|
|
||||||
iptables -I INPUT 1 -p udp --dport 1194 -j ACCEPT # :O
|
iptables -I INPUT 1 -p udp --dport 1194 -j ACCEPT
|
||||||
iptables -I FORWARD 1 -i $mega_tunel -o $if_dentro -j ACCEPT # :P
|
iptables -I FORWARD 1 -i $mega_tunel -o $if_dentro -j ACCEPT
|
||||||
iptables -I FORWARD 1 -i $if_dentro -o $mega_tunel -j ACCEPT # ;)
|
iptables -I FORWARD 1 -i $if_dentro -o $mega_tunel -j ACCEPT
|
||||||
iptables -I FORWARD 1 -i $mega_tunel -o $if_fora -j ACCEPT # faltava isto ?
|
iptables -I FORWARD 1 -i $mega_tunel -o $if_fora -j ACCEPT
|
||||||
iptables -I FORWARD 1 -i $if_fora -m state --state ESTABLISHED,RELATED -j ACCEPT # faltava isto ?
|
iptables -I FORWARD 1 -i $if_fora -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
iptables -t nat -A POSTROUTING -s $ip_mega_tunel -o $if_fora -j MASQUERADE # :D
|
iptables -t nat -A POSTROUTING -s $ip_mega_tunel -o $if_fora -j MASQUERADE
|
||||||
iptables-save > /etc/sysconfig/iptables # :3
|
iptables-save > /etc/sysconfig/iptables
|
||||||
|
|
||||||
# --- vpn server --- #
|
# --- vpn server --- #
|
||||||
vpn_dir="/etc/openvpn/server"
|
vpn_dir="/etc/openvpn/server"
|
||||||
@@ -41,4 +40,9 @@ cp ca/dh2048.pem $vpn_dir
|
|||||||
cp conf/vpn.conf $vpn_dir
|
cp conf/vpn.conf $vpn_dir
|
||||||
cp conf/ocsp-verify.sh $vpn_dir
|
cp conf/ocsp-verify.sh $vpn_dir
|
||||||
cp conf/totp /etc/pam.d/
|
cp conf/totp /etc/pam.d/
|
||||||
systemctl enable --now openvpn-server@vpn.service
|
|
||||||
|
# --- utilizador --- #
|
||||||
|
id -u john &>/dev/null || useradd john
|
||||||
|
echo "password" | passwd --stdin john
|
||||||
|
|
||||||
|
openvpn --config /etc/openvpn/server/vpn.conf
|
||||||
0
ca/create_all_keys.sh → assignment2/ca/create_all_keys.sh
Executable file → Normal file
0
ca/revoke_user.sh → assignment2/ca/revoke_user.sh
Executable file → Normal file
20
assignment2/conf/httpd.conf
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
ServerRoot "/etc/httpd"
|
||||||
|
|
||||||
|
Include conf.modules.d/*.conf
|
||||||
|
LoadModule authnz_pam_module modules/mod_authnz_pam.so
|
||||||
|
LoadModule mpm_event_module modules/mod_mpm_event.so
|
||||||
|
|
||||||
|
User apache
|
||||||
|
Group apache
|
||||||
|
|
||||||
|
Listen 80
|
||||||
|
Listen 443
|
||||||
|
|
||||||
|
Include conf.d/*.conf
|
||||||
|
|
||||||
|
DocumentRoot "/var/www/html"
|
||||||
|
<Directory "/var/www/html">
|
||||||
|
Options Indexes FollowSymLinks
|
||||||
|
AllowOverride None
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
15
assignment2/conf/ocsp-verify.sh
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
depth=$1
|
||||||
|
if [ "$depth" -eq 0 ]; then
|
||||||
|
if [ -n "$tls_serial_0" ]; then
|
||||||
|
# é preciso converter o serial para hexadecimal porque o openssl espera em hex
|
||||||
|
hex_serial=$(printf '%x' "$tls_serial_0")
|
||||||
|
status=$(openssl ocsp -issuer /etc/openvpn/server/ca.crt -serial "0x$hex_serial" -url http://10.60.0.1:8888 -CAfile /etc/openvpn/server/ca.crt 2>/dev/null)
|
||||||
|
if echo "$status" | grep -q "good"; then
|
||||||
|
exit 0 # sucesso
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 1 # revogado ou não encontrado
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
Listen 443 https
|
|
||||||
<VirtualHost *:443>
|
<VirtualHost *:443>
|
||||||
ServerName 10.60.0.1
|
ServerName 10.60.0.1
|
||||||
DocumentRoot /var/www/html
|
DocumentRoot /var/www/html
|
||||||
@@ -8,21 +7,21 @@ Listen 443 https
|
|||||||
SSLCertificateKeyFile /etc/httpd/ssl/apache.key
|
SSLCertificateKeyFile /etc/httpd/ssl/apache.key
|
||||||
SSLCACertificateFile /etc/httpd/ssl/ca.crt
|
SSLCACertificateFile /etc/httpd/ssl/ca.crt
|
||||||
|
|
||||||
# Mutual Authentication (Client Cert)
|
# mutual authentication
|
||||||
SSLVerifyClient require
|
SSLVerifyClient require
|
||||||
SSLVerifyDepth 1
|
SSLVerifyDepth 1
|
||||||
|
|
||||||
# OCSP Validation against CA
|
# ocsp validation
|
||||||
SSLOCSPEnable on
|
SSLOCSPEnable on
|
||||||
SSLOCSPDefaultResponder "http://10.60.0.1:8888"
|
SSLOCSPDefaultResponder "http://10.60.0.1:8888"
|
||||||
SSLOCSPOverrideResponder on
|
SSLOCSPOverrideResponder on
|
||||||
SSLOCSPUseRequestNonce off
|
SSLOCSPUseRequestNonce off
|
||||||
|
|
||||||
# Session management for Form Auth
|
# session management
|
||||||
Session On
|
Session On
|
||||||
SessionCookieName session path=/;HttpOnly;Secure
|
SessionCookieName session path=/;HttpOnly;Secure
|
||||||
|
|
||||||
# Protected Area
|
# proteger
|
||||||
<Location "/">
|
<Location "/">
|
||||||
AuthType Form
|
AuthType Form
|
||||||
AuthName "Coimbra VPN"
|
AuthName "Coimbra VPN"
|
||||||
@@ -32,26 +31,34 @@ Listen 443 https
|
|||||||
Require valid-user
|
Require valid-user
|
||||||
</Location>
|
</Location>
|
||||||
|
|
||||||
# Public Login Page
|
# public login page
|
||||||
<Location "/login.html">
|
<Location "/login.html">
|
||||||
AuthType None
|
AuthType None
|
||||||
Require all granted
|
Require all granted
|
||||||
</Location>
|
</Location>
|
||||||
|
|
||||||
# Login Handler
|
# login handler
|
||||||
<Location "/dologin">
|
<Location "/dologin">
|
||||||
SetHandler form-login-handler
|
SetHandler form-login-handler
|
||||||
AuthType Form
|
AuthType Form
|
||||||
AuthName "Coimbra VPN"
|
AuthName "Coimbra VPN"
|
||||||
AuthFormProvider PAM
|
AuthFormProvider PAM
|
||||||
AuthPAMService httpd-totp
|
AuthPAMService httpd-totp
|
||||||
|
Require all granted
|
||||||
AuthFormLoginSuccessLocation "/index.html"
|
AuthFormLoginSuccessLocation "/index.html"
|
||||||
AuthFormLoginRequiredLocation "/login.html?error=1"
|
AuthFormLoginRequiredLocation "/login.html?error=1"
|
||||||
</Location>
|
</Location>
|
||||||
|
|
||||||
# Logout Handler
|
# logout handler
|
||||||
<Location "/logout">
|
<Location "/logout">
|
||||||
SetHandler form-logout-handler
|
SetHandler form-logout-handler
|
||||||
AuthFormLogoutLocation "/login.html?loggedout=1"
|
AuthFormLogoutLocation "/login.html?loggedout=1"
|
||||||
</Location>
|
</Location>
|
||||||
|
|
||||||
|
</VirtualHost>
|
||||||
|
|
||||||
|
# redirect para https
|
||||||
|
<VirtualHost *:80>
|
||||||
|
ServerName 10.60.0.1
|
||||||
|
Redirect permanent / https://10.60.0.1/
|
||||||
</VirtualHost>
|
</VirtualHost>
|
||||||
@@ -3,16 +3,16 @@ port 1194
|
|||||||
proto udp
|
proto udp
|
||||||
dev tun
|
dev tun
|
||||||
|
|
||||||
|
verb 4
|
||||||
|
|
||||||
# Bro is too honorable
|
# Bro is too honorable
|
||||||
ca /etc/openvpn/server/ca.crt
|
ca /etc/openvpn/server/ca.crt
|
||||||
cert /etc/openvpn/server/vpn.crt
|
cert /etc/openvpn/server/vpn.crt
|
||||||
key /etc/openvpn/server/vpn.key
|
key /etc/openvpn/server/vpn.key
|
||||||
dh /etc/openvpn/server/dh2048.pem
|
dh /etc/openvpn/server/dh2048.pem
|
||||||
|
|
||||||
server 10.8.0.0 255.255.255.0
|
|
||||||
verb 4
|
|
||||||
|
|
||||||
topology subnet
|
topology subnet
|
||||||
|
server 10.8.0.0 255.255.255.0
|
||||||
push "route 10.60.0.0 255.255.255.0"
|
push "route 10.60.0.0 255.255.255.0"
|
||||||
|
|
||||||
# OCSP and Revocation
|
# OCSP and Revocation
|
||||||
BIN
assignment2/entrega.zip
Normal file
4702
assignment2/entrega.zip.asc
Normal file
BIN
assignment2/enunciado.pdf
Normal file
143
assignment2/enunciado.txt
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
FSI 2025/2026
|
||||||
|
Practical Assignment #2
|
||||||
|
|
||||||
|
1. Goals
|
||||||
|
•
|
||||||
|
|
||||||
|
Configure a VPN tunnel in the “road warrior” scenario.
|
||||||
|
|
||||||
|
•
|
||||||
|
|
||||||
|
Enable two-factor user authentication with OpenVPN and Apache services.
|
||||||
|
|
||||||
|
•
|
||||||
|
|
||||||
|
Manage PKI: certification authorities, X.509 certificates, revocation and OCSP.
|
||||||
|
|
||||||
|
2. General description
|
||||||
|
Figure 1 illustrates the scenario considered for our practical assignment. As illustrated, secure communications are
|
||||||
|
supported by a VPN tunnel established between a remote client (road warrior) and the VPN gateway, with the purpose of
|
||||||
|
enabling accesses to services in the Internal Network, particularly a web server running Apache. To enable the VPN tunnel,
|
||||||
|
we will use OpenVPN (https://openvpn.net).
|
||||||
|
|
||||||
|
Figure 1 – Scenario for the Practical Assignment #1
|
||||||
|
|
||||||
|
Regarding authentication, the two communication entities participating in the VPN tunnel (road warrior and the VPN
|
||||||
|
gateway) should possess valid X.509 certificates, which are created with a private Certification Authority (CA). Users
|
||||||
|
establishing remote connections to the VPN gateway (road warriors), as well as users connecting to the Apache server, will
|
||||||
|
also use two-factor authentication, as described below. Apache must also implement client authentication via X.509
|
||||||
|
certificates. Figure 2 provides an illustration of the interactions between all the entities involved in this setup.
|
||||||
|
|
||||||
|
Figure 2 – X.509 mutual authentication and OCSP
|
||||||
|
|
||||||
|
As we can observe in Figure 2, the VPN gateway and the Apache web server must verify the status of validity of certificates
|
||||||
|
using OCSP (Online Certificate Status Protocol) and revocation information from the CA. OCSP verification in not
|
||||||
|
required for the road warrior. Next, we describe the configuration requirements for the various components of the
|
||||||
|
assignment.
|
||||||
|
|
||||||
|
3. Configuration requirements
|
||||||
|
VPN tunnel for remote access (road warriors)
|
||||||
|
As illustrated in Figure 1, remote clients (road warriors) are able to connect to the Coimbra VPN gateway, and using the
|
||||||
|
tunnel remotely access hosts in the Internal network. The following configuration requirements should be considered:
|
||||||
|
•
|
||||||
|
|
||||||
|
In order to establish a VPN tunnel with the Coimbra gateway, the road warrior must be in the possession of a valid
|
||||||
|
X.509 certificate, issued by the private CA of the scenario.
|
||||||
|
|
||||||
|
•
|
||||||
|
|
||||||
|
The road warrior and the Coimbra VPN gateway must perform mutual authentication using X.509 digital certificates.
|
||||||
|
|
||||||
|
•
|
||||||
|
|
||||||
|
The Coimbra VPN gateway should verify the validity of the X.509 certificate presented by the road warrior using OCSP
|
||||||
|
and, in case the certificate is revoked, the gateway should refuse the connection.
|
||||||
|
|
||||||
|
•
|
||||||
|
|
||||||
|
In order to authorize the remote user, the Coimbra gateway should also enforce two other authentication steps: the user
|
||||||
|
must present a valid username and password, plus a one-time password (OTP, or an authentication token).
|
||||||
|
|
||||||
|
Web server
|
||||||
|
2
|
||||||
|
|
||||||
|
The road warrior user should be able to contact the Apache web server with HTTPS through the VPN tunnel. The
|
||||||
|
following configuration requirements should be considered:
|
||||||
|
•
|
||||||
|
|
||||||
|
Apache should enforce two-factor authentication in order to authorize accesses from clients: the client (browser) should
|
||||||
|
present a valid X.509 certificate (issued with the private CA of the scenario) and the user should also present a valid onetime password (or authentication token).
|
||||||
|
|
||||||
|
•
|
||||||
|
|
||||||
|
As in the VPN, the validity of the X.509 certificate presented by the client should be checked in the CA using OCSP.
|
||||||
|
|
||||||
|
Two-factor user authentication
|
||||||
|
As previously discussed, VPN establishment and HTTPS accesses to Apache make use of one-time passwords
|
||||||
|
(authentication tokens), which may be generated by an appropriate application. One-time passwords may be generated using
|
||||||
|
the TOTP (Time-based One-time Password Algorithm). This algorithm employs a secret key shared between the user
|
||||||
|
(client) and the remote service, plus a timestamp (obtained from the current system time), to obtain a one-time password.
|
||||||
|
In order to generate a one-time password, the user may use an application such as Google Authenticator, illustrated in
|
||||||
|
Figure 3. This application periodically generates a new one-time password that can be used to authenticate the user with the
|
||||||
|
remote service. This application is available for iOS and Android 1.
|
||||||
|
Certification authority
|
||||||
|
As already discussed, the goal is to use OpenSSL to configure a private Certification Authority, as well as to issue and revoke
|
||||||
|
X.509 digital certificates for the VPN gateways and remote users. The following configuration requirements should be
|
||||||
|
considered:
|
||||||
|
•
|
||||||
|
|
||||||
|
The Certification Authority is used to issue certificates for the VPN gateway, VPN client and Apache web server.
|
||||||
|
|
||||||
|
•
|
||||||
|
|
||||||
|
The Certification Authority allows the revocation of certificates previously issued.
|
||||||
|
|
||||||
|
•
|
||||||
|
|
||||||
|
The Certification Authority also supports a OCSP responder.
|
||||||
|
|
||||||
|
For Android: https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en and
|
||||||
|
for Apple iOS: https://itunes.apple.com/us/app/google-authenticator/id388497605?mt=8
|
||||||
|
1
|
||||||
|
|
||||||
|
3
|
||||||
|
|
||||||
|
Figure 3 – Google Authenticator app, to generate a one-time password to access services enabled with two-factor authentication
|
||||||
|
|
||||||
|
4. Delivery of the Practical Assignment
|
||||||
|
With the assignment, please deliver also a report, containing the following information:
|
||||||
|
•
|
||||||
|
|
||||||
|
Descriptions of the configurations for the implementation of the previous requirements.
|
||||||
|
|
||||||
|
•
|
||||||
|
|
||||||
|
A description of how the private Certification Authority was created using OpenSSL.
|
||||||
|
|
||||||
|
•
|
||||||
|
|
||||||
|
A description of how X.509 certificates were issued and revoked using the private Certification Authority.
|
||||||
|
|
||||||
|
•
|
||||||
|
|
||||||
|
A description of the tests performed to validate the functionalities implemented.
|
||||||
|
|
||||||
|
•
|
||||||
|
|
||||||
|
Remaining information considered relevant.
|
||||||
|
|
||||||
|
For the delivery of the assignment, put your report, as well as the relevant configuration files, in a single archive. This archive
|
||||||
|
should be signed using your PGP key and encrypted using the PGP key of your PL teacher.
|
||||||
|
Note: Assignments without PGP will be accepted, although with a discount of 5% in the final grade.
|
||||||
|
Delivery deadline:
|
||||||
|
•
|
||||||
|
|
||||||
|
The deadline for the delivery of the assignment (configuration files and report) is May 3rd 2026.
|
||||||
|
|
||||||
|
•
|
||||||
|
|
||||||
|
Submission via Inforestudante.
|
||||||
|
|
||||||
|
4
|
||||||
|
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
27
assignment2/relatorio/relatorio.aux
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
\relax
|
||||||
|
\providecommand \babel@aux [2]{\global \let \babel@toc \@gobbletwo }
|
||||||
|
\@nameuse{bbl@beforestart}
|
||||||
|
\catcode `"\active
|
||||||
|
\providecommand\hyper@newdestlabel[2]{}
|
||||||
|
\providecommand\HyField@AuxAddToFields[1]{}
|
||||||
|
\providecommand\HyField@AuxAddToCoFields[2]{}
|
||||||
|
\babel@aux{portuguese}{}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {1}Introdução}{3}{section.1}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {2}Preparação Inicial}{3}{section.2}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Criação de Certificados}{3}{subsection.2.1}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Configuração geral}{4}{subsection.2.2}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {3}VPN Gateway}{5}{section.3}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.1}Configuração da Máquina}{5}{subsection.3.1}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2}Configuração do Serviço OpenVPN}{6}{subsection.3.2}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3}Erros}{7}{subsection.3.3}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.4}Configurar o utilizador com TOTP}{7}{subsection.3.4}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {4}VPN Client (Road Warrior)}{8}{section.4}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {4.1}Configuração da Máquina}{8}{subsection.4.1}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {4.2}Configuração do Cliente OpenVPN}{8}{subsection.4.2}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {4.3}Testes}{9}{subsection.4.3}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {5}Servidor Apache e OCSP}{9}{section.5}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {5.1}Configuração da Máquina}{10}{subsection.5.1}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsubsection}{\numberline {5.1.1}Testes}{12}{subsubsection.5.1.1}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {6}Teste Integrado}{13}{section.6}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {7}Conclusão}{13}{section.7}\protected@file@percent }
|
||||||
|
\gdef \@abspage@last{13}
|
||||||
1
assignment2/relatorio/relatorio.listing
Normal file
@@ -0,0 +1 @@
|
|||||||
|
openssl ca -revoke user.crt -config cheese.cfg -keyfile ca.key -cert ca.crt
|
||||||
1288
assignment2/relatorio/relatorio.log
Normal file
18
assignment2/relatorio/relatorio.out
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
\BOOKMARK [1][-]{section.1}{\376\377\000I\000n\000t\000r\000o\000d\000u\000\347\000\343\000o}{}% 1
|
||||||
|
\BOOKMARK [1][-]{section.2}{\376\377\000P\000r\000e\000p\000a\000r\000a\000\347\000\343\000o\000\040\000I\000n\000i\000c\000i\000a\000l}{}% 2
|
||||||
|
\BOOKMARK [2][-]{subsection.2.1}{\376\377\000C\000r\000i\000a\000\347\000\343\000o\000\040\000d\000e\000\040\000C\000e\000r\000t\000i\000f\000i\000c\000a\000d\000o\000s}{section.2}% 3
|
||||||
|
\BOOKMARK [2][-]{subsection.2.2}{\376\377\000C\000o\000n\000f\000i\000g\000u\000r\000a\000\347\000\343\000o\000\040\000g\000e\000r\000a\000l}{section.2}% 4
|
||||||
|
\BOOKMARK [1][-]{section.3}{\376\377\000V\000P\000N\000\040\000G\000a\000t\000e\000w\000a\000y}{}% 5
|
||||||
|
\BOOKMARK [2][-]{subsection.3.1}{\376\377\000C\000o\000n\000f\000i\000g\000u\000r\000a\000\347\000\343\000o\000\040\000d\000a\000\040\000M\000\341\000q\000u\000i\000n\000a}{section.3}% 6
|
||||||
|
\BOOKMARK [2][-]{subsection.3.2}{\376\377\000C\000o\000n\000f\000i\000g\000u\000r\000a\000\347\000\343\000o\000\040\000d\000o\000\040\000S\000e\000r\000v\000i\000\347\000o\000\040\000O\000p\000e\000n\000V\000P\000N}{section.3}% 7
|
||||||
|
\BOOKMARK [2][-]{subsection.3.3}{\376\377\000E\000r\000r\000o\000s}{section.3}% 8
|
||||||
|
\BOOKMARK [2][-]{subsection.3.4}{\376\377\000C\000o\000n\000f\000i\000g\000u\000r\000a\000r\000\040\000o\000\040\000u\000t\000i\000l\000i\000z\000a\000d\000o\000r\000\040\000c\000o\000m\000\040\000T\000O\000T\000P}{section.3}% 9
|
||||||
|
\BOOKMARK [1][-]{section.4}{\376\377\000V\000P\000N\000\040\000C\000l\000i\000e\000n\000t\000\040\000\050\000R\000o\000a\000d\000\040\000W\000a\000r\000r\000i\000o\000r\000\051}{}% 10
|
||||||
|
\BOOKMARK [2][-]{subsection.4.1}{\376\377\000C\000o\000n\000f\000i\000g\000u\000r\000a\000\347\000\343\000o\000\040\000d\000a\000\040\000M\000\341\000q\000u\000i\000n\000a}{section.4}% 11
|
||||||
|
\BOOKMARK [2][-]{subsection.4.2}{\376\377\000C\000o\000n\000f\000i\000g\000u\000r\000a\000\347\000\343\000o\000\040\000d\000o\000\040\000C\000l\000i\000e\000n\000t\000e\000\040\000O\000p\000e\000n\000V\000P\000N}{section.4}% 12
|
||||||
|
\BOOKMARK [2][-]{subsection.4.3}{\376\377\000T\000e\000s\000t\000e\000s}{section.4}% 13
|
||||||
|
\BOOKMARK [1][-]{section.5}{\376\377\000S\000e\000r\000v\000i\000d\000o\000r\000\040\000A\000p\000a\000c\000h\000e\000\040\000e\000\040\000O\000C\000S\000P}{}% 14
|
||||||
|
\BOOKMARK [2][-]{subsection.5.1}{\376\377\000C\000o\000n\000f\000i\000g\000u\000r\000a\000\347\000\343\000o\000\040\000d\000a\000\040\000M\000\341\000q\000u\000i\000n\000a}{section.5}% 15
|
||||||
|
\BOOKMARK [3][-]{subsubsection.5.1.1}{\376\377\000T\000e\000s\000t\000e\000s}{subsection.5.1}% 16
|
||||||
|
\BOOKMARK [1][-]{section.6}{\376\377\000T\000e\000s\000t\000e\000\040\000I\000n\000t\000e\000g\000r\000a\000d\000o}{}% 17
|
||||||
|
\BOOKMARK [1][-]{section.7}{\376\377\000C\000o\000n\000c\000l\000u\000s\000\343\000o}{}% 18
|
||||||
BIN
assignment2/relatorio/relatorio.pdf
Normal file
575
assignment2/relatorio/relatorio.tex
Normal file
@@ -0,0 +1,575 @@
|
|||||||
|
\documentclass[11pt,a4paper]{article}
|
||||||
|
\usepackage[portuguese]{babel}
|
||||||
|
\usepackage[lining]{ebgaramond}
|
||||||
|
\usepackage{style}
|
||||||
|
|
||||||
|
\setlength{\parindent}{0em}
|
||||||
|
\setlength{\parskip}{2ex}
|
||||||
|
|
||||||
|
\title{Practical Assignment \#2}
|
||||||
|
\author{
|
||||||
|
João Neto -- 2023234004\\[1em]
|
||||||
|
Vasco Alves -- 2022228207
|
||||||
|
}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\maketitle
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
\tableofcontents
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
|
||||||
|
\section{Introdução}
|
||||||
|
|
||||||
|
Este projeto tem como âmbito implementar, uma rede virtual privada (VPN) num cenário
|
||||||
|
de road-warrior, configurar \textit{two-factor authentication} (2FA) com os serviços
|
||||||
|
OpenVPN e Apache, e gerir certificados X.509 utilizando OCSP.
|
||||||
|
|
||||||
|
% NOTE(vasco): Eu acho que basta explicar o cenario e explicar como decidimos
|
||||||
|
% implementar <- yeah agree, also esta introdução acho que é boa fala sobre o objetivo
|
||||||
|
% e o cenario, e porque é que o nosso cenario é como é. Não sei se a parte das razões de
|
||||||
|
%segurança devia estar nesta parte ou na conclusão como perpetiva futura e reflexão, mas aqui
|
||||||
|
%também não está mal.
|
||||||
|
|
||||||
|
% Para tal, foi implementado um servidor e um cliente OpenVPN, certificados por uma
|
||||||
|
% autoridade central (CA) que em si é \textit{self-signed}. Para além disto, foi implementado
|
||||||
|
% um sistema de autenticação de dois factores através do plugin
|
||||||
|
% \textit{google-authenticator} para o OpenVPN e para o servidor de Apache.
|
||||||
|
|
||||||
|
Decidimos utilizar apenas três máquinas virtuais: o cliente (ou \textit{road warrior}),
|
||||||
|
a \textit{gateway} que utiliza OpenVPN e um servidor interno com OpenSSL e Apache.
|
||||||
|
Isto simplifica a elaboração do projecto, mas por razões de segurança poderia querer
|
||||||
|
separar a máquina de OpenSSL de outras máquinas destinadas a serviços da rede interna,
|
||||||
|
pois esta contém o \textit{certificate authority} (CA).
|
||||||
|
|
||||||
|
% Ambos o OpenVPN eo servidor Apache utilizam 2FA,
|
||||||
|
% recebendo o utilizador, e uma password que é uma concatenação da palavra-passe do utilizador
|
||||||
|
% e de uma password temporária (TOTP) de 6 dígitos. O servidor de Apache implementa a mesma autenticação.
|
||||||
|
|
||||||
|
\begin{tabular}{l l l}
|
||||||
|
{\bf Nome} & {\bf Script} & {\bf Rede} \\\toprule
|
||||||
|
Road Warrior & VM\_ROAD\_WARRIOR.sh & Rede Externa 193.168.0.0/24 \\
|
||||||
|
VPN Gateway & VM\_OPENVPN\_GATEWAY.sh & Router \\
|
||||||
|
OpenSSL / Apache & VM\_OPENSSL\_APACHE.sh & Rede Interna 10.60.0.0/24 \\
|
||||||
|
\end{tabular}
|
||||||
|
|
||||||
|
\section{Preparação Inicial}
|
||||||
|
|
||||||
|
\subsection{Criação de Certificados}
|
||||||
|
|
||||||
|
Os certificados utilizados foram auto-certificados por uma autoridade central que ``pertence''
|
||||||
|
à máquina de OpenSSL. Esta mesma faz a gestão da lista de revogação.
|
||||||
|
|
||||||
|
Todas as chaves foram criadas no mesmo computador, com as variáveis que estão
|
||||||
|
neste código. Aspetos importantes para mais tarde serão os parâmetros de Comon Name (CN)
|
||||||
|
pois servem para a validação do certificado ambos pelo OpenSSL e pelo browser.
|
||||||
|
|
||||||
|
Nós optamos por assumir que num cenário real, teríamos acesso físico às máquinas, por isso em vez
|
||||||
|
de utilizar, por exemplo SCP ou FTP, escolhemos partilhar os ficheiros a partir da máquina host. No entanto, outra abordagem também estaria correta.
|
||||||
|
|
||||||
|
\begin{codeblock}[bash]{create\_all\_keys.sh}
|
||||||
|
cert_ca="/C=PT/ST=Coimbra/L=Coimbra/O=UC/CN=CoimbraVPN"
|
||||||
|
cert_vpn="/C=PT/ST=Coimbra/L=Coimbra/O=UC/CN=gateway"
|
||||||
|
cert_user="/C=PT/ST=Coimbra/L=Coimbra/O=UC/CN=warrior"
|
||||||
|
cert_apache="/C=PT/ST=Coimbra/L=Coimbra/O=UC/CN=apache.coimbra"
|
||||||
|
|
||||||
|
openssl genrsa -out "ca.key" 2048
|
||||||
|
openssl req -x509 -nodes -days 365 -key "ca.key" -out "ca.crt" -subj "$cert_ca"
|
||||||
|
openssl genrsa -out "vpn.key" 2048
|
||||||
|
openssl req -new -key "vpn.key" -out "vpn.csr" -subj "$cert_vpn"
|
||||||
|
openssl ca -batch -in "vpn.csr" -cert "ca.crt" -keyfile "ca.key" -out "vpn.crt" -config cheese.cfg
|
||||||
|
openssl dhparam -out "dh2048.pem" 2048
|
||||||
|
openvpn --genkey secret "ta.key"
|
||||||
|
openssl genrsa -out user.key
|
||||||
|
openssl req -new -key user.key -out user.csr -subj "$cert_user"
|
||||||
|
openssl ca -batch -in "user.csr" -cert "ca.crt" -keyfile "ca.key" -out "user.crt" -config cheese.cfg
|
||||||
|
openssl genrsa -out apache.key
|
||||||
|
openssl req -new -key apache.key -out apache.csr -subj "$cert_apache" -addext "subjectAltName = IP:10.60.0.1,DNS:apache"
|
||||||
|
openssl ca -batch -in "apache.csr" -cert "ca.crt" -keyfile "ca.key" -out "apache.crt" -config cheese.cfg
|
||||||
|
openssl --genkey secret ta.key
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
Como o CA foi criado ``\textit{in place}'', e não na sua pasta prédefinida, foi necessário utilizar
|
||||||
|
um configuração própria para definir os ficheiros \textit{index.txt} e \textit{serial}.
|
||||||
|
|
||||||
|
\begin{codeblock}[bash]{cheese.cfg}
|
||||||
|
[ ca ]
|
||||||
|
default_ca = CA_default
|
||||||
|
[ CA_default ]
|
||||||
|
default_days = 365
|
||||||
|
database = index.txt
|
||||||
|
serial = serial
|
||||||
|
copy_extensions = copy
|
||||||
|
new_certs_dir = .
|
||||||
|
default_md = sha256
|
||||||
|
policy = policy_any
|
||||||
|
[ policy_any ]
|
||||||
|
commonName = supplied
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\subsection{Configuração geral}
|
||||||
|
Para evitar repetição e redundancia; e para garantir consistencia na elaboração do projeto criamos varios shell scripts, um destinado a cada maquina virtual.
|
||||||
|
|
||||||
|
Para configurar as VMs era preciso introduzir os mesmos comandos várias vezes, o que levava muitas vezes a erros de escrita,
|
||||||
|
ou a correr o mesmo comando várias vezes, por isso criamos vários ficheiros .sh para conseguir facilitar o processo.
|
||||||
|
A utilização de ficheiros .sh também vem com outros positivos pois facilita a testagem, e a recriação do cenário rapidamente.
|
||||||
|
|
||||||
|
No entanto para os serviços que configuramos, instalar, desativar e dar flush às iptables não foi suficiente, tivemos que criar
|
||||||
|
pastas e sincronizar os relógios de todas as VMs visto que elas estarem ligeiramente atrasadas nunca conseguíamos acertar na
|
||||||
|
password do google-authenticator visto que utiliza o tempo local para calcular a sua chave.
|
||||||
|
|
||||||
|
\begin{codeblock}[bash]{VM\_CONFIG.sh}
|
||||||
|
yum install -y epel-release
|
||||||
|
yum install -y openvpn iptables-services dhcp-client
|
||||||
|
systemctl stop firewalld
|
||||||
|
systemctl disable firewalld
|
||||||
|
systemctl mask firewalld
|
||||||
|
systemctl enable iptables
|
||||||
|
iptables -F
|
||||||
|
|
||||||
|
CA_DIR="/etc/pki/CA"
|
||||||
|
mkdir -p "${CA_DIR}/newcerts"
|
||||||
|
mkdir -p "${CA_DIR}/private"
|
||||||
|
touch "${CA_DIR}/index.txt"
|
||||||
|
cp ca/serial "${CA_DIR}/serial"
|
||||||
|
|
||||||
|
mkdir -p /etc/openvpn/server
|
||||||
|
mkdir -p /etc/openvpn/client
|
||||||
|
|
||||||
|
# NOTE(vasco): tive problemas com a sincronizacao de tempo
|
||||||
|
# se nao tiver sincronizado, o TOTP nao funciona
|
||||||
|
systemctl stop chronyd
|
||||||
|
ntpdate pool.ntp.org
|
||||||
|
systemctl start chronyd
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
|
||||||
|
\section{VPN Gateway}
|
||||||
|
|
||||||
|
\subsection{Configuração da Máquina}
|
||||||
|
|
||||||
|
Como já foi dito anteriormente, cada máquina vem com um \textit{script}
|
||||||
|
que instala toda a configuração necessária.
|
||||||
|
|
||||||
|
Para que a gateway funcione como router entre a rede externa e a rede interna,
|
||||||
|
foi necessário ativar o \textit{IP forwarding} no kernel e configurar as regras
|
||||||
|
de \textit{iptables} para permitir o tráfego da VPN e realizar o mascaramento
|
||||||
|
de IP (NAT).
|
||||||
|
|
||||||
|
% NOTA(vasco): Não temos regras de DROP a packets
|
||||||
|
% talvez deviamos mudar isso nao sei <- não diz nada no enunciado ¯\_(ツ)_/¯
|
||||||
|
% também o trabalho não é sobre ip tables por isso it does make sense não fazer drop
|
||||||
|
%e utilizar as regras apenas para encaminhar corretamente.
|
||||||
|
% Colocar isso na conclusão tho
|
||||||
|
|
||||||
|
\begin{codeblock}[bash]{VM\_VPN\_GATEWAY.sh}
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# --- configuracao --- #
|
||||||
|
source VM_CONFIG.sh
|
||||||
|
yum install -y google-authenticator qrencode ntpsec
|
||||||
|
|
||||||
|
# --- forwarding --- #
|
||||||
|
if_fora="enp0s8"
|
||||||
|
ip_fora="193.136.212.1"
|
||||||
|
if_dentro="enp0s9"
|
||||||
|
ip_dentro="10.60.0.3"
|
||||||
|
mega_tunel="tun0"
|
||||||
|
ip_mega_tunel="10.8.0.0/24"
|
||||||
|
|
||||||
|
ifconfig $if_fora $ip_fora netmask 255.255.255.0
|
||||||
|
ifconfig $if_dentro $ip_dentro netmask 255.255.255.0
|
||||||
|
|
||||||
|
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
|
||||||
|
sysctl -p /etc/sysctl.conf
|
||||||
|
|
||||||
|
iptables -I INPUT 1 -p udp --dport 1194 -j ACCEPT
|
||||||
|
iptables -I FORWARD 1 -i $mega_tunel -o $if_dentro -j ACCEPT
|
||||||
|
iptables -I FORWARD 1 -i $if_dentro -o $mega_tunel -j ACCEPT
|
||||||
|
iptables -I FORWARD 1 -i $mega_tunel -o $if_fora -j ACCEPT
|
||||||
|
iptables -I FORWARD 1 -i $if_fora -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||||
|
iptables -t nat -A POSTROUTING -s $ip_mega_tunel -o $if_fora -j MASQUERADE
|
||||||
|
iptables-save > /etc/sysconfig/iptables
|
||||||
|
|
||||||
|
# --- vpn server --- #
|
||||||
|
vpn_dir="/etc/openvpn/server"
|
||||||
|
cp ca/ta.key $vpn_dir
|
||||||
|
cp ca/ca.crt $vpn_dir
|
||||||
|
cp ca/vpn.key $vpn_dir
|
||||||
|
cp ca/vpn.crt $vpn_dir
|
||||||
|
cp ca/dh2048.pem $vpn_dir
|
||||||
|
cp conf/vpn.conf $vpn_dir
|
||||||
|
cp conf/ocsp-verify.sh $vpn_dir
|
||||||
|
cp conf/totp /etc/pam.d/
|
||||||
|
|
||||||
|
# --- utilizador --- #
|
||||||
|
id -u john &>/dev/null || useradd john
|
||||||
|
echo "password" | passwd --stdin john
|
||||||
|
|
||||||
|
openvpn --config /etc/openvpn/server/vpn.conf
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\subsection{Configuração do Serviço OpenVPN}
|
||||||
|
|
||||||
|
|
||||||
|
O servidor OpenVPN utiliza um certificado X.509 assinado pelo nosso \textit{Certificate Authority} (CA).
|
||||||
|
E faz uso de um script \texttt{oscp-verify.sh} para validar ou revogar os certificados através do servidor OCSP.
|
||||||
|
|
||||||
|
\begin{codeblock}{vpn.conf}
|
||||||
|
local 193.136.212.1
|
||||||
|
port 1194
|
||||||
|
proto udp
|
||||||
|
dev tun
|
||||||
|
|
||||||
|
verb 4
|
||||||
|
|
||||||
|
ca /etc/openvpn/server/ca.crt
|
||||||
|
cert /etc/openvpn/server/vpn.crt
|
||||||
|
key /etc/openvpn/server/vpn.key
|
||||||
|
dh /etc/openvpn/server/dh2048.pem
|
||||||
|
|
||||||
|
topology subnet
|
||||||
|
server 10.8.0.0 255.255.255.0
|
||||||
|
push "route 10.60.0.0 255.255.255.0"
|
||||||
|
|
||||||
|
# ocsp and revocation
|
||||||
|
script-security 2
|
||||||
|
tls-verify /etc/openvpn/server/ocsp-verify.sh
|
||||||
|
# auth
|
||||||
|
cipher AES-256-GCM
|
||||||
|
auth SHA256
|
||||||
|
|
||||||
|
plugin /usr/lib64/openvpn/plugins/openvpn-plugin-auth-pam.so totp
|
||||||
|
tls-auth /etc/openvpn/server/ta.key 0
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
Foi criado o ficheiro \texttt{totp} com a configuração de autenticação a
|
||||||
|
ser utilizada pelo plugin de PAM para o openvpn.
|
||||||
|
|
||||||
|
\begin{codeblock}{totp}
|
||||||
|
auth required pam_google_authenticator.so forward_pass
|
||||||
|
auth required pam_unix.so use_first_pass
|
||||||
|
account required pam_unix.so
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
Este script simplesmente comunica com o servidor OpenSSl
|
||||||
|
e verifica o resultado.
|
||||||
|
|
||||||
|
\begin{codeblock}{ocsp\_verify.sh}
|
||||||
|
#!/bin/bash
|
||||||
|
depth=$1
|
||||||
|
if [ "$depth" -eq 0 ]; then
|
||||||
|
if [ -n "$tls_serial_0" ]; then
|
||||||
|
# e preciso converter o serial para hexadecimal porque o openssl espera em hex
|
||||||
|
hex_serial=$(printf '%x' "$tls_serial_0")
|
||||||
|
status=$(openssl ocsp -issuer /etc/openvpn/server/ca.crt -serial "0x$hex_serial" -url http://10.60.0.1:8888 -CAfile /etc/openvpn/server/ca.crt 2>/dev/null)
|
||||||
|
if echo "$status" | grep -q "good"; then
|
||||||
|
exit 0 # sucesso
|
||||||
|
fi
|
||||||
|
exit 1 # revogado ou nao encontrado
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\subsection{Erros}
|
||||||
|
|
||||||
|
Um dos erros que encontramos pelo caminho foi que o OpenSSL OCSP espera que o
|
||||||
|
\textit{serial} esteja num formato diferente do que o esperado. Foi necessário
|
||||||
|
converter para hexadecimal primeiro.
|
||||||
|
|
||||||
|
Adicionalmente, devido às restrições de segurança do \textit{systemd},
|
||||||
|
tentamos desativar o \texttt{ProtectHome} no serviço do OpenVPN
|
||||||
|
para que o plugin PAM consiga ler os ficheiros de segredo do Google Authenticator
|
||||||
|
localizados nas diretorias \textit{home} dos utilizadores. Mas isto não
|
||||||
|
foi suficiente, por isso acabamos por correr os serviços pela linha
|
||||||
|
de comandoos.
|
||||||
|
|
||||||
|
\subsection{Configurar o utilizador com TOTP}
|
||||||
|
|
||||||
|
Primeiro, na gateway, entramos como o utilizador desejado e obtemos a chave
|
||||||
|
do gerador de palavras passes temporárias. Ao inserir a chave no
|
||||||
|
\texttt{google authenticator} podemos obter um código QR, a nossa primeira
|
||||||
|
chave de 6 dígitos.
|
||||||
|
|
||||||
|
\begin{figure}[h]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=8em]{google-authenticator}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\begin{codeblock}[bash]{}
|
||||||
|
su john
|
||||||
|
google-authenticator
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\section{VPN Client (Road Warrior)}
|
||||||
|
|
||||||
|
\subsection{Configuração da Máquina}
|
||||||
|
Para a configuração da Máquina, configuramos o edereço, o default gateway e adicionamos apache aos Hosts:
|
||||||
|
|
||||||
|
\begin{codeblock}{VM\_ROAD\_WARRIOR.sh}
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# --- configuracao --- #
|
||||||
|
source VM_CONFIG.sh
|
||||||
|
ifconfig enp0s8 193.136.212.10 netmask 255.255.255.0
|
||||||
|
route add default gw 193.136.212.1
|
||||||
|
|
||||||
|
if ! grep -q "apache" /etc/hosts; then
|
||||||
|
echo "10.60.0.1 apache" >> /etc/hosts
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- vpn client --- #
|
||||||
|
vpn_dir="/etc/openvpn/client/"
|
||||||
|
cp ca/ta.key $vpn_dir
|
||||||
|
cp ca/ca.crt $vpn_dir
|
||||||
|
cp ca/user.key $vpn_dir
|
||||||
|
cp ca/user.crt $vpn_dir
|
||||||
|
cp conf/client.conf $vpn_dir
|
||||||
|
|
||||||
|
openvpn --config "${vpn_dir}/client.conf"
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
|
||||||
|
% Esta configuração foi necessaria, porque sem edereço a VM não conseguia-se identificar na rede. Sem o default gateway
|
||||||
|
% os edereços desconhecidos seriam enviados para a porta da internet, e adicionamos apache aos Hosts para que fosse igual
|
||||||
|
% ao domain para não haver erros.
|
||||||
|
%(I dunno about this Apache part??) Also sinto que ainda precisa de mais um bocado.
|
||||||
|
Também foram movidos os certificados e chaves necessarias para as pastas do serviço openvpn, para que o Road Warrior
|
||||||
|
consiga comunicar e ser validado pela gateway.
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Configuração do Cliente OpenVPN}
|
||||||
|
|
||||||
|
O cliente encontra-se na rede externa (\texttt{193.136.212.10}) e liga-se à VPN
|
||||||
|
gateway na porta 1194. Para garantir a segurança, utilizamos autenticação mútua (os certificados X.509)
|
||||||
|
e um \textit{two factor authentication} (2FA) como palavras-passe temporárias, geradas através do
|
||||||
|
\textit{Google Authenticator}.
|
||||||
|
|
||||||
|
\begin{codeblock}{client.conf}
|
||||||
|
client
|
||||||
|
dev tun
|
||||||
|
proto udp
|
||||||
|
remote 193.136.212.1 1194
|
||||||
|
ca ca.crt
|
||||||
|
cert user.crt
|
||||||
|
key user.key
|
||||||
|
auth-user-pass
|
||||||
|
cipher AES-256-GCM
|
||||||
|
auth SHA256
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\subsection{Testes}
|
||||||
|
Para verificar que a autenticação foi corretamente implementada, inserimos a password de um utilizador sem os digitos do TOTP, e identificamos que utilizar somente a password não é suficiente para autenticar. Igualmente ao utilizar ambos a autenticação é bem sucedida.
|
||||||
|
|
||||||
|
Para verificar que o tunel foi estabelecido, primeiro corremos na linha de comandos \texttt{ip a}. Observamos a existencia de uma nova interface tun0, ou seja o tunel foi corretamente establecido. Depois demos ping ao route e depois ao servidor interno, que resultou em pacotes devolvidos para ambos.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
% TODO: screenshots? dizer que erros exatos nos obtemos a cada etapa
|
||||||
|
% TODO: erros ortograficos lol
|
||||||
|
|
||||||
|
Para verificar que o OCSP funciona correctamente, o cliente conectou ao servidor OpenVPN:
|
||||||
|
primeiro, sem o servidor OCSP a correr, uma segunda vez com ele a correr e com o certificado correcto
|
||||||
|
e uma terceira vez com um certificado revogado. Fizemos estes testes sabendo que o
|
||||||
|
cliente e o servidor já estavam correctamente configurados.
|
||||||
|
|
||||||
|
Verificamos que, como é suposto: sem OCSP não é possivel autenticar; com OCSP e com certificado válido,
|
||||||
|
podemos autenticar; e com OCSP mas com certificado revogado, a autenticação falha.
|
||||||
|
|
||||||
|
\section{Servidor Apache e OCSP}
|
||||||
|
Para a configuração da ultima maquina, temos o OpenSSL e Apache no mesmo servidor, por isso temos de configurar
|
||||||
|
as pastas necessarias, os utilizadores do serviço, configurar os edereços e uma route:
|
||||||
|
\begin{codeblock}{VM\_OPENSSL\_APACHE.sh}
|
||||||
|
#!/bin/bash
|
||||||
|
# configuracao
|
||||||
|
source VM_CONFIG.sh
|
||||||
|
|
||||||
|
sudo yum install -y epel-release
|
||||||
|
sudo yum install -y openssl httpd mod_ssl mod_authnz_pam google-authenticator
|
||||||
|
sudo yum install -y mod_session
|
||||||
|
|
||||||
|
# utilizador
|
||||||
|
id -u john &>/dev/null || useradd john
|
||||||
|
echo "password" | passwd --stdin john
|
||||||
|
|
||||||
|
if_dentro="enp0s8"
|
||||||
|
ip_dentro="10.60.0.1"
|
||||||
|
ifconfig $if_dentro $ip_dentro netmask 255.255.255.0
|
||||||
|
|
||||||
|
# route de volta para comunicar com o warrior
|
||||||
|
route add -net 10.8.0.0 netmask 255.255.255.0 gw 10.60.0.3
|
||||||
|
|
||||||
|
cp conf/openssl.cnf /etc/pki/tls/
|
||||||
|
|
||||||
|
# copiar ca para esta VM
|
||||||
|
cp ca/index.txt $CA_DIR
|
||||||
|
cp ca/ca.crt $CA_DIR
|
||||||
|
cp ca/ca.key $CA_DIR
|
||||||
|
cp ca/serial $CA_DIR
|
||||||
|
cp ca/dh2048.pem $CA_DIR
|
||||||
|
|
||||||
|
# correr oscp
|
||||||
|
killall openssl 2>/dev/null
|
||||||
|
openssl ocsp -index $CA_DIR/index.txt -port 8888 -rsigner $CA_DIR/ca.crt -rkey $CA_DIR/ca.key -CA $CA_DIR/ca.crt -text &
|
||||||
|
|
||||||
|
# apache
|
||||||
|
mkdir -p /etc/httpd/ssl
|
||||||
|
cp ca/ca.crt /etc/httpd/ssl/
|
||||||
|
cp ca/apache.crt /etc/httpd/ssl/
|
||||||
|
cp ca/apache.key /etc/httpd/ssl/
|
||||||
|
cp conf/ssl.conf /etc/httpd/conf.d/ssl.conf
|
||||||
|
cp conf/httpd.conf /etc/httpd/conf/httpd.conf
|
||||||
|
cp conf/httpd-totp /etc/pam.d/httpd-totp
|
||||||
|
|
||||||
|
echo "LoadModule session_module modules/mod_session.so" > /etc/httpd/conf.modules.d/01-session.conf
|
||||||
|
echo "LoadModule session_cookie_module modules/mod_session_cookie.so" >> /etc/httpd/conf.modules.d/01-session.conf
|
||||||
|
echo "LoadModule auth_form_module modules/mod_auth_form.so" > /etc/httpd/conf.modules.d/01-auth_form.conf
|
||||||
|
|
||||||
|
cp -r www/* /var/www/html/
|
||||||
|
chown -R apache:apache /var/www/html/
|
||||||
|
|
||||||
|
httpd -X
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\subsection{Configuração da Máquina}
|
||||||
|
|
||||||
|
Como já referimos a Máquina tem ambos o serviço OpenSSL e Apache, por isso vai precisar de dois .conf files para
|
||||||
|
configurar-los. O httpd.conf tem as portas e modulos enquanto o ssl.conf tem a configuração da autenticação mútua, e o OCSP:
|
||||||
|
\begin{codeblock}{httpd.conf}
|
||||||
|
ServerRoot "/etc/httpd"
|
||||||
|
|
||||||
|
Include conf.modules.d/*.conf
|
||||||
|
LoadModule authnz_pam_module modules/mod_authnz_pam.so
|
||||||
|
LoadModule mpm_event_module modules/mod_mpm_event.so
|
||||||
|
|
||||||
|
User apache
|
||||||
|
Group apache
|
||||||
|
|
||||||
|
Listen 80
|
||||||
|
Listen 443
|
||||||
|
|
||||||
|
Include conf.d/*.conf
|
||||||
|
|
||||||
|
DocumentRoot "/var/www/html"
|
||||||
|
<Directory "/var/www/html">
|
||||||
|
Options Indexes FollowSymLinks
|
||||||
|
AllowOverride None
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\begin{codeblock}{ssl.conf}
|
||||||
|
<VirtualHost *:443>
|
||||||
|
ServerName 10.60.0.1
|
||||||
|
DocumentRoot /var/www/html
|
||||||
|
|
||||||
|
SSLEngine on
|
||||||
|
SSLCertificateFile /etc/httpd/ssl/apache.crt
|
||||||
|
SSLCertificateKeyFile /etc/httpd/ssl/apache.key
|
||||||
|
SSLCACertificateFile /etc/httpd/ssl/ca.crt
|
||||||
|
|
||||||
|
# mutual authentication
|
||||||
|
SSLVerifyClient require
|
||||||
|
SSLVerifyDepth 1
|
||||||
|
|
||||||
|
# ocsp validation
|
||||||
|
SSLOCSPEnable on
|
||||||
|
SSLOCSPDefaultResponder "http://10.60.0.1:8888"
|
||||||
|
SSLOCSPOverrideResponder on
|
||||||
|
SSLOCSPUseRequestNonce off
|
||||||
|
|
||||||
|
# session management
|
||||||
|
Session On
|
||||||
|
SessionCookieName session path=/;HttpOnly;Secure
|
||||||
|
|
||||||
|
# proteger
|
||||||
|
<Location "/">
|
||||||
|
AuthType Form
|
||||||
|
AuthName "Coimbra VPN"
|
||||||
|
AuthFormProvider PAM
|
||||||
|
AuthPAMService httpd-totp
|
||||||
|
AuthFormLoginRequiredLocation "/login.html"
|
||||||
|
Require valid-user
|
||||||
|
</Location>
|
||||||
|
|
||||||
|
# public login page
|
||||||
|
<Location "/login.html">
|
||||||
|
AuthType None
|
||||||
|
Require all granted
|
||||||
|
</Location>
|
||||||
|
|
||||||
|
# login handler
|
||||||
|
<Location "/dologin">
|
||||||
|
SetHandler form-login-handler
|
||||||
|
AuthType Form
|
||||||
|
AuthName "Coimbra VPN"
|
||||||
|
AuthFormProvider PAM
|
||||||
|
AuthPAMService httpd-totp
|
||||||
|
Require all granted
|
||||||
|
AuthFormLoginSuccessLocation "/index.html"
|
||||||
|
AuthFormLoginRequiredLocation "/login.html?error=1"
|
||||||
|
</Location>
|
||||||
|
|
||||||
|
# logout handler
|
||||||
|
<Location "/logout">
|
||||||
|
SetHandler form-logout-handler
|
||||||
|
AuthFormLogoutLocation "/login.html?loggedout=1"
|
||||||
|
</Location>
|
||||||
|
|
||||||
|
</VirtualHost>
|
||||||
|
|
||||||
|
# redirect para https
|
||||||
|
<VirtualHost *:80>
|
||||||
|
ServerName 10.60.0.1
|
||||||
|
Redirect permanent / https://10.60.0.1/
|
||||||
|
</VirtualHost>
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\subsubsection{Testes}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Domínio:} Verificou-se que o acesso só é permitido utilizando o endereço correto, pois se for inserido outro dominio, não é direcionado para o site do Apache.
|
||||||
|
\item \textbf{Redirecionamento HTTPS:} Ao testar quando colocamos http, e o dominio certo, era redirecionado para https.
|
||||||
|
\item \textbf{Autenticação com o Certificado:} O acesso foi negado ao apresentar certificados inválidos ou ausentes no browser, devolvendo um erro com sobre não conseguir establecer connexão porque falta de certificado.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
Para testar o OCSP, fizemos os seguintes paços:
|
||||||
|
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Estabelecer a ligação VPN e verificar a conectividade à rede interna.
|
||||||
|
\item No diretório da autoridade de certificação (máquina \textit{host}), revogar o certificado do utilizador:
|
||||||
|
\begin{codeblock}[bash]{revoke.sh}
|
||||||
|
openssl ca -revoke user.crt -config cheese.cfg -keyfile ca.key -cert ca.crt
|
||||||
|
\end{codeblock}
|
||||||
|
\item Atualizar o ficheiro \texttt{index.txt} no servidor OCSP e reiniciar o serviço para carregar o novo estado de revogação.
|
||||||
|
\item Tentar estabelecer uma nova ligação VPN e verificar que a autenticação falha devido à resposta \texttt{revoked} do responder OCSP.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
|
||||||
|
\section{Teste Integrado}
|
||||||
|
|
||||||
|
Para validar, efetuámos um teste integrado englobando todos os requisitos:
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Começamos por iniciar todas as máquinas com os devidos \textit{scripts}.
|
||||||
|
\item Na máquina \textit{Road Warrior}, iniciámos a ligação OpenVPN com o utilizador, a sua password e o \textit{token} TOTP.
|
||||||
|
\item O \textit{Gateway} OpenVPN verifica as credenciais e verifica o certificado cliente contra o servidor OCSP.
|
||||||
|
\item Antes de acedermos ao firefox, temos que verificar que já adicionámos a nossa a nossa CA e o certificado \texttt{p12}.
|
||||||
|
\item Através do túnel VPN, acedemos agora ao endereço \texttt{https://apache.coimbra} no browser.
|
||||||
|
\item O servidor Apache solicitou o certificado X.509 do utilizador e validou a sua autenticidade e estado de revogação no OCSP.
|
||||||
|
\item Finalmente, o Apache apresentou a página de login, onde inserimos as credenciais e o código TOTP.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
|
||||||
|
\section{Conclusão}
|
||||||
|
|
||||||
|
Atingimos o objetivo deste trabalho: conseguimos configurar o túnel VPN,
|
||||||
|
o \textit{two-factor authentication} em múltiplos serviços, e conseguimos gerir o ciclo de vida dos
|
||||||
|
certificados emitidos através de uma CA própria e OCSP. Utilizar mais máquinas para simular um cenário
|
||||||
|
maior seria redundante e apenas exigiria a emissão de mais certificados, não acrescentando muito ao nível de aprendizagem.
|
||||||
|
|
||||||
|
Aplicando conhecimentos de trabalhos anteriores,
|
||||||
|
poderíamos aplicar políticas mais restritas nas \textit{iptables} (ex: regras de DROP aos pacotes indesejados),
|
||||||
|
e implementar ferramentas como o Suricata para identificar possíveis anomalias e ataques aos serviços.
|
||||||
|
|
||||||
|
\end{document}
|
||||||
19
assignment2/relatorio/relatorio.toc
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
\babel@toc {portuguese}{}\relax
|
||||||
|
\contentsline {section}{\numberline {1}Introdução}{3}{section.1}%
|
||||||
|
\contentsline {section}{\numberline {2}Preparação Inicial}{3}{section.2}%
|
||||||
|
\contentsline {subsection}{\numberline {2.1}Criação de Certificados}{3}{subsection.2.1}%
|
||||||
|
\contentsline {subsection}{\numberline {2.2}Configuração geral}{4}{subsection.2.2}%
|
||||||
|
\contentsline {section}{\numberline {3}VPN Gateway}{5}{section.3}%
|
||||||
|
\contentsline {subsection}{\numberline {3.1}Configuração da Máquina}{5}{subsection.3.1}%
|
||||||
|
\contentsline {subsection}{\numberline {3.2}Configuração do Serviço OpenVPN}{6}{subsection.3.2}%
|
||||||
|
\contentsline {subsection}{\numberline {3.3}Erros}{7}{subsection.3.3}%
|
||||||
|
\contentsline {subsection}{\numberline {3.4}Configurar o utilizador com TOTP}{7}{subsection.3.4}%
|
||||||
|
\contentsline {section}{\numberline {4}VPN Client (Road Warrior)}{8}{section.4}%
|
||||||
|
\contentsline {subsection}{\numberline {4.1}Configuração da Máquina}{8}{subsection.4.1}%
|
||||||
|
\contentsline {subsection}{\numberline {4.2}Configuração do Cliente OpenVPN}{8}{subsection.4.2}%
|
||||||
|
\contentsline {subsection}{\numberline {4.3}Testes}{9}{subsection.4.3}%
|
||||||
|
\contentsline {section}{\numberline {5}Servidor Apache e OCSP}{9}{section.5}%
|
||||||
|
\contentsline {subsection}{\numberline {5.1}Configuração da Máquina}{10}{subsection.5.1}%
|
||||||
|
\contentsline {subsubsection}{\numberline {5.1.1}Testes}{12}{subsubsection.5.1.1}%
|
||||||
|
\contentsline {section}{\numberline {6}Teste Integrado}{13}{section.6}%
|
||||||
|
\contentsline {section}{\numberline {7}Conclusão}{13}{section.7}%
|
||||||
64
assignment2/relatorio/style.sty
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
\usepackage[margin=1in]{geometry}
|
||||||
|
\usepackage{raleway}
|
||||||
|
\renewcommand{\familydefault}{\sfdefault}
|
||||||
|
\usepackage{ulem}
|
||||||
|
\usepackage{wrapfig}
|
||||||
|
\usepackage{graphicx,tabularx,booktabs}
|
||||||
|
\usepackage{paracol}
|
||||||
|
\usepackage[dvipsnames]{xcolor}
|
||||||
|
\usepackage{enumitem,amssymb}
|
||||||
|
\usepackage[colorlinks=true,urlcolor=blue,linkcolor=MidnightBlue]{hyperref}
|
||||||
|
\graphicspath{{./img/}}
|
||||||
|
|
||||||
|
\usepackage{enumitem,amssymb}
|
||||||
|
\newlist{todolist}{itemize}{2}
|
||||||
|
\setlist[todolist]{noitemsep, topsep=0pt,label=$\square$}
|
||||||
|
|
||||||
|
\usepackage{pifont}
|
||||||
|
\usepackage{amssymb}
|
||||||
|
|
||||||
|
\usepackage[most]{tcolorbox}
|
||||||
|
\tcbuselibrary{listings, skins, breakable}
|
||||||
|
|
||||||
|
\lstdefinestyle{mystyle}{
|
||||||
|
basicstyle=\ttfamily\footnotesize,
|
||||||
|
breakatwhitespace=false,
|
||||||
|
breaklines=true,
|
||||||
|
captionpos=b,
|
||||||
|
keepspaces=true,
|
||||||
|
numbers=left,
|
||||||
|
numbersep=5pt,
|
||||||
|
showspaces=false,
|
||||||
|
showstringspaces=false,
|
||||||
|
showtabs=false,
|
||||||
|
tabsize=2,
|
||||||
|
commentstyle=\color{gray},
|
||||||
|
keywordstyle=\color{MidnightBlue}\bfseries,
|
||||||
|
stringstyle=\color{ForestGreen}
|
||||||
|
}
|
||||||
|
|
||||||
|
\newtcblisting{codeblock}[2][]{
|
||||||
|
enhanced,
|
||||||
|
breakable,
|
||||||
|
colback=gray!2!white,
|
||||||
|
colframe=gray!20!black,
|
||||||
|
attach boxed title to top left={yshift*=-\tcboxedtitleheight/2, xshift=4mm},
|
||||||
|
boxed title style={
|
||||||
|
colback=gray!20!black,
|
||||||
|
outer arc=0pt,
|
||||||
|
arc=0pt,
|
||||||
|
top=1pt,
|
||||||
|
bottom=1pt,
|
||||||
|
},
|
||||||
|
fonttitle=\bfseries\ttfamily\footnotesize,
|
||||||
|
title={#2},
|
||||||
|
listing only,
|
||||||
|
listing options={
|
||||||
|
style=mystyle,
|
||||||
|
language=#1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
\setlength{\parskip}{1em}%
|
||||||
|
\setlength{\parindent}{0em}%
|
||||||
|
|
||||||
@@ -1 +1,90 @@
|
|||||||
# LoadModule authnz_pam_module modules/mod_authnz_pam.so
|
ServerRoot "/etc/httpd"
|
||||||
|
ServerName "10.60.0.1"
|
||||||
|
|
||||||
|
Listen 80
|
||||||
|
User apache
|
||||||
|
Group apache
|
||||||
|
|
||||||
|
Include conf.modules.d/*.conf
|
||||||
|
Include conf/modsecurity.conf
|
||||||
|
|
||||||
|
<Directory />
|
||||||
|
AllowOverride none
|
||||||
|
Require all denied
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
DocumentRoot "/var/www/html"
|
||||||
|
|
||||||
|
<Directory "/var/www">
|
||||||
|
AllowOverride None
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
# Further relax access to the default document root:
|
||||||
|
<Directory "/var/www/html">
|
||||||
|
Options Indexes FollowSymLinks
|
||||||
|
AllowOverride None
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
# DirectoryIndex: sets the file that Apache will serve if a directory
|
||||||
|
# is requested.
|
||||||
|
#
|
||||||
|
<IfModule dir_module>
|
||||||
|
DirectoryIndex index.html
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
# The following lines prevent .htaccess and .htpasswd files from being
|
||||||
|
# viewed by Web clients.
|
||||||
|
<Files ".ht*">
|
||||||
|
Require all denied
|
||||||
|
</Files>
|
||||||
|
|
||||||
|
ErrorLog "logs/error_log"
|
||||||
|
LogLevel warn
|
||||||
|
|
||||||
|
<IfModule log_config_module>
|
||||||
|
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
|
||||||
|
LogFormat "%h %l %u %t \"%r\" %>s %b" common
|
||||||
|
|
||||||
|
<IfModule logio_module>
|
||||||
|
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
CustomLog "logs/access_log" combined
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
<IfModule mime_module>
|
||||||
|
TypesConfig /etc/mime.types
|
||||||
|
|
||||||
|
AddType application/x-compress .Z
|
||||||
|
AddType application/x-gzip .gz .tgz
|
||||||
|
|
||||||
|
AddType text/html .shtml
|
||||||
|
AddOutputFilter INCLUDES .shtml
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
AddDefaultCharset UTF-8
|
||||||
|
|
||||||
|
<IfModule mime_magic_module>
|
||||||
|
MIMEMagicFile conf/magic
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
# reverse proxy for juice shop
|
||||||
|
ProxyRequests Off
|
||||||
|
ProxyPreserveHost On
|
||||||
|
|
||||||
|
<VirtualHost 10.60.0.1:80>
|
||||||
|
<IfModule mod_headers.c>
|
||||||
|
RequestHeader unset Accept-Encoding
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
ProxyPass / http://127.0.0.1:3000/
|
||||||
|
ProxyPassReverse / http://127.0.0.1:3000/
|
||||||
|
</VirtualHost>
|
||||||
|
|
||||||
|
# EnableMMAP off
|
||||||
|
# EnableSendfile on
|
||||||
|
IncludeOptional conf.d/*.conf
|
||||||
|
ServerAdmin jeevacation@gmail.com
|
||||||
|
# ServerName www.coimbravpn.com:80
|
||||||
38
conf/modsecurity.conf
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
SecRuleEngine On
|
||||||
|
SecRequestBodyAccess On
|
||||||
|
SecResponseBodyAccess On
|
||||||
|
SecDebugLog /var/log/modsecurity/debug.log
|
||||||
|
SecDebugLogLevel 0
|
||||||
|
SecAuditLogParts ABIJ
|
||||||
|
SecAuditLogType Serial
|
||||||
|
SecAuditLog /var/log/modsecurity/audit.log
|
||||||
|
SecRequestBodyJsonParser On
|
||||||
|
|
||||||
|
# sql injection
|
||||||
|
SecRule REQUEST_BODY "['\"].*--" \
|
||||||
|
"id:950001,phase:2,deny,status:403,msg:'SQL Injection: quote and comment',log"
|
||||||
|
|
||||||
|
# xss / html injection
|
||||||
|
SecRule REQUEST_URI|ARGS "(<.*>)|(%3C.*%3E)" \
|
||||||
|
"id:950003,phase:1,deny,status:403,msg:'XSS/HTML INJECTION DETECTED!!!',log"
|
||||||
|
|
||||||
|
# command injection
|
||||||
|
SecRule ARGS "(\"role\".*:.*\"admin\")|exec|cat|more|ls|dir|/etc/passwd" \
|
||||||
|
"id:950006,phase:2,deny,status:403,msg:'COMMAND INJECTION DETECTED!!!',log"
|
||||||
|
|
||||||
|
# path traversal
|
||||||
|
SecRule REQUEST_URI|ARGS "\%00|\%2500|\.\./|ftp|metrics|api-docs" \
|
||||||
|
"id:950007,phase:2,deny,status:403,msg:'PATH TRAVERSAL ATTEMPT!!!',log"
|
||||||
|
|
||||||
|
# exposed stuff (redundante ?)
|
||||||
|
SecRule REQUEST_URI|ARGS "\%00|\%2500|ftp|metrics|api-docs" \
|
||||||
|
"id:950008,phase:2,deny,status:500,msg:'ATTEMPT TO ACCESS FTP, METRICS, API-DOCS!!!',log"
|
||||||
|
|
||||||
|
# rate limiting on login endpoint
|
||||||
|
# (max 5 requests per 30s per IP)
|
||||||
|
SecAction \
|
||||||
|
"id:950009,phase:1,initcol:ip=%{REMOTE_ADDR},pass,nolog"
|
||||||
|
SecRule REQUEST_URI "@streq /rest/user/login" \
|
||||||
|
"id:950010,phase:2,pass,nolog,setvar:ip.login_count=+1,expirevar:ip.login_count=30"
|
||||||
|
SecRule IP:LOGIN_COUNT "@gt 5" \
|
||||||
|
"id:950011,phase:2,deny,status:429,msg:'Rate Limit Exceeded on Login',log"
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
depth=$1
|
|
||||||
env >> /etc/openvpn/server/ocsp_env.log
|
|
||||||
if [ "$depth" -eq 0 ]; then
|
|
||||||
echo "Checking OCSP for serial=$tls_serial_0" >> /etc/openvpn/server/ocsp.log
|
|
||||||
if [ -n "$tls_serial_0" ]; then
|
|
||||||
# é preciso converter o serial para hexadecimal porque o openssl espera em hex
|
|
||||||
hex_serial=$(printf '%x' "$tls_serial_0")
|
|
||||||
status=$(openssl ocsp -issuer /etc/openvpn/server/ca.crt -serial "0x$hex_serial" -url http://10.60.0.1:8888 -CAfile /etc/openvpn/server/ca.crt 2>>/etc/openvpn/server/ocsp.log)
|
|
||||||
echo "OCSP Status: $status" >> /etc/openvpn/server/ocsp.log
|
|
||||||
|
|
||||||
if echo "$status" | grep -q "revoked"; then
|
|
||||||
echo "Result: REVOKED" >> /etc/openvpn/server/ocsp.log
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if echo "$status" | grep -q "good"; then
|
|
||||||
echo "Result: GOOD" >> /etc/openvpn/server/ocsp.log
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Result: UNKNOWN/ERROR" >> /etc/openvpn/server/ocsp.log
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "tls_serial_0 is empty!" >> /etc/openvpn/server/ocsp.log
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "ERROR: depth > 0" >> /etc/openvpn/server/ocsp.log
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
BIN
entrega.zip
Normal file
3680
entrega.zip.asc
Normal file
BIN
enunciado.pdf
218
enunciado.txt
@@ -1,142 +1,152 @@
|
|||||||
FSI 2025/2026
|
FSI 2025/2026
|
||||||
Practical Assignment #2
|
Practical Assignment #3
|
||||||
|
|
||||||
1. Goals
|
1. Goals
|
||||||
•
|
•
|
||||||
|
|
||||||
Configure a VPN tunnel in the “road warrior” scenario.
|
Explore the WSTG (Web Security Testing Guide)1 web security testing guidelines.
|
||||||
|
|
||||||
•
|
•
|
||||||
|
|
||||||
Enable two-factor user authentication with OpenVPN and Apache services.
|
Configure and explore the usage of ModSecurity reverse proxy as a WAF (Web Application Firewall)
|
||||||
|
|
||||||
•
|
|
||||||
|
|
||||||
Manage PKI: certification authorities, X.509 certificates, revocation and OCSP.
|
|
||||||
|
|
||||||
2. General description
|
2. General description
|
||||||
Figure 1 illustrates the scenario considered for our practical assignment. As illustrated, secure communications are
|
The main goals of this assignment are to explore web application security and to implement a web application firewall to
|
||||||
supported by a VPN tunnel established between a remote client (road warrior) and the VPN gateway, with the purpose of
|
secure a web application against application-layer attacks. The web application to be used in this assignment is the OWASP
|
||||||
enabling accesses to services in the Internal Network, particularly a web server running Apache. To enable the VPN tunnel,
|
JuiceShop2 3. This assignment is split in two phases: the first phase is dedicated to exploring the security of the JuiceShop
|
||||||
we will use OpenVPN (https://openvpn.net).
|
web application, and the second phase aims at monitor, filter, and block HTTP traffic to the JuiceShop, through the
|
||||||
|
implementation of a WAF using ModSecurity, with the aim to address the security issues identified in the first phase. Figure
|
||||||
|
1 illustrates the two phases of the assignment, depicting the JuiceShop web server, the penetration testing client and the
|
||||||
|
WAF.
|
||||||
|
|
||||||
Figure 1 – Scenario for the Practical Assignment #1
|
Figure 1 – Security testing and WAF phases of the Assignment
|
||||||
|
|
||||||
Regarding authentication, the two communication entities participating in the VPN tunnel (road warrior and the VPN
|
1
|
||||||
gateway) should possess valid X.509 certificates, which are created with a private Certification Authority (CA). Users
|
|
||||||
establishing remote connections to the VPN gateway (road warriors), as well as users connecting to the Apache server, will
|
|
||||||
also use two-factor authentication, as described below. Apache must also implement client authentication via X.509
|
|
||||||
certificates. Figure 2 provides an illustration of the interactions between all the entities involved in this setup.
|
|
||||||
|
|
||||||
Figure 2 – X.509 mutual authentication and OCSP
|
WSTG with v42 is available at: https://owasp.org/www-project-web-security-testing-guide/
|
||||||
|
|
||||||
As we can observe in Figure 2, the VPN gateway and the Apache web server must verify the status of validity of certificates
|
|
||||||
using OCSP (Online Certificate Status Protocol) and revocation information from the CA. OCSP verification in not
|
|
||||||
required for the road warrior. Next, we describe the configuration requirements for the various components of the
|
|
||||||
assignment.
|
|
||||||
|
|
||||||
3. Configuration requirements
|
|
||||||
VPN tunnel for remote access (road warriors)
|
|
||||||
As illustrated in Figure 1, remote clients (road warriors) are able to connect to the Coimbra VPN gateway, and using the
|
|
||||||
tunnel remotely access hosts in the Internal network. The following configuration requirements should be considered:
|
|
||||||
•
|
|
||||||
|
|
||||||
In order to establish a VPN tunnel with the Coimbra gateway, the road warrior must be in the possession of a valid
|
|
||||||
X.509 certificate, issued by the private CA of the scenario.
|
|
||||||
|
|
||||||
•
|
|
||||||
|
|
||||||
The road warrior and the Coimbra VPN gateway must perform mutual authentication using X.509 digital certificates.
|
|
||||||
|
|
||||||
•
|
|
||||||
|
|
||||||
The Coimbra VPN gateway should verify the validity of the X.509 certificate presented by the road warrior using OCSP
|
|
||||||
and, in case the certificate is revoked, the gateway should refuse the connection.
|
|
||||||
|
|
||||||
•
|
|
||||||
|
|
||||||
In order to authorize the remote user, the Coimbra gateway should also enforce two other authentication steps: the user
|
|
||||||
must present a valid username and password, plus a one-time password (OTP, or an authentication token).
|
|
||||||
|
|
||||||
Web server
|
|
||||||
2
|
2
|
||||||
|
|
||||||
The road warrior user should be able to contact the Apache web server with HTTPS through the VPN tunnel. The
|
OWASP JuiceShop: https://owasp.org/www-project-juice-shop/
|
||||||
following configuration requirements should be considered:
|
For this assignment, it is recommended to use the most recent version of the JuiceShop. At the time of writing this document it is v17.2.0
|
||||||
•
|
|
||||||
|
|
||||||
Apache should enforce two-factor authentication in order to authorize accesses from clients: the client (browser) should
|
|
||||||
present a valid X.509 certificate (issued with the private CA of the scenario) and the user should also present a valid onetime password (or authentication token).
|
|
||||||
|
|
||||||
•
|
|
||||||
|
|
||||||
As in the VPN, the validity of the X.509 certificate presented by the client should be checked in the CA using OCSP.
|
|
||||||
|
|
||||||
Two-factor user authentication
|
|
||||||
As previously discussed, VPN establishment and HTTPS accesses to Apache make use of one-time passwords
|
|
||||||
(authentication tokens), which may be generated by an appropriate application. One-time passwords may be generated using
|
|
||||||
the TOTP (Time-based One-time Password Algorithm). This algorithm employs a secret key shared between the user
|
|
||||||
(client) and the remote service, plus a timestamp (obtained from the current system time), to obtain a one-time password.
|
|
||||||
In order to generate a one-time password, the user may use an application such as Google Authenticator, illustrated in
|
|
||||||
Figure 3. This application periodically generates a new one-time password that can be used to authenticate the user with the
|
|
||||||
remote service. This application is available for iOS and Android 1.
|
|
||||||
Certification authority
|
|
||||||
As already discussed, the goal is to use OpenSSL to configure a private Certification Authority, as well as to issue and revoke
|
|
||||||
X.509 digital certificates for the VPN gateways and remote users. The following configuration requirements should be
|
|
||||||
considered:
|
|
||||||
•
|
|
||||||
|
|
||||||
The Certification Authority is used to issue certificates for the VPN gateway, VPN client and Apache web server.
|
|
||||||
|
|
||||||
•
|
|
||||||
|
|
||||||
The Certification Authority allows the revocation of certificates previously issued.
|
|
||||||
|
|
||||||
•
|
|
||||||
|
|
||||||
The Certification Authority also supports a OCSP responder.
|
|
||||||
|
|
||||||
For Android: https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en and
|
|
||||||
for Apple iOS: https://itunes.apple.com/us/app/google-authenticator/id388497605?mt=8
|
|
||||||
1
|
|
||||||
|
|
||||||
3
|
3
|
||||||
|
|
||||||
Figure 3 – Google Authenticator app, to generate a one-time password to access services enabled with two-factor authentication
|
3. Phase 1 - Web application security testing
|
||||||
|
In this phase the goal is to explore web application security using the JuiceShop website following the relevant and applicable
|
||||||
|
WSTG web security testing guidelines, and for this purpose any security tools can be used. In this context, OWASP ZAP
|
||||||
|
and security tools already available in Kali Linux are particularly relevant. This web security testing phase is described in
|
||||||
|
Figure 1, where the client has direct communications to the web server. As part of your tests, the OWASP ZAP penetration
|
||||||
|
tests must, at least:
|
||||||
|
a. Perform an automated scan to the website.
|
||||||
|
b. Perform an active scan to the website (explore the most effective policies).
|
||||||
|
c. Manage add-on required to improve the test and maximize threats identification.
|
||||||
|
d. Perform a Fuzz attack to the login form.
|
||||||
|
e. Perform a manual penetration test to explore logged in threats.
|
||||||
|
f.
|
||||||
|
|
||||||
4. Delivery of the Practical Assignment
|
Configure OWASP ZAP active scan to explore authenticated area.
|
||||||
With the assignment, please deliver also a report, containing the following information:
|
|
||||||
|
The JuiceShop application can be installed via source code or using docker, as follows:
|
||||||
•
|
•
|
||||||
|
|
||||||
Descriptions of the configurations for the implementation of the previous requirements.
|
Installation through source code in one of the virtual machines
|
||||||
|
|
||||||
•
|
•
|
||||||
|
|
||||||
A description of how the private Certification Authority was created using OpenSSL.
|
Using a docker approach (requires Docker Desktop)
|
||||||
|
|
||||||
|
As a result of your tests, you should prepare a web application security report, structured along the WSTG guidelines. The
|
||||||
|
report must document the identified vulnerabilities and on how these can be exploited (e.g., weak passwords, insecure
|
||||||
|
configurations).
|
||||||
|
|
||||||
|
4. Phase 2 – Setup and testing of a WAF (web application firewall)
|
||||||
|
Based on the web application security report produced in the first phase of the assignment, deploy an WAF between the
|
||||||
|
client and the web server, as depicted in Figure 1. The goals of this WAF are to monitor, filter, and block HTTP traffic to
|
||||||
|
the Juice Shop. This WAF server should be composed of an Apache 2 service with ModSecurity, and the WAF
|
||||||
|
configuration should be optimized to prevent all possible attacks.
|
||||||
|
As a result of this phase of the Assignment, you should repeat all penetration tests performed in the previous task and assess
|
||||||
|
the performance of the WAF in detecting and blocking the attacks. You should update the web application security report
|
||||||
|
accordingly, by including the configurations, description of the tests and performance results in a separate section.
|
||||||
|
5. Delivery of the Practical Assignment
|
||||||
|
2
|
||||||
|
|
||||||
|
•
|
||||||
|
|
||||||
|
The deadline for the delivery of the assignment (configuration files and report, via Inforestudante) is 31/5/2026.
|
||||||
|
|
||||||
•
|
•
|
||||||
|
|
||||||
A description of how X.509 certificates were issued and revoked using the private Certification Authority.
|
Notes:
|
||||||
|
o
|
||||||
|
|
||||||
•
|
Assignments without PGP will be accepted, although with a discount of 5% in the final grade.
|
||||||
|
|
||||||
A description of the tests performed to validate the functionalities implemented.
|
o
|
||||||
|
|
||||||
•
|
Submissions via Inforestudante.
|
||||||
|
|
||||||
Remaining information considered relevant.
|
The delivery of the practical assignment can document aspects regarding the methodology of testing, the analysis of results
|
||||||
|
and can be structured as follows:
|
||||||
|
|
||||||
For the delivery of the assignment, put your report, as well as the relevant configuration files, in a single archive. This archive
|
1) Introduction
|
||||||
should be signed using your PGP key and encrypted using the PGP key of your PL teacher.
|
2) Arquitecture considered for the PA#3 (for both scenarios 1 and 2)
|
||||||
Note: Assignments without PGP will be accepted, although with a discount of 5% in the final grade.
|
- Network structure
|
||||||
Delivery deadline:
|
- Servers
|
||||||
•
|
- Services
|
||||||
|
3) Web application security testing
|
||||||
|
1 Information Gathering
|
||||||
|
2 Configuration and Deployment Management Testing
|
||||||
|
3 Identity Management Testing
|
||||||
|
4 Authentication Testing
|
||||||
|
5 Authorization Testing
|
||||||
|
6 Session Management Testing
|
||||||
|
7 Input Validation Testing
|
||||||
|
8 Testing for Error Handling
|
||||||
|
9 Testing for Weak Cryptography
|
||||||
|
10 Business Logic Testing
|
||||||
|
11 Client Side Testing
|
||||||
|
4) Web application security firewall
|
||||||
|
1 Information Gathering
|
||||||
|
2 Configuration and Deployment Management Testing
|
||||||
|
3 Identity Management Testing
|
||||||
|
4 Authentication Testing
|
||||||
|
5 Authorization Testing
|
||||||
|
6 Session Management Testing
|
||||||
|
7 Input Validation Testing
|
||||||
|
8 Testing for Error Handling
|
||||||
|
9 Testing for Weak Cryptography
|
||||||
|
10 Business Logic Testing
|
||||||
|
11 Client Side Testing
|
||||||
|
5) Conclusions
|
||||||
|
|
||||||
The deadline for the delivery of the assignment (configuration files and report) is May 3rd 2026.
|
3
|
||||||
|
|
||||||
•
|
6. Important/relevant aspects
|
||||||
|
The Web Application Security Testing document includes several sections, providing guidelines for testing. The guideline
|
||||||
Submission via Inforestudante.
|
applicable to this assignment is mainly in Section 4, which must be analysed carefully, since testing tools may be suggested in
|
||||||
|
each section.
|
||||||
|
The practical assignment targets black-box testing, which is according to OWASP in WSTG “the art of testing a system or
|
||||||
|
application remotely to find security vulnerabilities, without knowing the inner workings of the target itself”. Thus, in this
|
||||||
|
type of testing strategy we focus on tools such as web application security scanners, vulnerability scanners and penetration
|
||||||
|
testing software.
|
||||||
|
The following aspects are relevant in what respects the WSTG guidelines and structure:
|
||||||
|
1. Section 4.7 should be considered as a whole, which can be tested with OWASP ZAP or a similar tool. There are
|
||||||
|
some subsections, that do not apply in this assignment. For instance, the Juice Shop does not include any support
|
||||||
|
for LDAP, so subsection 4.7.6 – “Testing for LDAP injection” does not require any action/testing.
|
||||||
|
2. Section 4.11 should be considered as a whole, which can be tested with OWASP ZAP or a similar tool.
|
||||||
|
3. Section 4.9 should not be considered since communications with Juice Shop are not over HTTPS.
|
||||||
|
4. Section 4.10 should not be considered as well, as it is out of scope of this assignment.
|
||||||
|
5. Other subsections are out of scope of this assignment, and students should identify these in the report (and explain
|
||||||
|
why). For instance. subsection 4.2.9, 4.2.10 and 4.2.11 are not applicable in this assignment.
|
||||||
|
Regarding the second phase of the work, with the Web Application Firewall, the following aspects should be considered:
|
||||||
|
1. The main goal of the project in the second phase is to enable detection and prevention of the issues identified in the
|
||||||
|
first phase. Nonetheless, all the detection and prevention actions must be possible using Apache and ModSecurity
|
||||||
|
(with OWASP CRS), no other tools should be considered for this purpose.
|
||||||
|
2. The issues identified Section 4.3 of WSTG cannot be detected and solved with ModSecurity (with OWASP CRS),
|
||||||
|
so no action is required. ModSecurity is a WAF that operates at the HTTP level — it analyzes HTTP requests and
|
||||||
|
responses and blocks traffic based on patterns (malicious payloads, suspicious headers, etc.). Identity Management
|
||||||
|
issues are application logic flaws, not attacks with detectable patterns in HTTP traffic.
|
||||||
|
|
||||||
4
|
4
|
||||||
|
|
||||||
|
|||||||
BIN
relatorio.pdf
Normal file
BIN
relatorio/imgs/dir-fuzzing.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
relatorio/imgs/email-invalido.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
relatorio/imgs/email-unique.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
relatorio/imgs/ftp.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
relatorio/imgs/login-fuzzing.png
Normal file
|
After Width: | Height: | Size: 174 KiB |
BIN
relatorio/imgs/metrics.png
Normal file
|
After Width: | Height: | Size: 249 KiB |
BIN
relatorio/imgs/sqlmap.png
Normal file
|
After Width: | Height: | Size: 270 KiB |
BIN
relatorio/imgs/stack-trace.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
relatorio/imgs/suspiciouserrors.png
Normal file
|
After Width: | Height: | Size: 109 KiB |
BIN
relatorio/imgs/suspiciouserrors2.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
relatorio/imgs/swagger.png
Normal file
|
After Width: | Height: | Size: 113 KiB |
|
After Width: | Height: | Size: 2.0 MiB |
@@ -6,19 +6,47 @@
|
|||||||
\providecommand\HyField@AuxAddToFields[1]{}
|
\providecommand\HyField@AuxAddToFields[1]{}
|
||||||
\providecommand\HyField@AuxAddToCoFields[2]{}
|
\providecommand\HyField@AuxAddToCoFields[2]{}
|
||||||
\babel@aux{portuguese}{}
|
\babel@aux{portuguese}{}
|
||||||
\def\@LN@column{1}
|
\@writefile{toc}{\contentsline {section}{\numberline {1}Introduction}{3}{section.1}\protected@file@percent }
|
||||||
\@writefile{toc}{\contentsline {section}{\numberline {1}Introdução}{2}{section.1}\protected@file@percent }
|
\@writefile{toc}{\contentsline {section}{\numberline {2}Architecture Considered for Both Stages}{3}{section.2}\protected@file@percent }
|
||||||
\@writefile{toc}{\contentsline {section}{\numberline {2}Criação de certificados}{2}{section.2}\protected@file@percent }
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Network structure}{3}{subsection.2.1}\protected@file@percent }
|
||||||
\def\@LN@column{1}
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Servers}{3}{subsection.2.2}\protected@file@percent }
|
||||||
\@writefile{toc}{\contentsline {section}{\numberline {3}Configuração geral}{3}{section.3}\protected@file@percent }
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3}Services}{3}{subsection.2.3}\protected@file@percent }
|
||||||
\@writefile{toc}{\contentsline {section}{\numberline {4}Configuração da \textit {Gateway} VPN}{3}{section.4}\protected@file@percent }
|
\@writefile{toc}{\contentsline {section}{\numberline {3}Web application security testing}{4}{section.3}\protected@file@percent }
|
||||||
\@writefile{toc}{\contentsline {subsection}{\numberline {4.1}Configurar TOTP}{3}{subsection.4.1}\protected@file@percent }
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.1}Information Gathering}{4}{subsection.3.1}\protected@file@percent }
|
||||||
\def\@LN@column{1}
|
\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces ftp}}{4}{figure.1}\protected@file@percent }
|
||||||
\@writefile{toc}{\contentsline {subsection}{\numberline {4.2}Encaminhamento e Firewall}{4}{subsection.4.2}\protected@file@percent }
|
\newlabel{fig:ftp}{{1}{4}{ftp}{figure.1}{}}
|
||||||
\@writefile{toc}{\contentsline {section}{\numberline {5}Configuração do Cliente (Road Warrior)}{4}{section.5}\protected@file@percent }
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2}Configuration and Deployment Management Testing}{4}{subsection.3.2}\protected@file@percent }
|
||||||
\def\@LN@column{1}
|
\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces metrics}}{5}{figure.2}\protected@file@percent }
|
||||||
\@writefile{toc}{\contentsline {section}{\numberline {6}Servidor Apache e OCSP}{5}{section.6}\protected@file@percent }
|
\newlabel{fig:metrics}{{2}{5}{metrics}{figure.2}{}}
|
||||||
\@writefile{toc}{\contentsline {subsection}{\numberline {6.1}Revocation e OCSP}{5}{subsection.6.1}\protected@file@percent }
|
\@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces swagger}}{5}{figure.3}\protected@file@percent }
|
||||||
\@writefile{toc}{\contentsline {section}{\numberline {7}Conclusão}{5}{section.7}\protected@file@percent }
|
\newlabel{fig:swagger}{{3}{5}{swagger}{figure.3}{}}
|
||||||
\xdef \mintedoldcachechecksum{\detokenize{\minted@cachechecksum }}
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3}Identity Management Testing}{6}{subsection.3.3}\protected@file@percent }
|
||||||
\gdef \@abspage@last{5}
|
\@writefile{lof}{\contentsline {figure}{\numberline {4}{\ignorespaces email-unique}}{7}{figure.4}\protected@file@percent }
|
||||||
|
\newlabel{fig:email-unique}{{4}{7}{email-unique}{figure.4}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.4}Authentication Testing}{7}{subsection.3.4}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.5}Authorization Testing}{7}{subsection.3.5}\protected@file@percent }
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {5}{\ignorespaces email-invalido}}{8}{figure.5}\protected@file@percent }
|
||||||
|
\newlabel{fig:email-invalido}{{5}{8}{email-invalido}{figure.5}{}}
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {6}{\ignorespaces suspiciouserrors}}{8}{figure.6}\protected@file@percent }
|
||||||
|
\newlabel{fig:suspiciouserrors}{{6}{8}{suspiciouserrors}{figure.6}{}}
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {7}{\ignorespaces suspiciouserrors2}}{9}{figure.7}\protected@file@percent }
|
||||||
|
\newlabel{fig:suspiciouserrors2}{{7}{9}{suspiciouserrors2}{figure.7}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.6}Session Management Testing}{9}{subsection.3.6}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.7}Input Validation Testing}{9}{subsection.3.7}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsubsection}{\numberline {3.7.1}Testing for SQL Injection}{10}{subsubsection.3.7.1}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.8}Testing for Error Handling}{10}{subsection.3.8}\protected@file@percent }
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {8}{\ignorespaces stack-trace}}{11}{figure.8}\protected@file@percent }
|
||||||
|
\newlabel{fig:stack-trace}{{8}{11}{stack-trace}{figure.8}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.9}Client Side Testing}{11}{subsection.3.9}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {4}Web Application Security Firewall}{11}{section.4}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {4.1}Information Gathering}{12}{subsection.4.1}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {4.2}Configuration and Deployment Management Testing}{12}{subsection.4.2}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {4.3}Identity Management Testing}{13}{subsection.4.3}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {4.4}Authentication Testing}{13}{subsection.4.4}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {4.5}Authorization Testing}{13}{subsection.4.5}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {4.6}Session Management Testing}{13}{subsection.4.6}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {4.7}Input Validation Testing}{13}{subsection.4.7}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {4.8}Testing for Error Handling}{14}{subsection.4.8}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {4.9}Client Side Testing}{14}{subsection.4.9}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {5}Conclusions}{14}{section.5}\protected@file@percent }
|
||||||
|
\gdef \@abspage@last{14}
|
||||||
|
|||||||
38
relatorio/relatorio.listing
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
SecRuleEngine On
|
||||||
|
SecRequestBodyAccess On
|
||||||
|
SecResponseBodyAccess On
|
||||||
|
SecDebugLog /var/log/modsecurity/debug.log
|
||||||
|
SecDebugLogLevel 0
|
||||||
|
SecAuditLogParts ABIJ
|
||||||
|
SecAuditLogType Serial
|
||||||
|
SecAuditLog /var/log/modsecurity/audit.log
|
||||||
|
|
||||||
|
# sql injection
|
||||||
|
SecRule REQUEST_URI|ARGS "['\";]|--" \
|
||||||
|
SecRule REQUEST_URI|ARGS "(?i:(?:select|insert|update|delete|drop|union|create|alter|truncate)\s+.+\s+from|'[^']*'|--|;|\b(or|and)\b\s+\d+\s*=\s*\d+)" \
|
||||||
|
"id:950001,phase:1,deny,status:403,msg:'SQL INJECTION ATTACK DETECTED!!!',log,t:urlDecode,t:sqlHexDecode,t:lowercase"
|
||||||
|
|
||||||
|
# xss / html injection
|
||||||
|
SecRule REQUEST_URI|ARGS "(<.*>)|(%3C.*%3E)" \
|
||||||
|
"id:950003,phase:1,deny,status:403,msg:'XSS/HTML INJECTION DETECTED!!!',log"
|
||||||
|
|
||||||
|
# command injection
|
||||||
|
SecRule ARGS "(\"role\".*:.*\"admin\")|exec|cat|more|ls|dir|/etc/passwd" \
|
||||||
|
"id:950006,phase:2,deny,status:403,msg:'COMMAND INJECTION DETECTED!!!',log"
|
||||||
|
|
||||||
|
# path traversal
|
||||||
|
SecRule REQUEST_URI|ARGS "\%00|\%2500|\.\./|ftp|metrics|api-docs" \
|
||||||
|
"id:950007,phase:2,deny,status:403,msg:'PATH TRAVERSAL ATTEMPT!!!',log"
|
||||||
|
|
||||||
|
# exposed stuff (redundante ?)
|
||||||
|
SecRule REQUEST_URI|ARGS "\%00|\%2500|ftp|metrics|api-docs" \
|
||||||
|
"id:950008,phase:2,deny,status:500,msg:'ATTEMPT TO ACCESS FTP, METRICS, API-DOCS!!!',log"
|
||||||
|
|
||||||
|
# rate limiting on login endpoint
|
||||||
|
# (max 5 requests per 30s per IP)
|
||||||
|
SecAction \
|
||||||
|
"id:950009,phase:1,initcol:ip=%{REMOTE_ADDR},pass,nolog"
|
||||||
|
SecRule REQUEST_URI "@streq /rest/user/login" \
|
||||||
|
"id:950010,phase:2,pass,nolog,setvar:ip.login_count=+1,expirevar:ip.login_count=30"
|
||||||
|
SecRule IP:LOGIN_COUNT "@gt 5" \
|
||||||
|
"id:950011,phase:2,deny,status:429,msg:'Rate Limit Exceeded on Login',log"
|
||||||
27
relatorio/relatorio.out
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
\BOOKMARK [1][-]{section.1}{\376\377\000I\000n\000t\000r\000o\000d\000u\000c\000t\000i\000o\000n}{}% 1
|
||||||
|
\BOOKMARK [1][-]{section.2}{\376\377\000A\000r\000c\000h\000i\000t\000e\000c\000t\000u\000r\000e\000\040\000C\000o\000n\000s\000i\000d\000e\000r\000e\000d\000\040\000f\000o\000r\000\040\000B\000o\000t\000h\000\040\000S\000t\000a\000g\000e\000s}{}% 2
|
||||||
|
\BOOKMARK [2][-]{subsection.2.1}{\376\377\000N\000e\000t\000w\000o\000r\000k\000\040\000s\000t\000r\000u\000c\000t\000u\000r\000e}{section.2}% 3
|
||||||
|
\BOOKMARK [2][-]{subsection.2.2}{\376\377\000S\000e\000r\000v\000e\000r\000s}{section.2}% 4
|
||||||
|
\BOOKMARK [2][-]{subsection.2.3}{\376\377\000S\000e\000r\000v\000i\000c\000e\000s}{section.2}% 5
|
||||||
|
\BOOKMARK [1][-]{section.3}{\376\377\000W\000e\000b\000\040\000a\000p\000p\000l\000i\000c\000a\000t\000i\000o\000n\000\040\000s\000e\000c\000u\000r\000i\000t\000y\000\040\000t\000e\000s\000t\000i\000n\000g}{}% 6
|
||||||
|
\BOOKMARK [2][-]{subsection.3.1}{\376\377\000I\000n\000f\000o\000r\000m\000a\000t\000i\000o\000n\000\040\000G\000a\000t\000h\000e\000r\000i\000n\000g}{section.3}% 7
|
||||||
|
\BOOKMARK [2][-]{subsection.3.2}{\376\377\000C\000o\000n\000f\000i\000g\000u\000r\000a\000t\000i\000o\000n\000\040\000a\000n\000d\000\040\000D\000e\000p\000l\000o\000y\000m\000e\000n\000t\000\040\000M\000a\000n\000a\000g\000e\000m\000e\000n\000t\000\040\000T\000e\000s\000t\000i\000n\000g}{section.3}% 8
|
||||||
|
\BOOKMARK [2][-]{subsection.3.3}{\376\377\000I\000d\000e\000n\000t\000i\000t\000y\000\040\000M\000a\000n\000a\000g\000e\000m\000e\000n\000t\000\040\000T\000e\000s\000t\000i\000n\000g}{section.3}% 9
|
||||||
|
\BOOKMARK [2][-]{subsection.3.4}{\376\377\000A\000u\000t\000h\000e\000n\000t\000i\000c\000a\000t\000i\000o\000n\000\040\000T\000e\000s\000t\000i\000n\000g}{section.3}% 10
|
||||||
|
\BOOKMARK [2][-]{subsection.3.5}{\376\377\000A\000u\000t\000h\000o\000r\000i\000z\000a\000t\000i\000o\000n\000\040\000T\000e\000s\000t\000i\000n\000g}{section.3}% 11
|
||||||
|
\BOOKMARK [2][-]{subsection.3.6}{\376\377\000S\000e\000s\000s\000i\000o\000n\000\040\000M\000a\000n\000a\000g\000e\000m\000e\000n\000t\000\040\000T\000e\000s\000t\000i\000n\000g}{section.3}% 12
|
||||||
|
\BOOKMARK [2][-]{subsection.3.7}{\376\377\000I\000n\000p\000u\000t\000\040\000V\000a\000l\000i\000d\000a\000t\000i\000o\000n\000\040\000T\000e\000s\000t\000i\000n\000g}{section.3}% 13
|
||||||
|
\BOOKMARK [3][-]{subsubsection.3.7.1}{\376\377\000T\000e\000s\000t\000i\000n\000g\000\040\000f\000o\000r\000\040\000S\000Q\000L\000\040\000I\000n\000j\000e\000c\000t\000i\000o\000n}{subsection.3.7}% 14
|
||||||
|
\BOOKMARK [2][-]{subsection.3.8}{\376\377\000T\000e\000s\000t\000i\000n\000g\000\040\000f\000o\000r\000\040\000E\000r\000r\000o\000r\000\040\000H\000a\000n\000d\000l\000i\000n\000g}{section.3}% 15
|
||||||
|
\BOOKMARK [2][-]{subsection.3.9}{\376\377\000C\000l\000i\000e\000n\000t\000\040\000S\000i\000d\000e\000\040\000T\000e\000s\000t\000i\000n\000g}{section.3}% 16
|
||||||
|
\BOOKMARK [1][-]{section.4}{\376\377\000W\000e\000b\000\040\000A\000p\000p\000l\000i\000c\000a\000t\000i\000o\000n\000\040\000S\000e\000c\000u\000r\000i\000t\000y\000\040\000F\000i\000r\000e\000w\000a\000l\000l}{}% 17
|
||||||
|
\BOOKMARK [2][-]{subsection.4.1}{\376\377\000I\000n\000f\000o\000r\000m\000a\000t\000i\000o\000n\000\040\000G\000a\000t\000h\000e\000r\000i\000n\000g}{section.4}% 18
|
||||||
|
\BOOKMARK [2][-]{subsection.4.2}{\376\377\000C\000o\000n\000f\000i\000g\000u\000r\000a\000t\000i\000o\000n\000\040\000a\000n\000d\000\040\000D\000e\000p\000l\000o\000y\000m\000e\000n\000t\000\040\000M\000a\000n\000a\000g\000e\000m\000e\000n\000t\000\040\000T\000e\000s\000t\000i\000n\000g}{section.4}% 19
|
||||||
|
\BOOKMARK [2][-]{subsection.4.3}{\376\377\000I\000d\000e\000n\000t\000i\000t\000y\000\040\000M\000a\000n\000a\000g\000e\000m\000e\000n\000t\000\040\000T\000e\000s\000t\000i\000n\000g}{section.4}% 20
|
||||||
|
\BOOKMARK [2][-]{subsection.4.4}{\376\377\000A\000u\000t\000h\000e\000n\000t\000i\000c\000a\000t\000i\000o\000n\000\040\000T\000e\000s\000t\000i\000n\000g}{section.4}% 21
|
||||||
|
\BOOKMARK [2][-]{subsection.4.5}{\376\377\000A\000u\000t\000h\000o\000r\000i\000z\000a\000t\000i\000o\000n\000\040\000T\000e\000s\000t\000i\000n\000g}{section.4}% 22
|
||||||
|
\BOOKMARK [2][-]{subsection.4.6}{\376\377\000S\000e\000s\000s\000i\000o\000n\000\040\000M\000a\000n\000a\000g\000e\000m\000e\000n\000t\000\040\000T\000e\000s\000t\000i\000n\000g}{section.4}% 23
|
||||||
|
\BOOKMARK [2][-]{subsection.4.7}{\376\377\000I\000n\000p\000u\000t\000\040\000V\000a\000l\000i\000d\000a\000t\000i\000o\000n\000\040\000T\000e\000s\000t\000i\000n\000g}{section.4}% 24
|
||||||
|
\BOOKMARK [2][-]{subsection.4.8}{\376\377\000T\000e\000s\000t\000i\000n\000g\000\040\000f\000o\000r\000\040\000E\000r\000r\000o\000r\000\040\000H\000a\000n\000d\000l\000i\000n\000g}{section.4}% 25
|
||||||
|
\BOOKMARK [2][-]{subsection.4.9}{\376\377\000C\000l\000i\000e\000n\000t\000\040\000S\000i\000d\000e\000\040\000T\000e\000s\000t\000i\000n\000g}{section.4}% 26
|
||||||
|
\BOOKMARK [1][-]{section.5}{\376\377\000C\000o\000n\000c\000l\000u\000s\000i\000o\000n\000s}{}% 27
|
||||||
@@ -1,31 +1,12 @@
|
|||||||
\documentclass[11pt,a4paper]{article}
|
\documentclass[11pt,a4paper]{article}
|
||||||
\usepackage[portuguese]{babel}
|
\usepackage[portuguese]{babel}
|
||||||
\usepackage[lining]{ebgaramond}
|
\usepackage[lining]{ebgaramond}
|
||||||
\usepackage{listings}
|
|
||||||
\usepackage{booktabs}
|
|
||||||
|
|
||||||
\usepackage{style}
|
\usepackage{style}
|
||||||
|
|
||||||
\lstdefinestyle{mystyle}{
|
|
||||||
basicstyle=\ttfamily\footnotesize,
|
|
||||||
breakatwhitespace=false,
|
|
||||||
breaklines=true,
|
|
||||||
captionpos=b,
|
|
||||||
keepspaces=true,
|
|
||||||
numbers=left,
|
|
||||||
numbersep=5pt,
|
|
||||||
showspaces=false,
|
|
||||||
showstringspaces=false,
|
|
||||||
showtabs=false,
|
|
||||||
tabsize=2
|
|
||||||
}
|
|
||||||
|
|
||||||
\lstset{style=mystyle}
|
|
||||||
|
|
||||||
\setlength{\parindent}{0em}
|
\setlength{\parindent}{0em}
|
||||||
\setlength{\parskip}{2ex}
|
\setlength{\parskip}{2ex}
|
||||||
|
|
||||||
\title{Practical Assignment \#2}
|
\title{Practical Assignment \#3}
|
||||||
\author{
|
\author{
|
||||||
João Neto -- 2023234004\\[1em]
|
João Neto -- 2023234004\\[1em]
|
||||||
Vasco Alves -- 2022228207
|
Vasco Alves -- 2022228207
|
||||||
@@ -33,224 +14,514 @@
|
|||||||
|
|
||||||
\begin{document}
|
\begin{document}
|
||||||
\maketitle
|
\maketitle
|
||||||
|
|
||||||
|
\newpage
|
||||||
\tableofcontents
|
\tableofcontents
|
||||||
|
|
||||||
\newpage
|
\newpage
|
||||||
|
|
||||||
\section{Introdução}
|
\section{Introduction}
|
||||||
|
|
||||||
Este projeto tem como âmbito implementar, uma rede virtual privada (VPN) num cenário
|
% FAZER EM ENGLISH??? O prof é BR temos que fazer em Brazileiro
|
||||||
de road-warrior, configurar \textit{two-factor authentication} (2FA) com os serviços
|
|
||||||
OpenVPN e Apache, e gerir certificados X.509 utilizando OCSP.
|
|
||||||
|
|
||||||
% NOTE(vasco): Eu acho que basta explicar o cenario e explicar como decidimos
|
Este trabalho tem como objetivo realizar testes de penetração numa aplicação
|
||||||
% implementar <- yeah agree, also esta introdução acho que é boa fala sobre o objetivo
|
cobaia (o \textit{Juicebox}) desenhada para aprendizagem.
|
||||||
% e o cenario, e porque é que o nosso cenario é como é. Não sei se a parte das razões de
|
|
||||||
%segurança devia estar nesta parte ou na conclusão como perpetiva futura e reflexão, mas aqui
|
|
||||||
%também não está mal.
|
|
||||||
|
|
||||||
% Para tal, foi implementado um servidor e um cliente OpenVPN, certificados por uma
|
Este trabalho tem como objetivo utilizar o \textbf{WSTG} (Web security
|
||||||
% autoridade central (CA) que em si é \textit{self-signed}. Para além disto, foi implementado
|
testing guide) e configurar um ModSecurity reverse proxy como uma
|
||||||
% um sistema de autenticação de dois factores através do plugin
|
\textbf{WAF}. Para esse fim temos uma aplicação cobaia (o \textit{Juicebox})
|
||||||
% \textit{google-authenticator} para o OpenVPN e para o servidor de Apache.
|
desenhada para aprendizagem que vamos utilizar num ambiente controlado
|
||||||
|
para aprender como descobrir vulnerabilidades (aplicando o \textbf{WSTG}
|
||||||
|
e recorrendo ao \textbf{OWASP ZAP}) e prevenir antes do serviço estar
|
||||||
|
online (elaborando uma \textbf{WAF}).
|
||||||
|
|
||||||
Decidimos utilizar apenas três máquinas virtuais: o cliente (ou \textit{road warrior}),
|
\section{Architecture Considered for Both Stages}
|
||||||
a \textit{gateway} que utiliza OpenVPN e um servidor interno com OpenSSL e Apache.
|
|
||||||
Isto simplifica a elaboração do projecto, mas por razões de segurança poderia querer
|
|
||||||
separar a máquina de OpenSSL de outras máquinas destinadas a serviços da rede intera,
|
|
||||||
pois esta contém o \textit{certificate authority} CA.
|
|
||||||
|
|
||||||
% Ambos o OpenVPN eo servidor Apache utilizam 2FA,
|
Utilizámos somente duas máquinas virtuais: um servidor a correr \textit{CentOS 9}
|
||||||
% recebendo o utilizador, e uma password que é uma concatenação da palavra-passe do utilizador
|
e um cliente a correr \textit{Kali Linux}. O servidor contém o serviço \textit{Apache},
|
||||||
% e de uma password temporária (TOTP) de 6 dígitos. O servidor de Apache implementa a mesma autenticação.
|
que age como \textit{firewall} através do módulo \textit{ModSecurity}, e um servidor
|
||||||
|
\textit{Node.js} que aloja o \textit{Juicebox} --- a aplicação que vai
|
||||||
|
servir de cobaia (\textit{dummy}).
|
||||||
|
|
||||||
\begin{tabular}{l l l}
|
% Vão ser realizadas duas etapas de testes: primeiro, sem WAF (\textit{Web Application Firewall})
|
||||||
|
% e com foco em explorar vulnerabilidades na aplicação; e, posteriormente, com uma WAF configurada para
|
||||||
|
% mitigar as várias vulnerabilidades que foram encontradas na etapa anterior.
|
||||||
|
|
||||||
{\bf Nome} & {\bf Script} & {\bf Rede} \\\toprule
|
% Para simular utilizámos \textit{Virtual Box}, como nos outros projetos, para criar as maquinas virtuais. O cenario que foi criado tem duas máquinas virtuais (servidor e cliente), e ambas as maquinas estão ligadas há mesma rede interna. O servidor vai ser executado numa das maquinas e vai ter o sistema operativo \textit{CentOS 9}, edereço 20.60.0.1, alojar um servidor \textit{Node.js} com o \textit{Juicebox} (a aplicação cobaia) na port 3000 e contém o seviço \textit{Apache} que através do módulo \textit{ModSecurity} funcionará como \textbf{WAF}. O cliente vai ser processado na maquina com o sistema operativo \textit{Kali Linux} e vai ter o edereço 20.60.0.2.
|
||||||
Road Warrior & VM\_ROAD\_WARRIOR.sh & Rede Externa 193.168.0.0/24 \\
|
|
||||||
VPN Gateway & VM\_OPENVPN\_GATEWAY.sh & Router \\
|
Com o ambiente criado foram realizadas duas etapas de testes:
|
||||||
OpenSSL / Apache & VM\_OPENSSL\_APACHE.sh & Rede Interna 10.60.0.0/24 \\
|
\begin{itemize}
|
||||||
|
\item \texttt{Primeira etapa}: Explorar vulnerabilidades na aplicação que existem sem a \textbf{WAF}
|
||||||
|
\item \texttt{Segunda etapa}:Verificar que vulnerabilidades foram mitigadas da primeira etapa com o uso de uma \textbf{WAF} configurada.
|
||||||
|
\end{itemize}
|
||||||
|
Realisticamente estas etapas podiam continuar a repetir-se, até que
|
||||||
|
estivessemos satisfeitos com o resultado, mas para o fim deste projeto
|
||||||
|
estas etapas serão suficientes.
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Network structure}
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Client (20.60.0.0/24)} Cliente.
|
||||||
|
\item \textbf{Server (10.60.0.0/24)} Apache+ModSecurity e JuiceShop.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Servers}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{10.60.0.1} Servidor CentOS 9 com WAF e aplicação JuiceShop.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\subsection{Services}
|
||||||
|
\begin{center}
|
||||||
|
\begin{tabular}{ll}
|
||||||
|
\toprule
|
||||||
|
Service & Port \\\midrule
|
||||||
|
NodeJS (JuiceShop) & 3000 \\
|
||||||
|
Apache (WAF) & 80 \\
|
||||||
|
\bottomrule
|
||||||
\end{tabular}
|
\end{tabular}
|
||||||
|
\end{center}
|
||||||
|
\section{Web application security testing}
|
||||||
|
|
||||||
\section{Criação de certificados}
|
\subsection{Information Gathering}
|
||||||
|
|
||||||
Os certificados utilizados foram auto-certificados por uma autoridade central que "pertence"
|
Utilizámos a política por omissão (\textit{default policy}) para a
|
||||||
à máquina de OpenSSL. Esta mesma faz a gestão da lista de revogação.
|
realização do \textit{Active Scan} através do OWASP ZAP. Com esta
|
||||||
|
abordagem, obtivemos múltiplos alertas automáticos. De forma a priorizar
|
||||||
|
a análise, investigamos as alertas principais com base no maior nível de
|
||||||
|
risco e grau de confiança reportados pela ferramenta.
|
||||||
|
|
||||||
Todas as chaves foram criadas no mesmo computador, com as variáveis que estão
|
% Para conseguir informação inicial realizamos um \textit{Active Scan} através do \textit{OWASP ZAP}, o policy utilizado para esse scan foi \textit{Default Policy}. Foi obtido vários aletas automáticos devido a esse scan e decidimos investigar as alertas principais com base no nível de risco e grau de confiança reportado pela ferramenta.
|
||||||
neste código, aspetos importantes para mais tarde serão os parâmetros de CN
|
|
||||||
que precisam de ser passados mais tarde para aceder ao Apache e ao gateway.
|
|
||||||
Numa situação normal teríamos uma autoridade de certificação para enviar e
|
|
||||||
no fundo gerir todos, mas para este cenário podemos inicializar as máquinas
|
|
||||||
com as chaves, requests e certificados necessários.
|
|
||||||
|
|
||||||
O código para gerar os certificados X.509:
|
Adicionalmente, realizámos testes de infraestrutura utilizando ferramentas especializadas:
|
||||||
|
|
||||||
\begin{lstlisting}[language=bash]
|
\begin{codeblock}{bash}
|
||||||
cert_ca="/C=PT/ST=Coimbra/L=Coimbra/O=UC/CN=CoimbraVPN"
|
sqlmap -u "http://192.168.1.1:3000/rest/products/search?q=apple" -p q --level=5 --risk=3 --banner
|
||||||
cert_vpn="/C=PT/ST=Coimbra/L=Coimbra/O=UC/CN=gateway"
|
\end{codeblock}
|
||||||
cert_user="/C=PT/ST=Coimbra/L=Coimbra/O=UC/CN=warrior"
|
|
||||||
cert_apache="/C=PT/ST=Coimbra/L=Coimbra/O=UC/CN=apache.coimbra"
|
|
||||||
|
|
||||||
openssl genrsa -out "ca.key" 2048
|
Ao executar o \textit{sqlmap}, descobrimos que o sistema de gestão de
|
||||||
openssl req -x509 -nodes -days 365 -key "ca.key" -out "ca.crt" -subj "$cert_ca"
|
base de dados subjacente é o \textit{SQLite}.
|
||||||
openssl genrsa -out "vpn.key" 2048
|
|
||||||
openssl req -new -key "vpn.key" -out "vpn.csr" -subj "$cert_vpn"
|
|
||||||
openssl ca -batch -in "vpn.csr" -cert "ca.crt" -keyfile "ca.key" -out "vpn.crt" -config cheese.cfg
|
|
||||||
openssl dhparam -out "dh2048.pem" 2048
|
|
||||||
openvpn --genkey secret "ta.key"
|
|
||||||
openssl genrsa -out user.key
|
|
||||||
openssl req -new -key user.key -out user.csr -subj "$cert_user"
|
|
||||||
openssl ca -batch -in "user.csr" -cert "ca.crt" -keyfile "ca.key" -out "user.crt" -config cheese.cfg
|
|
||||||
openssl genrsa -out apache.key
|
|
||||||
openssl req -new -key apache.key -out apache.csr -subj "$cert_apache" -addext "subjectAltName = IP:10.60.0.1,DNS:apache"
|
|
||||||
openssl ca -batch -in "apache.csr" -cert "ca.crt" -keyfile "ca.key" -out "apache.crt" -config cheese.cfg
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
% Porque é que precisamos de uma chave secreta?
|
Paralelamente, realizámos uma descoberta de ficheiros e diretórios
|
||||||
% Criar chave secreta.
|
através de técnicas de \textit{fuzzing} de URLs no OWASP ZAP recorrendo
|
||||||
|
à lista de permissões da \textit{DirBuster}. Esta exploração revelou os
|
||||||
|
seguintes endpoints publicamente expostos:
|
||||||
|
|
||||||
\begin{lstlisting}[language=bash]
|
\begin{itemize}
|
||||||
openssl --genkey secret ta.key
|
\item \texttt{/ftp}: Servidor de armazenamento e transferência de ficheiros exposto. (Figura \ref{fig:ftp})
|
||||||
\end{lstlisting}
|
\item \texttt{/metrics}: Métricas internas da infraestrutura expostas. (Figura \ref{fig:metrics})
|
||||||
\section{Configuração geral}
|
\item \texttt{/api-docs}: Documentação e esquemas estruturais da API. (Figura \ref{fig:swagger})
|
||||||
Para configurar as VMs era preciso introduzir os mesmos comandos várias vezes, o que levava muitas vezes a erros de escrita, ou a correr o mesmo comando várias vezes, por isso criamos vários ficheiros .sh para conseguir facilitar o processo. A utilização de ficheiros .sh também vem com outros positivos pois facilita a testagem, e a recriação do cenário rapidamente.
|
\end{itemize}
|
||||||
|
|
||||||
No entanto para os serviços que configuramos, instalar, desativar e dar flush às iptables não foi suficiente, tivemos que criar pastas e sincronizar os relógios de todas as VMs visto que elas estarem ligeiramente atrasadas nunca conseguíamos acertar na password do google-authenticator que utiliza o tempo local para calcular a sua chave.
|
\begin{figure}[h!]
|
||||||
\begin{lstlisting}[language=bash]
|
|
||||||
yum install -y epel-release
|
|
||||||
yum install -y openvpn iptables-services dhcp-client
|
|
||||||
systemctl stop firewalld
|
|
||||||
systemctl disable firewalld
|
|
||||||
systemctl mask firewalld
|
|
||||||
systemctl enable iptables
|
|
||||||
iptables -F
|
|
||||||
|
|
||||||
CA_DIR="/etc/pki/CA"
|
|
||||||
mkdir -p "${CA_DIR}/newcerts"
|
|
||||||
mkdir -p "${CA_DIR}/private"
|
|
||||||
touch "${CA_DIR}/index.txt"
|
|
||||||
cp ca/serial "${CA_DIR}/serial"
|
|
||||||
|
|
||||||
mkdir -p /etc/openvpn/server
|
|
||||||
mkdir -p /etc/openvpn/client
|
|
||||||
|
|
||||||
# NOTE(vasco): tive problemas com a sincronizacao de tempo
|
|
||||||
# se nao tiver sincronizado, o TOTP nao funciona
|
|
||||||
systemctl stop chronyd
|
|
||||||
ntpdate pool.ntp.org
|
|
||||||
systemctl start chronyd
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
\subsection{Configurar TOTP}
|
|
||||||
|
|
||||||
Foi criado o ficheiro \texttt{totp} com a configuração de autenticação a
|
|
||||||
ser utilizada pelo plugin de PAM para o openvpn.
|
|
||||||
|
|
||||||
\begin{lstlisting}[language=bash]
|
|
||||||
plugin /usr/lib64/openvpn/plugins/openvpn-plugin-auth-pam.so totp
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
Adicionalmente, devido às restrições de segurança do \textit{systemd},
|
|
||||||
foi necessário desativar o \texttt{ProtectHome} no serviço do OpenVPN
|
|
||||||
para que o plugin PAM consiga ler os ficheiros de segredo do Google Authenticator
|
|
||||||
localizados nas diretorias \textit{home} dos utilizadores.
|
|
||||||
|
|
||||||
\begin{lstlisting}[language=bash]
|
|
||||||
[Service]
|
|
||||||
ProtectHome=false
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
Primeiro, na gateway, entramos como o utilizador desejado e obtemos a chave
|
|
||||||
do gerador de palavras passes temporárias. Ao inserir a chave no
|
|
||||||
\texttt{google authenticator} podemos obter um código QR, a nossa primeira
|
|
||||||
chave de 6 dígitos.
|
|
||||||
|
|
||||||
\begin{figure}[h]
|
|
||||||
\centering
|
\centering
|
||||||
\includegraphics[width=8em]{google-authenticator}
|
\includegraphics[width=\textwidth]{ftp}
|
||||||
|
\caption{ftp}
|
||||||
|
\label{fig:ftp}
|
||||||
|
\end{figure}
|
||||||
|
\begin{figure}[h!]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=\textwidth]{metrics}
|
||||||
|
\caption{metrics}
|
||||||
|
\label{fig:metrics}
|
||||||
|
\end{figure}
|
||||||
|
\begin{figure}[h!]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=\textwidth]{swagger}
|
||||||
|
\caption{swagger}
|
||||||
|
\label{fig:swagger}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
\begin{lstlisting}[language=bash]
|
|
||||||
su john
|
|
||||||
google-authenticator
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
\subsection{Encaminhamento e Firewall}
|
|
||||||
|
|
||||||
Para que a gateway funcione como router entre a rede externa e a rede interna,
|
\subsection{Configuration and Deployment Management Testing}
|
||||||
foi necessário ativar o \textit{IP forwarding} no kernel e configurar as regras
|
|
||||||
de \textit{iptables} para permitir o tráfego da VPN e realizar o mascaramento
|
|
||||||
de IP (NAT).
|
|
||||||
|
|
||||||
% NOTA(vasco): Não temos regras de DROP a packets
|
\subsubsection*{Enumerate Infrastructure and Application Admin Interfaces}
|
||||||
% talvez deviamos mudar isso nao sei <- não diz nada no enunciado ¯\_(ツ)_/¯
|
|
||||||
% também o trabalho não é sobre ip tables por isso it does make sense não fazer drop
|
|
||||||
%e utilizar as regras apenas para encaminhar corretamente.
|
|
||||||
% Colocar isso na conclusão tho
|
|
||||||
|
|
||||||
\begin{lstlisting}[language=bash]
|
Identificámos e testámos o acesso ao endpoint \texttt{/api-docs}
|
||||||
# Ativar encaminhamento
|
(\textit{Swagger UI}), validando que as interfaces de documentação
|
||||||
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
|
interna do sistema e as definições da API estavam publicamente expostas
|
||||||
sysctl -p /etc/sysctl.conf
|
sem qualquer tipo de controlo de acesso ou autenticação prévia.
|
||||||
|
|
||||||
# Regras de Firewall
|
\subsubsection*{Test HTTP Methods}
|
||||||
iptables -I INPUT 1 -p udp --dport 1194 -j ACCEPT
|
|
||||||
iptables -I FORWARD 1 -i tun0 -o enp0s9 -j ACCEPT
|
|
||||||
iptables -I FORWARD 1 -i enp0s9 -o tun0 -j ACCEPT
|
|
||||||
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o enp0s8 -j MASQUERADE
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
\section{Configuração do Cliente (Road Warrior)}
|
Testámos os métodos HTTP permitidos pelo servidor através do envio de
|
||||||
|
pedidos \texttt{OPTIONS}. Verificámos que o servidor aceita métodos
|
||||||
|
potencialmente perigosos ou desnecessários para utilizadores comuns em
|
||||||
|
rotas específicas, expandindo a superfície de ataque da aplicação.
|
||||||
|
|
||||||
O cliente encontra-se na rede externa (\texttt{193.136.212.10}) e liga-se à VPN
|
\subsubsection*{Test File Permission}
|
||||||
gateway na porta 1194. Para garantir a segurança, utilizamos autenticação mútua (os certificados X.509)
|
|
||||||
e um \textit{two factor authentication} (2FA) como palavras-passe temporárias, geradas através do
|
|
||||||
\textit{Google Authenticator}.
|
|
||||||
|
|
||||||
\begin{lstlisting}[language=bash]
|
Analisámos as permissões de acesso no diretório \texttt{/ftp}.
|
||||||
client
|
Verificámos que a falta de restrições rígidas ao nível do sistema de
|
||||||
dev tun
|
ficheiros permite a qualquer utilizador anónimo listar o conteúdo de
|
||||||
proto udp
|
diretórios estruturais e descarregar ficheiros não indexados na
|
||||||
remote 193.136.212.1 1194
|
interface principal da aplicação.
|
||||||
ca ca.crt
|
|
||||||
cert user.crt
|
|
||||||
key user.key
|
|
||||||
auth-user-pass
|
|
||||||
cipher AES-256-GCM
|
|
||||||
auth SHA256
|
|
||||||
\end{lstlisting}
|
|
||||||
|
|
||||||
\section{Servidor Apache e OCSP}
|
|
||||||
|
|
||||||
O servidor interno (\texttt{10.60.0.1}) alberga o serviço Apache e o responder OCSP
|
|
||||||
da autoridade de certificação.
|
|
||||||
|
|
||||||
\subsection{Revocation e OCSP}
|
\subsection{Identity Management Testing}
|
||||||
|
|
||||||
|
\subsubsection*{Test Role Definitions}
|
||||||
|
|
||||||
|
Efetuámos testes de manipulação de parâmetros do lado do cliente através
|
||||||
|
das ferramentas de programador do navegador. Adicionámos manualmente os
|
||||||
|
cookies \texttt{isAdmin} com o valor \texttt{true} e \texttt{role} com o
|
||||||
|
valor \texttt{admin}. Após a atualização da página, não observámos
|
||||||
|
qualquer escalonamento de privilégios, indicando que a aplicação não
|
||||||
|
valida perfis administrativos com base nestes cookies específicos.
|
||||||
|
|
||||||
|
\subsubsection*{Test User Registration Process}
|
||||||
|
|
||||||
|
Utilizámos o OWASP ZAP para intercetar o tráfego de rede e definir um
|
||||||
|
\textit{breakpoint} no pedido HTTP POST de registo de novos utilizadores.
|
||||||
|
Modificámos o corpo do pedido JSON, injetando manualmente o parâmetro
|
||||||
|
\texttt{"role":"admin"}:
|
||||||
|
|
||||||
|
\begin{codeblock}{json}
|
||||||
|
{
|
||||||
|
"email": "johnGomas@gmail.com",
|
||||||
|
"role": "admin",
|
||||||
|
"password": "password",
|
||||||
|
"passwordRepeat": "password",
|
||||||
|
"securityQuestion": {
|
||||||
|
"id": 2,
|
||||||
|
"question": "Mother's maiden name?",
|
||||||
|
"createdAt": "2026-05-30T12:28:33.216Z",
|
||||||
|
"updatedAt": "2026-05-30T12:28:33.216Z"
|
||||||
|
},
|
||||||
|
"securityAnswer": "poker"
|
||||||
|
}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
O servidor backend processou o pedido sem validar se o utilizador
|
||||||
|
possuía autorização para definir o seu próprio perfil, o que resultou
|
||||||
|
na criação bem-sucedida de uma conta com permissões totais de
|
||||||
|
administrador (\textit{Mass Assignment Vulnerability}).
|
||||||
|
|
||||||
|
\subsubsection*{Testing for Account Enumeration and Guessable User Account}
|
||||||
|
|
||||||
|
Ao tentar registar um utilizador com o e-mail
|
||||||
|
\texttt{admin@juice-sh.op}, verificámos que a aplicação devolve uma
|
||||||
|
mensagem de erro explícita indicando que o e-mail já se encontra
|
||||||
|
registado no sistema. Este comportamento confirma a vulnerabilidade de
|
||||||
|
enumeração de contas, permitindo a um atacante mapear quais os e-mails
|
||||||
|
válidos na plataforma.
|
||||||
|
|
||||||
|
\begin{figure}[h!]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.7\textwidth]{email-unique}
|
||||||
|
\caption{email-unique}
|
||||||
|
\label{fig:email-unique}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\subsubsection*{Testing for Weak or Unenforced Username Policy}
|
||||||
|
|
||||||
|
Após testar vários caracteres especiais no formulário de registo,
|
||||||
|
criámos um utilizador com os seguintes dados nos campos de input:
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{E-mail:} \texttt{son'or1=1--@gmail.com}
|
||||||
|
\item \textbf{Nome/Campos Adicionais:} \texttt{<h1>STRONG}
|
||||||
|
\end{itemize}
|
||||||
|
A aplicação aceitou o registo sem validar a presença de carateres de
|
||||||
|
injeção SQL ou tags HTML. Contudo, verificámos que é impossível efetuar
|
||||||
|
login com esta conta posteriormente, uma vez que o processo de
|
||||||
|
autenticação falha e resulta num erro genérico do tipo
|
||||||
|
\texttt{[object Object]} no ecrã.
|
||||||
|
|
||||||
|
\begin{figure}[h!]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.7\textwidth]{email-invalido}
|
||||||
|
\caption{email-invalido}
|
||||||
|
\label{fig:email-invalido}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\subsection{Authentication Testing}
|
||||||
|
|
||||||
|
Realizámos testes de \textit{fuzzing} automatizado contra o formulário
|
||||||
|
de login utilizando dicionários de credenciais. Identificámos que a
|
||||||
|
aplicação não implementa mecanismos de bloqueio de conta ou limitação
|
||||||
|
de taxa de pedidos \textit{rate limiting}, permitindo ataques contínuos
|
||||||
|
de \textit{brute force}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Authorization Testing}
|
||||||
|
|
||||||
|
Testámos as permissões de acesso ao diretório \texttt{/ftp} e
|
||||||
|
verificámos que o servidor está configurado para permitir nativamente
|
||||||
|
apenas a visualização de ficheiros com as extensões \texttt{.md} e
|
||||||
|
\texttt{.pdf}.
|
||||||
|
|
||||||
|
Seguidamente, explorámos falhas na validação de inputs através de uma
|
||||||
|
injeção de \textit{Null Byte} codificado (\texttt{\%2500.md} ou
|
||||||
|
\texttt{\%2500.pdf}). O ataque foi bem-sucedido e contornou a validação
|
||||||
|
de extensões do servidor, garantindo o acesso e descarregamento de
|
||||||
|
ficheiros confidenciais restritos: \texttt{encrypt.pyc} e
|
||||||
|
\texttt{suspicious\_errors.yml}.
|
||||||
|
|
||||||
|
\begin{figure}[h!]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.7\textwidth]{suspiciouserrors}
|
||||||
|
\caption{suspiciouserrors}
|
||||||
|
\label{fig:suspiciouserrors}
|
||||||
|
\end{figure}
|
||||||
|
\begin{figure}[h!]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.7\textwidth]{suspiciouserrors2}
|
||||||
|
\caption{suspiciouserrors2}
|
||||||
|
\label{fig:suspiciouserrors2}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\subsection{Session Management Testing}
|
||||||
|
|
||||||
|
Identificámos que o cookie \texttt{token}, responsável por armazenar o
|
||||||
|
identificador da sessão ativa do utilizador, possui a flag
|
||||||
|
\texttt{HttpOnly} configurada como \texttt{false}. A ausência desta
|
||||||
|
proteção significa que o token está totalmente exposto e pode ser lido
|
||||||
|
por scripts do lado do cliente, tornando a sessão criticamente vulnerável
|
||||||
|
a roubo por Cross-Site Scripting (XSS).
|
||||||
|
|
||||||
|
\subsection{Input Validation Testing}
|
||||||
|
|
||||||
|
\subsubsection*{Testing for Reflected Cross Site Scripting}
|
||||||
|
|
||||||
|
Durante a auditoria à barra de pesquisa de produtos, validámos a
|
||||||
|
existência de uma vulnerabilidade de \textit{Reflected Cross-Site
|
||||||
|
Scripting} (XSS) devido à ausência de higienização do input do
|
||||||
|
utilizador.
|
||||||
|
|
||||||
\begin{enumerate}
|
\begin{enumerate}
|
||||||
\item Estabelecer a ligação VPN e verificar a conectividade à rede interna.
|
\item \textbf{Injeção HTML:} Introduzimos o valor \texttt{<h1>apple} na pesquisa e verificámos que o resultado foi renderizado no navegador como um título estrutural, confirmando que o código HTML é injetado diretamente na página.
|
||||||
\item No diretório da autoridade de certificação (máquina \textit{host}), revogar o certificado do utilizador:
|
\item \textbf{Tentativa com Script Direto:} Inserimos o payload tradicional \texttt{<script>alert("someones gotta do it")</script>apple}. Esta tentativa não foi executada, demonstrando a presença de uma validação simples contra tags explícitas de script.
|
||||||
\begin{lstlisting}[language=bash]
|
\item \textbf{Evasão com Evento de Erro:} Para contornar a restrição, injetámos uma tag de imagem com um caminho inválido acompanhado do manipulador de eventos \texttt{onerror}:
|
||||||
openssl ca -revoke user.crt -config cheese.cfg -keyfile ca.key -cert ca.crt
|
\begin{codeblock}{html}
|
||||||
\end{lstlisting}
|
<img src="x" onerror="alert('someones gotta do it')">apple
|
||||||
\item Atualizar o ficheiro \texttt{index.txt} no servidor OCSP e reiniciar o serviço para carregar o novo estado de revogação.
|
\end{codeblock}
|
||||||
\item Tentar estabelecer uma nova ligação VPN e verificar que a autenticação falha devido à resposta \texttt{revoked} do responder OCSP.
|
O filtro falhou ao inspecionar este atributo e o navegador executou o código JavaScript com sucesso quando a imagem falhou o carregamento.
|
||||||
\end{enumerate}
|
\end{enumerate}
|
||||||
|
|
||||||
|
\subsubsection{Testing for SQL Injection}
|
||||||
|
Adicionalmente, explorámos o mesmo parâmetro de pesquisa recorrendo ao
|
||||||
|
\textit{sqlmap} para validar falhas de injeção SQL, conseguindo extrair
|
||||||
|
com sucesso a estrutura de 22 tabelas da base de dados:
|
||||||
|
|
||||||
\section{Conclusão}
|
\begin{codeblock}{bash}
|
||||||
|
sqlmap -u "http://10.60.0.1:3000/rest/products/search?q=apple" -p q --dbms=sqlite --prefix="'%" --suffix="%'--" --tables --batch
|
||||||
|
|
||||||
% Conclusão!!!!
|
[22 tables]
|
||||||
Atingimos o objetivo deste trabalho, conseguimos configurar o VPN tunnel,
|
+-----------------------+
|
||||||
o two-factor authentication e conseguimos criar e retirar acesso aos
|
| Addresses |
|
||||||
certificados que emitimos. Utilizar mais maquinas para simular um cenario
|
| BasketItems |
|
||||||
maior seria redundante, teriamos que emitir mais certificados mas não iamos
|
| Baskets |
|
||||||
aprender muito mais. Se fossemos aplicar o que fizemos no trabalho anterior
|
| Captchas |
|
||||||
podiamos dar DROP aos pacotes que não nos interessa nesta cenario,
|
| Cards |
|
||||||
e implementar suricata para identificar possiveis ataques nos serviços.
|
| ChallengeDependencies |
|
||||||
%È estranho que para uma cadeira de cybersegurança nós implementamos
|
| Challenges |
|
||||||
%pouca you know segurança.
|
| Complaints |
|
||||||
|
| Deliveries |
|
||||||
|
| Feedbacks |
|
||||||
|
| Hints |
|
||||||
|
| ImageCaptchas |
|
||||||
|
| Memories |
|
||||||
|
| PrivacyRequests |
|
||||||
|
| Products |
|
||||||
|
| Quantities |
|
||||||
|
| Recycles |
|
||||||
|
| SecurityAnswers |
|
||||||
|
| SecurityQuestions |
|
||||||
|
| Users |
|
||||||
|
| Wallets |
|
||||||
|
| sqlite_sequence |
|
||||||
|
+-----------------------+
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
|
||||||
|
Apesar de não ter sido detetado pelo active scan foi feito fuzzing nos
|
||||||
|
detalhes de login para saber se estava vulneravel a esse tipo de ataques
|
||||||
|
visto que existia essa vulnerabilidade noutros paremetros. Verificamos
|
||||||
|
que de facto também estava vulneravel a SQL Injection, e que a resposta
|
||||||
|
era a tabela com o
|
||||||
|
|
||||||
|
\subsection{Testing for Error Handling}
|
||||||
|
|
||||||
|
Ao tentar forçar o acesso a uma página ou ficheiro inexistente no
|
||||||
|
servidor de ficheiros, como por exemplo na rota \texttt{/ftp/teste},
|
||||||
|
a aplicação falhou ao tratar a exceção de forma segura. Em vez de
|
||||||
|
apresentar uma página de erro genérica (404), o servidor devolveu uma
|
||||||
|
resposta detalhada expondo o \textit{stack trace} completo do ambiente
|
||||||
|
\textit{Express.js}, revelando caminhos internos do sistema de ficheiros
|
||||||
|
do servidor.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\begin{figure}[h!]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.7\textwidth]{stack-trace}
|
||||||
|
\caption{stack-trace}
|
||||||
|
\label{fig:stack-trace}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\subsection{Client Side Testing}
|
||||||
|
|
||||||
|
Validámos que o token de sessão (JWT) do utilizador autenticado está
|
||||||
|
armazenado diretamente no \texttt{localStorage} do navegador. Uma vez
|
||||||
|
que o \texttt{localStorage} não possui mecanismos de proteção
|
||||||
|
equivalentes à flag \texttt{HttpOnly} dos cookies, qualquer script
|
||||||
|
executado no contexto da página consegue ler estes dados.
|
||||||
|
|
||||||
|
Utilizando a falha de XSS identificada anteriormente na barra de pesquisas, injetámos o seguinte payload direcionado:
|
||||||
|
|
||||||
|
\begin{codeblock}{html}
|
||||||
|
<img src="x" onerror="alert(localStorage.getItem('token'))">apple
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
A execução deste vetor permitiu extrair o conteúdo do token diretamente
|
||||||
|
do armazenamento local da vítima. Isto prova que um atacante pode
|
||||||
|
automatizar a exfiltração destas informações e assumir a identidade de
|
||||||
|
qualquer utilizador afetado sem necessitar de saber as credenciais de
|
||||||
|
acesso de forma persistente.
|
||||||
|
|
||||||
|
|
||||||
|
\section{Web Application Security Firewall}
|
||||||
|
|
||||||
|
\begin{codeblock}{modsecurity.conf}
|
||||||
|
SecRuleEngine On
|
||||||
|
SecRequestBodyAccess On
|
||||||
|
SecResponseBodyAccess On
|
||||||
|
SecDebugLog /var/log/modsecurity/debug.log
|
||||||
|
SecDebugLogLevel 0
|
||||||
|
SecAuditLogParts ABIJ
|
||||||
|
SecAuditLogType Serial
|
||||||
|
SecAuditLog /var/log/modsecurity/audit.log
|
||||||
|
|
||||||
|
# sql injection
|
||||||
|
SecRule REQUEST_URI|ARGS "['\";]|--" \
|
||||||
|
SecRule REQUEST_URI|ARGS "(?i:(?:select|insert|update|delete|drop|union|create|alter|truncate)\s+.+\s+from|'[^']*'|--|;|\b(or|and)\b\s+\d+\s*=\s*\d+)" \
|
||||||
|
"id:950001,phase:1,deny,status:403,msg:'SQL INJECTION ATTACK DETECTED!!!',log,t:urlDecode,t:sqlHexDecode,t:lowercase"
|
||||||
|
|
||||||
|
# xss / html injection
|
||||||
|
SecRule REQUEST_URI|ARGS "(<.*>)|(%3C.*%3E)" \
|
||||||
|
"id:950003,phase:1,deny,status:403,msg:'XSS/HTML INJECTION DETECTED!!!',log"
|
||||||
|
|
||||||
|
# command injection
|
||||||
|
SecRule ARGS "(\"role\".*:.*\"admin\")|exec|cat|more|ls|dir|/etc/passwd" \
|
||||||
|
"id:950006,phase:2,deny,status:403,msg:'COMMAND INJECTION DETECTED!!!',log"
|
||||||
|
|
||||||
|
# path traversal
|
||||||
|
SecRule REQUEST_URI|ARGS "\%00|\%2500|\.\./|ftp|metrics|api-docs" \
|
||||||
|
"id:950007,phase:2,deny,status:403,msg:'PATH TRAVERSAL ATTEMPT!!!',log"
|
||||||
|
|
||||||
|
# exposed stuff (redundante ?)
|
||||||
|
SecRule REQUEST_URI|ARGS "\%00|\%2500|ftp|metrics|api-docs" \
|
||||||
|
"id:950008,phase:2,deny,status:500,msg:'ATTEMPT TO ACCESS FTP, METRICS, API-DOCS!!!',log"
|
||||||
|
|
||||||
|
# rate limiting on login endpoint
|
||||||
|
# (max 5 requests per 30s per IP)
|
||||||
|
SecAction \
|
||||||
|
"id:950009,phase:1,initcol:ip=%{REMOTE_ADDR},pass,nolog"
|
||||||
|
SecRule REQUEST_URI "@streq /rest/user/login" \
|
||||||
|
"id:950010,phase:2,pass,nolog,setvar:ip.login_count=+1,expirevar:ip.login_count=30"
|
||||||
|
SecRule IP:LOGIN_COUNT "@gt 5" \
|
||||||
|
"id:950011,phase:2,deny,status:429,msg:'Rate Limit Exceeded on Login',log"
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Information Gathering}
|
||||||
|
|
||||||
|
O acesso direto via URL (e.g., \texttt{/ftp}, \texttt{/metrics}, \texttt{/api-docs}) é
|
||||||
|
mitigado pela regra id:950008, que inspeciona o caminho do pedido (\texttt{REQUEST\_URI})
|
||||||
|
e devolve \texttt{500} ao bloquear qualquer acesso direto a estes endpoints!
|
||||||
|
A mitigação desta categoria é, portanto, completa ao nível de pedidos HTTP.
|
||||||
|
|
||||||
|
\subsection{Configuration and Deployment Management Testing}
|
||||||
|
|
||||||
|
A restrição de métodos HTTP e a validação de permissões de diretório requerem
|
||||||
|
intervenção ao nível do servidor Apache ou da aplicação, estando fora do âmbito
|
||||||
|
das regras \texttt{SecRule} definidas.
|
||||||
|
|
||||||
|
\subsection{Identity Management Testing}
|
||||||
|
|
||||||
|
A regra de XSS/injeção HTML (id:950003) bloqueia eficazmente o registo de utilizadores
|
||||||
|
com tags HTML nos campos de \textit{input}, como \texttt{<h1>STRONG}, devolvendo um erro
|
||||||
|
\texttt{403 Forbidden} antes que o pedido chegue à aplicação.
|
||||||
|
|
||||||
|
A vulnerabilidade de escalonamento de permissões (injeção do campo
|
||||||
|
\texttt{"role":"admin"} no corpo JSON do registo) \textbf{é mitigada
|
||||||
|
pela regra id:950006}, que deteta a sequência
|
||||||
|
\texttt{"role".*:.*"admin"} nos argumentos do pedido e devolve
|
||||||
|
\texttt{403 Forbidden}, impedindo a criação de contas com perfil de
|
||||||
|
administrador.
|
||||||
|
|
||||||
|
A enumeração de contas via mensagens de erro da aplicação \textbf{permanece sem mitigação} ao nível da WAF.
|
||||||
|
|
||||||
|
\subsection{Authentication Testing}
|
||||||
|
|
||||||
|
As regras id:950009--950011 implementam um mecanismo de \textit{rate limiting} sobre o
|
||||||
|
endpoint de autenticação (\texttt{/rest/user/login}). Para cada endereço IP, é mantido
|
||||||
|
um contador de pedidos com janela deslizante de 30 segundos: ao ultrapassar 5 tentativas
|
||||||
|
nessa janela, o servidor devolve \texttt{429 Too Many Requests}, bloqueando eficazmente
|
||||||
|
ataques de \textit{brute force} por dicionário.
|
||||||
|
|
||||||
|
O bloqueio de contas após múltiplas tentativas falhadas permanece fora do âmbito da WAF,
|
||||||
|
exigindo lógica aplicacional.
|
||||||
|
|
||||||
|
\subsection{Authorization Testing}
|
||||||
|
|
||||||
|
A regra id:950007 e id:950008 bloqueiam o uso de \textit{null byte}
|
||||||
|
codificadas para cobrir este vetor de ataque.
|
||||||
|
|
||||||
|
\subsection{Session Management Testing}
|
||||||
|
|
||||||
|
A configuração da WAF não tem capacidade de alterar os atributos dos
|
||||||
|
cookies definidos pela aplicação. Logo, a flag \texttt{HttpOnly} do cookie
|
||||||
|
\texttt{token} continua ausente, uma vez que esta é uma propriedade
|
||||||
|
definida pelo \textit{JuiceShop}. Ainda assim, a mitigação do XSS
|
||||||
|
pela regra id:950003, descrita na subsecção seguinte, reduz
|
||||||
|
indiretamente o risco de roubo de sessão ao bloquear os vetores que
|
||||||
|
permitiriam a sua exploração.
|
||||||
|
|
||||||
|
\subsection{Input Validation Testing}
|
||||||
|
|
||||||
|
A regra de SQL Injection (id:950001) bloqueia com sucesso pedidos ao
|
||||||
|
endpoint de pesquisa de produtos que contenham caracteres como
|
||||||
|
\texttt{'}, \texttt{"}, \texttt{;} ou a sequência \texttt{--},
|
||||||
|
devolvendo \texttt{403 Forbidden}.
|
||||||
|
|
||||||
|
O payload utilizado pelo \textit{sqlmap} ou por outros fuzzers
|
||||||
|
com \textit{SQL injections} são interceptado nesta fase.
|
||||||
|
|
||||||
|
A regra de XSS/injeção HTML (id:950003) bloqueia igualmente os payloads com tags
|
||||||
|
\texttt{<img src="x" onerror="...">} e \texttt{<h1>}, neutralizando
|
||||||
|
ambos estes vetores de ataque.
|
||||||
|
|
||||||
|
\subsection{Testing for Error Handling}
|
||||||
|
|
||||||
|
A exposição do \textit{stack trace} do \textit{Express.js} em rotas
|
||||||
|
inexistentes (e.g., \texttt{/ftp/teste}) aind não é mitigada. Para
|
||||||
|
suprimir estas respostas de erro detalhadas era necessário ativar
|
||||||
|
a inspeção do corpo da resposta e definir regras sobre o seu
|
||||||
|
conteúdo, ou configurar páginas de erro personalizadas no Apache.
|
||||||
|
|
||||||
|
\subsection{Client Side Testing}
|
||||||
|
|
||||||
|
O payload de exfiltração do token JWT via XSS
|
||||||
|
(\texttt{<img src="x" onerror="alert(localStorage.getItem('token'))">})
|
||||||
|
é bloqueado pela regra id:950003, uma vez que contém a expressão
|
||||||
|
\texttt{<.*>}.
|
||||||
|
|
||||||
|
\section{Conclusions}
|
||||||
|
|
||||||
|
Foi feita uma análise extensa dos possiveis vetores de ataque da aplicação
|
||||||
|
e com isso desenvolvemos uma \textbf{WAF} que cobriu uma maioria dos
|
||||||
|
ataques. Contudo, as vulnerabilidades estruturais da aplicação, como a ausência de flags \texttt{HttpOnly} em cookies,
|
||||||
|
a lógica de enumeração de utilizadores e a exposição de \textit{stack traces}, competem diretamente
|
||||||
|
ao desenvolvimento seguro do código e à configuração do web server.
|
||||||
|
|
||||||
|
Em suma, com poucas regras simples foi possible bloquear a maioria das ameaças de
|
||||||
|
injeção de código malicioso, no entanto, para cobrir uma maior superficie
|
||||||
|
de ataques seria necessário mudar a lógica interna da aplicação.
|
||||||
|
|
||||||
% Para aprofundar (???) yeah
|
|
||||||
|
|
||||||
\end{document}
|
\end{document}
|
||||||
|
|||||||
@@ -1,11 +1,28 @@
|
|||||||
\babel@toc {portuguese}{}\relax
|
\babel@toc {portuguese}{}\relax
|
||||||
\contentsline {section}{\numberline {1}Introdução}{2}{section.1}%
|
\contentsline {section}{\numberline {1}Introduction}{3}{section.1}%
|
||||||
\contentsline {section}{\numberline {2}Criação de certificados}{2}{section.2}%
|
\contentsline {section}{\numberline {2}Architecture Considered for Both Stages}{3}{section.2}%
|
||||||
\contentsline {section}{\numberline {3}Configuração geral}{3}{section.3}%
|
\contentsline {subsection}{\numberline {2.1}Network structure}{3}{subsection.2.1}%
|
||||||
\contentsline {section}{\numberline {4}Configuração da \textit {Gateway} VPN}{3}{section.4}%
|
\contentsline {subsection}{\numberline {2.2}Servers}{3}{subsection.2.2}%
|
||||||
\contentsline {subsection}{\numberline {4.1}Configurar TOTP}{3}{subsection.4.1}%
|
\contentsline {subsection}{\numberline {2.3}Services}{3}{subsection.2.3}%
|
||||||
\contentsline {subsection}{\numberline {4.2}Encaminhamento e Firewall}{4}{subsection.4.2}%
|
\contentsline {section}{\numberline {3}Web application security testing}{4}{section.3}%
|
||||||
\contentsline {section}{\numberline {5}Configuração do Cliente (Road Warrior)}{4}{section.5}%
|
\contentsline {subsection}{\numberline {3.1}Information Gathering}{4}{subsection.3.1}%
|
||||||
\contentsline {section}{\numberline {6}Servidor Apache e OCSP}{5}{section.6}%
|
\contentsline {subsection}{\numberline {3.2}Configuration and Deployment Management Testing}{4}{subsection.3.2}%
|
||||||
\contentsline {subsection}{\numberline {6.1}Revocation e OCSP}{5}{subsection.6.1}%
|
\contentsline {subsection}{\numberline {3.3}Identity Management Testing}{6}{subsection.3.3}%
|
||||||
\contentsline {section}{\numberline {7}Conclusão}{5}{section.7}%
|
\contentsline {subsection}{\numberline {3.4}Authentication Testing}{7}{subsection.3.4}%
|
||||||
|
\contentsline {subsection}{\numberline {3.5}Authorization Testing}{7}{subsection.3.5}%
|
||||||
|
\contentsline {subsection}{\numberline {3.6}Session Management Testing}{9}{subsection.3.6}%
|
||||||
|
\contentsline {subsection}{\numberline {3.7}Input Validation Testing}{9}{subsection.3.7}%
|
||||||
|
\contentsline {subsubsection}{\numberline {3.7.1}Testing for SQL Injection}{10}{subsubsection.3.7.1}%
|
||||||
|
\contentsline {subsection}{\numberline {3.8}Testing for Error Handling}{10}{subsection.3.8}%
|
||||||
|
\contentsline {subsection}{\numberline {3.9}Client Side Testing}{11}{subsection.3.9}%
|
||||||
|
\contentsline {section}{\numberline {4}Web Application Security Firewall}{11}{section.4}%
|
||||||
|
\contentsline {subsection}{\numberline {4.1}Information Gathering}{12}{subsection.4.1}%
|
||||||
|
\contentsline {subsection}{\numberline {4.2}Configuration and Deployment Management Testing}{12}{subsection.4.2}%
|
||||||
|
\contentsline {subsection}{\numberline {4.3}Identity Management Testing}{13}{subsection.4.3}%
|
||||||
|
\contentsline {subsection}{\numberline {4.4}Authentication Testing}{13}{subsection.4.4}%
|
||||||
|
\contentsline {subsection}{\numberline {4.5}Authorization Testing}{13}{subsection.4.5}%
|
||||||
|
\contentsline {subsection}{\numberline {4.6}Session Management Testing}{13}{subsection.4.6}%
|
||||||
|
\contentsline {subsection}{\numberline {4.7}Input Validation Testing}{13}{subsection.4.7}%
|
||||||
|
\contentsline {subsection}{\numberline {4.8}Testing for Error Handling}{14}{subsection.4.8}%
|
||||||
|
\contentsline {subsection}{\numberline {4.9}Client Side Testing}{14}{subsection.4.9}%
|
||||||
|
\contentsline {section}{\numberline {5}Conclusions}{14}{section.5}%
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
\usepackage[dvipsnames]{xcolor}
|
\usepackage[dvipsnames]{xcolor}
|
||||||
\usepackage{enumitem,amssymb}
|
\usepackage{enumitem,amssymb}
|
||||||
\usepackage[colorlinks=true,urlcolor=blue,linkcolor=MidnightBlue]{hyperref}
|
\usepackage[colorlinks=true,urlcolor=blue,linkcolor=MidnightBlue]{hyperref}
|
||||||
\graphicspath{{./img/}}
|
\graphicspath{{./imgs/}}
|
||||||
|
|
||||||
\usepackage{enumitem,amssymb}
|
\usepackage{enumitem,amssymb}
|
||||||
\newlist{todolist}{itemize}{2}
|
\newlist{todolist}{itemize}{2}
|
||||||
@@ -17,7 +17,47 @@
|
|||||||
\usepackage{pifont}
|
\usepackage{pifont}
|
||||||
\usepackage{amssymb}
|
\usepackage{amssymb}
|
||||||
|
|
||||||
\usepackage{minted}
|
\usepackage[most]{tcolorbox}
|
||||||
|
\tcbuselibrary{listings, skins, breakable}
|
||||||
|
|
||||||
|
\lstdefinestyle{mystyle}{
|
||||||
|
basicstyle=\ttfamily\footnotesize,
|
||||||
|
breakatwhitespace=false,
|
||||||
|
breaklines=true,
|
||||||
|
captionpos=b,
|
||||||
|
keepspaces=true,
|
||||||
|
numbers=left,
|
||||||
|
numbersep=5pt,
|
||||||
|
showspaces=false,
|
||||||
|
showstringspaces=false,
|
||||||
|
showtabs=false,
|
||||||
|
tabsize=2,
|
||||||
|
commentstyle=\color{gray},
|
||||||
|
keywordstyle=\color{MidnightBlue}\bfseries,
|
||||||
|
stringstyle=\color{ForestGreen}
|
||||||
|
}
|
||||||
|
|
||||||
|
\newtcblisting{codeblock}[2][]{
|
||||||
|
enhanced,
|
||||||
|
breakable,
|
||||||
|
colback=gray!2!white,
|
||||||
|
colframe=gray!20!black,
|
||||||
|
attach boxed title to top left={yshift*=-\tcboxedtitleheight/2, xshift=4mm},
|
||||||
|
boxed title style={
|
||||||
|
colback=gray!20!black,
|
||||||
|
outer arc=0pt,
|
||||||
|
arc=0pt,
|
||||||
|
top=1pt,
|
||||||
|
bottom=1pt,
|
||||||
|
},
|
||||||
|
fonttitle=\bfseries\ttfamily\footnotesize,
|
||||||
|
title={#2},
|
||||||
|
listing only,
|
||||||
|
listing options={
|
||||||
|
style=mystyle,
|
||||||
|
language=#1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
\setlength{\parskip}{1em}%
|
\setlength{\parskip}{1em}%
|
||||||
\setlength{\parindent}{0em}%
|
\setlength{\parindent}{0em}%
|
||||||
|
|||||||
21
relatorio/texput.log
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
This is pdfTeX, Version 3.141592653-2.6-1.40.29 (TeX Live 2026/Arch Linux) (preloaded format=pdflatex 2026.5.3) 29 MAY 2026 20:43
|
||||||
|
entering extended mode
|
||||||
|
restricted \write18 enabled.
|
||||||
|
%&-line parsing enabled.
|
||||||
|
**
|
||||||
|
|
||||||
|
! Emergency stop.
|
||||||
|
<*>
|
||||||
|
|
||||||
|
End of file on the terminal!
|
||||||
|
|
||||||
|
|
||||||
|
Here is how much of TeX's memory you used:
|
||||||
|
4 strings out of 469495
|
||||||
|
118 string characters out of 5470099
|
||||||
|
433756 words of memory out of 5000000
|
||||||
|
28764 multiletter control sequences out of 15000+600000
|
||||||
|
627721 words of font info for 40 fonts, out of 8000000 for 9000
|
||||||
|
16 hyphenation exceptions out of 8191
|
||||||
|
0i,0n,0p,1b,6s stack positions out of 10000i,1000n,20000p,200000b,200000s
|
||||||
|
! ==> Fatal error occurred, no output PDF file produced!
|
||||||