d58f5622b8b86dc166304c51909d9afa81a76292
[ssproject1617.git] / report / v2_authentication.tex
1
2 \begin{enumerate}[label={2.\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 \pass{}
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 should not be stored in plain text) are ever filled in by
26 the application.
27 \end{result}
28
29 \setcounter{enumi}{3}
30
31 \item
32 \pass{}
33 Verify all authentication controls are enforced on the
34 server side.
35
36 \begin{result}
37 All authentication controls (login credentials and client cookies) are
38 enforced by the application. Note however item~\ref{auth:6}, about the
39 security of these controls in the immplementation.
40 \end{result}
41
42 \setcounter{enumi}{5}
43
44 \item\label{auth:6}
45 \fail{}
46 Verify all authentication controls fail securely to ensure
47 attackers cannot log in.
48
49 \begin{result}
50 The input to various forms is not sanitized at all. This makes the implementation
51 in (not only) \texttt{Users::find} vulnerable to SQL injections. The login form
52 is also vulnerable. Any user can execute arbitrary SQL code from the username field.
53 The following example code can submitted as username in the login form, which
54 will set the password of the \texttt{admin} user to \texttt{s3cret}:
55
56 \code{"; UPDATE users SET password='\$1\$OWgsBb90\$Lkko6aZwmp9XOVrFI09Ab0' WHERE \\username='admin' AND 'a' = "a}
57
58 After using this exploit, the attacker (of course) knows the admin password.
59 \end{result}
60
61 \item
62 \pass{}
63 Verify password entry fields allow, or encourage, the use
64 of passphrases, and do not prevent password managers,
65 long passphrases or highly complex passwords being
66 entered.
67
68 \begin{result}
69 The application allows the user to use any password (except ones that contain
70 SQL code).
71 \end{result}
72
73 \item
74 \pass{}
75 Verify all account identity authentication functions (such
76 as update profile, forgot password, disabled / lost token,
77 help desk or IVR) that might regain access to the account
78 are at least as resistant to attack as the primary
79 authentication mechanism.
80
81 \begin{result}
82 The only alternative mechanism for authenticating (except for using
83 vulnerabilities as described in other point) is using the ``Recover
84 password'' functionality. This sends a secret token to the email
85 address owning the account.
86
87 After such a token is used, it cannot be reused, because the token is
88 derived from the password hash (and thus a random salt). Tokens do not
89 expire, however. It would be even better to require that a token be used
90 withing a day (or so) after creation.
91
92 The security of the SMTP connection is at the discretion of the web server.
93 Often these connections are not very secure, but this worry is beyond the
94 scope of this audit.
95 \end{result}
96
97 \item
98 \fail{}
99 Verify that the changing password functionality includes
100 the old password, the new password, and a password
101 confirmation.
102
103 \begin{result}
104 Changing a user's password does not require the original password, nor does the
105 password Changing form request for a password confirmation. This makes it easy
106 to set a wrong password for yourself.
107 \end{result}
108
109 \setcounter{enumi}{11}
110
111 \item
112 \fail{}
113 Verify that all authentication decisions can be logged,
114 without storing sensitive session identifiers or passwords.
115 This should include requests with relevant metadata
116 needed for security investigations.
117
118 \begin{result}
119 The application does not log any notable authentication event.
120 \end{result}
121
122 \item
123 \fail{}
124 Verify that account passwords are one way hashed with a
125 salt, and there is sufficient work factor to defeat brute
126 force and password hash recovery attacks.
127
128 \begin{result}
129 Password are stored in database using the PHP function \texttt{crypt}. Internally, this
130 function uses salted MD5. This is way too reverse with brute-force attacks using dictionary files.
131
132 Instead it would be better to use the \texttt{argon2} password hashing algorithm
133 or the PHP \texttt{password\_hash} function (which currently uses BCRYPT).
134 \end{result}
135
136 \setcounter{enumi}{15}
137
138 \item
139 \fail{}
140 Verify that credentials are transported using a suitable
141 encrypted link and that all pages/functions that require a
142 user to enter credentials are done so using an encrypted
143 link.
144
145 \begin{result}
146 The app allows admin users to log in over HTTP. This is insecure, as it allows
147 eavesdroppers to intercept password.
148 The app should force HTTPS for at least the login form, the \texttt{admin\_controller} and
149 for the installation script (because the users posts secrets like the database
150 password to this page).
151 \end{result}
152
153 \item
154 \pass{}
155 Verify that the forgotten password function and other
156 recovery paths do not reveal the current password and
157 that the new password is not sent in clear text to the user.
158
159 \begin{result}
160 No password is stored in plain text. The password recovery path works with
161 a secret token, which is used to reset the password. Although this token
162 is derived from the password hash, it does not reveal any secret
163 information.
164 \end{result}
165
166 \item
167 \fail{}
168 Verify that information enumeration is not possible via
169 login, password reset, or forgot account functionality.
170
171 \begin{result}
172 All these forms are vulnerable to SQL injection attacks. So any information
173 can leak any information from the database.
174 \end{result}
175
176 \item
177 \pass{}
178 Verify there are no default passwords in use for the
179 application framework or any components used by the
180 application (such as “admin/password”).
181
182 \begin{result}
183 No secrets are initialized by predefined values. The admin user will have
184 username \texttt{admin} by default. This is no secret and therefore not
185 considered unsafe.
186 \end{result}
187
188 \item
189 \fail{}
190 Verify that anti-automation is in place to prevent breached
191 credential testing, brute forcing, and account lockout
192 attacks.
193
194 \begin{result}
195 No anti-automation measures are deployed.
196
197 This is needed for:
198 \begin{itemize}
199 \item Email validation, to harden brute force email address discovery
200 \item Installation database check, to prevent guessing attacks for the database password
201 \item Login, to prevent login guessing
202 \item And comment submission, to prevent spam, phishing et cetera (by using CAPTCHA).
203 \end{itemize}
204 \end{result}
205
206 \item
207 \fail{}
208 Verify that all authentication credentials for accessing
209 services external to the application are encrypted and
210 stored in a protected location.
211
212 \begin{result}
213 The database credentials are hardcoded in \texttt{config.php}. While it
214 would be better to pass secrets as environment variables, this is not
215 really bad practice.
216
217 However, the installation instructions state the following:
218 \begin{verbatim}
219 Change the file permissions to allow all users write access to the folder
220 you extracted testcms to.
221 \end{verbatim}
222 This implies making the configuration file readable for all users on the
223 system. This information should not be accessible for any user other than
224 running the PHP script.
225 \end{result}
226
227 \item
228 \pass{}
229 Verify that forgotten password and other recovery paths
230 use a TOTP or other soft token, mobile push, or other
231 offline recovery mechanism. Use of a random value in an
232 e-mail or SMS should be a last resort and is known weak.
233
234 \begin{result}
235 The password recovery path uses a random looking token. It is sent over
236 e-mail, which is considered weak (but not unsafe).
237 \end{result}
238
239 \notapplicable{\item
240 Verify that account lockout is divided into soft and hard
241 lock status, and these are not mutually exclusive. If an
242 account is temporarily soft locked out due to a brute force
243 attack, this should not reset the hard lock status.
244
245 % The application has not implemented any lockout mechanisms.
246 }
247
248 \notapplicable{\item
249 Verify that if shared knowledge based questions (also
250 known as "secret questions") are required, the questions
251 do not violate privacy laws and are sufficiently strong to
252 protect accounts from malicious recovery.}
253
254 \item
255 \fail{}
256 Verify that the system can be configured to disallow the
257 use of a configurable number of previous passwords.
258
259 \begin{result}
260 The system does not remember any previously used passwords and does not
261 require variation in the use of different passwords.
262 \end{result}
263
264 \notapplicable{\item
265 Verify that risk based re-authentication, two factor or
266 transaction signing is in place for high value transactions.}
267
268 % There are no (really) risk based action or which re-authentication would be
269 % fit
270
271 \item
272 \fail{}
273 Verify that measures are in place to block the use of
274 commonly chosen passwords and weak passphrases.
275
276 \begin{result}
277 No password strengthening measures are implemented. The app should
278 use some password strength estimator like \texttt{zxcvbn}.
279 \end{result}
280
281 \item
282 \fail{}
283 Verify that all authentication challenges, whether
284 successful or failed, should respond in the same average
285 response time.
286
287 \begin{result}
288 String comparisation for checking password hases and password reset tokens
289 are not in constant time.
290 \end{result}
291
292 \item
293 \fail{}
294 Verify that secrets, API keys, and passwords are not
295 included in the source code, or online source code
296 repositories.
297
298 \begin{result}
299 The database credentials are hard coded in \texttt{config.php}. These
300 credentials should ideally be passed using environment variables.
301 \end{result}
302
303 \setcounter{enumi}{30}
304
305 \notapplicable{\item
306 Verify that if an application allows users to authenticate,
307 they can authenticate using two-factor authentication or
308 other strong authentication, or any similar scheme that
309 provides protection against username + password
310 disclosure.}
311
312 \item
313 \fail{}
314 Verify that administrative interfaces are not accessible to
315 untrusted parties.
316
317 \begin{result}
318 Any authenticated user is allowed to view and use the administrative
319 interface. A separation should be made between administrators and normal
320 users.
321 \end{result}
322
323 \item
324 \pass{}
325 Browser autocomplete, and integration with password
326 managers are permitted unless prohibited by risk based
327 policy.
328
329 \begin{result}
330 Browser autocomplete functionality is not restricted in any way.
331 \end{result}
332
333 \end{enumerate}