Skip to main content

Overview

The School Management Platform implements multiple layers of security to protect user data and prevent common web vulnerabilities. Security is integrated at every level: session management, database access, authentication, and authorization.

Security Architecture

Authentication

Password Security

Passwords are secured using PHP’s built-in password hashing functions.

Password Hashing

public function create($name, $email, $password)
{
    // Insert into users table with hashed password
    $stmt = $this->db->prepare(
        "INSERT INTO users (name, email, password, role) 
         VALUES (?, ?, ?, 'student')"
    );
    $stmt->execute([
        $name, 
        $email, 
        password_hash($password, PASSWORD_DEFAULT)  // Bcrypt hashing
    ]);
    
    $userId = $this->db->lastInsertId();
    
    // Insert into students table
    $stmt = $this->db->prepare("INSERT INTO students (id) VALUES (?)");
    return $stmt->execute([$userId]);
}
PASSWORD_DEFAULT currently uses the bcrypt algorithm. This automatically handles salt generation and provides strong one-way encryption.

Password Verification

app/controllers/AuthController.php:27
public function authenticate()
{
    require_once __DIR__ . '/../models/User.php';
    
    $email = $_POST['email'] ?? '';
    $password = $_POST['password'] ?? '';
    
    $userModel = new User();
    $user = $userModel->findByEmail($email);
    
    // Verify password against hashed version
    if (!$user || !password_verify($password, $user['password'])) {
        echo "Invalid email or password";
        return;
    }
    
    // Prevent session fixation attacks
    session_regenerate_id(true);
    
    // Store user session data
    $_SESSION['user'] = [
        'id' => $user['id'],
        'name' => $user['name'],
        'email' => $user['email'],
        'role' => strtolower($user['role']),
    ];
    
    // Initialize session timeout tracking
    $_SESSION['LAST_ACTIVITY'] = time();
    
    // Redirect to role-specific dashboard
    header("Location: /school_management/public/index.php/dashboard/{$_SESSION['user']['role']}");
    exit;
}

Key Password Security Features

One-Way Hashing

Passwords cannot be reversed from their hash

Automatic Salting

Each password gets a unique random salt

Adaptive Algorithm

PASSWORD_DEFAULT evolves with PHP security improvements

Constant-Time Comparison

password_verify() prevents timing attacks

Session Management

Secure Session Configuration

Session security is configured at application startup:
public/index.php:2-8
<?php
session_set_cookie_params([
    'httponly' => true,        // Prevent JavaScript access to session cookie
    'secure' => false,         // Set to true in production with HTTPS
    'samesite' => 'Strict'     // Prevent CSRF attacks
]);

session_start();
ParameterValuePurpose
httponlytruePrevents XSS attacks by blocking JavaScript access to cookies
securefalse (dev) / true (prod)Ensures cookies only sent over HTTPS
samesiteStrictBlocks cookies from being sent with cross-site requests (CSRF protection)
Production Requirement: Set secure to true when deploying with HTTPS to prevent session hijacking over unencrypted connections.

Session Timeout (30 Minutes)

Automatic logout after 30 minutes of inactivity:
app/core/Auth.php:12-27
public static function check()
{
    // Verify user is logged in
    if (!isset($_SESSION['user'])) {
        self::redirectLogin();
    }
    
    // Check for session timeout (1800 seconds = 30 minutes)
    if (isset($_SESSION['LAST_ACTIVITY']) && 
        (time() - $_SESSION['LAST_ACTIVITY'] > 1800)) {
        session_unset();      // Clear session variables
        session_destroy();    // Destroy session
        self::redirectLogin();
    }
    
    // Update last activity timestamp
    $_SESSION['LAST_ACTIVITY'] = time();
}
1

User Makes Request

Every protected page calls Auth::check()
2

Check Last Activity

Compare current time with $_SESSION['LAST_ACTIVITY']
3

Timeout Detection

If more than 30 minutes (1800 seconds) have passed, destroy session
4

Update Timestamp

On valid request, update last activity time to current timestamp

Session Fixation Prevention

app/controllers/AuthController.php:32-33
// Regenerate session ID after successful login
session_regenerate_id(true);
Session regeneration creates a new session ID while preserving session data, preventing attackers from using a pre-set session ID.

Authorization (Role-Based Access Control)

The application implements RBAC with three distinct roles:

Role Enforcement Methods

app/core/Auth.php
class Auth
{
    private static function redirectLogin()
    {
        header("Location: /school_management/public/index.php/login");
        exit;
    }
    
    // Verify admin role
    public static function admin()
    {
        self::check();  // First check if logged in
        if ($_SESSION['user']['role'] !== 'admin') {
            self::redirectLogin();
        }
    }
    
    // Verify teacher role
    public static function teacher()
    {
        self::check();
        if ($_SESSION['user']['role'] !== 'teacher') {
            self::redirectLogin();
        }
    }
    
