Compare commits
73 Commits
2e16b804ab
...
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 | ||
|
|
5bd7355e8b | ||
|
|
f1f40e9ebb | ||
|
|
ebc05382b3 | ||
|
|
eb5a014949 | ||
|
|
457018b127 | ||
|
|
790c789610 | ||
|
|
123a4cb709 |
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
|
||||||
7
TODO.md
@@ -1,7 +0,0 @@
|
|||||||
# Objectivos de acordo com o enunciado
|
|
||||||
|
|
||||||
## Goals
|
|
||||||
- [X] Configure a tunnel in the "road warrior"
|
|
||||||
- [ ] Enable two factor authentication with OpenSSL and Apache services
|
|
||||||
- [ ] Manage PKI: certification authorities, X.509 certificates, revocation and OCSP.
|
|
||||||
|
|
||||||
8
VM_CONFIG.sh → assignment2/VM_CONFIG.sh
Executable file → Normal file
@@ -7,7 +7,7 @@ if [[ "$USER" != "root" ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
yum install -y epel-release
|
yum install -y epel-release
|
||||||
yum install -y openvpn iptables-services dhcp-client
|
yum install -y openvpn iptables-services dhcp-client ntpsec
|
||||||
systemctl stop firewalld
|
systemctl stop firewalld
|
||||||
systemctl disable firewalld
|
systemctl disable firewalld
|
||||||
systemctl mask firewalld
|
systemctl mask firewalld
|
||||||
@@ -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,7 +4,12 @@
|
|||||||
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 google-authenticator
|
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"
|
if_dentro="enp0s8"
|
||||||
ip_dentro="10.60.0.1"
|
ip_dentro="10.60.0.1"
|
||||||
@@ -26,28 +31,22 @@ 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
|
# sim, é preciso fazer isto para carregar serviços
|
||||||
mkdir -p /etc/systemd/system/httpd.service.d
|
echo "LoadModule session_module modules/mod_session.so" > /etc/httpd/conf.modules.d/01-session.conf
|
||||||
echo -e "[Service]\nProtectHome=false" > /etc/systemd/system/httpd.service.d/override.conf
|
echo "LoadModule session_cookie_module modules/mod_session_cookie.so" >> /etc/httpd/conf.modules.d/01-session.conf
|
||||||
systemctl daemon-reload
|
echo "LoadModule auth_form_module modules/mod_auth_form.so" > /etc/httpd/conf.modules.d/01-auth_form.conf
|
||||||
|
|
||||||
# serviço !!!
|
# mega paginas webs
|
||||||
systemctl enable --now httpd
|
cp -r www/* /var/www/html/
|
||||||
|
chown -R apache:apache /var/www/html/
|
||||||
|
|
||||||
# acho ?????
|
httpd -X
|
||||||
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
@@ -1,3 +1,3 @@
|
|||||||
auth required pam_google_authenticator.so forward_pass secret=/home/${USER}/.google_authenticator user=apache
|
auth required pam_google_authenticator.so forward_pass secret=/home/${USER}/.google_authenticator user=apache
|
||||||
auth required pam_unix.so use_first_pass
|
auth required pam_unix.so use_first_pass
|
||||||
account required pam_unix.so
|
account required pam_unix.so
|
||||||
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
|
||||||
64
assignment2/conf/ssl.conf
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<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>
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
BIN
assignment2/relatorio/google-authenticator.jpg
Normal file
|
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}%
|
||||||
|
|
||||||
13
assignment2/www/index.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Coimbra VPN</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Coimbra VPN</h1>
|
||||||
|
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.
|
||||||
|
Minima porro unde praesentium sint itaque optio, deserunt eum est voluptatum, natus nihil repellat amet impedit? Fugiat fugit ex quis molestiae sit.</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
25
assignment2/www/login.html
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Coimbra VPN</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Two-Factor Auth</h1>
|
||||||
|
<p>Enter your UNIX credentials and TOTP code</p>
|
||||||
|
|
||||||
|
<form action="/dologin" method="POST">
|
||||||
|
|
||||||
|
<label for="username">Username</label>
|
||||||
|
<input type="text" id="username" name="httpd_username" placeholder="username">
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<label for="password">UNIX Password (password + 6 digit TOTP)</label>
|
||||||
|
<input type="password" id="password" name="httpd_password" placeholder="password + TOTP" required>
|
||||||
|
|
||||||
|
<button type="submit">Login</button>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -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
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
Listen 443 https
|
|
||||||
<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 (Client Cert)
|
|
||||||
SSLVerifyClient require
|
|
||||||
SSLVerifyDepth 1
|
|
||||||
|
|
||||||
# OCSP Validation against CA
|
|
||||||
SSLOCSPEnable on
|
|
||||||
SSLOCSPDefaultResponder "http://10.60.0.1:8888"
|
|
||||||
SSLOCSPOverrideResponder on
|
|
||||||
SSLOCSPUseRequestNonce off
|
|
||||||
|
|
||||||
# PAM + TOTP Authentication
|
|
||||||
<Location "/">
|
|
||||||
AuthType Basic
|
|
||||||
AuthName "Enter UNIX Password + Google Authenticator Code"
|
|
||||||
AuthBasicProvider PAM
|
|
||||||
AuthPAMService httpd-totp
|
|
||||||
Require valid-user
|
|
||||||
</Location>
|
|
||||||
</VirtualHost>
|
|
||||||
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 |
@@ -2,13 +2,51 @@
|
|||||||
\providecommand \babel@aux [2]{\global \let \babel@toc \@gobbletwo }
|
\providecommand \babel@aux [2]{\global \let \babel@toc \@gobbletwo }
|
||||||
\@nameuse{bbl@beforestart}
|
\@nameuse{bbl@beforestart}
|
||||||
\catcode `"\active
|
\catcode `"\active
|
||||||
|
\providecommand\hyper@newdestlabel[2]{}
|
||||||
|
\providecommand\HyField@AuxAddToFields[1]{}
|
||||||
|
\providecommand\HyField@AuxAddToCoFields[2]{}
|
||||||
\babel@aux{portuguese}{}
|
\babel@aux{portuguese}{}
|
||||||
\@writefile{toc}{\contentsline {section}{\numberline {1}Introdução}{2}{}\protected@file@percent }
|
\@writefile{toc}{\contentsline {section}{\numberline {1}Introduction}{3}{section.1}\protected@file@percent }
|
||||||
\@writefile{toc}{\contentsline {section}{\numberline {2}Criação de certificados}{2}{}\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 {3}Configuração da \textit {Gateway} VPN}{3}{}\protected@file@percent }
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Network structure}{3}{subsection.2.1}\protected@file@percent }
|
||||||
\@writefile{toc}{\contentsline {section}{\numberline {4}Configurar TOTP}{3}{}\protected@file@percent }
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Servers}{3}{subsection.2.2}\protected@file@percent }
|
||||||
\@writefile{toc}{\contentsline {subsection}{\numberline {4.1}Aceder ao código}{3}{}\protected@file@percent }
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3}Services}{3}{subsection.2.3}\protected@file@percent }
|
||||||
\@writefile{toc}{\contentsline {section}{\numberline {5}Revocation e OCSP}{3}{}\protected@file@percent }
|
\@writefile{toc}{\contentsline {section}{\numberline {3}Web application security testing}{4}{section.3}\protected@file@percent }
|
||||||
\@writefile{toc}{\contentsline {subsection}{\numberline {5.1}Testar OSCP via revoke}{3}{}\protected@file@percent }
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.1}Information Gathering}{4}{subsection.3.1}\protected@file@percent }
|
||||||
\@writefile{toc}{\contentsline {section}{\numberline {6}Conclusion}{4}{}\protected@file@percent }
|
\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces ftp}}{4}{figure.1}\protected@file@percent }
|
||||||
\gdef \@abspage@last{4}
|
\newlabel{fig:ftp}{{1}{4}{ftp}{figure.1}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2}Configuration and Deployment Management Testing}{4}{subsection.3.2}\protected@file@percent }
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces metrics}}{5}{figure.2}\protected@file@percent }
|
||||||
|
\newlabel{fig:metrics}{{2}{5}{metrics}{figure.2}{}}
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces swagger}}{5}{figure.3}\protected@file@percent }
|
||||||
|
\newlabel{fig:swagger}{{3}{5}{swagger}{figure.3}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3}Identity Management Testing}{6}{subsection.3.3}\protected@file@percent }
|
||||||
|
\@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{style}
|
||||||
\usepackage{booktabs}
|
|
||||||
|
|
||||||
% \usepa
|
|
||||||
|
|
||||||
\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,144 +14,514 @@
|
|||||||
|
|
||||||
\begin{document}
|
\begin{document}
|
||||||
\maketitle
|
\maketitle
|
||||||
|
|
||||||
|
\newpage
|
||||||
\tableofcontents
|
\tableofcontents
|
||||||
|
|
||||||
\newpage
|
\newpage
|
||||||
|
|
||||||
\section{Introdução}
|
\section{Introduction}
|
||||||
|
|
||||||
Este projecto tem como âmbito implementar, uma rede virtual privada (VPN) num cenário de road-warrior,
|
% FAZER EM ENGLISH??? O prof é BR temos que fazer em Brazileiro
|
||||||
configurar two-factor authentication com os serviços OpenVPN e Apache, e gerir certificados X.509 utilizando OCSP.
|
|
||||||
|
|
||||||
O nosso cenario vai envolver três maquinas, o cliente (road warrior), a gateway que utiliza OpenVPN e um servidor interno com OpenSSL e Apache. O OpenVPN utiliza two-factor authentication, recebendo o utilizador, e uma password que é uma junção de uma fixa, e de uma gerada pelo plugin google-authenticator. O servidor de Apache implementa a mesma authenticação.
|
Este trabalho tem como objetivo realizar testes de penetração numa aplicação
|
||||||
|
cobaia (o \textit{Juicebox}) desenhada para aprendizagem.
|
||||||
|
|
||||||
Temos então três máquinas virtuais:
|
Este trabalho tem como objetivo utilizar o \textbf{WSTG} (Web security
|
||||||
|
testing guide) e configurar um ModSecurity reverse proxy como uma
|
||||||
|
\textbf{WAF}. Para esse fim temos uma aplicação cobaia (o \textit{Juicebox})
|
||||||
|
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}).
|
||||||
|
|
||||||
\begin{tabular}{l l l}
|
\section{Architecture Considered for Both Stages}
|
||||||
|
|
||||||
{\bf Nome} & {\bf Script} & {\bf Rede} \\\toprule
|
Utilizámos somente duas máquinas virtuais: um servidor a correr \textit{CentOS 9}
|
||||||
Road Warrior & VM\_ROAD\_WARRIOR.sh & Rede Externa 193.168.0.0/24 \\
|
e um cliente a correr \textit{Kali Linux}. O servidor contém o serviço \textit{Apache},
|
||||||
VPN Gateway & VM\_OPENVPN\_GATEWAY.sh & Router \\
|
que age como \textit{firewall} através do módulo \textit{ModSecurity}, e um servidor
|
||||||
OpenSSL / Apache & VM\_OPENSSL\_APACHE.sh & Reder Interna 10.60.0.0/24 \\
|
\textit{Node.js} que aloja o \textit{Juicebox} --- a aplicação que vai
|
||||||
|
servir de cobaia (\textit{dummy}).
|
||||||
|
|
||||||
|
% 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.
|
||||||
|
|
||||||
|
% 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.
|
||||||
|
|
||||||
|
Com o ambiente criado foram realizadas duas etapas de testes:
|
||||||
|
\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}
|
||||||
|
|
||||||
Os certificados utilizados foram certificados por uma autoridade central que não está no nosso cenario. A gestão da lista de revogação está a ser gerido pelo serviço OpenSSL que está na mesma maquina que o Apache. Num cenario real seria melhor dividir estes serviços por outras maquinas, mas os computadores que temos acesso estão limitados na quantidade de maquinas virtuais que consegue simular simultaniamente.
|
\subsection{Information Gathering}
|
||||||
|
|
||||||
|
Utilizámos a política por omissão (\textit{default policy}) para a
|
||||||
|
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.
|
||||||
|
|
||||||
|
% 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.
|
||||||
|
|
||||||
|
Adicionalmente, realizámos testes de infraestrutura utilizando ferramentas especializadas:
|
||||||
|
|
||||||
|
\begin{codeblock}{bash}
|
||||||
|
sqlmap -u "http://192.168.1.1:3000/rest/products/search?q=apple" -p q --level=5 --risk=3 --banner
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
Ao executar o \textit{sqlmap}, descobrimos que o sistema de gestão de
|
||||||
|
base de dados subjacente é o \textit{SQLite}.
|
||||||
|
|
||||||
|
Paralelamente, realizámos uma descoberta de ficheiros e diretórios
|
||||||
|
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{itemize}
|
||||||
|
\item \texttt{/ftp}: Servidor de armazenamento e transferência de ficheiros exposto. (Figura \ref{fig:ftp})
|
||||||
|
\item \texttt{/metrics}: Métricas internas da infraestrutura expostas. (Figura \ref{fig:metrics})
|
||||||
|
\item \texttt{/api-docs}: Documentação e esquemas estruturais da API. (Figura \ref{fig:swagger})
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\begin{figure}[h!]
|
||||||
|
\centering
|
||||||
|
\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}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Configuration and Deployment Management Testing}
|
||||||
|
|
||||||
|
\subsubsection*{Enumerate Infrastructure and Application Admin Interfaces}
|
||||||
|
|
||||||
|
Identificámos e testámos o acesso ao endpoint \texttt{/api-docs}
|
||||||
|
(\textit{Swagger UI}), validando que as interfaces de documentação
|
||||||
|
interna do sistema e as definições da API estavam publicamente expostas
|
||||||
|
sem qualquer tipo de controlo de acesso ou autenticação prévia.
|
||||||
|
|
||||||
|
\subsubsection*{Test HTTP Methods}
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
\subsubsection*{Test File Permission}
|
||||||
|
|
||||||
|
Analisámos as permissões de acesso no diretório \texttt{/ftp}.
|
||||||
|
Verificámos que a falta de restrições rígidas ao nível do sistema de
|
||||||
|
ficheiros permite a qualquer utilizador anónimo listar o conteúdo de
|
||||||
|
diretórios estruturais e descarregar ficheiros não indexados na
|
||||||
|
interface principal da aplicação.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Identity Management Testing}
|
||||||
|
|
||||||
\section{Criação de certificados}
|
\subsubsection*{Test Role Definitions}
|
||||||
Criar chaves com 2048 bits.
|
|
||||||
|
|
||||||
Todas as chaves foram criadas no mesmo computador, com as variaveis que está neste codigo, aspetos importantes para mais tarde serão os parametros de CN que precisam de ser passados mais tarde para aceder ao Apache e ao gateway. Numa situação normal teriamos uma autoridade de certificação para enviar e no fundo gerir todos, mas para este cenario podemos inicializar as maquinas com as chaves, requests e certificados necessarios.
|
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.
|
||||||
|
|
||||||
O codigo para gerar os certificados X.509:
|
\subsubsection*{Test User Registration Process}
|
||||||
\begin{lstlisting}[language=bash]
|
|
||||||
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
|
Utilizámos o OWASP ZAP para intercetar o tráfego de rede e definir um
|
||||||
openssl req -x509 -nodes -days 365 -key "ca.key" -out "ca.crt" -subj "$cert_ca"
|
\textit{breakpoint} no pedido HTTP POST de registo de novos utilizadores.
|
||||||
openssl genrsa -out "vpn.key" 2048
|
Modificámos o corpo do pedido JSON, injetando manualmente o parâmetro
|
||||||
openssl req -new -key "vpn.key" -out "vpn.csr" -subj "$cert_vpn"
|
\texttt{"role":"admin"}:
|
||||||
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?
|
\begin{codeblock}{json}
|
||||||
Criar chave secreta.
|
{
|
||||||
\begin{lstlisting}[language=bash]
|
"email": "johnGomas@gmail.com",
|
||||||
openssl --genkey secret ta.key
|
"role": "admin",
|
||||||
\end{lstlisting}
|
"password": "password",
|
||||||
\section{Configuração geral}
|
"passwordRepeat": "password",
|
||||||
Para configurar as VM's era preciso introduzir os mesmos comandos varias vezes, o que levava muitas vezes a erros de escrita, ou a correr o mesmo comando varias vezes, por isso criamos varios 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 cenario rapidamente.
|
"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}
|
||||||
|
|
||||||
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 relogios de todas as VMs visto que elas estarem ligeiramente atrasadas nunca conseguiamos acertar na password do google-authenticator que utiliza o tempo local para calcular a sua chave.
|
O servidor backend processou o pedido sem validar se o utilizador
|
||||||
\begin{lstlisting}[language=bash]
|
possuía autorização para definir o seu próprio perfil, o que resultou
|
||||||
yum install -y epel-release
|
na criação bem-sucedida de uma conta com permissões totais de
|
||||||
yum install -y openvpn iptables-services dhcp-client
|
administrador (\textit{Mass Assignment Vulnerability}).
|
||||||
systemctl stop firewalld
|
|
||||||
systemctl disable firewalld
|
|
||||||
systemctl mask firewalld
|
|
||||||
systemctl enable iptables
|
|
||||||
iptables -F
|
|
||||||
|
|
||||||
CA_DIR="/etc/pki/CA"
|
\subsubsection*{Testing for Account Enumeration and Guessable User Account}
|
||||||
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
|
Ao tentar registar um utilizador com o e-mail
|
||||||
mkdir -p /etc/openvpn/client
|
\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.
|
||||||
|
|
||||||
# NOTE(vasco): tive problemas com a sincronização de tempo
|
\begin{figure}[h!]
|
||||||
# se nao tiver sincronizado, o TOTP nao funciona
|
\centering
|
||||||
systemctl stop chronyd
|
\includegraphics[width=0.7\textwidth]{email-unique}
|
||||||
ntpdate pool.ntp.org
|
\caption{email-unique}
|
||||||
systemctl start chronyd
|
\label{fig:email-unique}
|
||||||
\end{lstlisting}
|
\end{figure}
|
||||||
|
|
||||||
\section{Configuração da \textit{Gateway} VPN}
|
\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ã.
|
||||||
|
|
||||||
\section{Configurar TOTP}
|
\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}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Foi criado o ficheiro \texttt{totp} com a configuração de autenticação a
|
\subsection{Authorization Testing}
|
||||||
ser utilizada pelo plugin de PAM para o openvpn.
|
|
||||||
|
|
||||||
\begin{lstlisting}[language=bash]
|
Testámos as permissões de acesso ao diretório \texttt{/ftp} e
|
||||||
plugin /usr/lib64/openvpn/plugins/openvpn-plugin-auth-pam.so totp
|
verificámos que o servidor está configurado para permitir nativamente
|
||||||
\end{lstlisting}
|
apenas a visualização de ficheiros com as extensões \texttt{.md} e
|
||||||
|
\texttt{.pdf}.
|
||||||
|
|
||||||
\subsection{Aceder ao código}
|
Seguidamente, explorámos falhas na validação de inputs através de uma
|
||||||
Primeiro, na gateway, entramos como o utilizador desejado e obtemos a chave
|
injeção de \textit{Null Byte} codificado (\texttt{\%2500.md} ou
|
||||||
do gerador de palavras passes temporarias. Ao inserir a chave no
|
\texttt{\%2500.pdf}). O ataque foi bem-sucedido e contornou a validação
|
||||||
\texttt{google authenticator} podemos obter a nossa primeira chave de 6 digitos.
|
de extensões do servidor, garantindo o acesso e descarregamento de
|
||||||
|
ficheiros confidenciais restritos: \texttt{encrypt.pyc} e
|
||||||
|
\texttt{suspicious\_errors.yml}.
|
||||||
|
|
||||||
\begin{lstlisting}[language=bash]
|
\begin{figure}[h!]
|
||||||
su john
|
\centering
|
||||||
google-authenticator
|
\includegraphics[width=0.7\textwidth]{suspiciouserrors}
|
||||||
\end{lstlisting}
|
\caption{suspiciouserrors}
|
||||||
|
\label{fig:suspiciouserrors}
|
||||||
|
\end{figure}
|
||||||
|
\begin{figure}[h!]
|
||||||
|
\centering
|
||||||
|
\includegraphics[width=0.7\textwidth]{suspiciouserrors2}
|
||||||
|
\caption{suspiciouserrors2}
|
||||||
|
\label{fig:suspiciouserrors2}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
\section{Revocation e OCSP}
|
\subsection{Session Management Testing}
|
||||||
|
|
||||||
\subsection{Testar OSCP via revoke}
|
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 Conectar ao VPN e ver que funciona
|
\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 Na maquina host, nao nas vms, na repo mesmo.
|
\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.
|
||||||
\item revogar o certificado via openssl -revoke user.crt -config cheese.cfg -keyfile ca.key -cert ca.crt
|
\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}:
|
||||||
\item Fechae OSCP e correr VM\_OPENSSL novamente (copiar index.txt e serial?)
|
\begin{codeblock}{html}
|
||||||
\item Tentar outra vez e ver que de facto falha
|
<img src="x" onerror="alert('someones gotta do it')">apple
|
||||||
|
\end{codeblock}
|
||||||
|
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:
|
||||||
|
|
||||||
|
\begin{codeblock}{bash}
|
||||||
|
sqlmap -u "http://10.60.0.1:3000/rest/products/search?q=apple" -p q --dbms=sqlite --prefix="'%" --suffix="%'--" --tables --batch
|
||||||
|
|
||||||
|
[22 tables]
|
||||||
|
+-----------------------+
|
||||||
|
| Addresses |
|
||||||
|
| BasketItems |
|
||||||
|
| Baskets |
|
||||||
|
| Captchas |
|
||||||
|
| Cards |
|
||||||
|
| ChallengeDependencies |
|
||||||
|
| Challenges |
|
||||||
|
| Complaints |
|
||||||
|
| Deliveries |
|
||||||
|
| Feedbacks |
|
||||||
|
| Hints |
|
||||||
|
| ImageCaptchas |
|
||||||
|
| Memories |
|
||||||
|
| PrivacyRequests |
|
||||||
|
| Products |
|
||||||
|
| Quantities |
|
||||||
|
| Recycles |
|
||||||
|
| SecurityAnswers |
|
||||||
|
| SecurityQuestions |
|
||||||
|
| Users |
|
||||||
|
| Wallets |
|
||||||
|
| sqlite_sequence |
|
||||||
|
+-----------------------+
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
|
||||||
\section{Conclusion}
|
Apesar de não ter sido detetado pelo active scan foi feito fuzzing nos
|
||||||
Conclusão!!!
|
detalhes de login para saber se estava vulneravel a esse tipo de ataques
|
||||||
Atingimos o objetivo deste trabalho, conseguimos configurar o VPN tunnel, o two-factor authentication e conseguimos criar e retirar acesso aos certificados que emitimos. Utilizar mais maquinas para simular um cenario maior seria redundante, teriamos que emitir mais certificados mas não iamos aprender muito mais. Para aprofundar (???)
|
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.
|
||||||
|
|
||||||
|
|
||||||
\end{document}
|
\end{document}
|
||||||
Para tal, foi implementado um servidor e um cliente OpenVPN, certificados por uma autoriadade central (CA)
|
|
||||||
que em si é self-signed. Para além disto, foi implementado um sistema de autenticação de dois factores
|
|
||||||
através do plugin google-authenticator para o OpenVPN.
|
|
||||||
|
|
||||||
Existe ainda um servidor Apache e um servidro de OpenSSL OCSP. Para simpliflicar, a elaboração do
|
|
||||||
projecto foram colocados na mesma maquina virtual, mas por razoes de seguranca poderia querer ter
|
|
||||||
estes serviços separados.
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,28 @@
|
|||||||
\babel@toc {portuguese}{}\relax
|
\babel@toc {portuguese}{}\relax
|
||||||
\contentsline {section}{\numberline {1}Introdução}{2}{}%
|
\contentsline {section}{\numberline {1}Introduction}{3}{section.1}%
|
||||||
\contentsline {section}{\numberline {2}Criação de certificados}{2}{}%
|
\contentsline {section}{\numberline {2}Architecture Considered for Both Stages}{3}{section.2}%
|
||||||
\contentsline {section}{\numberline {3}Configuração da \textit {Gateway} VPN}{3}{}%
|
\contentsline {subsection}{\numberline {2.1}Network structure}{3}{subsection.2.1}%
|
||||||
\contentsline {section}{\numberline {4}Configurar TOTP}{3}{}%
|
\contentsline {subsection}{\numberline {2.2}Servers}{3}{subsection.2.2}%
|
||||||
\contentsline {subsection}{\numberline {4.1}Aceder ao código}{3}{}%
|
\contentsline {subsection}{\numberline {2.3}Services}{3}{subsection.2.3}%
|
||||||
\contentsline {section}{\numberline {5}Revocation e OCSP}{3}{}%
|
\contentsline {section}{\numberline {3}Web application security testing}{4}{section.3}%
|
||||||
\contentsline {subsection}{\numberline {5.1}Testar OSCP via revoke}{3}{}%
|
\contentsline {subsection}{\numberline {3.1}Information Gathering}{4}{subsection.3.1}%
|
||||||
\contentsline {section}{\numberline {6}Conclusion}{4}{}%
|
\contentsline {subsection}{\numberline {3.2}Configuration and Deployment Management Testing}{4}{subsection.3.2}%
|
||||||
|
\contentsline {subsection}{\numberline {3.3}Identity Management Testing}{6}{subsection.3.3}%
|
||||||
|
\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}%
|
||||||
|
|||||||
64
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{{./imgs/}}
|
||||||
|
|
||||||
|
\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}%
|
||||||
|
|
||||||
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!
|
||||||