reference/session/security.xml
ccb379494533c9b7d63a81f0221231a9e526eee9
...
...
@@ -7,9 +7,10 @@
7
7
External links: <link xlink:href="&url.session-fixation;">Session fixation</link>
8
8
</para>
9
9
<para>
10
-
HTTP session management is core of web security. All of mitigation
11
-
should be adopted to make sure session security. Developer should
12
-
enable/use applicable security measures.
10
+
HTTP session management represents the core of web security.
11
+
All possible mitigation measures <emphasis>should</emphasis>
12
+
be adopted to ensure sessions are secured.
13
+
Developers should also enable/use applicable security measures.
13
14
</para>
14
15

15
16
<sect1 xml:id="features.session.security.management">
...
...
@@ -19,145 +20,148 @@
19
20
<title>Session Security</title>
20
21

21
22
<para>
22
-
The session module cannot guarantee that the information you store
23
-
in a session is only viewed by the user who created the session. You
24
-
need to take additional measures to protect the confidentiality
23
+
The session module can not guarantee that the information stored
24
+
in a session is only viewed by the user who created the session.
25
+
Additional measures are needed to protect the confidentiality
25
26
of the session, depending on the value associated with it.
26
27
</para>
27
28

28
29
<para>
29
-
Assess the importance of the data carried by your sessions and
30
-
deploy additional protections -- this usually comes at a price,
31
-
reduced convenience for the user. For example, if you want to
32
-
protect users from simple social engineering tactics, you need to
33
-
enable <literal>session.use_only_cookies</literal>. In that case,
34
-
cookies must be enabled unconditionally on the user side, or
35
-
sessions will not work.
30
+
The importance of the data carried in the session needs to be
31
+
assessed and further protection may be deployed; this typically
32
+
comes at a price, such as reduced convenience for the user.
33
+
For example, to protect users from a simple social engineering tactic,
34
+
<link linkend="ini.session.use-only-cookies">session.use_only_cookies</link>
35
+
needs to be enabled. In that case, cookies must be enabled
36
+
unconditionally on the client side, or sessions will not work.
36
37
</para>
37
38

38
39
<para>
39
40
There are several ways to leak an existing session ID to third
40
-
parties. e.g. JavaScript injections, session ID in URLs, packet
41
-
sniffing, physical access to device. A leaked session ID enables
42
-
the third party to access all resources which are associated with
43
-
a specific ID. First, URLs carrying session IDs. If you link to
44
-
an external site, the URL including the session ID might be
45
-
stored in the external site's referrer logs. Second, a more
46
-
active attacker might listen to your network traffic. If it is
47
-
not encrypted, session IDs will flow in plain text over the
48
-
network. The solution here is to implement SSL/TLS on your server
49
-
and make it mandatory for users. HSTS should be used for better
50
-
security.
41
+
parties. E.g. JavaScript injections, session IDs in URLs,
42
+
packet sniffing, physical access to the device, etc.
43
+
A leaked session ID enables the third party to access all
44
+
resources associated with a specific ID. First, URLs carrying
45
+
session IDs. If there are links to an external site or resource,
46
+
the URL including the session ID might be stored in the external
47
+
site's referrer logs. Second, a more active attacker might listen
48
+
to network traffic. If it is unencrypted, session IDs will flow
49
+
in plain text over the network. The solution is to implement
50
+
SSL/TLS on the server and make it mandatory for users.
51
+
HSTS should be used for improved security.
51
52
</para>
52
53

53
54
<note>
54
55
<simpara>
55
-
Even HTTPS cannot protect confidential data in contents sometimes.
56
-
e.g. CRIME, Beast attack. There are many networks that use
57
-
HTTPS MITM proxy for audit purpose. Attackers may setup such proxy
58
-
also.
56
+
Even HTTPS can not protect confidential data at all times.
57
+
For example the CRIME and Beast vulnerabilities may enable an
58
+
attacker to read the data. Also, note that many networks employ
59
+
HTTPS MITM proxies for audit purposes.
60
+
Attackers may also set up such a proxy.
59
61
</simpara>
60
62
</note>
61
63

62
64
</sect2>
63
65

64
66
<sect2 xml:id="features.session.security.management.non-adaptive-session">
65
-
<title>Non-Adaptive Session Management</title>
67
+
<title>Non-adaptive Session Management</title>
66
68

67
69
<para>
68
-
PHP's session manager is adaptive by default currently. Adaptive session manger
69
-
has additional risks.
70
+
PHP's session manager is adaptive by default currently.
71
+
An adaptive session manager bears additional risks.
70
72
</para>
71
73

72
74
<para>
73
-
Since PHP 5.5.2, <link linkend="ini.session.use-strict-mode">session.use_strict_mode</link>
74
-
is available. When it is enabled and session save handler supports
75
-
it, uninitialized session ID is rejected and new session ID is
76
-
created. This protects attack that forces users to use known session
77
-
ID. Attacker may paste links or send mail that contains session
78
-
ID. e.g. http://example.com/page.php?PHPSESSID=123456789 If <link
79
-
linkend="ini.session.use-trans-sid">session.use_trans_sid</link> is
80
-
enabled, victim will start session using attacker provided session
81
-
ID. <link linkend="ini.session.use-strict-mode">session.use_strict_mode</link>
82
-
mitigates the risk.
75
+
When <link linkend="ini.session.use-strict-mode">session.use_strict_mode</link> is enabled,
76
+
and the session save handler supports it,
77
+
an uninitialized session ID is rejected and a new one is created.
78
+
This prevents an attack that forces users to use a known session ID.
79
+
An attacker may paste links or send emails that contains the session ID.
80
+
E.g. <literal>http://example.com/page.php?PHPSESSID=123456789</literal> if
81
+
<link linkend="ini.session.use-trans-sid">session.use_trans_sid</link>
82
+
is enabled, the victim will start a session using the session ID provided
83
+
by the attacker.
84
+
<link linkend="ini.session.use-strict-mode">session.use_strict_mode</link>
85
+
mitigate this risk.
83
86
</para>
84
87

85
88
<warning>
86
89
<simpara>
87
-
User defined save handler can also support strict session mode by implementing
88
-
session ID validation function/method. All user defined save handlers must
89
-
implement session ID validation function/method.
90
+
User defined save handlers can also support strict session mode by
91
+
implementing session ID validation. All user defined save handlers
92
+
should implement session ID validation.
90
93
</simpara>
91
94
</warning>
92
95

