d2407c4c254d0fb9414a6ba4b40233c5a9ae9496
[ssproject1617.git] / report / v2_authentication.tex
1
2 \begin{enumerate}[label={V2.\arabic*}]
3
4 \item
5 \fail{}
6 Verify all pages and resources by default require
7 authentication except those specifically intended to be
8 public (Principle of complete mediation).
9
10 \begin{result}
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.
15 \end{result}
16
17 \item
18 \fail{}
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.
23
24 \begin{result}
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.}
31 \end{result}
32
33 \setcounter{enumi}{3}
34
35 \item
36 \pass{}
37 Verify all authentication controls are enforced on the
38 server side.
39
40 \begin{result}
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.
44 \end{result}
45
46 \setcounter{enumi}{5}
47
48 \item\label{auth:6}
49 \fail{}
50 Verify all authentication controls fail securely to ensure
51 attackers cannot log in.
52
53 \begin{result}
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}:
59
60 \code{"; UPDATE users SET password='\$1\$OWgsBb90\$Lkko6aZwmp9XOVrFI09Ab0' WHERE \\username='admin' AND 'a' = "a}
61
62 After using this exploit, the attacker (of course) knows the admin password.
63 \end{result}
64
65 \item
66 \pass{}
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
70 entered.
71
72 \begin{result}
73 The application allows the user to use any password (except ones that contain
74 \SQL{} code).
75 \end{result}
76
77 \item
78 \pass{}
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.
84
85 \begin{result}
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.
90
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.
95
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
98 scope of this audit.
99 \end{result}
100
101 \item
102 \fail{}
103 Verify that the changing password functionality includes
104 the old password, the new password, and a password
105 confirmation.
106
107 \begin{result}
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.
111 \end{result}
112
113 \setcounter{enumi}{11}
114
115 \item
116 \fail{}
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.
121
122 \begin{result}
123 The application does not log any notable authentication event.
124 \end{result}
125
126 \item
127 \fail{}
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.
131
132 \begin{result}
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.
135
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).
138 \end{result}
139
140 \setcounter{enumi}{15}
141
142 \item
143 \fail{}
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
147 link.
148
149 \begin{result}
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).
155 \end{result}
156
157 \item
158 \pass{}
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.
162
163 \begin{result}
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
167 information.
168 \end{result}
169
170 \item
171 \fail{}
172 Verify that information enumeration is not possible via
173 login, password reset, or forgot account functionality.
174
175 \begin{result}
176 All these forms are vulnerable to \SQL{} injection attacks. So any information
177 can leak any information from the database.
178 \end{result}
179
180 \item
181 \pass{}
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”).
185
186 \begin{result}
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
189 considered unsafe.
190 \end{result}
191
192 \item
193 \fail{}
194 Verify that anti-automation is in place to prevent breached
195 credential testing, brute forcing, and account lockout
196 attacks.
197
198 \begin{result}
199 No anti-automation measures are deployed.
200
201 This is needed for:
202 \begin{itemize}
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).
208 \end{itemize}
209 \end{result}
210
211 \item
212 \fail{}
213 Verify that all authentication credentials for accessing
214 services external to the application are encrypted and
215 stored in a protected location.
216
217 \begin{result}
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
220 really bad practice.
221
222 However, the installation instructions state the following:
223 \begin{verbatim}
224 Change the file permissions to allow all users write access to the
225 folder you extracted testcms to.
226 \end{verbatim}
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.
230 \end{result}
231
232 \item
233 \pass{}
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.
238
239 \begin{result}
240 The password recovery path uses a random looking token. It is sent over
241 e-mail, which is considered weak (but not unsafe).
242 \end{result}
243
244 \item
245 \fail{}
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.
250
251 \begin{result}
252 The application has not implemented any lockout mechanisms.
253 \end{result}
254
255 \item
256 \pass{}
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.
261
262 \begin{result}
263 The application uses no shared knowledge based questions, and thus not
264 violate any privacy laws.
265 \end{result}
266
267 \item
268 \fail{}
269 Verify that the system can be configured to disallow the
270 use of a configurable number of previous passwords.
271
272 \begin{result}
273 The system does not remember any previously used passwords and does not
274 require variation in the use of different passwords.
275 \end{result}
276
277 \item
278 \pass{}
279 Verify that risk based re-authentication, two factor or
280 transaction signing is in place for high value transactions.
281
282 \begin{result}
283 There are no (really) risk based action or which re-authentication would be
284 fit.
285 \end{result}
286
287 \item
288 \fail{}
289 Verify that measures are in place to block the use of
290 commonly chosen passwords and weak passphrases.
291
292 \begin{result}
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}}.
295 \end{result}
296
297 \notapplicable{
298 \item
299 % \fail{}
300 Verify that all authentication challenges, whether
301 successful or failed, should respond in the same average
302 response time.
303
304 % \begin{result}
305 % String comparisation for checking password hashes and password reset
306 % tokens are not in constant time.
307 % \end{result}
308 }
309
310 \notapplicable{
311 \item
312 % \fail{}
313 Verify that secrets, \API{} keys, and passwords are not
314 included in the source code, or online source code
315 repositories.
316
317 % \begin{result}
318 % The database credentials are hard coded in \code{config.php}. These
319 % credentials should ideally be passed using environment variables.
320 % \end{result}
321 }
322
323 \setcounter{enumi}{30}
324
325 \item
326 \fail{}
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
331 disclosure.
332
333 \begin{result}
334 No surch features are implemented.
335 \end{result}
336
337 \item
338 \fail{}
339 Verify that administrative interfaces are not accessible to
340 untrusted parties.
341
342 \begin{result}
343 Any authenticated user is allowed to view and use the administrative
344 interface. A separation should be made between administrators and normal
345 users.
346 \end{result}
347
348 \item
349 \pass{}
350 Browser autocomplete, and integration with password
351 managers are permitted unless prohibited by risk based
352 policy.
353
354 \begin{result}
355 Browser autocomplete functionality is not restricted in any way.
356 \end{result}
357
358 \end{enumerate}