\documentclass[11pt,a4paper]{article}
\usepackage[portuguese]{babel}
\usepackage[lining]{ebgaramond}
\usepackage{style}

\setlength{\parindent}{0em}
\setlength{\parskip}{2ex}

\title{Practical Assignment \#3}
\author{
    João Neto -- 2023234004\\[1em]
    Vasco Alves -- 2022228207
}

\begin{document}
\maketitle

\newpage
\tableofcontents

\newpage

\section{Introduction}

% FAZER EM ENGLISH???  O prof é BR temos que fazer em Brazileiro

Este trabalho tem como objetivo realizar testes de penetração numa aplicação
cobaia (o \textit{Juicebox}) desenhada para aprendizagem. 

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}).

\section{Architecture Considered for Both Stages}

Utilizámos somente duas máquinas virtuais: um servidor a correr \textit{CentOS 9}
e um cliente a correr \textit{Kali Linux}. O servidor contém o serviço \textit{Apache},
que age como \textit{firewall} através do módulo \textit{ModSecurity}, e um servidor
\textit{Node.js} que aloja o \textit{Juicebox} --- a aplicação que vai servir de cobaia (\textit{dummy}).

% 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{center}
\section{Web application security testing}

\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}

\subsubsection*{Test Role Definitions}

Efetuámos testes de manipulação de parâmetros do lado do cliente através das ferramentas de programador do navegador. Adicionámos manualmente os cookies \texttt{isAdmin} com o valor \texttt{true} e \texttt{role} com o valor \texttt{admin}. Após a atualização da página, não observámos qualquer escalonamento de privilégios, indicando que a aplicação não valida perfis administrativos com base nestes cookies específicos.

\subsubsection*{Test User Registration Process}

Utilizámos o OWASP ZAP para intercetar o tráfego de rede e definir um \textit{breakpoint} no pedido HTTP POST de registo de novos utilizadores. Modificámos o corpo do pedido JSON, injetando manualmente o parâmetro \texttt{"role":"admin"}:

\begin{codeblock}{json}
{
  "email": "johnGomas@gmail.com",
  "role": "admin",
  "password": "password",
  "passwordRepeat": "password",
  "securityQuestion": {
    "id": 2,
    "question": "Mother's maiden name?",
    "createdAt": "2026-05-30T12:28:33.216Z",
    "updatedAt": "2026-05-30T12:28:33.216Z"
  },
  "securityAnswer": "poker"
}
\end{codeblock}

O servidor backend processou o pedido sem validar se o utilizador possuía autorização para definir o seu próprio perfil, o que resultou na criação bem-sucedida de uma conta com permissões totais de administrador (\textit{Mass Assignment Vulnerability}).

\subsubsection*{Testing for Account Enumeration and Guessable User Account}

Ao tentar registar um utilizador com o e-mail \texttt{admin@juice-sh.op}, verificámos que a aplicação devolve uma mensagem de erro explícita indicando que o e-mail já se encontra registado no sistema. Este comportamento confirma a vulnerabilidade de enumeração de contas, permitindo a um atacante mapear quais os e-mails válidos na plataforma.

\begin{figure}[h!]
    \centering
    \includegraphics[width=0.7\textwidth]{email-unique}
    \caption{email-unique}
    \label{fig:email-unique}
\end{figure}

\subsubsection*{Testing for Weak or Unenforced Username Policy}