93
96
<para>
94
-
Session ID cookie could be set with domain, path, httponly, secure
95
-
attributes. There is precedence defined by browsers. By using the
96
-
precedence, attacker can set session ID that could be used
97
-
permanently. Use of <link
98
-
linkend="ini.session.use-only-cookies">session.use_only_cookies</link>
99
-
will not solve this issue. <link
100
-
linkend="ini.session.use-strict-mode">session.use_strict_mode</link>
101
-
mitigates this risk. With <link
102
-
linkend="ini.session.use-strict-mode">session.use_strict_mode</link>=On,
103
-
uninitialized session ID will not be accepted. Session module
104
-
creates new session ID always when session ID is not initialized by
105
-
session module.
97
+
The session ID cookie may be set with the domain, path, httponly,
98
+
secure and, as of PHP 7.3, SameSite attributes.
99
+
<!-- Not exactly sure what the meaning here is - girgias -->
100
+
There is precedence defined by browsers.
101
+
By using the precedence, an attacker can set session ID that
102
+
could be used permanently. Use of
103
+
<link linkend="ini.session.use-only-cookies">session.use_only_cookies</link>
104
+
will not solve this issue.
105
+
<link linkend="ini.session.use-strict-mode">session.use_strict_mode</link>
106
+
mitigates this risk. With
107
+
<link linkend="ini.session.use-strict-mode">session.use_strict_mode</link>=On,
108
+
the uninitialized session ID will be refused.
106
109
</para>
107
110

108
111
<note>
109
112
<simpara>
110
-
Even though <link
111
-
linkend="ini.session.use-strict-mode">session.use_strict_mode</link>
112
-
mitigates risk of adoptive session management, attacker can force
113
-
users to use initialized session ID which is created by attacker. e.g.
114
-
JavaScript injection. This attack could be mitigated by this manual's
115
-
recommendations.
113
+
Even though
114
+
<link linkend="ini.session.use-strict-mode">session.use_strict_mode</link>
115
+
mitigates the risk of adaptive session management, an attacker can force
116
+
users to use an initialized session ID which has been created by an attacker.
117
+
E.g. JavaScript injection.
118
+
This attack can be mitigated by this manual's recommendations.
116
119
</simpara>
117
120

118
121
<simpara>
119
-
If you follow this manual, you will enable <link
120
-
linkend="ini.session.use-strict-mode">session.use_strict_mode</link>,
121
-
use time-stamp based session management, and regenerate session ID
122
-
by <function>session_regenerate_id</function> with recommended procedure.
123
-
If you do all of these, attacker generated session ID will eventually
124
-
deleted.
122
+
By following this manual, developers should enable,
123
+
<link linkend="ini.session.use-strict-mode">session.use_strict_mode</link>,
124
+
use timestamp based session management, and regenerate session IDs using
125
+
<function>session_regenerate_id</function> with recommended procedures.
126
+
If developers follow all of the above, an attacker generated session ID
127
+
will eventually be deleted.
125
128
</simpara>
126
129

127
130
<simpara>
128
-
When obsolete session access happened, you should save all active
129
-
session data for the user. It will be useful for investigation later.
130
-
Then, force user to logout from all sessions. i.e. Require users
131
-
to re-authenticate. This way, you can prevent attackers from
132
-
keep abusing stolen sessions.
131
+
When access to an obsolete session occurs, developers should save all
132
+
active session data of the user. As this information will be relevant
133
+
for an ensuing investigation. The user should be forcefully logged out
134
+
of all sessions, i.e. require them to reauthenticate.
135
+
This prevents attackers from abusing stolen sessions.
133
136
</simpara>
134
137
</note>
135
138

136
139
<warning>
137
140
<simpara>
138
-
Access to obsolete session data does not mean attack always.
139
-
Unstable network and/or immediate active session deletion will
140
-
cause legitimate users to use obsolete sessions.
141
+
Access to an obsolete session does not necessarily suggest an attack.
142
+
An unstable network and/or immediate deletion of the active session
143
+
will result in legitimate users using obsolete sessions.
141
144
</simpara>
142
145
</warning>
143
146

144
147
<para>
145
-
Since PHP 7.1.0, <function>session_create_id</function> is added.
146
-
This function could be used to prefix session ID by user ID to
147
-
access active sessions for a user efficiently. Enabling
148
+
As of PHP 7.1.0, <function>session_create_id</function> has been added.
149
+
This function may be operated to access all active sessions of a user
150
+
efficiently by prefixing the session IDs with the user ID. Enabling
148
151
<link linkend="ini.session.use-strict-mode">session.use_strict_mode</link>
149
-
is very important with this setup. Otherwise, malicious users can set
152
+
is vital with this setup. Otherwise, malicious users can set
150
153
malicious session ID for other users.
151
154
</para>
152
155

153
156
<note>
154
157
<simpara>
155
-
Users prior to PHP 7.1.0 should use CSPRNG, e.g. /dev/urandom, or
158
+
Users prior to PHP 7.1.0 <emphasis>should</emphasis> use
159
+
<acronym>CSPRNG</acronym>, e.g. <filename>/dev/urandom</filename>, or
156
160
<function>random_bytes</function> and hash functions to generate
157
-
new session ID. <function>session_create_id</function> has
158
-
collision detection and generates session ID according to session
159
-
INI settings. Use of <function>session_create_id</function> is
160
-
preferred.
161
+
a new session ID. <function>session_create_id</function> has
162
+
collision detection and generates a session ID according to the
163
+
session's INI settings.
164
+
Use of <function>session_create_id</function> is preferred.
161
165
</simpara>
162
166
</note>
163
167

...
...
@@ -168,110 +172,107 @@
168
172

169
173
<para>
170
174
<link linkend="ini.session.use-strict-mode">session.use_strict_mode</link>
171
-
is good mitigation, but it is not enough mitigation. Developer must use
175
+
is a good mitigation, however not sufficient. Developers must equally use
172
176
<function>session_regenerate_id</function> for session security.
173
177
</para>
174
178

