From: Mart Lubbers Date: Tue, 15 Nov 2016 18:34:44 +0000 (+0100) Subject: alle afkortingen zijn nu commando's, clobber toegevoegd naast clean speciaal voor... X-Git-Url: https://git.martlubbers.net/?a=commitdiff_plain;h=c7388c6be83d270119266dd7ff2170fc689a15b3;p=ssproject1617.git alle afkortingen zijn nu commando's, clobber toegevoegd naast clean speciaal voor Kelley --- diff --git a/report/Makefile b/report/Makefile index 8d4dc16..b12d7fd 100644 --- a/report/Makefile +++ b/report/Makefile @@ -23,3 +23,6 @@ all: $(DOC).pdf clean: $(RM) $(addprefix $(DOC).,aux log fmt toc bbl blg mlog run.xml out)\ $(DOC)-blx.bib logo.png + +clobber: clean + $(RM) $(DOC).pdf diff --git a/report/fortify.tex b/report/fortify.tex index 8e2bb66..28cbb27 100644 --- a/report/fortify.tex +++ b/report/fortify.tex @@ -5,13 +5,13 @@ Fortify's results can be summarized to the following: \begin{enumerate}[label=(\Alph*)] - \item 50 cases of \textbf{XSS} vurnerabilities, all labeled \textbf{critical}, because none of the CMS's forms include nonces / protection against XSS is indeed missing. + \item 50 cases of \XSS{} vurnerabilities, all labeled \textbf{critical}, because none of the \CMS{}'s forms include nonces / protection against \XSS{} is indeed missing. \item \textbf{Password management}. In a user password reset form in \code{reset.php}, if the resetting fails, the password the user just entered reappears in the password field. This is not a database-retrieved password, and hence not actually as \textbf{critical} as Fortify labels it, but of course bad practice nonetheless. \item In the \textbf{privact violation} category, Fortify found errors and warnings printed back to the browser, and labelled it \textbf{critical}. However, this happens in the installer script, which we have decided to treat separately, as explained earlier. - \item \textbf{SQL injection} attacks are possible on the installer script, labelled \textbf{critical}. Yet again: the installer script. + \item \textbf{\SQL{} injection} attacks are possible on the installer script, labelled \textbf{critical}. Yet again: the installer script. \item \textbf{Cookie security}: the \code{HttpOnly} header is not set, labelled \textbf{high}. - \item \textbf{Privacy violation}: HTML forms don't disable autocompletion. Labelled \textbf{high}. However, autocompletion of HTML forms by means of the \code{autocompletion="none"} attribute notoriously doesn't really work. The larger problem is that the post/redirect/get pattern is not followed, as stated above at our analysis of OWASP requirement (9.1). - \item Fortify complains that PHP's \code{crypt(...)} function is \textbf{weak encryption} and labels the 5 usages \textbf{high}. + \item \textbf{Privacy violation}: \HTML{} forms don't disable autocompletion. Labelled \textbf{high}. However, autocompletion of \HTML{} forms by means of the \code{autocompletion="none"} attribute notoriously doesn't really work. The larger problem is that the post/redirect/get pattern is not followed, as stated above at our analysis of OWASP requirement (9.1). + \item Fortify complains that \PHP{}'s \code{crypt(...)} function is \textbf{weak encryption} and labels the 5 usages \textbf{high}. \end{enumerate} @@ -21,12 +21,12 @@ The main point that must be observed is that all the above results are quite low \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.. \\ - (\textit{The CMS passed this requirement in our analysis.}) + (\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.. \\ + (\textit{The \CMS{} passed this requirement in our analysis.}) \end{description} -For this reason, Fortify was nowhere near able to identifying all the problems we found in the CMS. An overview of our findings, where Fortify's concurrences are outlined explicitly, is given by the table below. +For this reason, Fortify was nowhere near able to identifying all the problems we found in the \CMS{}. An overview of our findings, where Fortify's concurrences are outlined explicitly, is given by the table below. \newcommand{\p}{{\color{lightgray}\pass}} diff --git a/report/preamble.tex b/report/preamble.tex index 0de5d4e..0e1a1ce 100644 --- a/report/preamble.tex +++ b/report/preamble.tex @@ -32,17 +32,38 @@ innertopmargin=2pt, innerbottommargin=2pt, skipabove=\topsep, - skipbelow=\topsep + skipbelow=\topsep% ]{result} % 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{\LDAP}{\textsc{LDAP}} +\newcommand{\SSO}{\emph{SSO}} +\newcommand{\TOTP}{\emph{TOTP}} +\newcommand{\TRACE}{\emph{TRACE}} \newcommand{\XML}{\textsc{XML}} -\newcommand{\HTML}{\textsc{HTML}} -\newcommand{\JSON}{\textsc{JSON}} -\newcommand{\JQuery}{\textsc{JQuery}} +\newcommand{\XSS}{\emph{XSS}} + % Reference naar de source \newcommand{\srcref}[2]{{\small\texttt{#1}} (line (s) #2)} diff --git a/report/v11_httpsec.tex b/report/v11_httpsec.tex index 1840059..4fb8da8 100644 --- a/report/v11_httpsec.tex +++ b/report/v11_httpsec.tex @@ -3,29 +3,29 @@ \item\fail{} Verify that the application accepts only a defined -set of required HTTP request methods, such as -GET and POST are accepted, and unused methods -(e.g. TRACE, PUT, and DELETE) are explicitly +set of required \HTTP{} request methods, such as +\GET{} and \POST{} are accepted, and unused methods +(e.g. \TRACE{}, \PUT{}, and \DELETE{}) are explicitly blocked. \begin{result} - The application treats only \texttt{POST} requests as different from + The application treats only \POST{} requests as different from others and in an opportunistic manner. It assumes all other methods to be - treated as \texttt{GET} requests. + treated as \GET{} requests. \end{result} \item\pass{} -Verify that every HTTP response contains a +Verify that every \HTTP{} response contains a content type header specifying a safe character set -(e.g., UTF-8, ISO 8859-1). +(e.g., \emph{UTF-8}, \emph{ISO 8859{-}1}). \begin{result} Content type headers may be set anywhere in the application. Furthermure, - \texttt{Response::send} ensures that if no content type header is set, all - responses will fall back to using \texttt{text/html; charset=UTF-8}. + \code{Response::send} ensures that if no content type header is set, all + responses will fall back to using \code{text/html; charset=UTF-8}. \end{result} \notapplicable{\item -Verify that HTTP headers added by a trusted proxy -or SSO devices, such as a bearer token, are +Verify that \HTTP{} headers added by a trusted proxy +or \SSO{} devices, such as a bearer token, are authenticated by the application.} % No proxies are present @@ -35,30 +35,30 @@ Verify that a suitable X-FRAME-OPTIONS header is in use for sites where content should not be viewed in a 3rd-party X-Frame. \begin{result} - The application will never supply an \texttt{X-FRAME-OPTIONS} header. While + The application will never supply an \code{X-FRAME-OPTIONS} header. While this is not really a problem for the home page, a 3rd party X-Frame should not be able to refer to the administrative interfaces of the application. \end{result} \item\pass{} -Verify that the HTTP headers or any part of the -HTTP response do not expose detailed version +Verify that the \HTTP{} headers or any part of the +\HTTP{} response do not expose detailed version information of system components. \begin{result} - The headers provide information about the PHP version (these are added by - the PHP interpreter by default) and information about the webserver. This + The headers provide information about the \PHP{} version (these are added by + the \PHP{} interpreter by default) and information about the webserver. This information is not specific for the application. It would be advisable to - hide the PHP version to the client, but this is specific to the way the + hide the \PHP{} version to the client, but this is specific to the way the application is installed. \end{result} \item\fail{} -Verify that all API responses contain X-Content-Type-Options: -nosniff and Content-Disposition: -attachment; filename="api.json" (or other +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} - The application does not supply the \texttt{X-Content-Type-Options} header. + The application does not supply the \code{X-Content-Type-Options} header. \end{result} \item\fail{} @@ -71,10 +71,10 @@ JSON, and JavaScript injection vulnerabilities. \item\fail{} Verify that the X-XSS-Protection: 1; mode=block -header is in place to enable browser reflected XSS +header is in place to enable browser reflected \XSS{} filters. \begin{result} - The application does not supply the \texttt{X-XSS-Protection} header. + The application does not supply the \code{X-XSS-Protection} header. \end{result} \end{enumerate} diff --git a/report/v2_authentication.tex b/report/v2_authentication.tex index b0b6889..74875af 100644 --- a/report/v2_authentication.tex +++ b/report/v2_authentication.tex @@ -48,10 +48,10 @@ attackers cannot log in. \begin{result} The input to various forms is not sanitized at all. This makes the implementation - in (not only) \texttt{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. The login form + is also vulnerable. Any user can execute arbitrary \SQL{} code from the username field. The following example code can submitted as username in the login form, which - will set the password of the \texttt{admin} user to \texttt{s3cret}: + will set the password of the \code{admin} user to \code{s3cret}: \code{"; UPDATE users SET password='\$1\$OWgsBb90\$Lkko6aZwmp9XOVrFI09Ab0' WHERE \\username='admin' AND 'a' = "a} @@ -67,7 +67,7 @@ entered. \begin{result} The application allows the user to use any password (except ones that contain - SQL code). + \SQL{} code). \end{result} \item @@ -89,7 +89,7 @@ authentication mechanism. expire, however. It would be even better to require that a token be used withing a day (or so) after creation. - The security of the SMTP connection is at the discretion of the web server. + The security of the \SMTP{} connection is at the discretion of the web server. Often these connections are not very secure, but this worry is beyond the scope of this audit. \end{result} @@ -126,11 +126,11 @@ salt, and there is sufficient work factor to defeat brute force and password hash recovery attacks. \begin{result} - Password are stored in database using the PHP function \texttt{crypt}. Internally, this + 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 \texttt{argon2} password hashing algorithm - or the PHP \texttt{password\_hash} function (which currently uses BCRYPT). + Instead it would be better to use the \code{argon2} password hashing algorithm + or the \PHP{} \code{password\_hash} function (which currently uses BCRYPT). \end{result} \setcounter{enumi}{15} @@ -143,9 +143,9 @@ user to enter credentials are done so using an encrypted link. \begin{result} - The app allows admin users to log in over HTTP. This is insecure, as it allows + 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 \texttt{admin\_controller} and + 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). \end{result} @@ -169,7 +169,7 @@ Verify that information enumeration is not possible via login, password reset, or forgot account functionality. \begin{result} - All these forms are vulnerable to SQL injection attacks. So any information + All these forms are vulnerable to \SQL{} injection attacks. So any information can leak any information from the database. \end{result} @@ -181,7 +181,7 @@ application (such as “admin/password”). \begin{result} No secrets are initialized by predefined values. The admin user will have - username \texttt{admin} by default. This is no secret and therefore not + username \code{admin} by default. This is no secret and therefore not considered unsafe. \end{result} @@ -210,7 +210,7 @@ services external to the application are encrypted and stored in a protected location. \begin{result} - The database credentials are hardcoded in \texttt{config.php}. While it + The database credentials are hardcoded in \code{config.php}. While it would be better to pass secrets as environment variables, this is not really bad practice. @@ -221,13 +221,13 @@ you extracted testcms to. \end{verbatim} This implies making the configuration file readable for all users on the system. This information should not be accessible for any user other than - running the PHP script. + running the \PHP{} script. \end{result} \item \pass{} Verify that forgotten password and other recovery paths -use a TOTP or other soft token, mobile push, or other +use a \TOTP{} or other soft token, mobile push, or other offline recovery mechanism. Use of a random value in an e-mail or SMS should be a last resort and is known weak. @@ -247,7 +247,7 @@ attack, this should not reset the hard lock status. \notapplicable{\item Verify that if shared knowledge based questions (also -known as "secret questions") are required, the questions +known as ``secret questions'') are required, the questions do not violate privacy laws and are sufficiently strong to protect accounts from malicious recovery.} @@ -275,7 +275,7 @@ commonly chosen passwords and weak passphrases. \begin{result} No password strengthening measures are implemented. The app should - use some password strength estimator like \texttt{zxcvbn}. + use some password strength estimator like \code{zxcvbn}. \end{result} \item @@ -291,12 +291,12 @@ response time. \item \fail{} -Verify that secrets, API keys, and passwords are not +Verify that secrets, \API{} keys, and passwords are not included in the source code, or online source code repositories. \begin{result} - The database credentials are hard coded in \texttt{config.php}. These + The database credentials are hard coded in \code{config.php}. These credentials should ideally be passed using environment variables. \end{result} diff --git a/report/v3_session.tex b/report/v3_session.tex index 94cf919..d1a02b4 100644 --- a/report/v3_session.tex +++ b/report/v3_session.tex @@ -40,7 +40,7 @@ \begin{result} The logout functionality is plainly visible on the top right of the application on every page that requires authentication. This is defined in - \srcref{admin/themes/header.php}{16-30} + \srcref{admin/themes/header.php}{16{-}30} \end{result} @@ -91,7 +91,7 @@ session tokens additionally set the “HttpOnly” and “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 ``HttpOnly'' and ``secure'' attributes are not set for this cookie. \end{result} diff --git a/report/v4_access.tex b/report/v4_access.tex index a26d279..45b7515 100644 --- a/report/v4_access.tex +++ b/report/v4_access.tex @@ -1,6 +1,6 @@ \noindent -The CMS has the following access control mechanisms: +The \CMS{} has the following access control mechanisms: \begin{itemize} \item A login mechanism, where logged in users are allowed to access the backend, and anonymous users are not. @@ -35,7 +35,7 @@ These are the results of our check: \item \fail{} -Verify that the principle of least privilege exists - users +Verify that the principle of least privilege exists {-} users should only be able to access functions, data files, URLs, controllers, services, and other resources, for which they possess specific authorization. This implies protection @@ -56,7 +56,9 @@ user (for example, protect against users tampering with a parameter to see or alter another user's account). \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. +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. \end{result} \item @@ -69,7 +71,7 @@ such as \code{Thumbs.db}, \code{.DS\_Store}, \code{.git} or \code{.svn} folders. \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 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. + \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} @@ -98,7 +100,7 @@ information used by access controls cannot be manipulated by end users unless specifically authorized. \begin{result} -This item is the main remaining security concern. I haven't found any obvious fail in the login system, but given the architecture and security status of the whole CMS, I'm not very sure of it. +This item is the main remaining security concern. I haven't found any obvious fail in the login system, but given the architecture and security status of the whole \CMS{}, I'm not very sure of it. \end{result} \notapplicable{ @@ -120,7 +122,7 @@ No such decision logging present. There is only a minor amount of logging, and t \item \fail{} Verify that the application or framework uses strong -random anti-CSRF tokens or has another transaction +random anti-\CSRF{} tokens or has another transaction protection mechanism. \begin{result} diff --git a/report/v5_input.tex b/report/v5_input.tex index 27ee206..4eb09e4 100644 --- a/report/v5_input.tex +++ b/report/v5_input.tex @@ -45,8 +45,8 @@ \srcref{classes/users.php}{145}. \end{result} - \item\pass{} Verify that the application is not susceptible to LDAP - Injection, or that security controls prevent LDAP Injection. + \item\pass{} Verify that the application is not susceptible to \LDAP{} + Injection, or that security controls prevent \LDAP{} Injection. \begin{result} \LDAP{} is not used, thus the application is not susceptible. @@ -72,7 +72,7 @@ recovery\\ (\srcref{classes/user.php}{115}) filepaths are calculated on the hash of the password. All non standard filepaths, such as admin or - theme files, are generated using functions. CMS urls are parsed using a + theme files, are generated using functions. \CMS{} urls are parsed using a standard system wide \code{parse} function. \end{result} @@ -89,10 +89,10 @@ web client code is either properly contextually encoded manually, or utilize templates that automatically encode contextually to ensure the application is not susceptible to reflected, stored and DOM Cross-Site - Scripting (XSS) attacks. + Scripting (\XSS{}) attacks. \begin{result} - A lot of \HTML{} tags are allowed in the post screen, therefore an XSS + A lot of \HTML{} tags are allowed in the post screen, therefore an \XSS{} attack is trivial. Even the comment section uses no input validation whatsoever. \end{result} @@ -104,15 +104,15 @@ malicious automatic binding. \begin{result} - There is some automatic variable binding happening in the POST and GET + There is some automatic variable binding happening in the \POST{} and \GET{} however, defaults are always given and there is no possibility of accidentally binding extra variables. Also the variables are in an array. \end{result} - \item\pass{} Verify that the application has defenses against HTTP + \item\pass{} 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, + makes no distinction about the source of request parameters (\GET{}, \POST{}, cookies, headers, environment, etc.) \begin{result} @@ -132,14 +132,14 @@ \end{result} \item\fail{} Verify that all input data is validated, not only \HTML{} form - fields but all sources of input such as REST calls, query parameters, - HTTP headers, cookies, batch files, RSS feeds, etc; using positive + fields but all sources of input such as \REST{} calls, query parameters, + \HTTP{} headers, cookies, batch files, \RSS{} feeds, etc; using positive validation (whitelisting), then lesser forms of validation such as greylisting (eliminating known bad strings), or rejecting bad inputs (blacklisting). \begin{result} - REST calls are validated using whitelisting, query parameters are not, + \REST{} calls are validated using whitelisting, query parameters are not, headers are not, cookies not, batch files are non-existent and RSS feed output is not filtered. \end{result} diff --git a/report/v7_cryptography.tex b/report/v7_cryptography.tex index 952d832..da88237 100644 --- a/report/v7_cryptography.tex +++ b/report/v7_cryptography.tex @@ -15,7 +15,7 @@ \addtocounter{enumi}{3} \notapplicable{ \item - Verify that all random numbers, random file names, random GUIDs, and random + Verify that all random numbers, random file names, random \GUID{}s, and random strings are generated using the cryptographic module’s approved random number generator when these random values are intended to be not guessable by an attacker. @@ -24,7 +24,7 @@ \item \TODO{} Verify that cryptographic algorithms used by the application have been - validated against FIPS 140-2 or an equivalent standard. + validated against FIPS 140{-}2 or an equivalent standard. \begin{result} The application uses md-5 for password hashing, which should be insecure by now. diff --git a/report/v9_data.tex b/report/v9_data.tex index 0e49d1d..d43c21e 100644 --- a/report/v9_data.tex +++ b/report/v9_data.tex @@ -4,7 +4,7 @@ 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 \texttt{Cache-Control} isn't explicitly used anywhere in the CMS to aid the situation. In my test setup, the response does send \texttt{Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0}, but that'll be a default global Apache setting, I 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 my 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, I think. \end{result} \notapplicable{\item Verify that the list of sensitive data processed by the @@ -14,7 +14,7 @@ directives.} \item\pass{} Verify that all sensitive data is sent to the server in the - HTTP message body or headers (i.e., URL parameters are + \HTTP{} message body or headers (i.e., URL parameters are never used to send sensitive data). \begin{result} @@ -34,7 +34,7 @@ \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 my test setup is probably due to default global Apache settings. + Cache control header are never set by the \CMS{}. The fact that headers as these are indeed sent to the broswer in my test setup is probably due to default global Apache settings. \end{result} \item\pass{} Verify that on the server, all cached or temporary copies @@ -55,7 +55,7 @@ variables, cookies and header values. \begin{result} - The CMS by no means sends any larger amount of parameters than would be expected, seen as it is but a simple app and mostly lacks extra functionality often leading to this kind of excessive parameter transferring, so I count this as a pass. + The \CMS{} by no means sends any larger amount of parameters than would be expected, seen as it is but a simple app and mostly lacks extra functionality often leading to this kind of excessive parameter transferring, so I count this as a pass. \end{result} \notapplicable{\item Verify the application has the ability to detect and alert @@ -63,9 +63,9 @@ an example screen scraping.} \item\pass{} Verify that data stored in client side storage (such as - HTML5 local storage, session storage, IndexedDB, regular + \HTMLF{} local storage, session storage, IndexedDB, regular cookies or Flash cookies) does not contain sensitive data - or PII. + or \PII{}. \begin{result} Vacuously: data is not stored on the client side. @@ -84,7 +84,7 @@ to mitigate memory dumping attacks. \begin{result} - I consider this outside of the scope of the CMS's security requirements, as it is written in, and thus relies on the (memory) security of, PHP. + I consider this outside of the scope of the \CMS{}'s security requirements, as it is written in, and thus relies on the (memory) security of, \PHP{}. \end{result} \end{enumerate}