Após testar vários caracteres especiais no formulário de registo, criámos um utilizador com os seguintes dados nos campos de input:
\begin{itemize}
    \item \textbf{E-mail:} \texttt{son'or1=1--@gmail.com}
    \item \textbf{Nome/Campos Adicionais:} \texttt{<h1>STRONG}
\end{itemize}
A aplicação aceitou o registo sem validar a presença de carateres de injeção SQL ou tags HTML. Contudo, verificámos que é impossível efetuar login com esta conta posteriormente, uma vez que o processo de autenticação falha e resulta num erro genérico do tipo \texttt{[object Object]} no ecrã.

\begin{figure}[h!]
    \centering
    \includegraphics[width=0.7\textwidth]{email-invalido}
    \caption{email-invalido}
    \label{fig:email-invalido}
\end{figure}

\subsection{Authentication Testing}

Realizámos testes de \textit{fuzzing} automatizado contra o formulário de login utilizando dicionários de credenciais. Identificámos que a aplicação não implementa mecanismos de bloqueio de conta ou limitação de taxa de pedidos \textit{rate limiting}, permitindo ataques contínuos de \textit{brute force}.



\subsection{Authorization Testing}

Testámos as permissões de acesso ao diretório \texttt{/ftp} e verificámos que o servidor está configurado para permitir nativamente apenas a visualização de ficheiros com as extensões \texttt{.md} e \texttt{.pdf}. 

Seguidamente, explorámos falhas na validação de inputs através de uma injeção de \textit{Null Byte} codificado (\texttt{\%2500.md} ou \texttt{\%2500.pdf}). O ataque foi bem-sucedido e contornou a validação de extensões do servidor, garantindo o acesso e descarregamento de ficheiros confidenciais restritos: \texttt{encrypt.pyc} e \texttt{suspicious\_errors.yml}.

\begin{figure}[h!]
    \centering
    \includegraphics[width=0.7\textwidth]{suspiciouserrors}
    \caption{suspiciouserrors}
    \label{fig:suspiciouserrors}
\end{figure}
\begin{figure}[h!]
    \centering
    \includegraphics[width=0.7\textwidth]{suspiciouserrors2}
    \caption{suspiciouserrors2}
    \label{fig:suspiciouserrors2}
\end{figure}

\subsection{Session Management Testing}

Identificámos que o cookie \texttt{token}, responsável por armazenar o identificador da sessão ativa do utilizador, possui a flag \texttt{HttpOnly} configurada como \texttt{false}. A ausência desta proteção significa que o token está totalmente exposto e pode ser lido por scripts do lado do cliente, tornando a sessão criticamente vulnerável a roubo por Cross-Site Scripting (XSS).

\subsection{Input Validation Testing}

\subsubsection*{Testing for Reflected Cross Site Scripting}

Durante a auditoria à barra de pesquisa de produtos, validámos a existência de uma vulnerabilidade de \textit{Reflected Cross-Site Scripting} (XSS) devido à ausência de higienização do input do utilizador.

\begin{enumerate}
    \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 \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 \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}:
    \begin{codeblock}{html}
<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}

\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}


Apesar de não ter sido detetado pelo active scan foi feito fuzzing nos detalhes de login para saber se estava vulneravel a esse tipo de ataques visto que existia essa vulnerabilidade noutros paremetros. Verificamos que de facto também estava vulneravel a SQL Injection, e que a resposta era a tabela com o

\subsection{Testing for Error Handling}

Ao tentar forçar o acesso a uma página ou ficheiro inexistente no servidor de ficheiros, como por exemplo na rota \texttt{/ftp/teste}, a aplicação falhou ao tratar a exceção de forma segura. Em vez de apresentar uma página de erro genérica (404), o servidor devolveu uma resposta detalhada expondo o \textit{stack trace} completo do ambiente \textit{Express.js}, revelando caminhos internos do sistema de ficheiros do servidor.



\begin{figure}[h!]
    \centering
    \includegraphics[width=0.7\textwidth]{stack-trace}
    \caption{stack-trace}
    \label{fig:stack-trace}
\end{figure}

\subsection{Client Side Testing}

Validámos que o token de sessão (JWT) do utilizador autenticado está armazenado diretamente no \texttt{localStorage} do navegador. Uma vez que o \texttt{localStorage} não possui mecanismos de proteção equivalentes à flag \texttt{HttpOnly} dos cookies, qualquer script executado no contexto da página consegue ler estes dados.

Utilizando a falha de XSS identificada anteriormente na barra de pesquisas, injetámos o seguinte payload direcionado:

\begin{codeblock}{html}
<img src="x" onerror="alert(localStorage.getItem('token'))">apple
\end{codeblock}

A execução deste vetor permitiu extrair o conteúdo do token diretamente do armazenamento local da vítima. Isto prova que um atacante pode automatizar a exfiltração destas informações e assumir a identidade de qualquer utilizador afetado sem necessitar de saber as credenciais de acesso de forma persistente.


\section{Web Application Security Firewall}

% Esta seccao sera preenchida com os resultados da Segunda Etapa (Com WAF ativada)
\subsection{Information Gathering}
\subsection{Configuration and Deployment Management Testing}
\subsection{Identity Management Testing}
\subsection{Authentication Testing}
\subsection{Authorization Testing}
\subsection{Session Management Testing}
\subsection{Input Validation Testing}
\subsection{Testing for Error Handling}
\subsection{Client Side Testing}

\section{Conclusions}

\end{document}