175
179
<para>
176
-
Session ID regeneration reduces risk of stolen session ID, thus
180
+
Session ID regeneration reduces the risk of stolen session IDs, thus
177
181
<function>session_regenerate_id</function> must be called periodically.
178
-
e.g. Regenerate session ID for every 15 minutes for security
179
-
sensitive content. Even when session ID is stolen, either legitimate
180
-
user or attacker session will be expired. i.e. User or attacker access
181
-
will generate obsolete session access error.
182
+
E.g. Regenerate the session ID every 15 minutes for security sensitive content.
183
+
Even in the case that a session ID is stolen, both the legitimate
184
+
user's and the attacker's session will expire.
185
+
In other words access by the user or the attacker will
186
+
generate an obsolete session access error.
182
187
</para>
183
188

184
189
<para>
185
-
Session ID must be regenerated when user is authenticated.
190
+
Session IDs <emphasis>must</emphasis> be regenerated when user privileges
191
+
are elevated, such as after authenticating.
186
192
<function>session_regenerate_id</function> must be called prior to
187
-
set authentication information to $_SESSION. (Since PHP 7.0.0,
188
-
<function>session_regenerate_id</function> saves current session
189
-
data automatically in order to save time-stamp/etc to current session.)
190
-
Make sure only new session contains authenticated flag.
193
+
setting the authentication information to <varname>$_SESSION</varname>.
194
+
(<function>session_regenerate_id</function> saves the current session data
195
+
automatically in order to save timestamp/etc. to the current session.)
196
+
Ensure only the new session contains the authenticated flag.
191
197
</para>
192
198

193
199
<para>
194
-
Developer must NOT rely on session ID expiration by <link
195
-
linkend="ini.session.gc-maxlifetime">session.gc_maxlifetime</link>.
196
-
Attackers may access victim's session ID periodically to prevent
197
-
expiration and keep exploiting victim's session ID including
198
-
authenticated sessions.
200
+
Developers <emphasis>must not</emphasis> rely on session ID expiration by
201
+
<link linkend="ini.session.gc-maxlifetime">session.gc_maxlifetime</link>.
202
+
Attackers may access a victim's session ID periodically to prevent its
203
+
expiration and keep exploiting it, including an authenticated session.
199
204
</para>
200
205

201
206
<para>
202
-
Instead, you must implement time-stamp based session data management
203
-
by yourself.
207
+
Instead, developers must implement timestamp based session data management.
204
208
</para>
205
209

206
210
<warning>
207
211
<simpara>
208
-
Although session manager can manage time-stamp transparently, but this
209
-
feature is not implemented. Old session data must be kept until
210
-
GC. At the same time, developers must make sure obsolete session data
211
-
is removed. However, developers must NOT remove active session data
212
-
immediately.
213
-
i.e. Never call <literal>session_regenerate_id(true);</literal>
214
-
and <function> session_destroy</function> for active session.
215
-
This may sound contradictory, but this is the mandatory requirement.
212
+
Although the session manager can manage timestamps transparently,
213
+
this feature is not implemented. Old session data must be kept until GC.
214
+
Simultaneously, developers must assure themselves obsolete session data
215
+
is removed. However, developers must not remove active session data immediately.
216
+
I.e. <code>session_regenerate_id(true);</code> and
217
+
<function>session_destroy</function> must never be called together for an active session.
218
+
This may sound contradictory, but this is a mandatory requirement.
216
219
</simpara>
217
220
</warning>
218
221

219
222
<para>
220
-
<function>session_regenerate_id</function> does not delete
221
-
old session by default. Old authenticated session may be available
222
-
for use. Developers must prevent old session to be used by anyone,
223
-
must prohibit access to obsolete session data by themselves using
224
-
time-stamp.
223
+
<function>session_regenerate_id</function> does <emphasis>not</emphasis>
224
+
delete outdated sessions by default.
225
+
Obsolete authenticated sessions may be present for use.
226
+
Developers must prevent outdated sessions to be consumed by anyone.
227
+
They must prohibit access to obsolete session data by themselves using timestamps.
225
228
</para>
226
229

227
230
<warning>
228
231
<simpara>
229
-
Immediate active session removal has unwanted side effects.
230
-
Session could be vanished when there are concurrent connections
231
-
to web application and/or network is unstable.
232
+
The sudden removal of an active session produces undesirable side effects.
233
+
Sessions can vanish when there are concurrent connections to the web
234
+
application and/or the network is unstable.
232
235
</simpara>
233
236
<simpara>
234
-
Possibly malicious access cannot be detected with immediate active
235
-
session removal also.
237
+
Potential malicious access is undetectable with the sudden removal of active sessions.
236
238
</simpara>
237
239
<simpara>
238
-
Instead of deleting old session immediately, you must set short term
239
-
expiration time (time-stamp) in $_SESSION, and prohibit access to
240
-
the session data by yourself.
240
+
Instead of deleting outdated sessions immediately, developers must set a
241
+
short-term expiration time (timestamp) in <varname>$_SESSION</varname>,
242
+
and prohibit access to the session data by themselves.
241
243
</simpara>
242
244
<simpara>
243
-
You must not prohibit access to old session data immediately after
244
-
<function>session_regenerate_id</function>. It must be prohibited
245
-
a little later. e.g. A few seconds later for stable wired network.
246
-
A few minutes later for unstable network such as mobile or WiFi.
245
+
Developers must not prohibit access to old session data immediately after
246
+
<function>session_regenerate_id</function>. It must be prohibited at a
247
+
later stage. E.g. a few seconds later for stable networks, like a wired network,
248
+
and a few minutes later for unstable networks such as cell phones or Wi-Fi.
247
249
</simpara>
248
250
<simpara>
249
-
If user accesses to obsolete session(expired session),
250
-
deny access to it. It is recommended to remove authenticated status
251
-
from all of the users' session because it is likely an attack.
251
+
If a user accesses an obsolete session (expired session), access to it should be denied.
252
+
It is also recommended to remove the authenticated status from all of the user's
253
+
sessions to as it is likely to represent an attack.
252
254
</simpara>
253
255
</warning>
254
256

255
257
<para>
256
258
Proper use of <link linkend="ini.session.use-only-cookies">session.use_only_cookies</link>
257
-
and <function>session_regenerate_id</function> could cause personal
258
-
DoS by undeletable cookies set by attackers. When this is the case,
259
-
you may ask users to remove cookies and warn users that there could
260
-
be possible security issues. Attackers may set malicious cookies via
261
-
vulnerable web application, vulnerable/malicious browser plugins,
262
-
physically compromised device, etc.
259
+
and <function>session_regenerate_id</function> can cause personal DoS with
260
+
undeletable cookies set by attackers. In this case, developers may invite users
261
+
to remove cookies and advise them they may be affected by a security issue.
262
+
Attackers may set malicious cookies via a vulnerable web application,
263
+
an exposed/vicious browser plugin, a physically compromised device, etc.
263
264
</para>
264
265