    // Verify student role
    public static function student()
    {
        self::check();
        if ($_SESSION['user']['role'] !== 'student') {
            self::redirectLogin();
        }
    }
}

Controller Protection Examples

public function index()
{
    Auth::admin();  // Only admins can view student list
    
    $students = $this->model->getAll();
    require __DIR__ . '/../views/students/index.php';
}

Role Permissions Matrix

FeatureAdminTeacherStudent
Manage Students
Manage Teachers
Manage Subjects
Create Courses
Manage Enrollments
Create Timetable
View All Bulletins
Assign Grades
View Assigned Courses
View Teacher Timetable
View Personal Grades
View Personal Bulletin
View Student Timetable

SQL Injection Prevention

All database queries use PDO prepared statements to prevent SQL injection attacks.

Prepared Statement Examples

public function findByEmail($email)
{
    $stmt = $this->db->prepare("SELECT * FROM users WHERE email = ?");
    $stmt->execute([$email]);  // Parameter bound safely
    return $stmt->fetch(PDO::FETCH_ASSOC);
}

Why Prepared Statements Are Secure

1

SQL and Data Separation

SQL structure is sent to database separately from user data
2

Parameter Binding

User input is bound as data, never executed as SQL code
3

Type Safety

PDO enforces type constraints on parameters
4

Automatic Escaping

Special characters are automatically escaped by the database driver
Never concatenate user input into SQL queries. Always use prepared statements with parameter binding.

Cross-Site Scripting (XSS) Prevention

While not explicitly shown in the model code, views should use output escaping:
View Output Escaping Best Practice
<!-- VULNERABLE -->
<td><?= $student['name'] ?></td>

<!-- SECURE -->
<td><?= htmlspecialchars($student['name'], ENT_QUOTES, 'UTF-8') ?></td>
htmlspecialchars() converts special characters to HTML entities, preventing malicious scripts from executing in the browser.

Cross-Site Request Forgery (CSRF) Protection

CSRF protection is partially implemented through:
  1. SameSite Cookie Attribute: Prevents cookies from being sent with cross-origin requests
session_set_cookie_params([
    'sameSite' => 'Strict'  // Blocks CSRF attacks
]);
  1. Session Validation: All state-changing operations require valid session
Enhancement Opportunity: Implement CSRF tokens for critical actions like delete operations.

Security Best Practices Implementation

Users only have access to features required for their role:
  • Students cannot modify grades
  • Teachers cannot manage users
  • Only admins can create/delete entities
Multiple security layers:
  1. Session validation
  2. Role-based authorization
  3. Prepared statements
  4. Password hashing
  5. HttpOnly cookies
Security features enabled by default:
  • Sessions always checked
  • Prepared statements required
  • Passwords always hashed
On authentication/authorization failure:
  • Sessions destroyed
  • Users redirected to login
  • No sensitive information leaked

Security Checklist

Production Security Recommendations

Before deploying to production, implement these additional security measures:
1

Enable HTTPS

Set secure cookie parameter to true and enforce HTTPS-only connections
2

Add CSRF Tokens

Implement CSRF token validation for all state-changing operations
3

Rate Limiting

Add rate limiting on login attempts to prevent brute force attacks
4

Input Validation

Validate and sanitize all user inputs on the server side
5

Error Handling

Disable error display and log errors securely
ini_set('display_errors', 0);
ini_set('log_errors', 1);
6

Security Headers

Add security headers (CSP, X-Frame-Options, etc.)
7

Database User Permissions

Use database user with minimal required privileges

Common Vulnerabilities Prevented

SQL Injection

Status: ✅ PreventedPDO prepared statements throughout

Session Hijacking

Status: ✅ PreventedHttpOnly cookies + session regeneration

Session Fixation

Status: ✅ PreventedSession ID regeneration on login

Brute Force

Status: ⚠️ PartialPassword hashing implemented; rate limiting recommended

CSRF

Status: ⚠️ PartialSameSite cookies; CSRF tokens recommended

XSS

Status: ⚠️ View-DependentRequires proper output escaping in views

Security Monitoring

Session Activity Tracking

Every request updates the last activity timestamp:
app/core/Auth.php:26
$_SESSION['LAST_ACTIVITY'] = time();
This enables:
  • Automatic timeout enforcement
  • Activity logging (if implemented)
  • Session duration tracking

User Session Data

$_SESSION['user'] = [
    'id' => $user['id'],
    'name' => $user['name'],
    'email' => $user['email'],
    'role' => strtolower($user['role']),
];
Password not stored in session: Only non-sensitive user information is kept in session data.

Next Steps

MVC Structure

Understand how security is integrated into the MVC pattern

Database Schema

Review database-level security constraints

Build docs developers (and LLMs) love