Difference between revisions for Users / Eo Ny
|
← Previous edit |
Next edit →
Revision 4 as of
05/05/2026 18:48
▼
6
05/21/2026 16:13
WikiAdmin
5
05/19/2026 11:04
WikiAdmin
4
05/05/2026 18:48
EoNy
3
05/05/2026 18:39
EoNy
(49.6 KiB) +1,595 EoNy |
Additions:
Session Management Technical Documentation
Overview
TheSession class is an abstract session management system for WackoWiki that extends ArrayObject to provide secure, configurable session handling. It implements sophisticated security features including session ID regeneration, anti-replay protection, nonce verification, and user agent/IP validation.Location:
src/class/session.php Type: Abstract class (must be extended with a
SessionStoreInterface implementation) Inheritance:
ArrayObjectTable of Contents
- Core Concepts
- Architecture
- Configuration
- Usage
- Security Features
- API Reference
- Session Lifecycle
- Flash Data
- Nonce System
- Cookie Management
- Error Handling
- Implementation Guide
Core Concepts
Session State
- Inactive (
$active = false): Session not yet started or has been closed - Active (
$active = true): Session is running and can store/retrieve data - Regenerated: Session ID has been replaced (tracked via
$regeneratedflag)
Session Data Storage
Session data is stored as an array accessible throughArrayObject interface:php
Sticky Data
Variables prefixed withsticky_ are persistent across session resets:-
sticky__created: Session creation timestamp -
sticky__flash: Flash data lifetime tracking -
sticky__log: Regeneration event log -
sticky__ip: IP change tracking
Internal Tracking Variables
Variables prefixed with__ are internal session metadata:-
__started: Session start time -
__updated: Last session update time -
__regenerated: Last session ID regeneration time -
__user_agent: Client user agent string -
__user_ip: Client IP address -
__user_tls: TLS/SSL status -
__nonces: Active nonce storage -
__expire: Session expiration time (for old sessions)
Architecture
Class Hierarchy
Key Methods Categories
-
__construct(): Initialize session object -
start(): Begin a session -
write_close(): Save and close session -
restart(): Destroy and restart session -
terminator(): Shutdown handler (garbage collection, flash data cleanup) -
regenerate_id(): Replace session ID -
verify_nonce(): Validate nonce tokens -
prevent_replay(): Anti-replay protection -
create_nonce(): Generate nonce tokens -
store_open(): Open session storage -
store_read(): Read session data -
store_write(): Write session data -
store_close(): Close session storage -
store_gc(): Garbage collection -
store_validate_id(): Validate session ID format -
store_generate_id(): Generate new session ID -
setcookie(): Set HTTP cookie with security headers -
get_cookie(): Retrieve cookie value -
set_cookie(): Set cookie (legacy interface) -
delete_cookie(): Remove cookie -
send_cookie(): Internal cookie transmission
Configuration
Configuration Properties (Public)
All configuration properties are prefixed withcf_ (config) and can be set before calling start():Session Behavior
php
Nonce & Replay Protection
php
Garbage Collection
php
Cookie Settings
php
Cache Control
php
Security Validation
php
HTTP Context (Set by HTTP class)
php
Usage
Basic Session Setup
php
Session Data Access
php
Session ID Management
php
Session State
php
Security Features
1. Session ID Regeneration
- Initial session creation (
regenerated = 2) - First request after creation (
regenerated = 1) - Periodic forced regeneration (based on
cf_regen_timeandcf_regen_probability) - Session validation failures
php
-
$delete_old: -
false(0): Keep old session active for 5 seconds (for pending AJAX requests) -
true(1): Keep old session for time specified (unused in current code) -
2: Immediately destroy old session - New session ID is generated via
store_generate_id() - Old session data is copied to new ID
- Old session marked with
__expiretimestamp - Cookie immediately updated with new ID
- Single regeneration per request (checked via
$this->regeneratedflag) - Logged in
sticky__logfor debugging (max 15 entries)
php
2. User Agent Validation
- Stores user agent on first request
- Compares on subsequent requests using
similar_text() - Destroys session if similarity < 95%
- Useful against bot attacks or stolen sessions
php
3. IP Address Validation
- Stores IP on first request
- Compares on subsequent requests
- Soft failure on mismatch:
destroy = 1(keeps regenerating) - Tracks IP changes in
sticky__ip
php
php
4. TLS/SSL Validation
- Checks if connection transitioned from HTTPS to HTTP
- Destroys session on mismatch
php
5. Anti-Replay Protection
- Generates unique "NoReplay" nonce on each request
- Cookie-based nonce verification
- Detects rapid-fire requests (AJAX attacks)
php
6. Referer Validation (Optional)
php
API Reference
Public Methods
Lifecycle Management
start($name = null, $id = null): bool
-
$name(string|null): Session name (cookie name base). Alphanumeric + underscore/dash. Defaults to 'sesid' -
$id(string|null): Existing session ID to resume. If null, attempts to read from cookie
true if session started successfully, false on error- Sets headers (cookies, cache control)
- Populates session data from storage
- Performs security validations
- May trigger session ID regeneration
php
- Reject if headers already sent
- Validate session name format
- Retrieve ID from parameter or cookie
- Check Referer header (if configured)
- Validate ID format via
store_validate_id() - Read session data from storage
- Verify nonces and timestamps
- Check user agent, IP, TLS
- Regenerate if needed
write_close(): void
- Calls
write_session()to serialize and store data - Calls
store_close()to close storage handler - Sets
$active = false
php
restart(): bool
Equivalent to: regenerate_id(true) + clean_vars() + populate()Returns:
true on success, false on error- User logout and new login
- Security reset
- Complete session refresh
php
Session Access
id(): mixed
php
name(): string
php
active(): bool
Returns: true if session is started and active, false otherwisephp
message(): string|null
-
'replay': Replay attack detected -
'obsolete': Session marked for expiration -
'reg_expire': Regeneration expiration reached -
'max_session': Max session lifetime exceeded -
'max_idle': Idle timeout exceeded -
'ua': User agent mismatch (>5% difference) -
'tls': TLS status changed -
'ip': IP address mismatch -
'restart': Session manually restarted -
null: No state change
php
toArray(): array
Note: This is a direct call to ArrayObject::getArrayCopy()php
Nonce System
create_nonce($action, $expires = null): string
-
$action(string): Action identifier (e.g., 'form_submit', 'delete_action') -
$expires(int|null): Expiration time in seconds. Defaults tocf_nonce_lifetime
php
- Stored in
$session->__nonces[] - Key:
{action}.{base64_encoded_hash} - Value: Expiration timestamp
verify_nonce($action, $code, $protect = 0)
-
$action(string): Action identifier that was used increate_nonce() -
$code(string): Nonce token from user -
$protect(int): Protection level -
0: Single-use nonce (consumed on first verification) -
1+: Protected nonce (can verify multiple times, prevents fast replays) -
true(1): Nonce verified and valid -
false(0): Nonce invalid or expired -
-1: Protected nonce used twice in quick succession (possible AJAX attack)
php
- Expired nonces automatically removed
- Verified single-use nonces removed from storage
Cookie Management
setcookie($name, $value = null, $expires = 0, $path = null, $domain = null, $secure = null, $httponly = null, $samesite = null): bool
-
$name: Cookie name (automatically URL-encoded) -
$value: Cookie value (automatically URL-encoded, null to delete) -
$expires: Expiration timestamp (0 = session cookie) -
$path: Cookie path (default:cf_cookie_path) -
$domain: Cookie domain (default:cf_cookie_domain) -
$secure: HTTPS only (default:cf_cookie_secure) -
$httponly: Disable JS access (default:cf_cookie_httponly) -
$samesite: SameSite attribute (default:cf_cookie_samesite)
true on success, false if headers already sent- RFC 2616 2.2 token encoding for cookie name
- RFC 6265 4.1.1 cookie-octet encoding for value
- Removes duplicate cookie headers automatically
- Adds all security attributes (secure, httponly, samesite)
- Does NOT replace existing cookies (allows multiple Set-Cookie headers)
php
get_cookie($name)
-
$name: Cookie name (prefix automatically added)
php
set_cookie($name, $value, $persistent = false): void
Legacy cookie setter (alternative to setcookie()).-
$name: Cookie name (prefix added) -
$value: Cookie value -
$persistent: -
false: Session cookie (deleted on browser close) -
0: Usecf_cookie_persistentconfig
php
delete_cookie($name): void
-
$name: Cookie name (prefix added)
php
unsetcookie($name): void
Alias for setcookie($name) with no value (convenience method).php
Protected Methods (For Store Implementation)
regenerate_id($delete_old = false, $message = ''): bool
store_generate_id(): string
Default Implementation: Returns 21-character random alphanumeric string via Ut::random_token(21)php
store_validate_id($id): bool
Default Implementation: Regex check: /^[a-zA-Z\d]{21}$/php
store_open($name): void
php
store_read($id, $lock = false): string|false
-
$id: Session ID to read -
$lock: If true, lock the session file for writing (create new) - Serialized session data (string) if found and locked
- Empty string (
'') if new session should be created -
falseif session doesn't exist or read error
php
store_write($id, $data): void
-
$id: Session ID -
$data: Serialized session data (already processed byUt::serialize())
php
store_close(): void
php
store_gc(): void
- Shutdown handler (probabilistic, based on
cf_gc_probability) - Sessions older than
cf_gc_maxlifetimeseconds
php
Private Methods (Internal Use)
populate(): void
Called by: start(), restart()-
__started: Current timestamp -
__regenerated: Current timestamp -
__user_agent: Browser user agent -
__user_ip: Client IP (if configured) -
__user_tls: TLS status (if configured) -
sticky__created: Creation time (if not exists)
write_session(): void
Called by: regenerate_id(), write_close(), terminator()-
__updated: Current timestamp - Calls
store_write()with serialized data
clean_vars(): void
Called by: restart(), session validation failurePreserves: Variables starting with
sticky_ prevent_replay(): void
Called by: populate()- Creates 'NoReplay' nonce
- Sends in cookie:
{cf_cookie_prefix}NoReplay
cache_limiter(): void
Called by: start() after session data loaded-
'public': Cacheable,Cache-Control: public, max-age=... -
'private': Private,Cache-Control: private, max-age=... -
'private_no_expire': Private no TTL -
'nocache': No storage,Cache-Control: no-store -
'none': No headers (default)
set_new_id(): void
Called by: regenerate_id(), start() (for new sessions) remove_cookie($cookie): void
Called by: setcookie() before setting new value nonce_index($action, $code): string (static)
Returns: {action}.{base64_encoded_hash}Session Lifecycle
Complete Session Flow
First Request (New Session)
Subsequent Request (Resume Session)
Session ID Regeneration
Session Destruction
Flash Data
Usage
php
How It Works
- Storage: Flash data stored in
$session->sticky__flash
- Key: Variable name
- Value: Lifetime in requests
- Cleanup: In
terminator()(shutdown handler):
php
- Persistence: Flash variables are kept in
sticky__flasheven during session resets
Example: Login Flow
php
Nonce System
Terminology
- Nonce: Number used ONCE - cryptographic token for action verification
- Action: Type of operation being protected (e.g., 'form_submit', 'delete_user')
- Protected Nonce: Can be verified multiple times with protection against rapid reuse
Complete Example: Form Protection
php
Example: Protected Nonce (AJAX-Safe)
php
Nonce Storage Format
Security Properties
- CSRF Protection: Nonce must match to process form
- One-Time Use: Each nonce consumed after first verification (unless protected)
- Expiration: Nonces automatically expire
- Action-Specific: Each action has separate nonce space
- AJAX-Safe: Protected nonces allow multiple quick verifications
Cookie Management
Security Features
Thesetcookie() method implements comprehensive cookie security:Encoding
php
Security Attributes
php
No Duplicate Headers
php
Configuration-Driven Defaults
php
Typical Secure Configuration
php
Error Handling
Graceful Degradation
Headers Already Sent
php
Cookie Setting Failure
php
Storage Errors
php
Debug Logging
php
To enable: Uncomment lines and ensure
Ut::dbg() function existsEvent Logging
Session events tracked insticky__log:php
- Session regeneration (with reason)
- Limited to 15 most recent events (old entries archived as '...')
Implementation Guide
Creating a Concrete Session Class
File-Based Storage
php
Database Storage (PDO)
php
Redis Storage
php
Complete Integration Example
php
Configuration Best Practices
php
Testing Tips
php
Security Checklist
- [ ] Use HTTPS only in production
- [ ] Enable
cf_cookie_secure - [ ] Enable
cf_cookie_httponly - [ ] Set
cf_cookie_samesiteto 'Strict' or 'Lax' - [ ] Set appropriate
cf_max_sessiontimeout - [ ] Set appropriate
cf_max_idletimeout - [ ] Enable
cf_prevent_replay - [ ] Validate
cf_ipif possible - [ ] Validate
cf_tlson HTTPS sites - [ ] Use nonces for all state-changing forms
- [ ] Implement proper logout (call
restart()) - [ ] Regenerate on privilege escalation (login)
- [ ] Monitor
sticky__ipfor suspicious changes - [ ] Review
sticky__logfor attack patterns - [ ] Implement garbage collection (
store_gc) - [ ] Hash session IDs before storing (see TODOs)
- [ ] Use secure random token generation
Common Patterns
Login Flow
php
Logout Flow
php
CSRF-Protected Form
php
Permission Check with Session Regeneration
php
Session Messages/Flash
php
Performance Considerations
Optimization Tips
- Minimize Session Writes:
- Session data only written during
write_close()or regeneration - No unnecessary serialization during reads
- Garbage Collection:
- Probabilistic GC (based on
cf_gc_probability) - Only runs on 2% of requests by default
- Customize based on your session volume
- Nonce Cleanup:
- Expired nonces automatically removed on verification
- Verified nonces removed from storage
- No manual cleanup needed
- Session ID Validation:
- Regex-based validation is fast
- No database lookup needed
- Caching Strategy:
- Cache expensive lookups between session operations
- Session data loaded once per request
Benchmarks
- Session start: 1-5ms (file) / 2-10ms (database)
- Session write: <1ms (file) / 1-5ms (database)
- Nonce generation: <1ms
- Nonce verification: <1ms
Troubleshooting
Session Not Starting
php
Cookie Not Setting
php
Session ID Not Regenerating
php
Nonce Verification Failing
php
Session Data Lost
php
TODO Items (From Code Comments)
- Do not store session ID in filename or DB index - store hash instead
- Improves security by not exposing IDs in storage layer
- Would require hashing logic in store_* methods
- Log of IP changes and other possible security alerts
- Track
sticky__ipchanges more comprehensively - Create security audit trail
- Allocate internal unique session which lives through lifetime of uber-session
- Multi-session management (parent/child sessions)
- Useful for complex user flows
- Do not delete old sessions, but use them as hijack pointers
- Maintain session history for analysis
- Detect potential session hijacking patterns
- Implement session relationship tracking
- All SIDs used later than 5secs of regenerations is hijacks
- Detect and block delayed session ID usage
- Current implementation allows 5-second window
- Could be more granular
References
Security Standards
- RFC 2616: HTTP/1.1 (Cookie syntax)
- RFC 6265: HTTP State Management Mechanism
- RFC 6234: US Secure Hash and Message Authentication Code Algorithms
- OWASP: Session Management Cheat Sheet
- OWASP: Cross-Site Request Forgery (CSRF) Prevention
Related Code
-
Ut::serialize()/Ut::unserialize(): Session data serialization -
Ut::random_token(): Cryptographic token generation -
Ut::http_date(): HTTP date formatting -
Ut::urlencode(): Cookie-safe encoding -
Ut::is_empty(): Empty value checking
See Also
-
src/class/http.php: HTTP request/response handling -
src/class/auth.php: Authentication (uses Session) - Session security best practices in OWASP documentation
Version History
- Current: Abstract session class with security features
- Planned: Implementation of TODO items above
- Documentation generated: 2026-05-05*
- For latest updates, see: https://github.com/Trojer/wack[...]ION_DOCUMENTATION.md*
Deletions:
# Session Management Technical Documentation
## Overview
The `Session` class is an abstract session management system for WackoWiki that extends `ArrayObject` to provide secure, configurable session handling. It implements sophisticated security features including session ID regeneration, anti-replay protection, nonce verification, and user agent/IP validation.
Location: `src/class/session.php`
Type: Abstract class (must be extended with a `SessionStoreInterface` implementation)
Inheritance: `ArrayObject`
## Table of Contents
1. [Core Concepts](#core-concepts)
2. [Architecture](#architecture)
3. [Configuration](#configuration)
4. [Usage](#usage)
5. [Security Features](#security-features)
6. [API Reference](#api-reference)
7. [Session Lifecycle](#session-lifecycle)
8. [Flash Data](#flash-data)
9. [Nonce System](#nonce-system)
10. [Cookie Management](#cookie-management)
11. [Error Handling](#error-handling)
12. [Implementation Guide](#implementation-guide)
## Core Concepts
### Session State
- Inactive (`$active = false`): Session not yet started or has been closed
- Active (`$active = true`): Session is running and can store/retrieve data
- Regenerated: Session ID has been replaced (tracked via `$regenerated` flag)
### Session Data Storage
Session data is stored as an array accessible through `ArrayObject` interface:
### Sticky Data
Variables prefixed with `sticky_` are persistent across session resets:
- `sticky__created`: Session creation timestamp
- `sticky__flash`: Flash data lifetime tracking
- `sticky__log`: Regeneration event log
- `sticky__ip`: IP change tracking
### Internal Tracking Variables
Variables prefixed with `__` are internal session metadata:
- `__started`: Session start time
- `__updated`: Last session update time
- `__regenerated`: Last session ID regeneration time
- `__user_agent`: Client user agent string
- `__user_ip`: Client IP address
- `__user_tls`: TLS/SSL status
- `__nonces`: Active nonce storage
- `__expire`: Session expiration time (for old sessions)
## Architecture
### Class Hierarchy
### Key Methods Categories
- `__construct()`: Initialize session object
- `start()`: Begin a session
- `write_close()`: Save and close session
- `restart()`: Destroy and restart session
- `terminator()`: Shutdown handler (garbage collection, flash data cleanup)
- `regenerate_id()`: Replace session ID
- `verify_nonce()`: Validate nonce tokens
- `prevent_replay()`: Anti-replay protection
- `create_nonce()`: Generate nonce tokens
- `store_open()`: Open session storage
- `store_read()`: Read session data
- `store_write()`: Write session data
- `store_close()`: Close session storage
- `store_gc()`: Garbage collection
- `store_validate_id()`: Validate session ID format
- `store_generate_id()`: Generate new session ID
- `setcookie()`: Set HTTP cookie with security headers
- `get_cookie()`: Retrieve cookie value
- `set_cookie()`: Set cookie (legacy interface)
- `delete_cookie()`: Remove cookie
- `send_cookie()`: Internal cookie transmission
## Configuration
### Configuration Properties (Public)
All configuration properties are prefixed with `cf_` (config) and can be set before calling `start()`:
## Usage
### Basic Session Setup
### Session Data Access
### Session ID Management
### Session State
## Security Features
### 1. Session ID Regeneration
- Initial session creation (`regenerated = 2`)
- First request after creation (`regenerated = 1`)
- Periodic forced regeneration (based on `cf_regen_time` and `cf_regen_probability`)
- Session validation failures
- `$delete_old`:
- Old session data is copied to new ID
- Old session marked with `__expire` timestamp
- Cookie immediately updated with new ID
- Single regeneration per request (checked via `$this->regenerated` flag)
- Logged in `sticky__log` for debugging (max 15 entries)
### 2. User Agent Validation
- Stores user agent on first request
- Compares on subsequent requests using `similar_text()`
- Destroys session if similarity < 95%
- Useful against bot attacks or stolen sessions
### 3. IP Address Validation
- Stores IP on first request
- Compares on subsequent requests
- Soft failure on mismatch: `destroy = 1` (keeps regenerating)
- Tracks IP changes in `sticky__ip`
### 4. TLS/SSL Validation
- Checks if connection transitioned from HTTPS to HTTP
- Destroys session on mismatch
### 5. Anti-Replay Protection
- Generates unique "NoReplay" nonce on each request
- Cookie-based nonce verification
- Detects rapid-fire requests (AJAX attacks)
### 6. Referer Validation (Optional)
## API Reference
### Public Methods
- `$name` (string|null): Session name (cookie name base). Alphanumeric + underscore/dash. Defaults to 'sesid'
- `$id` (string|null): Existing session ID to resume. If null, attempts to read from cookie
Returns: `true` if session started successfully, `false` on error
- Sets headers (cookies, cache control)
- Populates session data from storage
- Performs security validations
- May trigger session ID regeneration
1. Reject if headers already sent
2. Validate session name format
3. Retrieve ID from parameter or cookie
4. Check Referer header (if configured)
5. Validate ID format via `store_validate_id()`
6. Read session data from storage
7. Verify nonces and timestamps
8. Check user agent, IP, TLS
9. Regenerate if needed
- Calls `write_session()` to serialize and store data
- Calls `store_close()` to close storage handler
- Sets `$active = false`
Equivalent to: `regenerate_id(true) + clean_vars() + populate()`
Returns: `true` on success, `false` on error
- User logout and new login
- Security reset
- Complete session refresh
Returns: `true` if session is started and active, `false` otherwise
- `'replay'`: Replay attack detected
- `'obsolete'`: Session marked for expiration
- `'reg_expire'`: Regeneration expiration reached
- `'max_session'`: Max session lifetime exceeded
- `'max_idle'`: Idle timeout exceeded
- `'ua'`: User agent mismatch (>5% difference)
- `'tls'`: TLS status changed
- `'ip'`: IP address mismatch
- `'restart'`: Session manually restarted
- `null`: No state change
Note: This is a direct call to `ArrayObject::getArrayCopy()`
- `$action` (string): Action identifier (e.g., 'form_submit', 'delete_action')
- `$expires` (int|null): Expiration time in seconds. Defaults to `cf_nonce_lifetime`
- Stored in `$session->__nonces[]`
- Key: `{action}.{base64_encoded_hash}`
- Value: Expiration timestamp
- `$action` (string): Action identifier that was used in `create_nonce()`
- `$code` (string): Nonce token from user
- `$protect` (int): Protection level
- `false` (0): Nonce invalid or expired
- `-1`: Protected nonce used twice in quick succession (possible AJAX attack)
- Expired nonces automatically removed
- Verified single-use nonces removed from storage
- `$name`: Cookie name (automatically URL-encoded)
- `$value`: Cookie value (automatically URL-encoded, null to delete)
- `$expires`: Expiration timestamp (0 = session cookie)
- `$path`: Cookie path (default: `cf_cookie_path`)
- `$domain`: Cookie domain (default: `cf_cookie_domain`)
- `$secure`: HTTPS only (default: `cf_cookie_secure`)
- `$httponly`: Disable JS access (default: `cf_cookie_httponly`)
- `$samesite`: SameSite attribute (default: `cf_cookie_samesite`)
Returns: `true` on success, `false` if headers already sent
- RFC 2616 2.2 token encoding for cookie name
- RFC 6265 4.1.1 cookie-octet encoding for value
- Removes duplicate cookie headers automatically
- Adds all security attributes (secure, httponly, samesite)
- Does NOT replace existing cookies (allows multiple Set-Cookie headers)
- `$name`: Cookie name (prefix automatically added)
Legacy cookie setter (alternative to `setcookie()`).
- `$name`: Cookie name (prefix added)
- `$value`: Cookie value
- `$persistent`:
- `$name`: Cookie name (prefix added)
Alias for `setcookie($name)` with no value (convenience method).
### Protected Methods (For Store Implementation)
Default Implementation: Returns 21-character random alphanumeric string via `Ut::random_token(21)`
Default Implementation: Regex check: `/^[a-zA-Z\d]{21}$/`
- `$id`: Session ID to read
- `$lock`: If true, lock the session file for writing (create new)
- Serialized session data (string) if found and locked
- Empty string (`''`) if new session should be created
- `false` if session doesn't exist or read error
- `$id`: Session ID
- `$data`: Serialized session data (already processed by `Ut::serialize()`)
- Shutdown handler (probabilistic, based on `cf_gc_probability`)
- Sessions older than `cf_gc_maxlifetime` seconds
### Private Methods (Internal Use)
Called by: `start()`, `restart()`
- `__started`: Current timestamp
- `__regenerated`: Current timestamp
- `__user_agent`: Browser user agent
- `__user_ip`: Client IP (if configured)
- `__user_tls`: TLS status (if configured)
- `sticky__created`: Creation time (if not exists)
Called by: `regenerate_id()`, `write_close()`, `terminator()`
- `__updated`: Current timestamp
- Calls `store_write()` with serialized data
Called by: `restart()`, session validation failure
Preserves: Variables starting with `sticky_`
Called by: `populate()`
- Creates 'NoReplay' nonce
- Sends in cookie: `{cf_cookie_prefix}NoReplay`
Called by: `start()` after session data loaded
- `'public'`: Cacheable, `Cache-Control: public, max-age=...`
- `'private'`: Private, `Cache-Control: private, max-age=...`
- `'private_no_expire'`: Private no TTL
- `'nocache'`: No storage, `Cache-Control: no-store`
- `'none'`: No headers (default)
Called by: `regenerate_id()`, `start()` (for new sessions)
Called by: `setcookie()` before setting new value
Returns: `{action}.{base64_encoded_hash}`
## Session Lifecycle
### Complete Session Flow
### First Request (New Session)
### Subsequent Request (Resume Session)
### Session ID Regeneration
### Session Destruction
## Flash Data
### Usage
### How It Works
1. Storage: Flash data stored in `$session->sticky__flash`
3. Persistence: Flash variables are kept in `sticky__flash` even during session resets
### Example: Login Flow
## Nonce System
### Terminology
- Nonce: Number used ONCE - cryptographic token for action verification
- Action: Type of operation being protected (e.g., 'form_submit', 'delete_user')
- Protected Nonce: Can be verified multiple times with protection against rapid reuse
### Complete Example: Form Protection
### Example: Protected Nonce (AJAX-Safe)
### Nonce Storage Format
### Security Properties
- CSRF Protection: Nonce must match to process form
- One-Time Use: Each nonce consumed after first verification (unless protected)
- Expiration: Nonces automatically expire
- Action-Specific: Each action has separate nonce space
- AJAX-Safe: Protected nonces allow multiple quick verifications
## Cookie Management
### Security Features
The `setcookie()` method implements comprehensive cookie security:
### Configuration-Driven Defaults
### Typical Secure Configuration
## Error Handling
### Graceful Degradation
### Debug Logging
To enable: Uncomment lines and ensure `Ut::dbg()` function exists
### Event Logging
Session events tracked in `sticky__log`:
- Session regeneration (with reason)
- Limited to 15 most recent events (old entries archived as '...')
## Implementation Guide
### Creating a Concrete Session Class
### Complete Integration Example
### Configuration Best Practices
### Testing Tips
## Security Checklist
- [ ] Use HTTPS only in production
- [ ] Enable `cf_cookie_secure`
- [ ] Enable `cf_cookie_httponly`
- [ ] Set `cf_cookie_samesite` to 'Strict' or 'Lax'
- [ ] Set appropriate `cf_max_session` timeout
- [ ] Set appropriate `cf_max_idle` timeout
- [ ] Enable `cf_prevent_replay`
- [ ] Validate `cf_ip` if possible
- [ ] Validate `cf_tls` on HTTPS sites
- [ ] Use nonces for all state-changing forms
- [ ] Implement proper logout (call `restart()`)
- [ ] Regenerate on privilege escalation (login)
- [ ] Monitor `sticky__ip` for suspicious changes
- [ ] Review `sticky__log` for attack patterns
- [ ] Implement garbage collection (`store_gc`)
- [ ] Hash session IDs before storing (see TODOs)
- [ ] Use secure random token generation
## Common Patterns
### Login Flow
### Logout Flow
### CSRF-Protected Form
### Permission Check with Session Regeneration
### Session Messages/Flash
## Performance Considerations
### Optimization Tips
1. Minimize Session Writes:
- Session start: 1-5ms (file) / 2-10ms (database)
- Session write: <1ms (file) / 1-5ms (database)
- Nonce generation: <1ms
- Nonce verification: <1ms
## Troubleshooting
### Session Not Starting
### Cookie Not Setting
### Session ID Not Regenerating
### Nonce Verification Failing
### Session Data Lost
## TODO Items (From Code Comments)
1. Do not store session ID in filename or DB index - store hash instead
## References
### Security Standards
- RFC 2616: HTTP/1.1 (Cookie syntax)
- RFC 6265: HTTP State Management Mechanism
- RFC 6234: US Secure Hash and Message Authentication Code Algorithms
- OWASP: Session Management Cheat Sheet
- OWASP: Cross-Site Request Forgery (CSRF) Prevention
### Related Code
- `Ut::serialize()` / `Ut::unserialize()`: Session data serialization
- `Ut::random_token()`: Cryptographic token generation
- `Ut::http_date()`: HTTP date formatting
- `Ut::urlencode()`: Cookie-safe encoding
- `Ut::is_empty()`: Empty value checking
### See Also
- `src/class/http.php`: HTTP request/response handling
- `src/class/auth.php`: Authentication (uses Session)
- Session security best practices in OWASP documentation
## Version History
- Current: Abstract session class with security features
- Planned: Implementation of TODO items above
*Documentation generated: 2026-05-05*
*For latest updates, see: https://github.com/Trojer/wack[...]ION_DOCUMENTATION.md*
## Overview
The `Session` class is an abstract session management system for WackoWiki that extends `ArrayObject` to provide secure, configurable session handling. It implements sophisticated security features including session ID regeneration, anti-replay protection, nonce verification, and user agent/IP validation.
Location: `src/class/session.php`
Type: Abstract class (must be extended with a `SessionStoreInterface` implementation)
Inheritance: `ArrayObject`
## Table of Contents
1. [Core Concepts](#core-concepts)
2. [Architecture](#architecture)
3. [Configuration](#configuration)
4. [Usage](#usage)
5. [Security Features](#security-features)
6. [API Reference](#api-reference)
7. [Session Lifecycle](#session-lifecycle)
8. [Flash Data](#flash-data)
9. [Nonce System](#nonce-system)
10. [Cookie Management](#cookie-management)
11. [Error Handling](#error-handling)
12. [Implementation Guide](#implementation-guide)
## Core Concepts
### Session State
- Inactive (`$active = false`): Session not yet started or has been closed
- Active (`$active = true`): Session is running and can store/retrieve data
- Regenerated: Session ID has been replaced (tracked via `$regenerated` flag)
### Session Data Storage
Session data is stored as an array accessible through `ArrayObject` interface:
`php`
### Sticky Data
Variables prefixed with `sticky_` are persistent across session resets:
- `sticky__created`: Session creation timestamp
- `sticky__flash`: Flash data lifetime tracking
- `sticky__log`: Regeneration event log
- `sticky__ip`: IP change tracking
### Internal Tracking Variables
Variables prefixed with `__` are internal session metadata:
- `__started`: Session start time
- `__updated`: Last session update time
- `__regenerated`: Last session ID regeneration time
- `__user_agent`: Client user agent string
- `__user_ip`: Client IP address
- `__user_tls`: TLS/SSL status
- `__nonces`: Active nonce storage
- `__expire`: Session expiration time (for old sessions)
## Architecture
### Class Hierarchy
``
### Key Methods Categories
- `__construct()`: Initialize session object
- `start()`: Begin a session
- `write_close()`: Save and close session
- `restart()`: Destroy and restart session
- `terminator()`: Shutdown handler (garbage collection, flash data cleanup)
- `regenerate_id()`: Replace session ID
- `verify_nonce()`: Validate nonce tokens
- `prevent_replay()`: Anti-replay protection
- `create_nonce()`: Generate nonce tokens
- `store_open()`: Open session storage
- `store_read()`: Read session data
- `store_write()`: Write session data
- `store_close()`: Close session storage
- `store_gc()`: Garbage collection
- `store_validate_id()`: Validate session ID format
- `store_generate_id()`: Generate new session ID
- `setcookie()`: Set HTTP cookie with security headers
- `get_cookie()`: Retrieve cookie value
- `set_cookie()`: Set cookie (legacy interface)
- `delete_cookie()`: Remove cookie
- `send_cookie()`: Internal cookie transmission
## Configuration
### Configuration Properties (Public)
All configuration properties are prefixed with `cf_` (config) and can be set before calling `start()`:
Session Behavior`php`
Nonce & Replay Protection`php`
Garbage Collection`php`
Cookie Settings`php`
Cache Control`php`
Security Validation`php`
HTTP Context (Set by HTTP class)`php`
## Usage
### Basic Session Setup
`php`
### Session Data Access
`php`
### Session ID Management
`php`
### Session State
`php`
## Security Features
### 1. Session ID Regeneration
- Initial session creation (`regenerated = 2`)
- First request after creation (`regenerated = 1`)
- Periodic forced regeneration (based on `cf_regen_time` and `cf_regen_probability`)
- Session validation failures
`php`
- `$delete_old`:
- `false` (0): Keep old session active for 5 seconds (for pending AJAX requests)
- `true` (1): Keep old session for time specified (unused in current code)
- `2`: Immediately destroy old session
- Old session data is copied to new ID
- Old session marked with `__expire` timestamp
- Cookie immediately updated with new ID
- Single regeneration per request (checked via `$this->regenerated` flag)
- Logged in `sticky__log` for debugging (max 15 entries)
`php`
### 2. User Agent Validation
- Stores user agent on first request
- Compares on subsequent requests using `similar_text()`
- Destroys session if similarity < 95%
- Useful against bot attacks or stolen sessions
`php`
### 3. IP Address Validation
- Stores IP on first request
- Compares on subsequent requests
- Soft failure on mismatch: `destroy = 1` (keeps regenerating)
- Tracks IP changes in `sticky__ip`
`php`
`php`
### 4. TLS/SSL Validation
- Checks if connection transitioned from HTTPS to HTTP
- Destroys session on mismatch
`php`
### 5. Anti-Replay Protection
- Generates unique "NoReplay" nonce on each request
- Cookie-based nonce verification
- Detects rapid-fire requests (AJAX attacks)
`php`
``
### 6. Referer Validation (Optional)
`php`
## API Reference
### Public Methods
Lifecycle Management# `start($name = null, $id = null): bool`- `$name` (string|null): Session name (cookie name base). Alphanumeric + underscore/dash. Defaults to 'sesid'
- `$id` (string|null): Existing session ID to resume. If null, attempts to read from cookie
Returns: `true` if session started successfully, `false` on error
- Sets headers (cookies, cache control)
- Populates session data from storage
- Performs security validations
- May trigger session ID regeneration
`php`
1. Reject if headers already sent
2. Validate session name format
3. Retrieve ID from parameter or cookie
4. Check Referer header (if configured)
5. Validate ID format via `store_validate_id()`
6. Read session data from storage
7. Verify nonces and timestamps
8. Check user agent, IP, TLS
9. Regenerate if needed
# `write_close(): void`- Calls `write_session()` to serialize and store data
- Calls `store_close()` to close storage handler
- Sets `$active = false`
`php`
# `restart(): bool`Equivalent to: `regenerate_id(true) + clean_vars() + populate()`
Returns: `true` on success, `false` on error
- User logout and new login
- Security reset
- Complete session refresh
`php`
Session Access# `id(): mixed``php`
# `name(): string``php`
# `active(): bool`Returns: `true` if session is started and active, `false` otherwise
`php`
# `message(): string|null`- `'replay'`: Replay attack detected
- `'obsolete'`: Session marked for expiration
- `'reg_expire'`: Regeneration expiration reached
- `'max_session'`: Max session lifetime exceeded
- `'max_idle'`: Idle timeout exceeded
- `'ua'`: User agent mismatch (>5% difference)
- `'tls'`: TLS status changed
- `'ip'`: IP address mismatch
- `'restart'`: Session manually restarted
- `null`: No state change
`php`
# `toArray(): array`Note: This is a direct call to `ArrayObject::getArrayCopy()`
`php`
Nonce System# `create_nonce($action, $expires = null): string`- `$action` (string): Action identifier (e.g., 'form_submit', 'delete_action')
- `$expires` (int|null): Expiration time in seconds. Defaults to `cf_nonce_lifetime`
`php`
- Stored in `$session->__nonces[]`
- Key: `{action}.{base64_encoded_hash}`
- Value: Expiration timestamp
# `verify_nonce($action, $code, $protect = 0)`- `$action` (string): Action identifier that was used in `create_nonce()`
- `$code` (string): Nonce token from user
- `$protect` (int): Protection level
- `0`: Single-use nonce (consumed on first verification)
- `1+`: Protected nonce (can verify multiple times, prevents fast replays)
- `false` (0): Nonce invalid or expired
- `-1`: Protected nonce used twice in quick succession (possible AJAX attack)
`php`
- Expired nonces automatically removed
- Verified single-use nonces removed from storage
Cookie Management# `setcookie($name, $value = null, $expires = 0, $path = null, $domain = null, $secure = null, $httponly = null, $samesite = null): bool`- `$name`: Cookie name (automatically URL-encoded)
- `$value`: Cookie value (automatically URL-encoded, null to delete)
- `$expires`: Expiration timestamp (0 = session cookie)
- `$path`: Cookie path (default: `cf_cookie_path`)
- `$domain`: Cookie domain (default: `cf_cookie_domain`)
- `$secure`: HTTPS only (default: `cf_cookie_secure`)
- `$httponly`: Disable JS access (default: `cf_cookie_httponly`)
- `$samesite`: SameSite attribute (default: `cf_cookie_samesite`)
Returns: `true` on success, `false` if headers already sent
- RFC 2616 2.2 token encoding for cookie name
- RFC 6265 4.1.1 cookie-octet encoding for value
- Removes duplicate cookie headers automatically
- Adds all security attributes (secure, httponly, samesite)
- Does NOT replace existing cookies (allows multiple Set-Cookie headers)
`php`
# `get_cookie($name)`- `$name`: Cookie name (prefix automatically added)
`php`
# `set_cookie($name, $value, $persistent = false): void`Legacy cookie setter (alternative to `setcookie()`).
- `$name`: Cookie name (prefix added)
- `$value`: Cookie value
- `$persistent`:
- `false`: Session cookie (deleted on browser close)
- `0`: Use `cf_cookie_persistent` config
`php`
# `delete_cookie($name): void`- `$name`: Cookie name (prefix added)
`php`
# `unsetcookie($name): void`Alias for `setcookie($name)` with no value (convenience method).
`php`
### Protected Methods (For Store Implementation)
`regenerate_id($delete_old = false, $message = ''): bool` `store_generate_id(): string`Default Implementation: Returns 21-character random alphanumeric string via `Ut::random_token(21)`
`php`
`store_validate_id($id): bool`Default Implementation: Regex check: `/^[a-zA-Z\d]{21}$/`
`php`
`store_open($name): void``php`
`store_read($id, $lock = false): string|false`- `$id`: Session ID to read
- `$lock`: If true, lock the session file for writing (create new)
- Serialized session data (string) if found and locked
- Empty string (`''`) if new session should be created
- `false` if session doesn't exist or read error
`php`
`store_write($id, $data): void`- `$id`: Session ID
- `$data`: Serialized session data (already processed by `Ut::serialize()`)
`php`
`store_close(): void``php`
`store_gc(): void`- Shutdown handler (probabilistic, based on `cf_gc_probability`)
- Sessions older than `cf_gc_maxlifetime` seconds
`php`
### Private Methods (Internal Use)
# `populate(): void`Called by: `start()`, `restart()`
- `__started`: Current timestamp
- `__regenerated`: Current timestamp
- `__user_agent`: Browser user agent
- `__user_ip`: Client IP (if configured)
- `__user_tls`: TLS status (if configured)
- `sticky__created`: Creation time (if not exists)
# `write_session(): void`Called by: `regenerate_id()`, `write_close()`, `terminator()`
- `__updated`: Current timestamp
- Calls `store_write()` with serialized data
# `clean_vars(): void`Called by: `restart()`, session validation failure
Preserves: Variables starting with `sticky_`
# `prevent_replay(): void`Called by: `populate()`
- Creates 'NoReplay' nonce
- Sends in cookie: `{cf_cookie_prefix}NoReplay`
# `cache_limiter(): void`Called by: `start()` after session data loaded
- `'public'`: Cacheable, `Cache-Control: public, max-age=...`
- `'private'`: Private, `Cache-Control: private, max-age=...`
- `'private_no_expire'`: Private no TTL
- `'nocache'`: No storage, `Cache-Control: no-store`
- `'none'`: No headers (default)
# `set_new_id(): void`Called by: `regenerate_id()`, `start()` (for new sessions)
# `remove_cookie($cookie): void`Called by: `setcookie()` before setting new value
# `nonce_index($action, $code): string` (static)Returns: `{action}.{base64_encoded_hash}`
## Session Lifecycle
### Complete Session Flow
``
### First Request (New Session)
``
### Subsequent Request (Resume Session)
``
### Session ID Regeneration
``
### Session Destruction
``
## Flash Data
### Usage
`php`
### How It Works
1. Storage: Flash data stored in `$session->sticky__flash`
- Key: Variable name
- Value: Lifetime in requests
2. Cleanup: In `terminator()` (shutdown handler):- Value: Lifetime in requests
`php`
### Example: Login Flow
`php`
## Nonce System
### Terminology
- Nonce: Number used ONCE - cryptographic token for action verification
- Action: Type of operation being protected (e.g., 'form_submit', 'delete_user')
- Protected Nonce: Can be verified multiple times with protection against rapid reuse
### Complete Example: Form Protection
`php`
### Example: Protected Nonce (AJAX-Safe)
`php`
### Nonce Storage Format
``
### Security Properties
- CSRF Protection: Nonce must match to process form
- One-Time Use: Each nonce consumed after first verification (unless protected)
- Expiration: Nonces automatically expire
- Action-Specific: Each action has separate nonce space
- AJAX-Safe: Protected nonces allow multiple quick verifications
## Cookie Management
### Security Features
The `setcookie()` method implements comprehensive cookie security:
Encoding`php`
Security Attributes`php`
No Duplicate Headers`php`
### Configuration-Driven Defaults
`php`
### Typical Secure Configuration
`php`
## Error Handling
### Graceful Degradation
Headers Already Sent`php`
Cookie Setting Failure`php`
Storage Errors`php`
### Debug Logging
`php`
To enable: Uncomment lines and ensure `Ut::dbg()` function exists
### Event Logging
Session events tracked in `sticky__log`:
`php`
- Session regeneration (with reason)
- Limited to 15 most recent events (old entries archived as '...')
## Implementation Guide
### Creating a Concrete Session Class
File-Based Storage`php`
Database Storage (PDO)`php`
Redis Storage`php`
### Complete Integration Example
`php`
### Configuration Best Practices
`php`
### Testing Tips
`php`
## Security Checklist
- [ ] Use HTTPS only in production
- [ ] Enable `cf_cookie_secure`
- [ ] Enable `cf_cookie_httponly`
- [ ] Set `cf_cookie_samesite` to 'Strict' or 'Lax'
- [ ] Set appropriate `cf_max_session` timeout
- [ ] Set appropriate `cf_max_idle` timeout
- [ ] Enable `cf_prevent_replay`
- [ ] Validate `cf_ip` if possible
- [ ] Validate `cf_tls` on HTTPS sites
- [ ] Use nonces for all state-changing forms
- [ ] Implement proper logout (call `restart()`)
- [ ] Regenerate on privilege escalation (login)
- [ ] Monitor `sticky__ip` for suspicious changes
- [ ] Review `sticky__log` for attack patterns
- [ ] Implement garbage collection (`store_gc`)
- [ ] Hash session IDs before storing (see TODOs)
- [ ] Use secure random token generation
## Common Patterns
### Login Flow
`php`
### Logout Flow
`php`
### CSRF-Protected Form
`php`
### Permission Check with Session Regeneration
`php`
### Session Messages/Flash
`php`
## Performance Considerations
### Optimization Tips
1. Minimize Session Writes:
- Session data only written during `write_close()` or regeneration
- No unnecessary serialization during reads
2. Garbage Collection:- No unnecessary serialization during reads
- Probabilistic GC (based on `cf_gc_probability`)
- Only runs on 2% of requests by default
- Customize based on your session volume
3. Nonce Cleanup:- Only runs on 2% of requests by default
- Customize based on your session volume
- Expired nonces automatically removed on verification
- Verified nonces removed from storage
- No manual cleanup needed
4. Session ID Validation:- Verified nonces removed from storage
- No manual cleanup needed
- Regex-based validation is fast
- No database lookup needed
5. Caching Strategy:- No database lookup needed
- Cache expensive lookups between session operations
- Session data loaded once per request
### Benchmarks- Session data loaded once per request
- Session start: 1-5ms (file) / 2-10ms (database)
- Session write: <1ms (file) / 1-5ms (database)
- Nonce generation: <1ms
- Nonce verification: <1ms
## Troubleshooting
### Session Not Starting
`php`
### Cookie Not Setting
`php`
### Session ID Not Regenerating
`php`
### Nonce Verification Failing
`php`
### Session Data Lost
`php`
## TODO Items (From Code Comments)
1. Do not store session ID in filename or DB index - store hash instead
- Improves security by not exposing IDs in storage layer
- Would require hashing logic in store_* methods
2. Log of IP changes and other possible security alerts- Would require hashing logic in store_* methods
- Track `sticky__ip` changes more comprehensively
- Create security audit trail
3. Allocate internal unique session which lives through lifetime of uber-session- Create security audit trail
- Multi-session management (parent/child sessions)
- Useful for complex user flows
4. Do not delete old sessions, but use them as hijack pointers- Useful for complex user flows
- Maintain session history for analysis
- Detect potential session hijacking patterns
- Implement session relationship tracking
5. All SIDs used later than 5secs of regenerations is hijacks- Detect potential session hijacking patterns
- Implement session relationship tracking
- Detect and block delayed session ID usage
- Current implementation allows 5-second window
- Could be more granular
- Current implementation allows 5-second window
- Could be more granular
## References
### Security Standards
- RFC 2616: HTTP/1.1 (Cookie syntax)
- RFC 6265: HTTP State Management Mechanism
- RFC 6234: US Secure Hash and Message Authentication Code Algorithms
- OWASP: Session Management Cheat Sheet
- OWASP: Cross-Site Request Forgery (CSRF) Prevention
### Related Code
- `Ut::serialize()` / `Ut::unserialize()`: Session data serialization
- `Ut::random_token()`: Cryptographic token generation
- `Ut::http_date()`: HTTP date formatting
- `Ut::urlencode()`: Cookie-safe encoding
- `Ut::is_empty()`: Empty value checking
### See Also
- `src/class/http.php`: HTTP request/response handling
- `src/class/auth.php`: Authentication (uses Session)
- Session security best practices in OWASP documentation
## Version History
- Current: Abstract session class with security features
- Planned: Implementation of TODO items above
*Documentation generated: 2026-05-05*
*For latest updates, see: https://github.com/Trojer/wack[...]ION_DOCUMENTATION.md*