265
266
<warning>
266
267
<simpara>
267
-
Do not misunderstand the DoS risk. <literal>use_strict_mode=On</literal>
268
-
is mandatory for general session ID security! All sites are advised
269
-
to enable <literal>use_strict_mode</literal>.
268
+
Do not misunderstand the DoS risk.
269
+
<link linkend="ini.session.use-strict-mode">session.use_strict_mode</link>=On
270
+
is mandatory for general session ID security! All sites are advised to enable
271
+
<link linkend="ini.session.use-strict-mode">session.use_strict_mode</link>.
270
272
</simpara>
271
273
<simpara>
272
-
DoS could happen only when the account is under attack by crackers.
273
-
JavaScript injection vulnerability in application is the most
274
-
common cause.
274
+
DoS can only happen when the account is under attack. A JavaScript injection
275
+
vulnerability in an application represents the most common cause.
275
276
</simpara>
276
277
</warning>
277
278

...
...
@@ -281,43 +282,44 @@
281
282
<title>Session Data Deletion</title>
282
283

283
284
<para>
284
-
Obsolete session data must be inaccessible and deleted. Current
285
-
session module does not handle this well.
285
+
Obsolete session data must be inaccessible and deleted.
286
+
The current session module does not handle this well.
286
287
</para>
287
288

288
289
<para>
289
-
Obsolete session data is better to be removed as soon as possible.
290
-
However, active sessions MUST NOT be removed immediately. To satisfy
291
-
these requirements, you MUST implement time-stamp based session
292
-
data management by yourself.
290
+
Obsolete session data should be removed as soon as possible.
291
+
However, active sessions must not be removed instantly.
292
+
To satisfy those requirements, developers must implement timestamp
293
+
based session data management by themselves.
293
294
</para>
294
295

295
296
<para>
296
-
Set and manage expiration time-stamp in $_SESSION. Prohibit access
297
-
to obsolete session data. When obsolete session data access is detected,
298
-
it is advised to remove all authenticated status from the user's sessions
299
-
and force them to re-authenticated. Obsolete session data access could be
300
-
an attack. To do this, you must keep track active sessions per user.
297
+
Set and manage expiration timestamp in $_SESSION.
298
+
Prohibit access to outdated session data.
299
+
When access to obsolete session data is detected, it is advised to remove all
300
+
authenticated status from the user's sessions and force them to re-authenticate.
301
+
Access to obsolete session data can represent an attack.
302
+
To achieve this, developers must keep track of all active sessions of every user.
301
303
</para>
302
304

303
305
<note>
304
306
<simpara>
305
-
Access to obsolete session could happen by unstable network and/or
306
-
concurrent access to web site also. Server tried to set new session
307
-
ID via cookie, but Set-Cookie packet may not be reached to client due to
308
-
lost connection. One connection may issue new session ID by
309
-
<function>session_regenerate_id</function>, but another conncurrent
310
-
connection may not get the new session ID yet.
311
-
Therefore, you must prohibit access to obsolete session a while later.
312
-
i.e. Time-stamp based session management is mandatory.
307
+
Access to an obsolete session can also happen because of an unstable network
308
+
and/or concurrent access to the website.
309
+
E.g. the server tried to set a new session ID via a cookie, but the Set-Cookie
310
+
packet may not have reached the client due to loss of connection.
311
+
One connection may issue a new session ID by <function>session_regenerate_id</function>,
312
+
but another concurrent connection may not have received the new session ID yet.
313
+
Therefore, developers must prohibit access to obsolete session at a later stage.
314
+
I.e. timestamp based session management is mandatory.
313
315
</simpara>
314
316
</note>
315
317

316
318
<para>
317
-
In short, do not destroy session data by <function>session_regenerate_id</function>
318
-
nor <function>session_destroy</function>, but use time-stamp to control
319
-
access to session data. Let <function>session_gc</function> to remove
320
-
obsolete data from session data storage.
319
+
In summary, session data must not be destroyed with
320
+
<function>session_regenerate_id</function> nor <function>session_destroy</function>,
321
+
but timestamps must be used to control access to session data.
322
+
Let <function>session_gc</function> remove obsolete data from the session data storage.
321
323
</para>
322
324

323
325
</sect2>
...
...
@@ -326,24 +328,25 @@
326
328
<title>Session and Locking</title>
327
329

328
330
<para>
329
-
Session data is locked to avoid races by default. Locking is mandatory
330
-
to keep session data consistent across requests.
331
+
Session data is locked to avoid race conditions by default.
332
+
Locking is mandatory to keep session data consistent across requests.
331
333
</para>
332
334

333
335
<para>
334
-
However, locking can be abused by attacker to perform DoS attacks. To
335
-
mitigate risks of DoS by session lock, minimize lock. Use read
336
-
only sessions when session data update is not required.
337
-
Use 'read_and_close' option with <function>session_start</function>.
338
-
<literal>session_start(['read_and_close'=>1]);</literal>
339
-
Close session as soon as you finish updating $_SESSION by
336
+
However, session-locking can be abused by attackers to perform DoS attacks.
337
+
To mitigate the risk of a DoS attack by session-locking, minimize locks.
338
+
Use read only sessions when session data does not need to be updated.
339
+
Use the 'read_and_close' option with <function>session_start</function>.
340
+
<code>session_start(['read_and_close'=>1]);</code>
341
+
Close the session as soon as possible after updating $_SESSION by
340
342
using <function>session_commit</function>.
341
343
</para>
342
344

343
345
<para>
344
-
Current session module does not detect $_SESSION modification while
345
-
session is inactive. It is your responsibility not to modify $_SESSION
346
-
when session is inactive.
346
+
The current session module does <emphasis>not</emphasis>
347
+
detect any modification of $_SESSION when the session is inactive.
348
+
It is the developer's responsibility not to modify $_SESSION when
349
+
the session is inactive.
347
350
</para>
348
351

349
352
</sect2>
...
...
@@ -352,114 +355,120 @@
352
355
<title>Active Sessions</title>
353
356

