This application was developed for educational purposes only to demonstrate race condition vulnerabilities in concurrent systems. It has intentional security vulnerabilities and MUST NOT BE USED IN PRODUCTION.
Racing Bank is a complete banking system consisting of:
- Backend API - FastAPI with intentional race condition vulnerabilities
- Android App - Mobile application with retro cyberpunk visual design
This project was created as an educational demonstration for TRECO and TREM, showing in practice how race conditions can affect financial systems.
- โ Two-factor authentication (TOTP)
- โ Deposits and withdrawals
- โ Account-to-account transfers
- โ Investment fund operations
- โ Transaction statements
- โ Interactive dashboard
- โ Double spending in transfers
- โ Lost updates in deposits
- โ Investment inconsistencies
- โ Phantom reads in queries
- โ Race conditions in all operations
racing-bank/
โโโ api/ # FastAPI Backend
โ โโโ routes/ # API endpoints
โ โ โโโ auth_routes.py # Authentication & onboarding
โ โ โโโ account_routes.py # Deposits & withdrawals
โ โ โโโ transfer_routes.py # Transfers
โ โ โโโ fund_routes.py # Investments
โ โโโ config.py # Configuration
โ โโโ database.py # SQLAlchemy models
โ โโโ auth.py # JWT & TOTP
โ โโโ schemas.py # Pydantic schemas
โ โโโ main.py # Entry point
โ โโโ requirements.txt # Python dependencies
โ โโโ Dockerfile # API container
โ โโโ compose.yaml # Docker Compose
โ โโโ README.md # API documentation
โ
โโโ app/ # Android Application
โ โโโ src/main/
โ โ โโโ java/com/hacknroll/bank/
โ โ โ โโโ data/ # Repository & API client
โ โ โ โโโ ui/ # Activities & Fragments
โ โ โ โ โโโ auth/ # Login & Registration
โ โ โ โ โโโ main/ # Dashboard & Operations
โ โ โ โ โโโ splash/ # Splash screen
โ โ โ โโโ utils/ # Utilities
โ โ โโโ res/ # Resources (layouts, themes)
โ โโโ build.gradle.kts # Build configuration
โ โโโ README.md # App documentation
โ
โโโ docs/ # Additional documentation
โ โโโ RACE_CONDITIONS.md # Detailed vulnerability examples
โ โโโ API_GUIDE.md # Complete API reference
โ โโโ ANDROID_SETUP.md # Android development setup
โ โโโ SECURITY.md # Security considerations
โ
โโโ scripts/ # Utility scripts
โ โโโ setup.sh # Quick setup script
โ โโโ demo.sh # Demo data loader
โ โโโ test_race_conditions.py # Race condition tests
โ
โโโ .gitignore # Git ignore rules
โโโ LICENSE # License file
โโโ README.md # This file
# 1. Clone the repository
git clone https://github.com/maycon/racing-bank.git
cd racing-bank
# 2. Start the API with Docker Compose
cd api
docker-compose up -d
# 3. View logs to get TOTP secrets for demo users
docker-compose logs api
# API will be available at http://localhost:8000
# Interactive docs at http://localhost:8000/docs# Navigate to API directory
cd api
# Install Python dependencies
pip install -r requirements.txt
# Start MariaDB (or use Docker)
docker run -d -p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=root \
-e MYSQL_DATABASE=bankao \
mariadb:11
# Run the API
python main.py# Open Android Studio
# File โ Open โ Select racing-bank/app directory
# Configure API endpoint (if not using emulator)
# Edit app/src/main/java/.../data/api/RetrofitClient.kt
# Change BASE_URL to your machine's IP
# Run the app on emulator or devicecd api
docker-compose up -ddocker-compose logs api | grep "TOTP secret"Demo users:
- alice / alice123 (Balance: $1,000)
- bob / bob123 (Balance: $500)
- Use Google Authenticator or similar app
- Scan QR code or enter TOTP secret manually
- Open the app
- Enter username and password
- Enter 6-digit TOTP code
- Start banking!
# Login
curl -X POST http://localhost:8000/login \
-H "Content-Type: application/json" \
-d '{"username": "alice", "password": "alice123"}'
# 2FA (use TOTP code from authenticator)
curl -X POST http://localhost:8000/2fa \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <temp_token>" \
-d '{"token": "123456"}'
# Check balance
curl -X GET http://localhost:8000/balance \
-H "Authorization: Bearer <access_token>"# Alice has $100, attempts to transfer $80 twice simultaneously
# Both checks pass ($100 >= $80) โ
# Both transfers execute
# Result: Alice has -$60 (overdraft!)
# Terminal 1
curl -X POST http://localhost:8000/transfer \
-H "Authorization: Bearer $TOKEN" \
-d '{"to_username": "bob", "amount": 80}' &
# Terminal 2 (run immediately)
curl -X POST http://localhost:8000/transfer \
-H "Authorization: Bearer $TOKEN" \
-d '{"to_username": "bob", "amount": 80}' &# Using Python to trigger concurrent deposits
import concurrent.futures
import requests
def deposit(amount):
return requests.post(
"http://localhost:8000/deposit",
headers={"Authorization": f"Bearer {TOKEN}"},
json={"amount": amount}
)
# Start balance: $100
# Execute 10 concurrent deposits of $10 each
# Expected: $200
# Actual: ~$110-$150 (lost updates!)
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
futures = [executor.submit(deposit, 10) for _ in range(10)]
results = [f.result() for f in futures]# Multiple users subscribing to fund simultaneously
# Can result in incorrect share price calculations
for i in {1..5}; do
curl -X POST http://localhost:8000/subscribe \
-H "Authorization: Bearer $TOKEN_USER_$i" \
-d '{"amount": 1000}' &
doneSee docs/RACE_CONDITIONS.md for detailed explanations and more examples.
- Framework: FastAPI 0.115.0
- Server: Uvicorn (ASGI)
- Database: MariaDB 11
- ORM: SQLAlchemy 2.0
- Auth: PyJWT + PyOTP (TOTP)
- Validation: Pydantic v2
- Language: Kotlin 1.9.0
- Min SDK: API 24 (Android 7.0)
- Target SDK: API 34 (Android 14)
- Architecture: MVVM + Repository Pattern
- Networking: Retrofit 2 + OkHttp 3
- UI: Material Design 3
- Security: EncryptedSharedPreferences
- API Documentation - Complete API reference
- Android App Documentation - App features and setup
- Race Conditions Guide - Detailed vulnerability examples
- Security Considerations - What NOT to do in production
This project demonstrates the following security issues:
- No database transaction isolation - All operations are vulnerable
- No pessimistic/optimistic locking - Concurrent modifications not prevented
- No idempotency checks - Operations can be duplicated
- No rate limiting - Enables automated attacks
- Weak password hashing - SHA-256 instead of bcrypt/argon2
- TOTP secrets exposed - Printed in logs for demo purposes
To make this production-ready, you must:
-
Implement proper database transactions
with session.begin(): account = session.query(Account).with_for_update().filter_by(id=user_id).one() account.balance -= amount session.commit()
-
Use optimistic locking with version numbers
class Account(Base): version = Column(Integer, default=0)
-
Implement idempotency keys
@app.post("/transfer") async def transfer( request: TransferRequest, idempotency_key: str = Header(...) ): # Check if operation already executed
-
Add rate limiting
from slowapi import Limiter limiter = Limiter(key_func=get_remote_address) @app.post("/transfer") @limiter.limit("10/minute") async def transfer(...):
-
Use strong password hashing
from passlib.context import CryptContext pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
-
Never expose secrets in responses or logs
-
Always use HTTPS in production
-
Implement proper error handling without leaking information
cd scripts
python test_race_conditions.py# Install Apache Bench
sudo apt-get install apache2-utils
# Test concurrent deposits
ab -n 1000 -c 50 -m POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-p deposit.json \
http://localhost:8000/depositcd app
./gradlew connectedAndroidTestThis is an educational project. Contributions are welcome for:
- Additional race condition examples
- Better documentation
- More test scenarios
- UI/UX improvements in the Android app
Important: Keep the vulnerabilities intact - that's the educational purpose!
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-example) - Commit your changes (
git commit -m 'Add race condition example') - Push to the branch (
git push origin feature/amazing-example) - Open a Pull Request
- Maycon Vitali - Initial work - GitHub
- Created as demonstration for TREM
- Inspired by real-world banking vulnerabilities
- Thanks to the open-source community
This project is for educational purposes only.
DO NOT USE IN PRODUCTION - The code intentionally contains security vulnerabilities to demonstrate race conditions in concurrent systems.
For questions about race conditions or concurrency issues:
- Open an issue on GitHub
- Check the documentation in
docs/ - Review the code comments explaining each vulnerability
๐ฎ Hack N Roll Racing Bank - Banking with intentional bugs for educational purposes! ๐ฐ๐