Compare commits

...

5 Commits

Author SHA1 Message Date
3086d1801d minimal visual improvements 2025-12-15 23:07:46 +10:00
5c4590ff16 vunerability added 2025-12-15 23:05:11 +10:00
c7d8803795 table creation added 2025-12-15 22:44:12 +10:00
9a1b84c267 minimal building container 2025-12-15 22:27:26 +10:00
d3e5abbc98 added readme (seems like i'm reaching my limits and getting tired) 2025-12-15 21:10:41 +10:00
6 changed files with 175 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
build
.vscode
**__pycache__
data

11
Dockerfile Normal file
View File

@@ -0,0 +1,11 @@
FROM python:3.11-slim
WORKDIR /app
COPY ./requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
COPY ./src /app/src
CMD ["fastapi","run", "./src/app.py"]

7
compose.yaml Normal file
View File

@@ -0,0 +1,7 @@
services:
vunerable-web-app:
image: web-app:v0.0.1a
ports:
- "80:8000"
volumes:
- ./data/:/app/data

10
readme.md Normal file
View File

@@ -0,0 +1,10 @@
К сожалениюя я не любитель PHP, так что всё будет на питоне (Fastapi|Uvicorn)
**На сервере Web написать уязвимое веб-приложение Весь проект писать на рабочем столе в папке Фамилия_Web_app, где “Фамилия” - это ваша настоящая фамилия**
1. Реализовать страницу регистрации пользователей **(1.5 балла)**
2. Реализовать страницу авторизации пользователей **(1.5 балла)**
3. Реализовать **Cookie (2 балла)**
4. Реализовать страницу **“приветствия пользователя”** (она должна выводить текст **“Привет, имя_пользователя”**) (Имя_пользователя, это переменная и должна равняться авторизованному пользователю), доступ на эту страницу только после авторизации **(2 балла)**
5. Обернуть готовое приложение в **Docker (3 балла)**

1
requirements.txt Normal file
View File

@@ -0,0 +1 @@
fastapi[standard]

142
src/app.py Normal file
View File

@@ -0,0 +1,142 @@
import sqlite3
from fastapi import FastAPI
from fastapi import Request, Form
from fastapi.responses import HTMLResponse, RedirectResponse
DB_PATH = "./data/database.db"
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, login TEXT NOT NULL UNIQUE, password TEXT NOT NULL)")
app = FastAPI(
docs_url=None, # Disable Swagger UI
redoc_url=None, # Disable ReDoc
openapi_url=None # Disable OpenAPI JSON schema
)
STYLES = """
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
}
</style>
"""
@app.get("/register", response_class=HTMLResponse)
async def register_form():
return f"""
<html>
<head><title>Регистрация</title>{STYLES}</head>
<body>
<h2>Регистрация</h2>
<form action="/register" method="post">
<input name="login" placeholder="Login" required><br>
<input name="password" type="password" placeholder="Password" required><br>
<button type="submit">Register</button>
</form>
<p>Уже есть аккаунт? <a href="/login">Войти</a></p>
</body>
</html>
"""
@app.post("/register")
async def register(login: str = Form(...), password: str = Form(...)):
try:
cursor.execute("INSERT INTO users (login, password) VALUES (?, ?)", (login, password))
conn.commit()
response = RedirectResponse(url="/welcome", status_code=302)
response.set_cookie("login", login)
response.set_cookie("password", password)
return response
except sqlite3.IntegrityError:
return HTMLResponse(f"""
<html>
<head><title>Ошибка регистрации</title>{STYLES}</head>
<body>
<h3>Login уже существует</h3>
<a href='/register'>Попробовать снова</a>
</body>
</html>
""", status_code=400)
@app.get("/login", response_class=HTMLResponse)
async def login_form():
return f"""
<html>
<head><title>Вход</title>{STYLES}</head>
<body>
<h2>Вход</h2>
<form action="/login" method="post">
<input name="login" placeholder="Login" required><br>
<input name="password" type="password" placeholder="Password" required><br>
<button type="submit">Login</button>
</form>
<p>Нет аккаунта? <a href="/register">Зарегистрироваться</a></p>
</body>
</html>
"""
@app.post("/login")
async def login(login: str = Form(...), password: str = Form(...)):
cursor.execute("SELECT * FROM users WHERE login=? AND password=?", (login, password))
user = cursor.fetchone()
if user:
response = RedirectResponse(url="/welcome", status_code=302)
response.set_cookie("login", login)
response.set_cookie("password", password)
return response
else:
return HTMLResponse(f"""
<html>
<head><title>Ошибка входа</title>{STYLES}</head>
<body>
<h3>Неверные учетные данные</h3>
<a href='/login'>Попробовать снова</a>
</body>
</html>
""", status_code=401)
@app.get("/welcome", response_class=HTMLResponse)
async def welcome(request: Request):
login = request.cookies.get("login")
password = request.cookies.get("password")
if not login or not password:
return RedirectResponse(url="/login")
cursor.execute("SELECT * FROM users WHERE login=? AND password=?", (login, password))
user = cursor.fetchone()
if user:
return f"""
<html>
<head><title>Добро пожаловать</title>{STYLES}</head>
<body>
<h1>Привет, {login}</h1>
<form action="/logout" method="post" onsubmit="return logoutAlert();">
<button type="submit">Выйти</button>
</form>
<script>
function logoutAlert() {{
alert('Вы вышли из аккаунта');
return true;
}}
</script>
</body>
</html>
"""
else:
return RedirectResponse(url="/login")
@app.post("/logout")
async def logout():
response = RedirectResponse(url="/login", status_code=302)
response.delete_cookie("login")
response.delete_cookie("password")
return response
@app.get("/", include_in_schema=False)
async def root():
return RedirectResponse(url="/login")