354
357
<para>
355
-
Developers should keep track active sessions per user and notify the user
356
-
how many active sessions, from which IP (and area), how long is active, etc.
357
-
PHP does not keep track these. You are supposed to do so.
358
+
Developers should keep track of all active sessions for every user.
359
+
And notify them of how many active sessions, from which IP (and area),
360
+
how long it has been active, etc.
361
+
PHP does not keep track of these. Developers are supposed to do so.
358
362
</para>
359
363

360
364
<para>
361
-
There are number of ways for the implementation. You may setup a
362
-
database that keeps track required data and store information
363
-
to it. Since session data is GCed, you have to take care of GCed data
365
+
Various ways to implement this exist.
366
+
One possible implementation is setting up a database that keeps track
367
+
of the required data and stores any relevant information.
368
+
Since session data is GCed, developers must take care of the GCed data
364
369
to maintain the active session database consistency.
365
370
</para>
366
371

367
372
<para>
368
-
One of the simplest implementation is "User ID prefixed session ID" and
369
-
store required information to $_SESSION. Many databases have good
370
-
performance for selecting string prefix. You can use
371
-
<function>session_regenerate_id</function> and
373
+
One of the simplest implementations is "User ID prefixed session ID"
374
+
and store the required information in $_SESSION.
375
+
Many databases posses good performance for selecting string prefix.
376
+
Developers MAY use <function>session_regenerate_id</function> and
372
377
<function>session_create_id</function> for this.
373
378
</para>
374
379

375
380
<warning>
376
381
<simpara>
377
-
Never use confidential data as prefix. If user ID is confidential,
378
-
consider to use <function>hash_hmac</function>.
382
+
Never employ confidential data as a prefix.
383
+
If the user ID is confidential, consider using
384
+
<function>hash_hmac</function>.
379
385
</simpara>
380
386
</warning>
381
387

382
388
<warning>
383
389
<simpara>
384
390
Enabling <link linkend="ini.session.use-strict-mode">session.use_strict_mode</link>
385
-
is mandatory for this setup. Make sure it is enabled, otherwise
386
-
active session database can be compromised.
391
+
is mandatory for this setup. Ensure it is enabled.
392
+
Otherwise, the active session database can be compromised.
387
393
</simpara>
388
394
</warning>
389
395

390
396
<para>
391
-
Time-stamp based session management is mandatory to detect obsolete session
392
-
access. When access to obsolete session is detected, you should remove authentication
393
-
flags from all of active sessions for the user. This prevents attackers to
394
-
keep exploiting stolen session.
397
+
Timestamp based session management is mandatory to detect access to obsolete sessions.
398
+
When access to an obsolete session is detected, authentication flags should
399
+
be removed from all active sessions of the user.
400
+
This prevents attackers to keep exploiting stolen sessions.
395
401
</para>
396
402

397
403
</sect2>
398
404

399
405
<sect2 xml:id="features.session.security.management.session-and-autologin">
400
-
<title>Session and Auto Login</title>
406
+
<title>Session and Auto-login</title>
401
407

402
408
<para>
403
-
Developers must NOT use long life session ID for auto login because it
404
-
increases risk of stolen session. Auto login should be implemented
405
-
by developer.
409
+
Developers must not use long life session IDs for auto-login because it
410
+
increases the risk of stolen sessions.
411
+
An auto-login feature should be implemented by the developer.
406
412
</para>
407
413

408
414
<para>
409
-
Use secure one time hash key as auto login key using
410
-
<function>setcookie</function>. Use secure hash stronger than SHA-2.
411
-
e.g. SHA-256 or greater with random data from <function>random_bytes</function>
412
-
or /dev/urandom.
415
+
Use a secure one time hash key as an auto-login key using
416
+
<function>setcookie</function>. Use a secure hash stronger than SHA-2.
417
+
E.g. SHA-256 or greater with random data from <function>random_bytes</function>
418
+
or <filename>/dev/urandom</filename>.
413
419
</para>
414
420

415
421
<para>
416
-
If user is not authenticated, check the one time auto login key is
417
-
valid or not. If key is valid, authenticate user and set new secure
418
-
one time hash key. Auto login key must be able to be used
419
-
only once. i.e. Never reuse auto login key, generate new auto login key
420
-
always.
422
+
If the user is unauthenticated, check whether the one-time auto-login key is valid or not.
423
+
In the case it is valid, authenticate the user and set a new secure one-time hash key.
424
+
An auto-login key must only be used once, i.e. never reuse an auto-login key,
425
+
always generate a new one.
421
426
</para>
422
427

423
428
<para>
424
-
Auto login key is long life authentication key, this key should be
425
-
protected as much as possible. Use path/httponly/secure
426
-
cookie attributes to protect. i.e. Never transmit auto login key
427
-
unless it is required.
429
+
An auto-login key is a long life authentication key,
430
+
it should be protected as much as possible.
431
+
Use path/httponly/secure/SameSite cookie attributes to secure it.
432
+
I.e. never transmit the auto-login key unless required.
428
433
</para>
429
434

430
435
<para>
431
-
Developer must implement feature that disables auto login and removes
432
-
unneeded auto login key cookie.
436
+
Developer must implement the features that disables
437
+
auto-login and removes unneeded auto-login key cookie.
433
438
</para>
434
439

435
440
</sect2>
436
441

437
442
<sect2 xml:id="features.session.security.management.csrf">
438
-
<title>CSRF(Cross Site Request Forgeries)</title>
443
+
<title>CSRF (Cross-Site Request Forgeries) attacks</title>
439
444

440
445
<para>
441
-
Session and authentication does not protect against CSRF attack. Developers
442
-
must implement CSRF protection by themselves.
446
+
Sessions and authentication do not protect against CSRF attacks.
447
+
Developers must implement CSRF protection by themselves.
443
448
</para>
444
449

445
450
<para>
446
-
<function>output_add_rewrite_var</function> can be used for CSRF
447
-
protection. Refer to the manual page for details.
451
+
<function>output_add_rewrite_var</function> can be used for CSRF protection.
452
+
Refer to the manual page for more details.
448
453
</para>
449
454

450
455
<note>
451
456
<simpara>
452
-
PHP prior to 7.2.0 uses the same output buffer and INI setting
453
-
as trans sid. Therefore, use of <function>output_add_rewrite_var</function>
454
-
with PHP prior to 7.2.0 is not recommended.
457
+
PHP prior to 7.2.0 uses the same output buffer and INI setting as trans sid.
458
+
Therefore, use of <function>output_add_rewrite_var</function>
459
+
with PHP prior to version 7.2.0 is not advised.
455
460
</simpara>
456
461
</note>
457
462

