diff --git a/report/report.pdf b/report/report.pdf
index 3e1bd40..989afd4 100644
Binary files a/report/report.pdf and b/report/report.pdf differ
diff --git a/report/report.tex b/report/report.tex
index 82f5306..28b7602 100755
--- a/report/report.tex
+++ b/report/report.tex
@@ -70,9 +70,12 @@
\usepackage{amsmath, amssymb, amsfonts}
\usepackage{graphicx}
+\usepackage{caption}
\usepackage{subcaption}
\usepackage{float}
+\captionsetup[figure]{name=Εικόνα}
+
% Requires: -shell-escape compile argument
\usepackage{minted}
\usepackage{xcolor} %
@@ -84,10 +87,11 @@
baselinestretch=1.1,
tabsize=2,
numbersep=8pt,
+ startinline,
gobble=0
}
-\setminted[σ;λ]{
+\setminted[sql]{
fontsize=\small,
breaklines,
autogobble,
@@ -126,8 +130,8 @@
Τα παραδοτέα της εργασίας αποτελούνται από:
\begin{itemize}
\item Την παρούσα αναφορά.
- \item Τον κατάλογο
- \item Το \href{\repo}{σύνδεσμο} με το αποθετήριο που περιέχει όλο το project με τον κώδικα της εφαρμογής, τον κώδικα της αναφοράς, τις διορθώσεις και τα παραδοτέα.
+ \item Τον κατάλογο \textit{passman-dev/} με τον κώδικα της εφαρμογής μετά τις αλλαγές.
+ \item Το \href{\repo}{σύνδεσμο} με το αποθετήριο που περιέχει όλο το project με τον κώδικα της εφαρμογής, τον κώδικα της αναφοράς, τα branch των διορθώσεων και τα παραδοτέα.
\end{itemize}
\section{Περιγραφή της εφαρμογής}
@@ -160,17 +164,18 @@
\section{Περιβάλλον δοκιμών και μεταφορά σε Docker}
-Πριν την ανάλυση των κενών ασφάλειας κρίθηκε απαραίτητο να δημιουργηθεί ένα ελεγχόμενο και αναπαραγώγιμο περιβάλλον δοκιμών.
-Αντί της χρήσης του προτεινόμενου περιβάλλοντος XAMPP, επιλέχθηκε η μεταφορά (porting) της εφαρμογής σε περιβάλλον Docker, το οποίο θεωρείται πιο σύγχρονη και ευέλικτη λύση.
+Πριν την ανάλυση των κενών ασφάλειας κρίθηκε απαραίτητο να δημιουργηθεί ένα \textbf{ελεγχόμενο και αναπαραγώγιμο} περιβάλλον δοκιμών.
+Αντί της χρήσης του προτεινόμενου περιβάλλοντος XAMPP, επιλέχθηκε η μεταφορά (porting) της εφαρμογής σε περιβάλλον \textbf{Docker}, το οποίο θεωρείται πιο σύγχρονη και ευέλικτη λύση.
Η επιλογή του Docker επιτρέπει την ακριβή καθοδήγηση των εκδόσεων λογισμικού που χρησιμοποιούνται, την εύκολη αναπαραγωγή του περιβάλλοντος σε διαφορετικά συστήματα και τον σαφή διαχωρισμό των επιμέρους υπηρεσιών.
-Συγκεκριμένα, η εφαρμογή διαχωρίστηκε σε δύο containers:
-έναν web server (Apache με PHP) και έναν database server (MariaDB).
+Συγκεκριμένα, η εφαρμογή διαχωρίστηκε αρχικά σε δύο containers: έναν web server (Apache με PHP) και έναν database server (MariaDB).
+Τον MariaDB τον χρησιμοποιούμε από το επίσημο αποθετήριο, αλλά τον web, τον χτίζουμε με δικό μας Dockerfile.
+Στο τέλος της διαδικασίας προστέθηκε ένας ακόμα (caddy) που αναλαμβάνει το reverse proxy για το https.
Κατά τη διαδικασία μεταφοράς απαιτήθηκαν ορισμένες στοχευμένες αλλαγές:
\begin{itemize}
\item \textbf{Διαχείριση HTTP headers και sessions}:
- Σε αντίθεση με το XAMPP, το περιβάλλον Docker χρησιμοποιεί αυστηρότερες ρυθμίσεις όσον αφορά την αποστολή HTTP headers.
+ Σε αντίθεση με το XAMPP, το περιβάλλον του Apache-php στο Docker χρησιμοποιεί αυστηρότερες ρυθμίσεις όσον αφορά την αποστολή HTTP headers.
Αυτό αποκάλυψε προβλήματα στη ροή του κώδικα, όπου HTML output προηγούνταν κλήσεων όπως \textit{session\_start()} και \textit{header()}.
Η λύση ήταν η αναδιάταξη του κώδικα, ώστε όλη η λογική ελέγχου και ανακατεύθυνσης να εκτελείται πριν από οποιοδήποτε HTML output.
@@ -199,7 +204,8 @@ docker compose up -d --build
Τα δεδομένα της βάσης αποθηκεύονται σε Docker named volume, εξασφαλίζοντας τη διατήρησή τους μεταξύ επανεκκινήσεων των containers.
Μετά την επιτυχή εκκίνηση, η εφαρμογή είναι προσβάσιμη μέσω web browser στη διεύθυνση:\\
-\texttt{http://localhost/passman}
+\texttt{http://localhost/passman}.\\
+Για περισσότερες πληροφορίες μπορείτε να επισκεφτείτε το \href{\repo}{αποθετήριο} της εφαρμογής.
Για λόγους δοκιμών και ανάλυσης, είναι επίσης δυνατή η απευθείας πρόσβαση στη βάση δεδομένων μέσω τερματικού, χρησιμοποιώντας την εντολή:
\begin{minted}[fontsize=\small]{bash}
@@ -212,20 +218,17 @@ docker compose exec db mariadb -uroot -prootpass
\label{sec:sqli}
Το πρώτο κενό ασφάλειας που εξετάζεται αφορά την ευπάθεια σε επιθέσεις SQL Injection.
-Η ευπάθεια αυτή προκύπτει όταν δεδομένα που παρέχονται από τον χρήστη ενσωματώνονται απευθείας σε SQL εντολές, χωρίς κατάλληλη επικύρωση ή χρήση μηχανισμών παραμετροποίησης (prepared statements).
+Η ευπάθεια αυτή προκύπτει όταν δεδομένα που παρέχονται από τον χρήστη \textbf{ενσωματώνονται απευθείας} σε SQL εντολές, χωρίς κατάλληλη επικύρωση ή χρήση μηχανισμών παραμετροποίησης (prepared statements).
Αποτέλεσμα είναι ο επιτιθέμενος να μπορεί να αλλοιώσει τη λογική του SQL query, οδηγώντας σε μη εξουσιοδοτημένη πρόσβαση ή/και διαρροή δεδομένων.
-Στην εφαρμογή, η ευπάθεια εντοπίζεται σε πολλά σημεία και παρότι θα τα λύσουμε όλα εδώ παραθέτουμε ως παράδειγμα την ευπάθεια στο \textit{login.php}, καθώς αυτό είναι ίσως οτ πιο σοβαρό.
+Στην εφαρμογή, η ευπάθεια εντοπίζεται σε πολλά σημεία και παρότι θα τα λύσουμε όλα, εδώ παραθέτουμε ως παράδειγμα την ευπάθεια στο \textit{login.php}, καθώς αυτό είναι ίσως οτ πιο σοβαρό.
Η είσοδος του χρήστη (username/password), όπως φαίνεται στο απόσπασμα παρακάτω, εισάγεται απευθείας στο query αυθεντικοποίησης μέσω string concatenation.
\begin{minted}{php}
$sql_query =
"SELECT * FROM login_users WHERE username='{$username}' AND password='{$password}';";
-// The SQL query is constructed by directly concatenating user-controlled input.
-// This enables SQL injection, because the attacker can break out of the quoted string
-// and inject additional SQL conditions (e.g., OR 1=1), bypassing authentication.
\end{minted}
\label{lst:sqli-login-query}
-Στο συγκεκριμένο σημείο, το περιεχόμενο των μεταβλητών \textit{\$username} και \textit{\$password} δεν υφίσταται κανέναν έλεγχο ή escaping.
+Στο συγκεκριμένο σημείο, το περιεχόμενο των μεταβλητών \textit{\$username} και \textit{\$password} \textbf{δεν υφίσταται κανέναν έλεγχο ή escaping}.
Επομένως, ένας επιτιθέμενος μπορεί να εισάγει ειδικούς χαρακτήρες (π.χ. \texttt{'}) και SQL τελεστές (π.χ. \texttt{OR}) ώστε να παρακάμψει τη συνθήκη αυθεντικοποίησης.
\begin{figure}[!ht]
@@ -271,18 +274,17 @@ $sql_query =
\label{fig:sqli_db_users}
\end{figure}
-Η συγκεκριμένη ευπάθεια θεωρείται ιδιαίτερα σοβαρή, καθώς υπονομεύει πλήρως τον μηχανισμό αυθεντικοποίησης και επιτρέπει μη εξουσιοδοτημένη πρόσβαση σε ευαίσθητα δεδομένα.
-Στα επόμενα τμήματα παρουσιάζεται η αντιμετώπισή της με χρήση prepared statements, ώστε τα δεδομένα του χρήστη να μην μπορούν να επηρεάσουν τη σύνταξη της SQL εντολής.
+Η συγκεκριμένη ευπάθεια θεωρείται \textbf{ιδιαίτερα σοβαρή}, καθώς υπονομεύει πλήρως τον μηχανισμό αυθεντικοποίησης και \textbf{επιτρέπει μη εξουσιοδοτημένη πρόσβαση σε ευαίσθητα δεδομένα}.
\subsection{Αντιμετώπιση SQL Injection}
\label{sec:sqli_fix}
Η αντιμετώπιση του SQL Injection βασίζεται στη θεμελιώδη αρχή του διαχωρισμού \textit{δεδομένων} από \textit{εντολές}.
-Το πρόβλημα στην αρχική υλοποίηση προέκυπτε επειδή το SQL query κατασκευαζόταν μέσω απλής συνένωσης (string concatenation) με δεδομένα που παρείχε ο χρήστης.
+Το πρόβλημα στην αρχική υλοποίηση προέκυπτε επειδή το SQL query κατασκευαζόταν μέσω \textbf{απλής συνένωσης (string concatenation)} με δεδομένα που παρείχε ο χρήστης.
Έτσι, ειδικοί χαρακτήρες και τελεστές SQL μπορούσαν να εισαχθούν ως μέρος της συμβολοσειράς, με αποτέλεσμα να αλλοιώνεται η σύνταξη και η λογική της SQL εντολής.
-Η καθιερωμένη πρακτική αντιμετώπισης, η οποία προτείνεται τόσο από τις επίσημες οδηγίες ασφαλούς κωδικοποίησης (secure coding guidelines) όσο και από τον οργανισμό OWASP (Open Worldwide Application Security Project), είναι η χρήση \textit{prepared statements} με παραμέτρους (parameterized queries).
-Με τη χρήση prepared statements, ο SQL server λαμβάνει πρώτα το statement (template) και στη συνέχεια τις παραμέτρους ως δεδομένα, χωρίς να επιτρέπεται η ερμηνεία τους ως τμήμα της SQL σύνταξης.
+Η καθιερωμένη πρακτική αντιμετώπισης, η οποία προτείνεται τόσο από τις επίσημες οδηγίες ασφαλούς κωδικοποίησης (secure coding guidelines) όσο και από τον οργανισμό OWASP (Open Worldwide Application Security Project), είναι η χρήση \textbf{prepared statements} με παραμέτρους (parameterized queries).
+Με τη χρήση prepared statements, ο SQL server λαμβάνει πρώτα το statement (template) και στη συνέχεια τις \textbf{παραμέτρους ως δεδομένα}, χωρίς να επιτρέπεται η ερμηνεία τους ως τμήμα της SQL σύνταξης.
Ως αποτέλεσμα, οποιαδήποτε κακόβουλη είσοδος αντιμετωπίζεται ως απλό κείμενο (data) και όχι ως εκτελέσιμο SQL.
\subsection{Υλοποίηση της διόρθωσης}
@@ -350,55 +352,46 @@ $sql_query =
\subsection{Περαιτέρω σημεία ευπάθειας σε SQL Injection}
-Πέρα από το αρχικό κενό ασφάλειας στον μηχανισμό αυθεντικοποίησης, εντοπίστηκαν επιπλέον σημεία στην εφαρμογή όπου SQL εντολές κατασκευάζονταν δυναμικά μέσω συνένωσης συμβολοσειρών με δεδομένα προερχόμενα από τον χρήστη ή από session μεταβλητές.
+Πέρα από το αρχικό κενό ασφάλειας στον μηχανισμό αυθεντικοποίησης, εντοπίστηκαν \textbf{επιπλέον σημεία} στην εφαρμογή όπου SQL εντολές κατασκευάζονταν δυναμικά μέσω συνένωσης συμβολοσειρών με δεδομένα προερχόμενα από τον χρήστη ή από session μεταβλητές.
Τα σημεία αυτά δημιουργούν πρόσθετες επιφάνειες επίθεσης και καθιστούν την εφαρμογή ευάλωτη σε άμεσες ή έμμεσες (second-order) επιθέσεις SQL Injection.
\subsubsection{Εγγραφή νέων χρηστών (\textit{register.php})}
Στο αρχείο \textit{register.php}, η εγγραφή νέου χρήστη υλοποιούνταν με απευθείας ενσωμάτωση των πεδίων \textit{username} και \textit{password} σε εντολή \texttt{INSERT}.
-Το Απόσπασμα~\ref{lst:sqli-register} παρουσιάζει τον προβληματικό κώδικα.
-
+Το Απόσπασμα παρακάτω παρουσιάζει τον προβληματικό κώδικα:
\begin{minted}{php}
// Vulnerable SQL construction: user-controlled input is concatenated directly.
$sql_query = "INSERT INTO login_users (username,password)
- VALUES ('{$new_username}','{$new_password}');";
+ VALUES ('{$new_username}','{$new_password}');";
$result = $conn->query($sql_query);
\end{minted}
\label{lst:sqli-register}
-Η πρακτική αυτή επιτρέπει την αλλοίωση της SQL σύνταξης μέσω κατάλληλης εισόδου, καθιστώντας δυνατή την εκτέλεση αυθαίρετων SQL εντολών.
-Η διόρθωση πραγματοποιήθηκε με χρήση prepared statements και δεσμευμένων παραμέτρων.
-
\subsubsection{Αποθήκευση σημειώσεων (\textit{notes.php})}
Στο \textit{notes.php}, η αποθήκευση νέων σημειώσεων πραγματοποιούνταν με δυναμική κατασκευή εντολής \texttt{INSERT}, η οποία περιλάμβανε τόσο το περιεχόμενο της σημείωσης όσο και το \textit{username} του συνδεδεμένου χρήστη.
-Ο προβληματικός κώδικας φαίνεται στο Απόσπασμα~\ref{lst:sqli-notes}.
-
+Ο προβληματικός κώδικας φαίνεται στο Απόσπασμα εδώ:
\begin{minted}{php}
// Vulnerable SQL construction: note content and session data are injected into SQL.
$sql_query = "INSERT INTO notes (login_user_id, note)
- VALUES ((SELECT id FROM login_users
- WHERE username='{$username}'), '{$new_note}')";
+ VALUES ((SELECT id FROM login_users WHERE username='{$username}'), '{$new_note}')";
$result = $conn->query($sql_query);
\end{minted}
\label{lst:sqli-notes}
Παρότι το \textit{username} προέρχεται από session μεταβλητή, δεν μπορεί να θεωρηθεί έμπιστο, καθώς μπορεί να αλλοιωθεί σε σενάρια XSS ή session hijacking.
-Η διόρθωση βασίστηκε στη χρήση prepared statements τόσο για το υποερώτημα όσο και για το περιεχόμενο της σημείωσης.
\subsubsection{Διαχείριση διαπιστευτηρίων ιστοσελίδων (\textit{dashboard.php})}
Στο αρχείο \textit{dashboard.php} εντοπίστηκαν πολλαπλά σημεία SQL Injection που αφορούν την εισαγωγή, διαγραφή και προβολή αποθηκευμένων διαπιστευτηρίων.
-Ενδεικτικά, το Απόσπασμα~\ref{lst:sqli-dashboard-insert} δείχνει τον τρόπο εισαγωγής νέας εγγραφής.
-
+Ενδεικτικά, το Απόσπασμα παρακάτω δείχνει τον τρόπο εισαγωγής νέας εγγραφής:
\begin{minted}{php}
// Vulnerable SQL construction: multiple user-controlled fields concatenated.
$sql_query = "INSERT INTO websites (login_user_id,web_url,web_username,web_password)
- VALUES ((SELECT id FROM login_users
- WHERE username='{$username}'),
- '{$new_website}','{$new_username}','{$new_password}');";
+ VALUES ((SELECT id FROM login_users WHERE username='{$username}'),
+ '{$new_website}','{$new_username}','{$new_password}');";
$result = $conn->query($sql_query);
\end{minted}
\label{lst:sqli-dashboard-insert}
-Αντίστοιχα, η διαγραφή εγγραφών βασιζόταν σε δυναμικά κατασκευασμένη εντολή \texttt{DELETE}, όπως φαίνεται στο Απόσπασμα~\ref{lst:sqli-dashboard-delete}.
+Αντίστοιχα, η διαγραφή εγγραφών βασιζόταν σε δυναμικά κατασκευασμένη εντολή \texttt{DELETE}, όπως φαίνεται στο επόμενο Απόσπασμα.
\begin{minted}{php}
// Vulnerable DELETE statement: identifier injected directly into SQL.
@@ -411,14 +404,13 @@ $sql_query =
\begin{minted}{php}
// Vulnerable SELECT statement: session data treated as trusted input.
$sql_query = "SELECT * FROM websites
- INNER JOIN login_users
- ON websites.login_user_id=login_users.id
- WHERE login_users.username='{$username}';";
+ INNER JOIN login_users ON websites.login_user_id=login_users.id
+ WHERE login_users.username='{$username}';";
$result = $conn->query($sql_query);
\end{minted}
\label{lst:sqli-dashboard-select}
-Η συνολική αντιμετώπιση των παραπάνω σημείων βασίστηκε στην ίδια αρχή με το αρχικό SQL Injection, ότι καμία τιμή που επηρεάζει τη σύνταξη SQL εντολής δεν ενσωματώνεται πλέον απευθείας στο query.
+Η συνολική αντιμετώπιση των παραπάνω σημείων βασίστηκε στην ίδια αρχή με το αρχικό SQL Injection, ότι \textbf{καμία τιμή που επηρεάζει τη σύνταξη SQL εντολής δεν ενσωματώνεται πλέον απευθείας στο query}.
Όλα τα παραπάνω αντικαταστάθηκαν με prepared statements και δεσμευμένες παραμέτρους, εξαλείφοντας τόσο άμεσα όσο και έμμεσα σενάρια SQL Injection.
Ο αναγνώστης μπορεί \href{\fixsqlitag}{εδώ} να βρει το branch με όλες τις αλλαγές.
@@ -436,10 +428,9 @@ $sql_query =
Η ευπάθεια προκύπτει όταν περιεχόμενο που εισάγει ο χρήστης αποθηκεύεται στη βάση δεδομένων και στη συνέχεια προβάλλεται -- πιθανόν σε άλλους χρήστες -- χωρίς κατάλληλη κωδικοποίηση εξόδου (output encoding).
Ως αποτέλεσμα, κακόβουλος κώδικας JavaScript μπορεί να εκτελεστεί στον browser του θύματος με τα δικαιώματα του αντίστοιχου session.
-\subsection{Root cause στον κώδικα}
+\subsection{XSS στο \textit{notes.php}}
Στο \textit{notes.php}, οι αποθηκευμένες σημειώσεις προβάλλονται απευθείας μέσα σε HTML με χρήση \texttt{echo}, χωρίς escaping.
-Ενδεικτικά, το Απόσπασμα~\ref{lst:xss-notes-echo} δείχνει το προβληματικό σημείο: το \texttt{\$row["note"]} (δεδομένο από τη βάση) θεωρείται ως έμπιστο και εισάγεται αυτούσιο στο DOM.
-
+Ενδεικτικά, το Απόσπασμα παρακάτω δείχνει το προβληματικό σημείο: το \texttt{\$row["note"]} (δεδομένο από τη βάση) θεωρείται ως έμπιστο και εισάγεται αυτούσιο στο DOM.
\begin{minted}{php}
while ($row = $result -> fetch_assoc()) {
echo "
";
@@ -521,7 +512,7 @@ $sql_query =
\subsubsection{Session hijacking demonstration μέσω \textit{usecookie.php}}
\label{sec:xss_hijack}
-Ο αντίκτυπος της ευπάθειας είναι ιδιαίτερα σοβαρός, καθώς το session cookie μπορεί να χρησιμοποιηθεί για πλαστοπροσωπία (session hijacking).
+Ο αντίκτυπος της ευπάθειας είναι ιδιαίτερα σοβαρός, καθώς το \textbf{session cookie μπορεί να χρησιμοποιηθεί για πλαστοπροσωπία} (session hijacking).
Στην Εικόνα~\ref{fig:xss_usecookie} φαίνεται η χρήση του \textit{usecookie.php} με παράμετρο το κλεμμένο \texttt{PHPSESSID}.
Στη συνέχεια, η πρόσβαση σε προστατευμένη σελίδα της εφαρμογής (π.χ. \textit{dashboard.php}) είναι εφικτή ως ο χρήστης-θύμα, όπως φαίνεται στην Εικόνα~\ref{fig:xss_dashboard_after_hijack}.
@@ -543,15 +534,13 @@ $sql_query =
\end{figure}
Με βάση τα παραπάνω, επιβεβαιώνεται ότι η εφαρμογή επιτρέπει αποθήκευση και εκτέλεση κακόβουλου JS κώδικα μέσω του μηχανισμού σημειώσεων, με αποτέλεσμα τόσο την εξαγωγή cookies όσο και την πρακτική επίδειξη πλαστοπροσωπίας.
-Στα επόμενα τμήματα παρουσιάζεται η αντιμετώπιση της ευπάθειας με \textit{context-aware output encoding}, ώστε το περιεχόμενο της βάσης να αντιμετωπίζεται ως μη-έμπιστο και να προβάλλεται με ασφάλεια.
-
\subsection{Αντιμετώπιση Stored XSS στο \textit{notes.php}}
\label{sec:xss_fix}
-Η αντιμετώπιση του Stored XSS βασίζεται στην αρχή ότι \textit{οποιοδήποτε περιεχόμενο προέρχεται από τον χρήστη ή/και τη βάση δεδομένων πρέπει να θεωρείται μη-έμπιστο}.
+Η αντιμετώπιση του Stored XSS βασίζεται στην αρχή ότι \textbf{οποιοδήποτε περιεχόμενο προέρχεται από τον χρήστη ή/και τη βάση δεδομένων πρέπει να θεωρείται μη-έμπιστο}.
Στην αρχική υλοποίηση, το περιεχόμενο των σημειώσεων εμφανιζόταν απευθείας στο HTML, με αποτέλεσμα ο browser να το ερμηνεύει ως markup και να εκτελεί τυχόν ενσωματωμένο JavaScript.
-Η καθιερωμένη πρακτική για την αποτροπή XSS σε \textit{HTML body context} είναι το \textit{context-aware output encoding}, δηλαδή η κωδικοποίηση ειδικών χαρακτήρων (π.χ. \texttt{<}, \texttt{>}, \texttt{"}, \texttt{'}) πριν από την προβολή τους.
+Η καθιερωμένη πρακτική για την αποτροπή XSS σε \textit{HTML body context} είναι το \textbf{context-aware output encoding}, δηλαδή η κωδικοποίηση ειδικών χαρακτήρων (π.χ. \texttt{<}, \texttt{>}, \texttt{"}, \texttt{'}) πριν από την προβολή τους.
Με αυτόν τον τρόπο, ακόμη και αν στη βάση υπάρχουν αποθηκευμένα payloads, αυτά προβάλλονται ως απλό κείμενο και δεν είναι δυνατόν να εκτελεστούν.
\subsubsection{Υλοποίηση της διόρθωσης}
@@ -588,11 +577,11 @@ $sql_query =
\label{fig:xss_fix_weblogs}
\end{figure}
-Συνεπώς, η εφαρμογή \textit{context-aware output encoding} στο σημείο προβολής εξαλείφει την εκτέλεση αποθηκευμένων XSS payloads στο συγκεκριμένο context, διατηρώντας αμετάβλητη τη λειτουργικότητα της εφαρμογής.
+Συνεπώς, η εφαρμογή \textit{context-aware output encoding} στο σημείο προβολής \textbf{εξαλείφει την εκτέλεση αποθηκευμένων XSS payloads} στο συγκεκριμένο context, διατηρώντας αμετάβλητη τη λειτουργικότητα της εφαρμογής.
\subsection{Επέκταση της αντιμετώπισης XSS στα επιπλέον σημεία}
-Η ευπάθεια Stored XSS που παρουσιάστηκε μέσω της λειτουργίας σημειώσεων δεν αποτελεί μεμονωμένο περιστατικό, αλλά ενδεικτικό ενός γενικότερου προγραμματιστικού μοτίβου στην εφαρμογή.
+Η ευπάθεια Stored XSS που παρουσιάστηκε μέσω της λειτουργίας σημειώσεων \textbf{δεν αποτελεί μεμονωμένο περιστατικό}, αλλά ενδεικτικό ενός γενικότερου προγραμματιστικού μοτίβου στην εφαρμογή.
Δεδομένα προερχόμενα από χρήστες ή από τη βάση δεδομένων προβάλλονταν απευθείας στο HTML χωρίς κατάλληλη κωδικοποίηση εξόδου.
Για τον λόγο αυτό πραγματοποιήθηκε εκτενέστερη ανάλυση και εντοπίστηκαν επιπλέον σημεία με δυνητική ή άμεση ευπάθεια σε XSS.
@@ -607,7 +596,7 @@ $sql_query =
\end{minted}
Η πρακτική αυτή επιτρέπει την αποθήκευση και εκτέλεση κακόβουλου HTML ή JavaScript κώδικα (\textit{Stored XSS}), με εκτέλεση του payload κάθε φορά που προβάλλεται η σελίδα.
-Η αντιμετώπιση πραγματοποιήθηκε με εφαρμογή \textit{context-aware output encoding} σε όλα τα αντίστοιχα πεδία.
+
\subsubsection{Εμφάνιση ονόματος χρήστη από session (\textit{dashboard.php})}
Στην ίδια σελίδα, το όνομα του συνδεδεμένου χρήστη εμφανιζόταν στο header της σελίδας.
@@ -619,7 +608,7 @@ $sql_query =
Παρότι τα session δεδομένα συχνά θεωρούνται έμπιστα, στην πράξη μπορούν να αλλοιωθούν σε σενάρια XSS, session hijacking ή cookie tampering.
-Η συγκεκριμένη περίπτωση αποτελεί χαρακτηριστικό παράδειγμα \textit{second-order XSS}.
+Η συγκεκριμένη περίπτωση αποτελεί χαρακτηριστικό παράδειγμα \textbf{second-order XSS}.
Η αντιμετώπιση βασίστηκε στην κωδικοποίηση της τιμής πριν την εμφάνιση της.
\subsubsection{Reflected XSS σε μηνύματα σφάλματος (\textit{login.php}, \textit{register.php})}
@@ -631,8 +620,8 @@ $sql_query =
\end{minted}
-Στην παρούσα υλοποίηση, οι μεταβλητές αυτές λαμβάνουν μόνο στατικές συμβολοσειρές και δεν ενσωματώνουν δεδομένα εισόδου χρήστη.
-Ως εκ τούτου, δεν είναι πρακτικά εκμεταλλεύσιμες για Reflected XSS στην τρέχουσα μορφή της εφαρμογής.
+Στην παρούσα υλοποίηση, οι μεταβλητές αυτές λαμβάνουν μόνο \textbf{στατικές συμβολοσειρές} και δεν ενσωματώνουν δεδομένα εισόδου χρήστη.
+Ως εκ τούτου, δεν είναι πρακτικά εκμεταλλεύσιμες για \textit{reflected XSS} στην τρέχουσα μορφή της εφαρμογής.
Για τον λόγο αυτό, δεν πραγματοποιήθηκε περαιτέρω εκμετάλλευση, αλλά το σημείο καταγράφεται ως θεωρητικό σενάριο που θα απαιτούσε αντιμετώπιση σε μελλοντική επέκταση της εφαρμογής.
Ο αναγνώστης μπορεί \href{\fixxsstag}{εδώ} να βρει το branch με όλες τις αλλαγές.
@@ -644,34 +633,31 @@ $sql_query =
\section{Αποθήκευση κωδικών αυθεντικοποίησης σε απλό κείμενο}
\label{subsec:plaintext-auth}
-Η εφαρμογή, στην αρχική της υλοποίηση, διαχειριζόταν τους κωδικούς αυθεντικοποίησης των χρηστών (login passwords) ως απλό κείμενο (plaintext).
+Η εφαρμογή, στην αρχική της υλοποίηση, διαχειριζόταν τους \textbf{κωδικούς} αυθεντικοποίησης των χρηστών (login passwords) ως \textbf{απλό κείμενο (plaintext)}.
Το πρόβλημα αυτό εμφανίζεται σε περισσότερα του ενός σημεία της εφαρμογής:
\begin{enumerate}
\item \textbf{Πίνακας βάσης δεδομένων \texttt{login\_users}:}
Οι κωδικοί πρόσβασης αποθηκεύονταν αυτούσιοι στη βάση δεδομένων, γεγονός που μπορεί να επιβεβαιωθεί με απευθείας ερώτημα SQL.
+ Η αποθήκευση του κωδικού σε απλό κείμενο είναι άμεσα ορατή και στο περιεχόμενο της βάσης δεδομένων, όπως φαίνεται στην Εικόνα~\ref{fig:pltxt_vuln_logins}.
+ \begin{figure}[!ht]
+ \centering
+ \includegraphics[width=0.7\textwidth]{img/pltxt-VulnLogins.png}
+ \caption{Κωδικοί χρηστών σε απλό κείμενο.}
+ \label{fig:pltxt_vuln_logins}
+ \end{figure}
\item \textbf{Διαδικασία εγγραφής χρήστη (\texttt{register.php}):}
Ο κωδικός που εισάγεται από τον χρήστη αποθηκευόταν στη βάση χωρίς καμία μορφή μετασχηματισμού (hashing).
+ \begin{minted}{php}
+ $sql_query = "INSERT INTO login_users (username,password) VALUES
+ ('{$new_username}','{$new_password}');";
+ $result = $conn->query($sql_query);
+ \end{minted}
\item \textbf{Διαδικασία σύνδεσης χρήστη (\texttt{login.php}):}
- Η αυθεντικοποίηση πραγματοποιούνταν με άμεση σύγκριση του κωδικού που εισάγει ο χρήστης με τον αποθηκευμένο κωδικό, μέσω της SQL εντολής \texttt{WHERE username = ? AND password = ?}.
-
- \item \textbf{Αποθήκευση κωδικών τρίτων ιστοσελίδων (\texttt{dashboard.php}):}
- Οι κωδικοί πρόσβασης ιστοσελίδων αποθηκεύονται και εμφανίζονται επίσης ως απλό κείμενο. Το συγκεκριμένο ζήτημα αναλύεται ξεχωριστά σε επόμενη ενότητα, καθώς απαιτεί διαφορετική προσέγγιση (κρυπτογράφηση αντί για hashing).
-\end{enumerate}
-
-\subsection{Επιπτώσεις ασφάλειας και σενάρια εκμετάλλευσης}
-
-Η αποθήκευση κωδικών αυθεντικοποίησης σε απλό κείμενο αυξάνει δραματικά τον αντίκτυπο οποιασδήποτε παραβίασης της βάσης δεδομένων.
-Σε περίπτωση που ένας επιτιθέμενος αποκτήσει πρόσβαση ανάγνωσης στη βάση (π.χ. μέσω SQL Injection, διαρροής backup ή εσφαλμένων δικαιωμάτων), μπορεί να ανακτήσει άμεσα όλους τους κωδικούς χρηστών χωρίς καμία επιπλέον προσπάθεια.
-
-Επιπλέον, επειδή η αυθεντικοποίηση βασιζόταν σε σύγκριση plaintext τιμών εντός της SQL εντολής, η διαρροή του πίνακα \texttt{login\_users} οδηγεί άμεσα σε πλήρη παραβίαση όλων των λογαριασμών, χωρίς να απαιτείται σπάσιμο (cracking) κωδικών ή hashes.
-
-\subsection{Ευάλωτη υλοποίηση}
-Στην αρχική υλοποίηση, η σύγκριση του κωδικού πραγματοποιούνταν απευθείας μέσα στη SQL εντολή αυθεντικοποίησης.
-
-\begin{minted}{php}
+ Η αυθεντικοποίηση πραγματοποιούνταν μέσω της SQL εντολής \texttt{WHERE username = ? AND password = ?}, με άμεση σύγκριση του κωδικού που εισάγει ο χρήστης με τον αποθηκευμένο κωδικό.
+ \begin{minted}{php}
$sql_query = "SELECT * FROM login_users WHERE username='{$username}'
AND password='{$password}';";
$result = $conn->query($sql_query);
@@ -681,31 +667,49 @@ $sql_query =
$_SESSION['loggedin'] = true;
// ...
}
-\end{minted}
+ \end{minted}
-Αντίστοιχα, κατά την εγγραφή νέου χρήστη, ο κωδικός αποθηκευόταν αυτούσιος στη βάση δεδομένων.
-\begin{minted}{php}
- $sql_query = "INSERT INTO login_users (username,password) VALUES
- ('{$new_username}','{$new_password}');";
- $result = $conn->query($sql_query);
-\end{minted}
+ \item \textbf{Αποθήκευση κωδικών τρίτων ιστοσελίδων (\texttt{dashboard.php}):}
+ Οι κωδικοί πρόσβασης ιστοσελίδων αποθηκεύονται και εμφανίζονται επίσης ως απλό κείμενο.
+ Η λύση του συγκεκριμένου ζητήματος απαιτεί τη δημιουργία επιπλέον κώδικα για την κωδικοποίηση και αποκωδικοποίηση των δεδομένων, αλλά και αρκετές αλλαγές σε επίπεδο αρχητεκτονικής.
+ Για παράδειγμα πρέπει να αποφασιστεί που θα αποθηκεύονται τα κλειδιά κωδικοποίησης, πως θα γίνει η αναδιάρθρωση του κώδικα για να αρχικοποιούνται τα κλειδιά κλπ.
+ Για το λόγο αυτό \textbf{η υλοποίησή κρίθηκε εκτός ορίων για τη συγκεκριμένη εργασία}.
-Η αποθήκευση του κωδικού σε απλό κείμενο είναι άμεσα ορατή και στο περιεχόμενο
-της βάσης δεδομένων, όπως φαίνεται στο αντίστοιχο στιγμιότυπο οθόνης.
-\begin{figure}[!ht]
- \centering
- \includegraphics[width=0.7\textwidth]{img/pltxt-VulnLogins.png}
- \caption{Κωδικοί χρηστών σε απλό κείμενο.}
- \label{fig:pltxt_vuln_logins}
-\end{figure}
+ Αν όμως θα υλοποιούσαμε τέτοια αλλαγή, η λύση θα έπρεπε να προσθέσει ένα νέο αρχείο, π.χ. \textit{crypto.php}, το οποίο θα περιείχε βοηθητικές συναρτήσεις συμμετρικής κρυπτογράφησης με authenticated encryption (π.χ. AES-256-GCM).
+ Ενδεικτικά:
+ \begin{enumerate}
+ \item \textbf{\texttt{pm\_get\_key()}}: ανάκτηση του μυστικού κλειδιού από environment variable (π.χ. \texttt{APP\_ENC\_KEY}) και παραγωγή σταθερού 32-byte key (π.χ. με \texttt{hash('sha256', ... , true)}), ώστε το κλειδί να μην βρίσκεται ποτέ hard-coded στο repository.
+
+ \item \textbf{\texttt{pm\_encrypt(\$plaintext)}}: κρυπτογράφηση του password πριν την αποθήκευση, με τυχαίο IV (\texttt{random\_bytes}) και παραγωγή authentication tag, και επιστροφή ενός base64 blob (π.χ. \texttt{base64(iv || tag || cipher)}) κατάλληλου για αποθήκευση σε \texttt{VARCHAR}.
+
+ \item \textbf{\texttt{pm\_decrypt(\$blob)}}: αποκρυπτογράφηση του αποθηκευμένου blob κατά την προβολή, με έλεγχο εγκυρότητας (base64 + μήκος + tag), και (προαιρετικά) fallback σε plaintext για παλαιές εγγραφές ώστε να διευκολυνθεί η μετάβαση (migration).
+ \end{enumerate}
+
+ Στη συνέχεια, θα έπρεπε να γίνουν στοχευμένες αλλαγές στο \textit{dashboard.php}:
+ \begin{enumerate}
+ \item Στο σημείο εισαγωγής νέας εγγραφής, να γίνεται \texttt{require\_once 'crypto.php'} και να αντικαθίσταται η αποθήκευση του \texttt{\$new\_password} με \texttt{\$enc\_password = pm\_encrypt(\$new\_password)} πριν το \texttt{INSERT} (ώστε στη βάση να καταλήγει μόνο ciphertext), και
+
+ \item Στο σημείο προβολής της λίστας, να γίνεται \texttt{\$plain\_pass = pm\_decrypt(\$row['web\_password'])} πριν το \texttt{htmlspecialchars} και την εκτύπωση στο HTML (ώστε να εμφανίζεται στον χρήστη το πραγματικό password, αλλά να παραμένει κρυπτογραφημένο στην αποθήκευση).
+
+ \item Τέλος, θα απαιτούνταν μία διαδικασία migration (π.χ. προσωρινό script) για να κρυπτογραφηθούν οι ήδη αποθηκευμένοι plaintext κωδικοί στο \texttt{websites} table, καθώς και ρύθμιση του container/compose ώστε να ορίζεται το \texttt{APP\_ENC\_KEY} ως secret μέσω environment variables.
+ \end{enumerate}
+
+\end{enumerate}
+
+\subsection{Επιπτώσεις ασφάλειας και σενάρια εκμετάλλευσης}
+
+Η αποθήκευση κωδικών αυθεντικοποίησης σε απλό κείμενο αυξάνει δραματικά τον αντίκτυπο οποιασδήποτε παραβίασης της βάσης δεδομένων.
+Σε περίπτωση που ένας επιτιθέμενος αποκτήσει πρόσβαση ανάγνωσης στη βάση (π.χ. μέσω SQL Injection, διαρροής backup ή εσφαλμένων δικαιωμάτων), μπορεί να ανακτήσει άμεσα όλους τους κωδικούς χρηστών χωρίς καμία επιπλέον προσπάθεια.
+
+Επιπλέον, επειδή η αυθεντικοποίηση βασιζόταν σε σύγκριση plaintext τιμών εντός της SQL εντολής, η διαρροή του πίνακα \texttt{login\_users} οδηγεί άμεσα σε πλήρη παραβίαση όλων των λογαριασμών, χωρίς να απαιτείται σπάσιμο (cracking) κωδικών ή hashes.
\subsection{Προσέγγιση αντιμετώπισης}
-Για την ασφαλή διαχείριση κωδικών αυθεντικοποίησης, οι κωδικοί δεν πρέπει ποτέ να αποθηκεύονται σε απλό κείμενο.
+Για την ασφαλή διαχείριση κωδικών αυθεντικοποίησης, \textbf{οι κωδικοί δεν πρέπει ποτέ να αποθηκεύονται σε απλό κείμενο}.
Η καθιερωμένη πρακτική είναι:
\begin{itemize}
- \item χρήση συναρτήσεων hashing με ενσωματωμένο salt κατά την εγγραφή,
- \item επαλήθευση του κωδικού κατά τη σύνδεση μέσω σύγκρισης hash και όχι μέσω SQL.
+ \item χρήση συναρτήσεων \textbf{hashing} με ενσωματωμένο salt κατά την εγγραφή,
+ \item \textbf{επαλήθευση} του κωδικού κατά τη σύνδεση μέσω σύγκρισης hash και \textbf{όχι μέσω SQL}.
\end{itemize}
Στην παρούσα εργασία χρησιμοποιούνται οι συναρτήσεις \texttt{password\_hash()} και \texttt{password\_verify()} της PHP, οι οποίες θεωρούνται βέλτιστη πρακτική για την αποθήκευση κωδικών.
@@ -713,14 +717,26 @@ $sql_query =
\subsection{Διορθωμένη υλοποίηση}
-Στη διορθωμένη υλοποίηση οι κωδικοί πλέον δεν εισάγονται στη βάση αυτούσιοι, αλλά περνούν πρώτα από:
+Στη διορθωμένη υλοποίηση οι κωδικοί πλέον δεν εισάγονται στη βάση απευθείας από τη μεταβλητή του UI \textit{new\_password}, αλλά \textbf{περνά πρώτα από hashing}:
\begin{minted}{php}
+ $sql_query = "INSERT INTO login_users (username, password) VALUES (?, ?)";
+ $stmt = $conn->prepare($sql_query);
+ // ...
$password_hash = password_hash($new_password, PASSWORD_DEFAULT);
+ $stmt->bind_param("ss", $new_username, $password_hash);
+ $result = $stmt->execute();
\end{minted}
-Ομοίως κατά το login, η επαλήθευση γίνεται με την:
+Ομοίως κατά το login (\textit{login.php}), η επαλήθευση στον κωδικό γίνεται με την \textit{password\_verify}.
\begin{minted}{php}
- password_verify($password, $stored_hash);
+ $stmt = $conn->prepare("SELECT id, password FROM login_users WHERE username = ?");
+ $stmt->bind_param("s", $username)->execute();
+ $result = $stmt->get_result();
+ if ($result && $result->num_rows === 1) {
+ if (password_verify($password, $result->fetch_assoc()["password"])) {
+ // succesful password verification
+ }
+ }
\end{minted}
\subsection{Απαιτούμενες αλλαγές περιβάλλοντος και βάσης δεδομένων}
@@ -728,17 +744,17 @@ $sql_query =
Για τον προ-εγκατεστημένο χρήστη δοκιμών (\texttt{u1/p1}), η διαδικασία πραγματοποιήθηκε χειροκίνητα στο περιβάλλον Docker, ως εξής:
Αρχικά δημιουργήσαμε ένα hashed κωδικό για τον υπάρχον χρήστη:
-\begin{verbatim}
+\begin{minted}{bash}
$ docker compose exec web bash
root@ee33aeda3931:/var/www/html# php -r \
'echo password_hash("p1", PASSWORD_DEFAULT), PHP_EOL;'
$2y$10$L18u5/PyVkDgsce/DsUOQu0sKhTzh854Euhog3cVb1W4YAfgRzY8W
root@ee33aeda3931:/var/www/html#
exit
-\end{verbatim}
+\end{minted}
Έπειτα αλλάξαμε των κωδικό χειροκίνητα στη βάση:
-\begin{verbatim}
+\begin{minted}{sql}
MariaDB [pwd_mgr]> SELECT * FROM login_users;
+----+----------+----------+
| id | username | password |
@@ -756,22 +772,25 @@ $sql_query =
+----+----------+--------------------------------------------------------------+
| 1 | u1 | $2y$10$L18u5/PyVkDgsce/DsUOQu0sKhTzh854Euhog3cVb1W4YAfgRzY8W |
+----+----------+--------------------------------------------------------------+
-\end{verbatim}
+\end{minted}
Η παραπάνω διαδικασία επιβεβαιώνει την επιτυχή αντικατάσταση του plaintext κωδικού με ασφαλές hash, διασφαλίζοντας τη συμβατότητα της βάσης δεδομένων με τη νέα υλοποίηση αυθεντικοποίησης.
-Τέλος ενημερώσαμε τον ίδιο κωδικό και στο αρχείο αρχικοποίησης της βάσης στον container.
+Τέλος ενημερώσαμε τον ίδιο κωδικό και στο αρχείο αρχικοποίησης (\textit{01-create-pwd\_mgr-db-withData.sql}) της βάσης στον container.
+\begin{minted}{sql}
+ -- php -r 'echo password_hash("p1", PASSWORD_DEFAULT), PHP_EOL;'
+ INSERT INTO `login_users` (`id`, `username`, `password`) VALUES
+ (1, 'u1', '$2y$10$L18u5/PyVkDgsce/DsUOQu0sKhTzh854Euhog3cVb1W4YAfgRzY8W');
+\end{minted}
-\begin{figure}[H]
+Στην Εικόνα~\ref{fig:pltxt_successful_login} φαίνεται η επιτυχής σύνδεση του υπάρχον χρήστη μετά την αλλαγή του κωδικού στην βάση.
+\begin{figure}[!ht]
\centering
\includegraphics[width=0.45\textwidth]{img/pltxt-SuccessfulLogin.png}
\caption{Επιτυχής σύνδεση χρήστη μετά την αλλαγή κωδικού.}
\label{fig:pltxt_successful_login}
\end{figure}
-Στην Εικόνα~\ref{fig:pltxt_successful_login} φαίνεται η επιτυχής σύνδεση του υπάρχον χρήστη μετά την αλλαγή του κωδικού στην βάση.
-
-
% =====================================================================
% DB admin credentials (root) used by the web app + mitigation
@@ -780,11 +799,8 @@ $sql_query =
\section{Χρήση διαπιστευτηρίων διαχειριστή (root)}
\label{subsec:db-root-user}
-Ένα επιπλέον σημαντικό πρόβλημα ασφάλειας της εφαρμογής είναι ότι η σύνδεση προς τη βάση δεδομένων
-πραγματοποιείται με διαπιστευτήρια διαχειριστή (\textit{administrator credentials}, χρήστης \texttt{root}).
-Η πρακτική αυτή παραβιάζει τη θεμελιώδη αρχή του \textit{least privilege} (ελάχιστα απαραίτητα προνόμια),
-διότι οποιοσδήποτε επιτιθέμενος αποκτήσει δυνατότητα εκτέλεσης SQL εντολών (π.χ. μέσω SQL injection ή
-μέσω πρόσβασης στη βάση) δεν περιορίζεται από δικαιώματα και μπορεί να πραγματοποιήσει καταστροφικές
+Ένα επιπλέον σημαντικό πρόβλημα ασφάλειας της εφαρμογής είναι ότι η \textbf{σύνδεση} προς τη βάση δεδομένων πραγματοποιείται με \textbf{διαπιστευτήρια διαχειριστή} (\textit{administrator credentials}, χρήστης \texttt{root}).
+Η πρακτική αυτή παραβιάζει τη θεμελιώδη αρχή του \textit{least privilege} (ελάχιστα απαραίτητα προνόμια), διότι οποιοσδήποτε επιτιθέμενος αποκτήσει δυνατότητα εκτέλεσης SQL εντολών (π.χ. μέσω SQL injection ή μέσω πρόσβασης στη βάση) δεν περιορίζεται από δικαιώματα και μπορεί να πραγματοποιήσει καταστροφικές
ενέργειες.
Το πρόβλημα εντοπίζεται στα ακόλουθα σημεία.
@@ -792,26 +808,26 @@ $sql_query =
\item config.php (defaults σε root).
Στο αρχείο \textit{config.php}, οι παράμετροι της βάσης διαβάζονται από environment variables,
αλλά αν δεν υπάρχουν τιμές, γίνεται fallback σε \texttt{root/rootpass}.
-\begin{minted}{php}
- $DB_HOST = getenv('DB_HOST') ?: 'db';
- $DB_USER = getenv('DB_USER') ?: 'root';
- $DB_PASS = getenv('DB_PASS') ?: 'rootpass';
- $DB_NAME = getenv('DB_NAME') ?: 'pwd_mgr';
-\end{minted}
+ \begin{minted}{php}
+ $DB_HOST = getenv('DB_HOST') ?: 'db';
+ $DB_USER = getenv('DB_USER') ?: 'root';
+ $DB_PASS = getenv('DB_PASS') ?: 'rootpass';
+ $DB_NAME = getenv('DB_NAME') ?: 'pwd_mgr';
+ \end{minted}
\label{lst:db-root-config}
\item docker-compose.yml (η web υπηρεσία τρέχει ως root στη DB).
Στο \textit{docker-compose.yml} τα environment variables της web υπηρεσίας ορίζονται ρητά ως \texttt{root/rootpass},
οπότε ακόμη και αν αλλάζαμε μόνο το \textit{config.php}, η εφαρμογή θα συνέχιζε να συνδέεται ως root.
-\begin{minted}{yaml}
- services:
- web:
- environment:
- DB_HOST: db
- DB_USER: root
- DB_PASS: rootpass
- DB_NAME: pwd_mgr
-\end{minted}
+ \begin{minted}{yaml}
+ services:
+ web:
+ environment:
+ DB_HOST: db
+ DB_USER: root
+ DB_PASS: rootpass
+ DB_NAME: pwd_mgr
+ \end{minted}
\label{lst:compose-web-root}
\item SQL init (δεν υπάρχει dedicated χρήστης εφαρμογής).
@@ -827,8 +843,7 @@ $sql_query =
\item είναι πιθανή \textbf{μόνιμη παραβίαση} (π.χ. αλλαγές σε grants/χρήστες), ανάλογα με τη ρύθμιση του DB server.
\end{itemize}
-Με άλλα λόγια, ακόμη και αν διορθωθούν SQLi σε επίπεδο κώδικα, η χρήση root αυξάνει σημαντικά το \textit{impact}
-(impact amplification) οποιασδήποτε επιτυχούς επίθεσης.
+Με άλλα λόγια, ακόμη και αν διορθωθούν SQLi σε επίπεδο κώδικα, η χρήση root αυξάνει σημαντικά τον αντίκτυπο (impact amplification) οποιασδήποτε επιτυχούς επίθεσης.
\subsection{Αντιμετώπιση: least privilege χρήστης βάσης δεδομένων}
@@ -836,7 +851,7 @@ $sql_query =
στον οποίο εκχωρούνται μόνο τα απολύτως απαραίτητα δικαιώματα στο schema \texttt{pwd\_mgr}.
\begin{itemize}
- \item Αλλαγή στο SQL init: δημιουργία χρήστη και GRANT.
+ \item Αλλαγή στο \textbf{SQL init}: δημιουργία χρήστη και GRANT.
Στο αρχείο \textit{01-create-pwd\_mgr-db-withData.sql} που φορτώνεται από \texttt{/docker-entrypoint-initdb.d}) προστέθηκαν οι παρακάτω εντολές:
\begin{minted}{sql}
-- Create a dedicated DB user for the web application (least privilege).
@@ -847,9 +862,9 @@ $sql_query =
\end{minted}
\label{lst:db-create-app-user}
Με αυτόν τον τρόπο, η εφαρμογή μπορεί να λειτουργήσει κανονικά,
- ενώ παράλληλα δεν επιτρέπονται επικίνδυνα δικαιώματα όπως \texttt{DROP}, \texttt{ALTER}, \texttt{CREATE USER}, \texttt{GRANT OPTION}.
+ ενώ παράλληλα \textbf{δεν επιτρέπονται επικίνδυνα δικαιώματα} όπως \texttt{DROP}, \texttt{ALTER}, \texttt{CREATE USER}, \texttt{GRANT OPTION}.
- \item Αλλαγή στο docker-compose.yml: web συνδέεται ως passman\_app.
+ \item Αλλαγή στο docker-compose.yml: web \textbf{συνδέεται ως passman\_app}.
Στη συνέχεια, στο \textit{docker-compose.yml} αλλάχθηκαν τα credentials της web υπηρεσίας ώστε να χρησιμοποιείται ο νέος χρήστης:
\begin{minted}{yaml}
services:
@@ -882,9 +897,8 @@ $sql_query =
\label{lst:db-config-fixed}
\end{itemize}
-Με τις παραπάνω αλλαγές, η εφαρμογή λειτουργεί με περιορισμένα δικαιώματα στη βάση δεδομένων,
-μειώνοντας σημαντικά τον αντίκτυπο (impact reduction) πιθανών επιθέσεων.
-Η πρακτική αυτή αποτελεί βασικό μέτρο \textit{defense-in-depth} και ευθυγραμμίζεται με θεμελιώδεις αρχές secure design.
+Με τις παραπάνω αλλαγές, \textbf{η εφαρμογή λειτουργεί με περιορισμένα δικαιώματα στη βάση δεδομένων}, μειώνοντας σημαντικά τον αντίκτυπο (impact reduction) πιθανών επιθέσεων.
+Η πρακτική αυτή αποτελεί βασικό μέτρο \textbf{defense-in-depth} και ευθυγραμμίζεται με θεμελιώδεις αρχές secure design.
Ένα παράδειγμα φαίνεται και στο στιγμιότυπο παρακάτω, όπου η βάση απορρίπτει τη διαγραφή πίνακα, στον χρήστη passman\_app:
\begin{minted}{sql}
@@ -912,13 +926,13 @@ MariaDB [(none)]>
\label{subsec:http-https}
Η εφαρμογή αρχικά λειτουργεί αποκλειστικά μέσω του μη ασφαλούς πρωτοκόλλου HTTP.
-Όπως αναφέρεται και στην εκφώνηση, η χρήση HTTP επιτρέπει σε έναν επιτιθέμενο που παρακολουθεί την κίνηση του δικτύου (\textit{network observer / man-in-the-middle}) να υποκλέψει τις πληροφορίες που εμφανίζονται στον χρήστη και τα δεδομένα που αυτός αποστέλλει (π.χ. username/password στα forms).
+Όπως αναφέρεται και στην εκφώνηση, η χρήση HTTP επιτρέπει σε έναν επιτιθέμενο που παρακολουθεί την κίνηση του δικτύου (\textit{network observer / man-in-the-middle}) \textbf{να υποκλέψει τις πληροφορίες} που εμφανίζονται στον χρήστη και τα δεδομένα που αυτός αποστέλλει (π.χ. username/password στα forms).
Σε πραγματικό περιβάλλον, αυτό σημαίνει ότι:
\begin{itemize}
- \item τα credentials μπορούν να διαρρεύσουν σε plaintext,
- \item το session cookie μπορεί να υποκλαπεί,
- \item το περιεχόμενο σελίδων (π.χ. αποθηκευμένοι κωδικοί ιστοσελίδων) μπορεί να αναγνωστεί από τρίτους.
+ \item τα \textbf{credentials} μπορούν να διαρρεύσουν σε \textbf{plaintext},
+ \item το \textbf{session cookie} μπορεί να \textbf{υποκλαπεί},
+ \item το περιεχόμενο σελίδων (π.χ. αποθηκευμένοι κωδικοί ιστοσελίδων) μπορεί να \textbf{αναγνωστεί από τρίτους}.
\end{itemize}
\subsection{Πού εμφανίζεται στην υλοποίηση}
@@ -936,6 +950,7 @@ MariaDB [(none)]>
Επιπλέον, στο \textit{index.html} υπάρχουν hard-coded σύνδεσμοι προς \texttt{http://localhost/...}, οι οποίοι επιβάλλουν τη χρήση HTTP από τον browser.
\begin{minted}{html}
Login Page
+ // ...
Dashboard
Notes
\end{minted}
@@ -946,13 +961,12 @@ MariaDB [(none)]>
\label{subsec:https-fix}
Για να επιτευχθεί ασφαλής μεταφορά δεδομένων (\textit{transport security}), απαιτείται η χρήση HTTPS.
-Σε περιβάλλον Docker, ένας πρακτικός και καθαρός τρόπος είναι να προστεθεί ένα reverse proxy
-(π.χ. Caddy / NGINX) μπροστά από τον Apache web server.
+Σε περιβάλλον Docker, ένας πρακτικός και καθαρός τρόπος είναι να προστεθεί ένα reverse proxy (π.χ. Caddy / NGINX) μπροστά από τον Apache web server.
Το reverse proxy αναλαμβάνει:
\begin{itemize}
- \item TLS termination (διαπραγμάτευση κρυπτογράφησης),
- \item αυτόματη ανακατεύθυνση από HTTP σε HTTPS,
- \item προώθηση (proxying) της κίνησης προς το εσωτερικό container της εφαρμογής.
+ \item \textbf{TLS termination} (διαπραγμάτευση κρυπτογράφησης),
+ \item αυτόματη \textbf{ανακατεύθυνση} από HTTP σε HTTPS,
+ \item \textbf{προώθηση} (proxying) \textbf{της κίνησης} προς το εσωτερικό container της εφαρμογής.
\end{itemize}
Με αυτή την αρχιτεκτονική, το container \texttt{web} \textbf{δεν εκτίθεται πλέον} απευθείας προς τα έξω.
@@ -982,11 +996,11 @@ MariaDB [(none)]>
\label{lst:https-compose-after}
\subsection{Ρύθμιση reverse proxy -- Caddyfile}
-Για χρήση σε τοπικό περιβάλλον (\texttt{localhost}), επιλέχθηκε self-signed / internal TLS (\texttt{tls internal}).
+Για χρήση σε τοπικό περιβάλλον (\texttt{localhost}), \textbf{επιλέχθηκε self-signed} (\texttt{tls internal}).
Αυτό είναι κατάλληλο για demo/testing, καθώς δεν απαιτεί domain name ή δημόσιο πιστοποιητικό.
Το \textit{Caddyfile} είναι:
-\begin{minted}{text}
+\begin{minted}{nginx}
# HTTP site: redirect everything to HTTPS
http://localhost {
redir https://{host}{uri} permanent
@@ -1008,7 +1022,7 @@ https://localhost {
\label{lst:caddyfile}
\paragraph{Σημείωση για τοπικά πιστοποιητικά (browser warning).}
-Η χρήση \texttt{tls internal} δημιουργεί self-signed πιστοποιητικό, το οποίο ενδέχεται να προκαλέσει warning στον browser.
+Η χρήση \texttt{tls internal} δημιουργεί self-signed πιστοποιητικό, το οποίο ενδέχεται να προκαλέσει \textbf{warning στον browser}.
Το γεγονός αυτό είναι αναμενόμενο σε τοπικό demo περιβάλλον και δεν αναιρεί τη λειτουργία κρυπτογράφησης.
Σε παραγωγικό περιβάλλον θα χρησιμοποιούνταν έγκυρο πιστοποιητικό (π.χ. μέσω Let's Encrypt) και domain name.
@@ -1023,7 +1037,8 @@ https://localhost {
\label{lst:https-index-after}
\subsection{Επαλήθευση}
-Όπως φαίνεται και στην Εικόνα~\ref{fig:https-sample}, μετά τις αλλαγές, η εφαρμογή είναι διαθέσιμη μέσω: \texttt{https://localhost/passman},.
+Όπως φαίνεται και στην Εικόνα~\ref{fig:https-sample}, μετά τις αλλαγές, η εφαρμογή είναι διαθέσιμη μέσω:\\
+\texttt{https://localhost/passman}.
\begin{figure}[!ht]
\centering
\includegraphics[width=0.55\textwidth]{img/https-Sample.png}
@@ -1033,13 +1048,13 @@ https://localhost {
Επιπλέον, η πρόσβαση σε \texttt{http://localhost/passman} οδηγεί σε αυτόματη ανακατεύθυνση προς HTTPS,
επιβεβαιώνοντας ότι η μεταφορά δεδομένων προστατεύεται σε επίπεδο δικτύου.
-\begin{verbatim}
- $ curl -I http://localhost/passman
- HTTP/1.1 301 Moved Permanently
- Location: https://localhost/passman
- Server: Caddy
- Date: Sun, 11 Jan 2026 20:01:49 GMT
-\end{verbatim}
+\begin{minted}{bash}
+$ curl -I http://localhost/passman
+ HTTP/1.1 301 Moved Permanently
+ Location: https://localhost/passman
+ Server: Caddy
+ Date: Sun, 11 Jan 2026 20:01:49 GMT
+\end{minted}
Με την εισαγωγή reverse proxy και την ενεργοποίηση HTTPS, μειώνεται σημαντικά ο κίνδυνος υποκλοπής δεδομένων (\textit{eavesdropping}) και επιτυγχάνεται προστασία στο επίπεδο μεταφοράς (transport layer), ενισχύοντας τη συνολική ασφάλεια της εφαρμογής.
@@ -1047,18 +1062,18 @@ https://localhost {
\section{Συμπεράσματα}
-Στην παρούσα εργασία μελετήθηκε μια απλή διαδικτυακή εφαρμογή διαχείρισης κωδικών πρόσβασης, με στόχο την ανάδειξη και αντιμετώπιση κρίσιμων κενών ασφάλειας που προκύπτουν από μη ασφαλείς προγραμματιστικές πρακτικές.
+Στην παρούσα εργασία μελετήθηκε μια απλή διαδικτυακή εφαρμογή διαχείρισης κωδικών πρόσβασης, με στόχο την \textbf{ανάδειξη και αντιμετώπιση κρίσιμων κενών ασφάλειας} που προκύπτουν από μη ασφαλείς προγραμματιστικές πρακτικές.
Η προσέγγιση που ακολουθήθηκε ήταν πειραματική και βασισμένη σε πραγματικά σενάρια επίθεσης.
Αρχικά εντοπίστηκαν ευπάθειες όπως SQL Injection, Stored Cross-Site Scripting, αποθήκευση κωδικών σε απλό κείμενο, χρήση διαπιστευτηρίων διαχειριστή για τη βάση δεδομένων και απουσία κρυπτογράφησης στο επίπεδο μεταφοράς (HTTP).
-Για κάθε περίπτωση παρουσιάστηκε ο τρόπος εκμετάλλευσης, τεκμηριώθηκαν οι επιπτώσεις και στη συνέχεια εφαρμόστηκαν στοχευμένα διορθωτικά μέτρα, με ελάχιστη αλλά ουσιαστική παρέμβαση στον κώδικα και στη συνολική αρχιτεκτονική.
+Για κάθε περίπτωση \textit{παρουσιάστηκε ο τρόπος εκμετάλλευσης, τεκμηριώθηκαν οι επιπτώσεις και στη συνέχεια εφαρμόστηκαν στοχευμένα διορθωτικά μέτρα}, με \textbf{ελάχιστη αλλά ουσιαστική παρέμβαση στον κώδικα} και στη συνολική αρχιτεκτονική.
-Οι διορθώσεις υλοποιήθηκαν με βάση θεμελιώδεις αρχές ασφαλούς σχεδίασης, όπως ο διαχωρισμός δεδομένων και εντολών (prepared statements), η αντιμετώπιση κάθε εισόδου ως μη έμπιστης (output encoding), η ασφαλής αποθήκευση κωδικών μέσω hashing, η αρχή του least privilege στη διαχείριση της βάσης δεδομένων και η προστασία της επικοινωνίας μέσω HTTPS.
-Ιδιαίτερη έμφαση δόθηκε όχι μόνο στη «διόρθωση» μεμονωμένων σφαλμάτων, αλλά και στη μείωση του συνολικού αντίκτυπου πιθανών επιθέσεων (impact reduction), υιοθετώντας μια προσέγγιση defense-in-depth.
-Μέσα από τη διαδικασία αυτή κατέστη σαφές ότι πολλές σοβαρές ευπάθειες δεν οφείλονται σε πολύπλοκα σφάλματα, αλλά σε απλές παραλείψεις και λανθασμένες παραδοχές κατά την ανάπτυξη της εφαρμογής.
+Οι διορθώσεις υλοποιήθηκαν με βάση θεμελιώδεις αρχές ασφαλούς σχεδίασης, όπως ο \textbf{διαχωρισμός δεδομένων και εντολών} (prepared statements), η \textbf{αντιμετώπιση κάθε εισόδου ως μη έμπιστης} (output encoding), η \textbf{ασφαλής αποθήκευση κωδικών μέσω hashing}, η αρχή του \textbf{least privilege} στη διαχείριση της βάσης δεδομένων και η προστασία της επικοινωνίας μέσω \textbf{HTTPS}.
+Ιδιαίτερη έμφαση δόθηκε όχι μόνο στη «διόρθωση» μεμονωμένων σφαλμάτων, αλλά και στη μείωση του συνολικού αντίκτυπου πιθανών επιθέσεων (impact reduction), υιοθετώντας μια προσέγγιση \textbf{defense-in-depth}.
+Μέσα από τη διαδικασία αυτή κατέστη σαφές ότι \textit{πολλές σοβαρές ευπάθειες δεν οφείλονται σε πολύπλοκα σφάλματα, αλλά σε απλές παραλείψεις και λανθασμένες παραδοχές} κατά την ανάπτυξη της εφαρμογής.
Συνολικά, η εργασία ανέδειξε τη σημασία της ασφάλειας ως αναπόσπαστο μέρος του σχεδιασμού λογισμικού και όχι ως μεταγενέστερη προσθήκη.
Η κατανόηση των μηχανισμών επίθεσης και η εφαρμογή βασικών πρακτικών secure coding επιτρέπουν τη δραστική βελτίωση της ασφάλειας ακόμη και σε απλές εφαρμογές.
-Η εμπειρία που αποκομίστηκε υπογραμμίζει ότι η συστηματική σκέψη, η σωστή αρχιτεκτονική και η επίγνωση των κινδύνων είναι καθοριστικοί παράγοντες για την ανάπτυξη αξιόπιστων και ασφαλών πληροφοριακών συστημάτων.
+Η εμπειρία που αποκομίστηκε υπογραμμίζει ότι η \textbf{συστηματική σκέψη}, η \textbf{σωστή αρχιτεκτονική} και η \textbf{επίγνωση των κινδύνων} είναι καθοριστικοί παράγοντες για την ανάπτυξη αξιόπιστων και ασφαλών πληροφοριακών συστημάτων.
\end{document}