\begin{description}
\item[V4.9] Verify that the same access control rules implied by the presentation layer are enforced on the server side. \\
(\textit{The \CMS{} failed this requirement in our analysis.})
- \item[V5.17] Verify that the application has defenses against \HTTP{} parameter pollution attacks, particularly if the application framework makes no distinction about the source of request parameters (\GET{}, \POST{}, cookies, headers, environment, etc.. \\
+ \item[V5.17] Verify that the application has defenses against \HTTP{} parameter pollution attacks, particularly if the application framework makes no distinction about the source of request parameters (\GET{}, \POST{}, cookies, headers, environment, etc. \\
(\textit{The \CMS{} passed this requirement in our analysis.})
\end{description}
%
-% (TODO write out: dsprenkels)
+% Written by dsprenkels
%
% This document describes our security analysis of the (?) CMS according to the OWASP ASVS (v3.0.1), as well as an analysis of Fortify's results compared to our findings \& the OWASP ASVS categories.
%
% Running the application
-Each of us has initially set up the CMS and made ourselves familiar with the
-CMS. This was easy, because one of us had made a \code{Dockerfile} for the
+Each of us has initially set up the \CMS{} and made ourselves familiar with the
+\CMS{}. This was easy, because one of us had made a \code{Dockerfile} for the
others to use. This made running and installing the application trivially
easy. Running the application made us understand the outline and components of
the application. We could also find some spots were easy to find vulnerabilities
could be expected. However, looking at the source code was more effective,
-especially when verifying that the CMS \emph{passes} a requirement. Buggy code
-is easy to find, bugless code is not.
+especially when verifying that the \CMS{} \emph{passes} a requirement. Buggy code
+is easy to find. Bugless code is not.
We have chosen to split the work by category of security requirements in
the OWASP Application Security Verification Standard. We set the goal to perform
% Initial approach
We were quickly set up and started to do each own parts of the audit by hand.
For each OWASP ASVS item specific to certain mechanisms (like login and input
-validation), we would take the source code of the CMS and follow the control
+validation), we took the source code of the \CMS{} and follow the control
flow to see if the application satisfies the security requirement. For more
general requirements, we could just look at the code that is responsible for
-this requirement (like the \code{Response} class in the case of HTTP security).
+this requirement (like the \code{Response} class in the case of \HTTP{} security).
When we had found that a requirement was not satisfied, we elaborate shortly
and move on.
This went well, because with five people the individual workload is just not
-that big. Furthermore, finding vulnerabilities is a lot easier that verifying the security in a lot of cases. This speeds up the auditing process, because
-the CMS turned out to not satisfy the ASVS in most cases.
+that big. Furthermore, finding vulnerabilities is a lot easier that verifying
+the security in a lot of cases. This speeds up the auditing process, because
+the \CMS{} turned out to not satisfy the ASVS in most cases.
% Use of Fortify
Because we were on track early, most of the audit was already done by when we
% Tools afkortingen
\newcommand{\API}{\emph{API}}
-\newcommand{\CMS}{\emph{CMS}}
-\newcommand{\CSRF}{\emph{CSRF}}
-\newcommand{\DELETE}{\emph{DELETE}}
-\newcommand{\DOM}{\emph{DOM}}
-\newcommand{\GET}{\emph{GET}}
-\newcommand{\GUID}{\emph{GUID}}
-\newcommand{\HTMLF}{\textsc{HTML5}}
-\newcommand{\HTML}{\textsc{HTML}}
-\newcommand{\HTTPS}{\textsc{HTTPS}}
-\newcommand{\HTTP}{\textsc{HTTP}}
-\newcommand{\JQuery}{\textsc{JQuery}}
-\newcommand{\JSON}{\textsc{JSON}}
-\newcommand{\LDAP}{\textsc{LDAP}}
-\newcommand{\PHP}{\textsc{PHP}}
-\newcommand{\PII}{\emph{PII}}
-\newcommand{\POST}{\emph{POST}}
-\newcommand{\PUT}{\emph{PUT}}
-\newcommand{\REST}{\emph{REST}}
-\newcommand{\RSS}{\emph{RSS}}
-\newcommand{\SMTP}{\emph{SMTP}}
-\newcommand{\SQL}{\textsc{SQL}}
-\newcommand{\SSO}{\emph{SSO}}
-\newcommand{\TOTP}{\emph{TOTP}}
-\newcommand{\TRACE}{\emph{TRACE}}
-\newcommand{\XML}{\textsc{XML}}
-\newcommand{\XSS}{\emph{XSS}}
+\newcommand{\CMS}{CMS}
+\newcommand{\CSRF}{CSRF}
+\newcommand{\DELETE}{\code{DELETE}}
+\newcommand{\DOM}{DOM}
+\newcommand{\GET}{\code{GET}}
+\newcommand{\GUID}{GUID}
+\newcommand{\HTMLF}{HTML5}
+\newcommand{\HTML}{HTML}
+\newcommand{\HTTPS}{HTTPS}
+\newcommand{\HTTP}{HTTP}
+\newcommand{\JQuery}{jQuery}
+\newcommand{\JSON}{JSON}
+\newcommand{\LDAP}{LDAP}
+\newcommand{\PHP}{PHP}
+\newcommand{\PII}{PII}
+\newcommand{\POST}{\code{POST}}
+\newcommand{\PUT}{\code{PUT}}
+\newcommand{\REST}{REST}
+\newcommand{\RSS}{RSS}
+\newcommand{\SMTP}{SMTP}
+\newcommand{\SQL}{SQL}
+\newcommand{\SSO}{SSO}
+\newcommand{\TOTP}{TOTP}
+\newcommand{\TRACE}{\code{TRACE}}
+\newcommand{\XML}{XML}
+\newcommand{\XSS}{XSS}
% Reference naar de source
The OWASP ASVS presents us with a nice case of the development of application security awareness.
- As an initial effort to provide a structured and general account of web app security concerns \&
+ As an initial effort to provide a structured and general account of web app security concerns and
their mitigation, it shows us in particular how awareness of, and development process around security
is still in its infancy, and also tells us some part of why exactly this open problem is so hard to tackle.
We view this as an effort to make it \emph{conceptually simple}, transparent and accessible; it even states
the aim to be designed in such a way as to be easily transformed into automated penetration tests etc.
-Another typical way to present security concerns \& measures would be to list appropriate security concerns
+Another typical way to present security concerns and measures would be to list appropriate security concerns
per type of architectural component of a web app, and thus integrate it into the development lifecycle.
We suspect the ASVS is presented the way it is, exactly because security is an \emph{emergent property},
and thus security measures should not be regarded as attachments to respective components of an app.
- Rather, it should be verified at each stage \& level; and thus a checklist is a better presentation.
+ Rather, it should be verified at each stage and level; and thus a checklist is a better presentation.
However, this method of presentation is just that. A philosophy on how to tackle security, and a
means to adoption and spread. More important to its nature is that it seems to present us with a
- (process towards a) tested \& true technical \emph{knowledge base} on web application security.
+ (process towards a) tested and true technical \emph{knowledge base} on web application security.
And as such, its more striking feature is that it is an endeavor to discover and structure an
\emph{effective ontology} of web app security. Analyzing the requirements, one finds
that they most often have the form:
requirements open-ended.
We feel that the above sums up the two key aspects of the ASVS: that it is a conceptually simply
- structured checklist, as to be easily used \& automated; and that it is an endeavor to provide
+ structured checklist, as to be easily used and automated; and that it is an endeavor to provide
an effective ontology of web app security. These two are in conflict to some degree, and thus
the key nature of the ASVS is that it is a careful compromise between the two.
team had to verify that there were no mistakes in the code. This would have
taken a lot of time if we had to verify each component for each requirement.
Furthermore, the ASVS is an easy guide for dividing the work\footnote{The
-categories in the ASVS are all of similar size. We settled on giving each team
+categories in the ASVS are all more or less of similar size. We settled on giving each team
member two categories to check.}. Dividing by component would have been a lot
harder to do fairly, especially because when beginning the project we had
little knowledge of the internals (and component sizes) of the CMS.
development of the application.
% Centralize user input
-Another improvement which would streamline the security audit would be to
-centralize the locations in which user input is handled. By doing this the whole
-class of vulnerabilities which stems from the handling of user input could be
+Another improvement which would streamline a security audit would be to
+centralize the locations in which user input is handled. By doing this, the whole
+class of vulnerabilities which stems from handling user input could be
neutralized to an extent. This would be a relatively easy change in the
-development process with comparatively big security benefits.
+development process with big security benefits.
% Centralize application output
-In the same category; during development the application could be designed in
+In the same category; the application could be designed in
such a way that all dynamic output is sanitized before outputting it to the
user. This would create another defense{-}in{-}depth layer for handling
attacker controlled input.
the tool as an initial guide trough the code. This forced us to manually check\r
the application source which took quite some time. After the tool became available we\r
didn't get any new insights regarding potential security risks, just more examples\r
-of problems we already detected. An example would be the use of the \emph{crypt()} \PHP\r
-function which uses the outdated \emph{DES} algorithm in order to encrypt data. The\r
+of problems we already detected. An example would be the use of the \code{crypt()} \PHP{}\r
+function which will, on some platforms, use the outdated \code{DES} algorithm in order to encrypt data. The\r
use of this function would pose a security risk and results in a failed check. Since\r
we where only interested in providing a verdict for each check a single occurrence of\r
this function allowed us to back-up our verdict. Fortify provides a full list of all\r
\r
% How did you experience the rates and amounts of false and true positives?\r
As far we where able to verify the tool didn't produce any false positives.\r
-However Fortify was not able to detect all problems we found.\r
+However, Fortify was not able to detect all problems we found.\r
Fortify concluded the application passed all checks in the \r
Error reporting and Logging (V8) section, however we detected a number of severe\r
problems in this area.\r
Since some problems occur multiple times it might be nice if Fortify was able to\r
generate a clear overview of which components of the application contain detected\r
problems. This could be very useful in combination with the information about\r
-components/functions which do pass the given security check. This would allow\r
+components and functions which do pass the given security check. This would allow\r
developers to determine if they suffer from chronically malformed code \r
-(e.g. all relevant code fails the check, indicating a very serious problem throughout the entire code-base) \r
+(e.g. all relevant code fails the check, indicating a very serious problem throughout the entire codebase) \r
or a single error (e.g. most relevant code passes the check except for a few isolated cases).\r
-In the tested code-base there is a clean distinction between an installer component and the\r
+In the tested codebase there is a clean distinction between an installer component and the\r
actual web application. If the installer suffers from problems not present in\r
the web application and Fortify would be able to point out the specific check is\r
-relevant to both components the company would know which team/developer needs some major\r
+relevant to both components the company would know which team or developer needs some major\r
reeducation and who would be the best person to teach them.\r
\item\pass{}
Verify that every \HTTP{} response contains a
content type header specifying a safe character set
-(e.g., \emph{UTF-8}, \emph{ISO 8859{-}1}).
+(e.g., UTF-8, ISO 8859{-}1).
\begin{result}
Content type headers may be set anywhere in the application. Furthermure,\\
\code{Response::send} ensures that if no content type header is set, all
% No proxies are present
\item\fail{}
-Verify that a suitable X-FRAME-OPTIONS header is
+Verify that a suitable \code{X-FRAME-OPTIONS} header is
in use for sites where content should not be
viewed in a 3rd-party X-Frame.
\begin{result}
\end{result}
\item\fail{}
-Verify that all \API{} responses contain \code{X-Content-Type-Options:
-nosniff} and\\
+Verify that all \API{} responses contain \code{X-Content-Type-Options: nosniff} and\\
\code{Content-Disposition: attachment; filename="api.json"} (or other
appropriate filename for the content type).
\begin{result}
\end{result}
\item\fail{}
-Verify that the X-XSS-Protection: 1; mode=block
+Verify that the \code{X-XSS-Protection: 1; mode=block}
header is in place to enable browser reflected \XSS{}
filters.
\begin{result}
\fail{}
Verify all pages and resources by default require
authentication except those specifically intended to be
-public (Principle of complete mediation).
+public (principle of complete mediation).
\begin{result}
All admin pages are private. Unpublished posts are also private.
\begin{result}
The input to various forms is not sanitized at all. This makes the implementation
- in (not only) \code{Users::find} vulnerable to \SQL{} injections. The login form
- is also vulnerable. Any user can execute arbitrary \SQL{} code from the username field.
+ in (not only) \code{Users::find} vulnerable to \SQL{} injections. Through this vulnerability,
+ an attacker can execute arbitrary \SQL{} code from the username field in the login form.
The following example code can submitted as username in the login form, which
will set the password of the \code{admin} user to \code{s3cret}:
entered.
\begin{result}
- The application allows the user to use any password (except ones that contain
- \SQL{} code).
+ The application allows the user to use any password (except ones that trigger
+ errors in injected \SQL{} code).
\end{result}
\item
force and password hash recovery attacks.
\begin{result}
- Password are stored in database using the \PHP{} function \code{crypt}. Internally, this
- function uses salted MD5. This is way too reverse with brute-force attacks using dictionary files.
-
- Instead it would be better to use the \code{argon2} password hashing algorithm
- or the \PHP{} \code{password\_hash} function (which currently uses BCRYPT).
+ Password are stored in database using the \PHP{} function \code{crypt}. Internally, this
+ function uses salted MD5 on modern UNIX systems. On legacy systems, this uses an old DES
+ based algorithm, which uses only the first eight characters of the supplied password.
+ This is way too easy to reverse with brute-force attacks using dictionary files.
+
+ Instead the \CMS{} should use the \code{argon2} password hashing algorithm
+ or the \PHP{} \code{password\_hash} function (which currently uses BCRYPT) which are
+ (at this moment) considered safe to use.
\end{result}
\setcounter{enumi}{15}
link.
\begin{result}
- The app allows admin users to log in over \HTTP{}. This is insecure, as it allows
- eavesdroppers to intercept password.
- The app should force \HTTPS{} for at least the login form, the \code{admin\_controller} and
+ The app allows admin users to log in over \HTTP{}. This is insecure, as it allows
+ eavesdroppers to intercept any password.
+ The app should force \HTTPS{} for at least the login form, the \code{admin\_controller} and
for the installation script (because the users posts secrets like the database
- password to this page).
+ password to this page and the \CMS{} supplies the user with the credentials of the \code{admin}
+ account).
\end{result}
\item
\item Installation database check, to prevent guessing attacks for the database password
\item Login, to prevent login guessing
\item And comment submission, to prevent spam, phishing et cetera (by
- using some CAPTCHA software).
+ using some CAPTCHA software.
\end{itemize}
\end{result}
transaction signing is in place for high value transactions.
\begin{result}
- There are no (really) risk based action or which re-authentication would be
+ There are no (really) risk based action for which re-authentication would be
fit.
\end{result}
disclosure.
\begin{result}
- No surch features are implemented.
+ No such features are implemented.
\end{result}
\item
\begin{result}
The session id is only used inside the cookie. And the \PHP{}
\code{\$\_SESSION} variable is never accessed outside of session
- management in \srcref{sessions.php}{}.
+ management in \code{sessions.php}.
\end{result}
\begin{result}
The application does not destroy the session id upon logout, it merely
invalidates it. However \PHP{}'s session managements automatically
- invalides these session id's after some time. % Discuss?
+ invalidates the session id after some time. % Discuss?
\end{result}
\fail{}
Verify that session ids stored in cookies have their path set to an
appropriately restrictive value for the application, and authentication
- session tokens additionally set the “HttpOnly” and “secure” attributes.
+ session tokens additionally set the \code{HttpOnly} and \code{secure} attributes.
\begin{result}
There is just one cookie for tha application and it's path includes the whole
- site. However this seems appropriate. The ``HttpOnly'' and ``secure''
+ site. However this seems appropriate. The \code{HttpOnly} and \code{secure}
attributes are not set for this cookie.
\end{result}
session.
\begin{result}
There is no indication whatsoever of any other active sessions a user may
- have open
+ have open.
\end{result}
\item
Verify the user is prompted with the option to terminate all other active
sessions after a successful change password process.
\begin{result}
- There is no such option, also notaeable is that there is no confirmation for
+ There is no such option, also notable is that there is no confirmation for
the password change.
\end{result}
\begin{itemize}
\item A login mechanism, where logged in users are allowed to access the backend, and anonymous users are not.
\item For logged in users, a role system with three specified roles: admin, editor and regular user.
- \item Different users (cap.~diff?)
\end{itemize}
\noindent
\item Folders, files, info over these data
\end{itemize}
-Our check reveales that the access control mechanisms are basically only a stub, and haven't been developed to their usually implied meaning, thus flattening the access control to the single ascept of being logged in or not. Hence, the main remaining security consideration deal with whether this login mechanism protects `backend' objects from anonymous users.
+Our check reveales that the access control mechanisms are basically only a stub, and haven't been developed to their usually implied meaning, thus flattening the access control to the single aspect of being logged in or not. Hence, the main remaining security consideration deal with whether this login mechanism protects `backend' objects from anonymous users.
These are the results of our check:
against spoofing and elevation of privilege.
\begin{result}
-The login system that is in place seems to work, and at least theoretically only allows registered users to access the backend.
+Aside from the authentication issues as described in V2, the login system that is in place works as intended, and theoretically only allows registered users to access the backend.
There is a role system, but it seems only to be a stub, for the role of a user has no effect whatsoever on their capabilities.
\end{result}
\begin{result}
There is no different access context for distinct users. In particular, they
are allowed to access and edit each others' account info, including
- password. Taken one way, this could be said to be by design and thus OK\. But in any reasonable design concept allowing for distinct user accounts, this is clearly not the desired setup.
+ password. Taken one way, this could be said to be by design and thus OK. But in any reasonable design concept allowing for distinct user accounts, this is clearly not the desired setup.
\end{result}
\item
\begin{result}
\begin{itemize}[leftmargin=*]
- \item \code{.gitignore} accessible, as well as any other dot-preceded file (except \code{.htaccess} itself by default Apache rules), as well as files such as \code{Thumbs.db} and \code{.DS\_Store}.
+ \item \code{.gitignore} is freely accessible, as well as any other dot-preceded file (except \code{.htaccess}, which is hidden by default Apache rules), as well as files such as \code{Thumbs.db} and \code{.DS\_Store}.
\item Directory contents were listed in my simple setup. A global apache setting may disable by default, but the \code{.htaccess} file doesn't explicitly disable (with \code{Options -Indexes}), so that the \CMS{}'s codebase basically enables the listing by default.
\end{itemize}
\end{result}
presentation layer are enforced on the server side.
\begin{result}
-Fail, because the role and distinct user systems are stubs.
+The role and distinct user systems are stubs.
\end{result}
\item
manipulated by end users unless specifically authorized.
\begin{result}
-This item is the main remaining security concern, as the login form allows SQL
+This item is the main security concern, as the login form allows \SQL{}
injections that are capable to alter any information stored in the database.
This is described in more detail in item V2.6 on page~\pageref{auth:6}.
\end{result}
all failed decisions are logged.
\begin{result}
-No such decision logging present. There is only a minor amount of logging, and this is related to not finding content (pages and articles).
+No such decision logging present. There is only a minor amount of logging, and
+this is only related to not finding content (pages and articles).
\end{result}
\item
overflows, or that security controls prevent buffer overflows.
\begin{result}
- As of \emph{OWASP}'s statement\footnote{\url{%
+ As of OWASP's statement\footnote{\url{%
https://www.owasp.org/index.php/Buffer_Overflows\#Platforms_Affected}}
\PHP{} is not surceptible to buffer overflows as long no external
programs or extensions are used which is not the case.
This requirement heavily depends on the configuration of the \PHP{}
interpreter and database, there are no system commands used but since
it is trivial to do an \SQL{} injection it might be possible to run
- commands via the database. However, which a sufficiently secure \SQL{}
- config this can not take place.
+ commands via the database. However, with a sufficiently secure \SQL{}
+ configuration this can not take place.
\end{result}
\item\pass{} Verify that the application is not susceptible to Remote File
post codes match).
\begin{result}
- Email addresses are validated against \PHP's stander functionality.
+ Email addresses are validated against \PHP's standard functionality.
Note that the \PHP{} email validation is not perfect and some valid
email addresses are rejected (such as email addresses with non-ASCII
characters). The other requirements are not used.
\begin{result}
Disabled by default but there is no way to enable error logging
- without outputting detailed error information. \emph{PDOException::getMessage}
+ without outputting detailed error information. \code{PDOException::getMessage}
is directly logged to the specified logging target (user or logfile).
\end{result}
unauthorized access and modification.
\begin{result}
- There is a htaccess which is supposed to block access to the log files.
+ There is an \code{.htaccess} which is supposed to block access to the log files.
Blocking access to the logs depends on the server configuration
because the log files are part of the main program directory.
Clear documentation which warns users about this behavior is missing.
hashes, or API tokens.
\begin{result}
- The application itself does not log any usernames/passwords.
- \emph{PDOException}'s end up in the log files however, the database driver implementation
+ The application itself does not log any usernames or passwords.
+ \code{PDOException}s end up in the log files however, the database driver implementation
could append sensitive data to the exception message.
Documentation suggesting users should verify that the database driver they end up using doesn't include sensitive data in exception messages is absent.
\end{result}
features.
\begin{result}
- The login and page/post editing/creation forms post back to the same page, thereby incentivising the browser to cache the form inputs as well. This is as opposed to the common post/redirect/get model (see \url{http://en.wikipedia.org/wiki/Post/Redirect/Get}). Also, the \code{Cache-Control} isn't explicitly used anywhere in the \CMS{} to aid the situation. In our test setup, the response does send \code{Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0}, but that'll be a default global Apache setting, we think.
+ The login and page/post editing/creation forms post back to the same page, thereby incentivising the browser to cache the form inputs as well. This is as opposed to the common post/redirect/get model (see \url{http://en.wikipedia.org/wiki/Post/Redirect/Get}). Also, the \code{Cache-Control} isn't explicitly used anywhere in the \CMS{} to aid the situation. In our test setup, the response does send \code{Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0}, but expect that this depends on the platform.
\end{result}
\notapplicable{\item Verify that the list of sensitive data processed by the
\end{verbatim}
\begin{result}
- Cache control header are never set by the \CMS{}. The fact that headers as these are indeed sent to the broswer in our test setup is probably due to default global Apache settings.
+ Cache control headers are never set by the \CMS{}. The fact that headers as these are indeed sent to the broswer in our test setup is probably due to default global Apache settings.
\end{result}
\item\pass{} Verify that on the server, all cached or temporary copies