458
463
<para>
459
-
Most web application frameworks support CSRF protection. Refer
460
-
to your web application framwork manual for detials.
464
+
Most web application frameworks support CSRF protection.
465
+
Refer to the web application framework manual for more details.
461
466
</para>
462
467

468
+
<para>
469
+
As of PHP 7.3 the SameSite attribute for the session cookie can be set.
470
+
This is an additional measure which can mitigate CSRF vulnerabilities.
471
+
</para>
463
472
</sect2>
464
473
</sect1>
465
474

...
...
@@ -467,9 +476,9 @@
467
476
<title>Securing Session INI Settings</title>
468
477

469
478
<para>
470
-
By securing session related INI settings, you can improve session security.
471
-
Some of important INI settings do not have recommended settings. You
472
-
are responsible to hardening session settings.
479
+
By securing session related INI settings, developers can improve session security.
480
+
Some important INI settings do not have any recommended settings.
481
+
Developers are responsible for hardening session settings.
473
482
</para>
474
483

475
484
<itemizedlist>
...
...
@@ -478,15 +487,17 @@
478
487
<link linkend="ini.session.cookie-lifetime">session.cookie_lifetime</link>=0
479
488
</para>
480
489
<para>
481
-
0 have special meaning. It tells browsers not to store cookie to
482
-
permanent storage. Therefore, when browser is terminated, session
483
-
ID cookie is deleted immediately. If developer set other than 0, it may
484
-
allow other users to use the session ID. Most applications should
485
-
use "0" for this.
490
+
<literal>0</literal> possesses a particular meaning.
491
+
It informs browsers not to store the cookie to permanent storage.
492
+
Therefore, when the browser is terminated, the session ID cookie is deleted immediately.
493
+
If developers set this other than 0, it may allow other users to use the session ID.
494
+
Most applications should use "<literal>0</literal>" for this.
486
495
</para>
487
496
<para>
488
-
If auto login feature is required, implement your own secure auto login
489
-
feature. Do not use long life session ID for it.
497
+
If an auto-login feature is required,
498
+
developers must implement their own secure auto-login feature.
499
+
Do not use long life session IDs for this.
500
+
More information can be found above in the relevant section.
490
501
</para>
491
502
</listitem>
492
503

...
...
@@ -498,15 +509,15 @@
498
509
<link linkend="ini.session.use-only-cookies">session.use_only_cookies</link>=On
499
510
</para>
500
511
<para>
501
-
Although HTTP cookie has some problems, cookie is preferred way to
502
-
manage session ID. Use only cookies for session ID management when
503
-
it is possible. Most applications should use cookie for session
504
-
ID.
512
+
Although HTTP cookies suffer some problems,
513
+
cookies remain the preferred way to manage session IDs.
514
+
Only use cookies for session ID management when it is possible.
515
+
Most applications should use a cookie for the session ID.
505
516
</para>
506
517
<para>
507
-
If <literal>session.use_only_cookies</literal>=Off,
508
-
session module will use session ID values set by GET/POST/URL is used when
509
-
session ID cookie is not initialized already.
518
+
If <link linkend="ini.session.use-only-cookies">session.use_only_cookies</link>=Off,
519
+
the session module will use the session ID values set by
520
+
GET or POST provided the session ID cookie is uninitialized.
510
521
</para>
511
522
</listitem>
512
523

...
...
@@ -515,28 +526,31 @@
515
526
<link linkend="ini.session.use-strict-mode">session.use_strict_mode</link>=On
516
527
</para>
517
528
<para>
518
-
Although, enabling <literal>session.use_strict_mode</literal> is
519
-
mandatory. It is not enabled by default.
529
+
Although, enabling
530
+
<link linkend="ini.session.use-strict-mode">session.use_strict_mode</link>
531
+
is mandatory for secure sessions. It is disabled by default.
520
532
</para>
521
533
<para>
522
-
This prevents session module to use uninitialized session ID. In
523
-
other word, session module only accepts valid session ID generated
524
-
by session module. It rejects session ID supplied by
525
-
users.
534
+
This prevents the session module to use an uninitialized session ID.
535
+
Put differently, the session module only accepts valid session IDs
536
+
generated by the session module.
537
+
It rejects any session ID supplied by users.
526
538
</para>
527
539
<para>
528
-
Because of cookie spec, attackers are able to set undeletable session ID
529
-
cookies via locally setting cookie database or JavaScript injections.
530
-
<literal>session.use_strict_mode</literal> can prevent attacker
531
-
initialized session ID being used.
540
+
Due to the cookie specification, attackers are capable to place
541
+
non-removable session ID cookies by locally setting a cookie database
542
+
or JavaScript injections.
543
+
<link linkend="ini.session.use-strict-mode">session.use_strict_mode</link>
544
+
can prevent an attacker-initialized session ID of being used.
532
545
</para>
533
546
<note>
534
547
<para>
535
-
Attackers may initialize session ID by their device and may set the
536
-
session ID to victim. They must keep the session ID active to abuse.
537
-
Attackers require additional steps to perform attack with this attack
538
-
scenario. Therefore, <literal>session.use_strict_mode</literal> works
539
-
as the mitigation.
548
+
Attackers may initialize a session ID with their device and may set
549
+
the session ID of the victim. They must keep the session ID active to abuse.
550
+
Attackers require additional steps to perform an attack in this scenario.
551
+
Therefore,
552
+
<link linkend="ini.session.use-strict-mode">session.use_strict_mode</link>
553
+
works as a mitigation.
540
554
</para>
541
555
</note>
542
556
</listitem>
...
...
@@ -546,20 +560,18 @@
546
560
<link linkend="ini.session.cookie-httponly">session.cookie_httponly</link>=On
547
561
</para>
548
562
<para>
549
-
Disallow access to session cookie by JavaScript. This setting
550
-
prevents cookies stolen by JavaScript injection.
563
+
Refuses access to the session cookie from JavaScript.
564
+
This setting prevents cookies snatched by a JavaScript injection.
551
565
</para>
552
566
<para>
553
-
It is possible to use session ID as CSRF protection key, but this is not
554
-
recommended. For example, HTML source may be saved and sent to
555
-
other users. Developer should not write session ID in web pages for
556
-
better security. Almost all applications must use httponly attribute for
557
-
session ID cookie.
567
+
It is possible to use a session ID as a CSRF token, but this is not recommended.
568
+
For example, HTML sources may be saved and sent to other users.
569
+
Developers should not write session IDs in web pages for better security.
570
+
Almost all applications must use the httponly attribute for the session ID cookie.
558
571
</para>
559
572
<note>
560
573
<para>
561
-
CSRF protection token should be renewed periodically just like
562
-
session ID
574
+
The CSRF token should be renewed periodically just like the session ID.
563
575
</para>
564
576
</note>
565
577
</listitem>
...
...
@@ -569,12 +581,28 @@
569
581
<link linkend="ini.session.cookie-secure">session.cookie_secure</link>=On
570
582
</para>
571
583
<para>
572
-
Allows access to session ID cookie only when protocol is HTTPS. If
573
-
your web site is HTTPS only web site, you must enable this
574
-
setting.
584
+
Allow access to the session ID cookie only when the protocol is HTTPS.
585
+
If a website is only accessible via HTTPS, it should enable this setting.
575
586
</para>
576
587
<para>
577
-
HSTS should be considered for HTTPS only web site.
588
+
HSTS should be considered for websites accessible only via HTTPS.
589
+
</para>
590
+
</listitem>
591
+

