A full-featured educational project demonstrating IDOR (Insecure Direct Object Reference) vulnerabilities with a complete web-based system.
SchoolMS is an intentionally vulnerable document management system built for educational purposes. It's designed to teach security professionals and developers about:
- IDOR Vulnerabilities: How missing access controls lead to unauthorized data access
- Authentication vs Authorization: The difference between verifying who a user is and what they can access
- Real-world scenarios: How document management systems can be compromised
✅ Student Dashboard - Upload and manage assignments
✅ Teacher Materials - Share study materials and exam papers
✅ Admin Console - Full system overview with user and document management
✅ Document Management - Create, upload, view, edit, and delete documents
✅ User Management - Admin can manage all system users
✅ Interactive IDOR Demo - Built-in guides showing how to exploit the vulnerability
Insecure Direct Object Reference occurs when an application uses user-supplied input (like an ID) to directly access objects in a database without proper access control checks.
In this system, the /view_document?doc_id=X endpoint allows any authenticated user to view ANY document in the system by simply changing the doc_id parameter—even documents they don't own!
- Login as any user
- Go to "All Documents"
- Click to view a document (e.g.,
?doc_id=5) - Change the URL to
?doc_id=1and press Enter - You can now see another user's document!
# ❌ VULNERABLE CODE (from app.py)
@app.route('/view_document')
def view_document():
if 'user_id' not in session:
return redirect(url_for('login'))
doc_id = request.args.get('doc_id')
cursor.execute("SELECT * FROM documents WHERE id = %s", (doc_id,))
document = cursor.fetchone()
# ⚠️ NO CHECK: Does session['user_id'] own this document?
return render_template('document.html', document=document)The system checks authentication (are you logged in?) but not authorization (do you own this document?).
- Python 3.8+
- MySQL 5.7+ (or XAMPP)
- pip
-
Clone the repository
git clone <repository-url> cd security-project
-
Create virtual environment
python -m venv venv # Windows venv\Scripts\activate # Mac/Linux source venv/bin/activate
-
Install dependencies
pip install -r requirements.txt
-
Setup Database
# Create .env file with your database credentials DB_HOST=localhost DB_USER=root DB_PASSWORD=your_password DB_NAME=dms SECRET_KEY=your_secret_key -
Import database schema
# Via phpMyAdmin: Import dms.sql # Or via MySQL CLI: mysql -u root -p dms < dms.sql
-
Run the application
python app.py
Access at:
http://localhost:5000
| Username | Password | Role |
|---|---|---|
| student1 | pass | Student |
| student2 | pass | Student |
| teacher1 | pass | Teacher |
| admin | pass | Admin |
- Entry point for all users
- Displays project information
- Test account credentials
- View your own documents
- Quick upload button
- Document statistics
- Security learning section
- Browse system-wide documents
- Search and filter by type
- Built-in IDOR exploitation guide
- Click any document and try changing
doc_idin the URL!
- Display document content
- Shows document metadata
- IDOR Alert: If viewing someone else's document
- Download, edit, and delete options
- Create new documents
- Set title, type, subject
- Add description and tags
- Document types: Assignment, Material, Exam, Report
- View all system users
- Filter by role
- Search functionality
- View user profiles
- System statistics
- Recent documents table
- Recent users table
- Security demo notice
- Login with any account
- Go to All Documents
- Click View on any document
- Change the
doc_idparameter in the URL - Access documents you shouldn't see!
- Create multiple test accounts
- Have each user upload a document
- Note each document's ID
- Use the dashboard to systematically access all documents
- Map out what data is publicly accessible
- Review the backend code in
app.py - Identify where the authorization check is missing
- Plan how to fix it:
# ✅ SECURE FIX cursor.execute( "SELECT * FROM documents WHERE id = %s AND owner_id = %s", (doc_id, session['user_id']) )
- Think about edge cases (admin access, sharing permissions, etc.)
security-project/
├── app.py # Flask backend (DO NOT MODIFY)
├── requirements.txt # Python dependencies
├── README.md # This file
├── dms.sql # Database dump with test data
├── init_db.sql # Initial database schema
├── templates/ # HTML templates
│ ├── base.html # Base layout with navbar
│ ├── login.html # Login page
│ ├── dashboard.html # User dashboard
│ ├── all_documents.html # IDOR demo page ⭐
│ ├── document.html # Document viewer with IDOR alert
│ ├── upload_document.html # Document upload form
│ ├── admin_dashboard.html # Admin panel
│ ├── manage_users.html # User management
│ └── view_user.html # User profile
└── static/
├── css/
│ └── style.css # Complete styling
└── js/
└── main.js # Frontend interactivity
This project is INTENTIONALLY VULNERABLE for educational purposes. It demonstrates:
- ❌ Improper Authorization: No checks on document ownership
- ❌ Weak Password Storage: Plaintext passwords (no hashing suggested)
- ❌ No CSRF Protection: Forms lack CSRF tokens
- ❌ Debug Mode: Active in production
- ✅ Parameterized Queries: Protected against SQL injection
Never deploy this in production. This is a learning tool only.
| Method | Endpoint | Description | Requires Auth |
|---|---|---|---|
| GET | / |
Redirect to dashboard/login | - |
| GET, POST | /login |
Login page | No |
| GET | /dashboard |
User dashboard | Yes |
| GET | /all_documents |
Browse all docs (IDOR) | Yes |
| GET | /view_document |
View document by ID | Yes |
| GET, POST | /upload_document |
Upload new document | Yes |
| GET | /manage_users |
User management | Yes (Admin) |
| GET | /admin_dashboard |
Admin panel | Yes (Admin) |
| GET | /view_user |
User profile | Yes (Admin) |
| GET | /logout |
Logout | Yes |
- How many documents exist in the system?
- Who are all the users?
- What types of documents are shared?
- Download all documents you can access
- Create a spreadsheet showing what you accessed vs. your role
- Modify
app.pyto add authorization checks - Update the document view to verify ownership
- Test that unauthorized access is blocked
- What if admins should see all documents?
- What if teachers should see student submissions?
- How would you implement document sharing?
- OWASP - Insecure Direct Object Reference
- CWE-639: Authorization Bypass Through User-Controlled Key
- OWASP Top 10 - A01:2021 Broken Access Control
- HackTricks - IDOR Guide
Q: Can I use this in my security course? A: Yes! This is designed for educational use. It's great for teaching real-world vulnerabilities.
Q: Why don't you fix the vulnerability? A: The vulnerability is intentional. Students should understand and identify it themselves. The fix is documented in comments.
Q: How do I reset the database?
A: Re-import dms.sql via phpMyAdmin or the MySQL CLI.
Q: Can I modify the backend? A: You can learn from it, but this project focuses on frontend security demonstration.
Created for security education and awareness.
Educational use only. Do not deploy in production.
- OWASP WebGoat
- OWASP Juice Shop
- HackTheBox
- TryHackMe
Happy Learning! 🎓
- Start the Flask app:
python app.py
- Open your web browser and navigate to: http://127.0.0.1:5000
| Username | Password | Role |
|---|---|---|
| userA | pass123 | user |
| userB | pass123 | user |
| admin | admin123 | admin |
- Log in as
userA. - Click on "UserA Private Doc".
- Observe the URL:
.../view_document?doc_id=1. - Exploit: Change
doc_id=1todoc_id=2in the URL. - Result: You can see UserB's private document.
This application is vulnerable by design. DO NOT deploy this code to a production environment.