2 \begin{enumerate
}[label=
{V2.
\arabic*
}]
6 Verify all pages and resources by default require
7 authentication except those specifically intended to be
8 public (principle of complete mediation).
11 All admin pages are private. Unpublished posts are also private.
12 However, the install submission page does not do any authentication at all,
13 allowing any user to reset the database and claim an admin account.
14 User pages can be viewed (and submitted) by any authenticated user.
19 Verify that forms containing credentials are not filled in by
20 the application. Pre-filling by the application implies that
21 credentials are stored in plain-text or a reversible format,
22 which is explicitly prohibited.
25 No credentials that come from the database are pre-filled by the application.
26 However, in some forms, the application pre-fills password fields from the
27 request's POST data. This is not necesarry.
\footnote{This issue was actually
28 overlooked when auditing manually, and was found when running the Fortify tool.
29 In the initial audit, we only ensured that no internal information (from the
30 database) was leaked in this way.
}
37 Verify all authentication controls are enforced on the
41 All authentication controls (login credentials and client cookies) are
42 enforced by the application. Note however item~
\ref{auth:
6}, about the
43 security of these controls in the implementation.
50 Verify all authentication controls fail securely to ensure
51 attackers cannot log in.
54 The input to various forms is not sanitized at all. This makes the implementation
55 in (not only)
\code{Users::find
} vulnerable to
\SQL{} injections. Through this vulnerability,
56 an attacker can execute arbitrary
\SQL{} code from the username field in the login form.
57 The following example code can submitted as username in the login form, which
58 will set the password of the
\code{admin
} user to
\code{s3cret
}:
60 \code{"; UPDATE users SET password='\$
1\$OWgsBb90\$Lkko6aZwmp9XOVrFI09Ab0' WHERE \
\username='admin' AND 'a' = "a
}
62 After using this exploit, the attacker (of course) knows the admin password.
67 Verify password entry fields allow, or encourage, the use
68 of pass-phrases, and do not prevent password managers,
69 long pass-phrases or highly complex passwords being
73 The application allows the user to use any password (except ones that trigger
74 errors in injected
\SQL{} code).
79 Verify all account identity authentication functions (such
80 as update profile, forgot password, disabled / lost token,
81 help desk or IVR) that might regain access to the account
82 are at least as resistant to attack as the primary
83 authentication mechanism.
86 The only alternative mechanism for authenticating (except for using
87 vulnerabilities as described in other point) is using the ``Recover
88 password'' functionality. This sends a secret token to the email
89 address owning the account.
91 After such a token is used, it cannot be reused, because the token is
92 derived from the password hash (and thus a random salt). Tokens do not
93 expire, however. It would be even better to require that a token be used
94 withing a day (or so) after creation.
96 The security of the
\SMTP{} connection is at the discretion of the web server.
97 Often these connections are not very secure, but this worry is beyond the
103 Verify that the changing password functionality includes
104 the old password, the new password, and a password
108 Changing a user's password does not require the original password, nor does the
109 password Changing form request for a password confirmation. This makes it easy
110 to set a wrong password for yourself.
113 \setcounter{enumi
}{11}
117 Verify that all authentication decisions can be logged,
118 without storing sensitive session identifiers or passwords.
119 This should include requests with relevant metadata
120 needed for security investigations.
123 The application does not log any notable authentication event.
128 Verify that account passwords are one way hashed with a
129 salt, and there is sufficient work factor to defeat brute
130 force and password hash recovery attacks.
133 Password are stored in database using the
\PHP{} function
\code{crypt
}. Internally, this
134 function uses salted MD5 on modern UNIX systems. On legacy systems, this uses an old DES
135 based algorithm, which uses only the first eight characters of the supplied password.
136 This is way too easy to reverse with brute-force attacks using dictionary files.
138 Instead the
\CMS{} should use the
\code{argon2
} password hashing algorithm
139 or the
\PHP{} \code{password
\_hash} function (which currently uses BCRYPT) which are
140 (at this moment) considered safe to use.
143 \setcounter{enumi
}{15}
147 Verify that credentials are transported using a suitable
148 encrypted link and that all pages/functions that require a
149 user to enter credentials are done so using an encrypted
153 The app allows admin users to log in over
\HTTP{}. This is insecure, as it allows
154 eavesdroppers to intercept any password.
155 The app should force
\HTTPS{} for at least the login form, the
\code{admin
\_controller} and
156 for the installation script (because the users posts secrets like the database
157 password to this page and the
\CMS{} supplies the user with the credentials of the
\code{admin
}
163 Verify that the forgotten password function and other
164 recovery paths do not reveal the current password and
165 that the new password is not sent in clear text to the user.
168 No password is stored in plain text. The password recovery path works with
169 a secret token, which is used to reset the password. Although this token
170 is derived from the password hash, it does not reveal any secret
176 Verify that information enumeration is not possible via
177 login, password reset, or forgot account functionality.
180 All these forms are vulnerable to
\SQL{} injection attacks. So any information
181 can leak any information from the database.
186 Verify there are no default passwords in use for the
187 application framework or any components used by the
188 application (such as “admin/password”).
191 No secrets are initialized by predefined values. The admin user will have
192 username
\code{admin
} by default. This is no secret and therefore not
198 Verify that anti-automation is in place to prevent breached
199 credential testing, brute forcing, and account lockout
203 No anti-automation measures are deployed.
207 \item Email validation, to harden brute force email address discovery
208 \item Installation database check, to prevent guessing attacks for the database password
209 \item Login, to prevent login guessing
210 \item And comment submission, to prevent spam, phishing et cetera (by
211 using some CAPTCHA software.
217 Verify that all authentication credentials for accessing
218 services external to the application are encrypted and
219 stored in a protected location.
222 The database credentials are hard-coded in
\code{config.php
}. While it
223 would be better to pass secrets as environment variables, this is not
226 However, the installation instructions state the following:
228 Change the file permissions to allow all users write access to the
229 folder you extracted TestCMS to.
231 This implies making the configuration file readable for all users on the
232 system. This information should not be accessible for any user other than
233 running the
\PHP{} script.
238 Verify that forgotten password and other recovery paths
239 use a
\TOTP{} or other soft token, mobile push, or other
240 offline recovery mechanism. Use of a random value in an
241 e-mail or SMS should be a last resort and is known weak.
244 The password recovery path uses a random looking token. It is sent over
245 e-mail, which is considered weak (but not unsafe).
250 Verify that account lockout is divided into soft and hard
251 lock status, and these are not mutually exclusive. If an
252 account is temporarily soft locked out due to a brute force
253 attack, this should not reset the hard lock status.
256 The application has not implemented any lockout mechanisms.
261 Verify that if shared knowledge based questions (also
262 known as ``secret questions'') are required, the questions
263 do not violate privacy laws and are sufficiently strong to
264 protect accounts from malicious recovery.
267 The application uses no shared knowledge based questions, and thus not
268 violate any privacy laws.
273 Verify that the system can be configured to disallow the
274 use of a configurable number of previous passwords.
277 The system does not remember any previously used passwords and does not
278 require variation in the use of different passwords.
283 Verify that risk based re-authentication, two factor or
284 transaction signing is in place for high value transactions.
287 There are no (really) risk based action for which re-authentication would be
293 Verify that measures are in place to block the use of
294 commonly chosen passwords and weak pass-phrases.
297 No password strengthening measures are implemented. The app should
298 use some password strength estimator like
\texttt{zxcvbn
}\footnote{\url{https://github.com/dropbox/zxcvbn
}}.
304 Verify that all authentication challenges, whether
305 successful or failed, should respond in the same average
309 % String comparisation for checking password hashes and password reset
310 % tokens are not in constant time.
317 Verify that secrets,
\API{} keys, and passwords are not
318 included in the source code, or online source code
322 % The database credentials are hard coded in \code{config.php}. These
323 % credentials should ideally be passed using environment variables.
327 \setcounter{enumi
}{30}
331 Verify that if an application allows users to authenticate,
332 they can authenticate using two-factor authentication or
333 other strong authentication, or any similar scheme that
334 provides protection against username + password
338 No such features are implemented.
343 Verify that administrative interfaces are not accessible to
347 Any authenticated user is allowed to view and use the administrative
348 interface. A separation should be made between administrators and normal
354 Browser auto-complete, and integration with password
355 managers are permitted unless prohibited by risk based
359 Browser auto-complete functionality is not restricted in any way.