592
+
<listitem>
593
+
<para>
594
+
<link linkend="ini.session.cookie-samesite">session.cookie_samesite</link>="Lax" or
595
+
<link linkend="ini.session.cookie-samesite">session.cookie_samesite</link>="Strict"
596
+
</para>
597
+
<para>
598
+
As of PHP 7.3 the <literal>"SameSite"</literal> attribute can be set for the session ID cookie.
599
+
This attribute is a way to mitigate CSRF (Cross Site Request Forgery) attacks.
600
+
</para>
601
+
<para>
602
+
The difference between Lax and Strict is the accessibility of the cookie in
603
+
requests originating from another registrable domain employing the HTTP GET method.
604
+
Cookies using Lax will be accessible in a GET request originated from
605
+
another registrable domain, whereas cookies using Strict will not.
578
606
</para>
579
607
</listitem>
580
608

...
...
@@ -583,33 +611,36 @@
583
611
<link linkend="ini.session.gc-maxlifetime">session.gc_maxlifetime</link>=[choose smallest possible]
584
612
</para>
585
613
<para>
586
-
<literal>session.gc_maxlifetime</literal>
587
-
is setting for deleting obsolete session ID. Reliance on this setting
588
-
is NOT recommend. You should manage session life time by time-stamp
589
-
by yourself.
614
+
<link linkend="ini.session.gc-maxlifetime">session.gc_maxlifetime</link>
615
+
is a setting for deleting obsolete session ID.
616
+
Reliance on this setting is <emphasis>not</emphasis> recommended.
617
+
Developers should manage the lifetime of sessions with a timestamp by themselves.
590
618
</para>
591
619
<para>
592
-
Session GC(garbage collection) is better to be performed by <function>session_gc</function>.
593
-
<function>session_gc</function> function is better to be executed by task
594
-
managers. e.g. cron on UNIX like systems.
620
+
Session GC (garbage collection) is best performed by using <function>session_gc</function>.
621
+
The <function>session_gc</function> function should be executed by a task
622
+
managers. E.g. cron on UNIX like systems.
595
623
</para>
596
624
<para>
597
-
GC is performed by probability by default. This setting does not
598
-
guarantee old session deletion. Although developer cannot rely
599
-
on this setting, setting this to smallest possible value is
600
-
recommended. Adjust <link
625
+
GC is performed by probability by default.
626
+
This setting does <emphasis>not</emphasis> guarantee that an outdated
627
+
session is deleted.
628
+
Although developers cannot rely on this setting,
629
+
specifying it to the smallest possible value is recommended.
630
+
Adjusting <link
601
631
linkend="ini.session.gc-probability">session.gc_probability</link>
602
632
and <link
603
633
linkend="ini.session.gc-divisor">session.gc_divisor</link> so
604
-
that obsolete sessions are deleted by appropriate frequency. If
605
-
auto login feature is required, implement your own secure auto
606
-
login feature. Never use long life session ID for it.
634
+
that obsolete sessions are deleted at an appropriate frequency.
635
+
If an auto-login feature is required, developers must implement their own
636
+
secure auto-login feature, see above for more information.
637
+
Never use long life session ID for this feature.
607
638
</para>
608
639
<note>
609
640
<para>
610
-
Some session save handler modules do not use this setting for
611
-
probability based expiration . e.g. memcached, memcache.
612
-
Refer to session save handler documentation for details.
641
+
Some session save handler modules do not use this setting for probability
642
+
based expiration. E.g. memcached, memcache.
643
+
Refer to the session save handler documentation for details.
613
644
</para>
614
645
</note>
615
646
</listitem>
...
...
@@ -619,54 +650,57 @@
619
650
<link linkend="ini.session.use-trans-sid">session.use_trans_sid</link>=Off
620
651
</para>
621
652
<para>
622
-
Use of transparent session ID management is not prohibited. You
623
-
may use it when it is needed. However, disabling transparent
624
-
session ID management would improve general session ID security by
625
-
removing possibility of session ID injection and session ID leak.
653
+
Use of a transparent session ID management is not prohibited.
654
+
Developers may employ it when it is required.
655
+
However, disabling transparent session ID management improves the general session
656
+
ID security by eliminating the possibility of a session ID injection and/or leak.
626
657
</para>
627
658
<note>
628
659
<para>
629
-
Session ID may leak from bookmarked URL, e-mailed URL, saved HTML
630
-
source.
660
+
Session ID may leak from bookmarked URLs, e-mailed URLs, saved HTML source, etc.
631
661
</para>
632
662
</note>
633
663
</listitem>
634
664

635
665
<listitem>
636
666
<para>
637
-
<link linkend="ini.session.trans-sid-tags">session.trans_sid_tags</link>=[limitted tags]
667
+
<link linkend="ini.session.trans-sid-tags">session.trans_sid_tags</link>=[limited tags]
638
668
</para>
639
669
<para>
640
-
(PHP 7.1.0 &gt;=) You should not rewrite unneeded HTML tags. Default
641
-
would be good enough for most usage. Older PHP uses
642
-
<link linkend="ini.url-rewriter.tags">url_rewriter.tags</link> for this.
670
+
(PHP 7.1.0 &gt;=) Developers should not rewrite unneeded HTML tags.
671
+
Default value should be sufficient for most usages.
672
+
Older PHP versions use
673
+
<link linkend="ini.url-rewriter.tags">url_rewriter.tags</link> instead.
643
674
</para>
644
675
</listitem>
645
676

