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 plaintext 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 immplementation.
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. The login form
56 is also vulnerable. Any user can execute arbitrary
\SQL{} code from the username field.
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 passphrases, and do not prevent password managers,
69 long passphrases or highly complex passwords being
73 The application allows the user to use any password (except ones that contain
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. This is way too reverse with brute-force attacks using dictionary files.
136 Instead it would be better to use the
\code{argon2
} password hashing algorithm
137 or the
\PHP{} \code{password
\_hash} function (which currently uses BCRYPT).
140 \setcounter{enumi
}{15}
144 Verify that credentials are transported using a suitable
145 encrypted link and that all pages/functions that require a
146 user to enter credentials are done so using an encrypted
150 The app allows admin users to log in over
\HTTP{}. This is insecure, as it allows
151 eavesdroppers to intercept password.
152 The app should force
\HTTPS{} for at least the login form, the
\code{admin
\_controller} and
153 for the installation script (because the users posts secrets like the database
154 password to this page).
159 Verify that the forgotten password function and other
160 recovery paths do not reveal the current password and
161 that the new password is not sent in clear text to the user.
164 No password is stored in plain text. The password recovery path works with
165 a secret token, which is used to reset the password. Although this token
166 is derived from the password hash, it does not reveal any secret
172 Verify that information enumeration is not possible via
173 login, password reset, or forgot account functionality.
176 All these forms are vulnerable to
\SQL{} injection attacks. So any information
177 can leak any information from the database.
182 Verify there are no default passwords in use for the
183 application framework or any components used by the
184 application (such as “admin/password”).
187 No secrets are initialized by predefined values. The admin user will have
188 username
\code{admin
} by default. This is no secret and therefore not
194 Verify that anti-automation is in place to prevent breached
195 credential testing, brute forcing, and account lockout
199 No anti-automation measures are deployed.
203 \item Email validation, to harden brute force email address discovery
204 \item Installation database check, to prevent guessing attacks for the database password
205 \item Login, to prevent login guessing
206 \item And comment submission, to prevent spam, phishing et cetera (by
207 using some CAPTCHA software).
213 Verify that all authentication credentials for accessing
214 services external to the application are encrypted and
215 stored in a protected location.
218 The database credentials are hardcoded in
\code{config.php
}. While it
219 would be better to pass secrets as environment variables, this is not
222 However, the installation instructions state the following:
224 Change the file permissions to allow all users write access to the
225 folder you extracted testcms to.
227 This implies making the configuration file readable for all users on the
228 system. This information should not be accessible for any user other than
229 running the
\PHP{} script.
234 Verify that forgotten password and other recovery paths
235 use a
\TOTP{} or other soft token, mobile push, or other
236 offline recovery mechanism. Use of a random value in an
237 e-mail or SMS should be a last resort and is known weak.
240 The password recovery path uses a random looking token. It is sent over
241 e-mail, which is considered weak (but not unsafe).
246 Verify that account lockout is divided into soft and hard
247 lock status, and these are not mutually exclusive. If an
248 account is temporarily soft locked out due to a brute force
249 attack, this should not reset the hard lock status.
252 The application has not implemented any lockout mechanisms.
257 Verify that if shared knowledge based questions (also
258 known as ``secret questions'') are required, the questions
259 do not violate privacy laws and are sufficiently strong to
260 protect accounts from malicious recovery.
263 The application uses no shared knowledge based questions, and thus not
264 violate any privacy laws.
269 Verify that the system can be configured to disallow the
270 use of a configurable number of previous passwords.
273 The system does not remember any previously used passwords and does not
274 require variation in the use of different passwords.
279 Verify that risk based re-authentication, two factor or
280 transaction signing is in place for high value transactions.
283 There are no (really) risk based action or which re-authentication would be
289 Verify that measures are in place to block the use of
290 commonly chosen passwords and weak passphrases.
293 No password strengthening measures are implemented. The app should
294 use some password strength estimator like
\texttt{zxcvbn
}\footnote{\url{https://github.com/dropbox/zxcvbn
}}.
300 Verify that all authentication challenges, whether
301 successful or failed, should respond in the same average
305 % String comparisation for checking password hashes and password reset
306 % tokens are not in constant time.
313 Verify that secrets,
\API{} keys, and passwords are not
314 included in the source code, or online source code
318 % The database credentials are hard coded in \code{config.php}. These
319 % credentials should ideally be passed using environment variables.
323 \setcounter{enumi
}{30}
327 Verify that if an application allows users to authenticate,
328 they can authenticate using two-factor authentication or
329 other strong authentication, or any similar scheme that
330 provides protection against username + password
334 No surch features are implemented.
339 Verify that administrative interfaces are not accessible to
343 Any authenticated user is allowed to view and use the administrative
344 interface. A separation should be made between administrators and normal
350 Browser autocomplete, and integration with password
351 managers are permitted unless prohibited by risk based
355 Browser autocomplete functionality is not restricted in any way.