646
677
<listitem>
647
678
<para>
648
-
<link linkend="ini.session.trans-sid-hosts">session.trans_sid_hosts</link>=[limitted hosts]
679
+
<link linkend="ini.session.trans-sid-hosts">session.trans_sid_hosts</link>=[limited hosts]
649
680
</para>
650
681
<para>
651
-
(PHP 7.1.0 &gt;=) This INI defines whitelist hosts that allows trans sid
652
-
rewrite. Never add untrusted host. Session module allow only $_SERVER['HTTP_HOST']
653
-
when this setting is empty.
682
+
(PHP 7.1.0 &gt;=) This INI defines whitelist hosts that allows trans sid rewrite.
683
+
Never add untrusted hosts.
684
+
Session module only allows <literal>$_SERVER['HTTP_HOST']</literal>
685
+
when this setting is empty.
654
686
</para>
655
687
</listitem>
656
688

657
689
<listitem>
658
690
<para>
659
-
<link linkend="ini.session.referer-check">session.referer_check</link>=[your originating URL]
691
+
<link linkend="ini.session.referer-check">session.referer_check</link>=[originating URL]
660
692
</para>
661
693
<para>
662
694
When <link
663
695
linkend="ini.session.use-trans-sid">session.use_trans_sid</link>
664
-
is enabled, use of this setting is recommended.
665
-
It reduces risk of session ID injection. If your site is
666
-
http://example.com/, set http://example.com/ to it. Note that when
667
-
HTTPS is used, browser will not send referrer header. Browser may
668
-
not send referrer header by configuration. Therefore, this setting
669
-
is not reliable security measure.
696
+
is enabled.
697
+
It reduces the risk of session ID injection.
698
+
If a website is <literal>http://example.com/</literal>,
699
+
set <literal>http://example.com/</literal> to it.
700
+
Note that with HTTPS browsers will not send the referrer header.
701
+
Browsers may not send the referrer header by configuration.
702
+
Therefore, this setting is not a reliable security measure.
703
+
Use of this setting is recommended.
670
704
</para>
671
705
</listitem>
672
706

...
...
@@ -675,13 +709,15 @@
675
709
<link linkend="ini.session.cache-limiter">session.cache_limiter</link>=nocache
676
710
</para>
677
711
<para>
678
-
Make sure HTTP contents are not cached for authenticated
679
-
session. Allow caching only when contents is not private.
680
-
Otherwise, contents may be exposed. "private" may be used
681
-
if HTTP content does not include security sensitive data. Note
682
-
that "private" may leave private data cached by shared
683
-
clients. "public" may be used only when HTTP content does not
684
-
contain any private data at all.
712
+
Ensure HTTP content are uncached for authenticated sessions.
713
+
Allow caching only when the content is not private.
714
+
Otherwise, content may be exposed.
715
+
<literal>"private"</literal> may be employed if HTTP content does not
716
+
include security sensitive data.
717
+
Note that <literal>"private"</literal> may transmit private data
718
+
cached by shared clients.
719
+
<literal>"public"</literal> must only be used when HTTP content does
720
+
not contain any private data at all.
685
721
</para>
686
722
</listitem>
687
723

...
...
@@ -690,9 +726,9 @@
690
726
<link linkend="ini.session.sid-length">session.sid_length</link>="48"
691
727
</para>
692
728
<para>
693
-
(PHP 7.1.0 &gt;=) Longer session ID results in stronger session
694
-
ID. Developer should consider session ID length 32 chars or more. At
695
-
least 26 chars is required when
729
+
(PHP 7.1.0 &gt;=) Longer session IDs results in stronger session IDs.
730
+
Developers should consider a session ID length of 32 characters or more.
731
+
At least 26 characters are required when
696
732
<link linkend="ini.session.sid-bits-per-character">session.sid_bits_per_character</link>="5".
697
733
</para>
698
734
</listitem>
...
...
@@ -702,8 +738,9 @@
702
738
<link linkend="ini.session.sid-bits-per-character">session.sid_bits_per_character</link>="6"
703
739
</para>
704
740
<para>
705
-
(PHP 7.1.0 &gt;=) The more bits in a session ID char, session module
706
-
generates stronger session ID for the same session ID length.
741
+
(PHP 7.1.0 &gt;=) The more bits there are in a session ID character,
742
+
the stronger the session ID generated by the session module is for an
743
+
identical session ID length.
707
744
</para>
708
745
</listitem>
709
746

...
...
@@ -712,12 +749,24 @@
712
749
<link linkend="ini.session.hash-function">session.hash_function</link>="sha256"
713
750
</para>
714
751
<para>
715
-
(PHP 7.1.0 &lt;) Stronger hash function will generates stronger session
716
-
ID. Although hash collision is unlikely even with MD5 hash, developers
717
-
should use SHA-2 or stronger hash functions for the task. Developers may
718
-
use stronger hashes like sha384 and sha512. Make sure you feed long
719
-
enough <link linkend="ini.session.entropy-length">entropy</link> for
720
-
the hash function used.
752
+
(PHP 7.1.0 &lt;) A stronger hash function will generate a stronger session ID.
753
+
Although hash collision is unlikely even with the MD5 hashing algorithm,
754
+
developers should use SHA-2 or a stronger hashing algorithm like sha384 and sha512.
755
+
Developers must ensure they feed a long enough
756
+
<link linkend="ini.session.entropy-length">entropy</link>
757
+
for the hashing function used.
758
+
</para>
759
+
</listitem>
760
+

761
+
<listitem>
762
+
<para>
763
+
<link linkend="ini.session.save-path">session.save_path</link>=[non world-readable directory]
764
+
</para>
765
+
<para>
766
+
If this is set to a world-readable directory, such as
767
+
<filename>/tmp</filename> (the default), other users on the
768
+
server may be able to hijack sessions by getting the list of
769
+
files in that directory.
721
770
</para>
722
771
</listitem>
723
772

...
...
@@ -746,4 +795,3 @@ vim600: syn=xml fen fdm=syntax fdl=2 si
746
795
vim: et tw=78 syn=sgml
747
796
vi: ts=1 sw=1
748
797
-->
749
-

750
798