{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "a698dfac",
   "metadata": {},
   "source": [
    "# 22-32 · Parametryzacja vs wstrzyknięcie\n",
    "\n",
    "Praktyka do [Podstawy bezpieczeństwa aplikacji webowych](.. /.. /site/chapters/glava-22/22-32-bezopasnost.html)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f2a551b8",
   "metadata": {},
   "source": [
    "## Cel\n",
    "\n",
    "W rzeczywistości sqlite3 porównać niebezpieczny zestaw żądania za pomocą łańcuch znaków f-string z bezpiecznym parametryzowanym zapytaniem — i zobaczyć, do czego prowadzi wstrzyknięcie SQL-, jeśli nie zostanie zatrzymane."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "661f7c2d",
   "metadata": {},
   "source": [
    "## Przykład roboczy — podatna wersja\n",
    "\n",
    "Używamy wstrzyknięcia pojedynczej instrukcji, które wykonuje regularny `sqlite3.execute()`. Atak złożony z `DROP TABLE` ta metoda odrzuciłaby, ale to ograniczenie sterownika Python- nie czyni SQL z struny f-bezpiecznym."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "284d1333",
   "metadata": {},
   "outputs": [],
   "source": [
    "import sqlite3\n",
    "\n",
    "baza = sqlite3.connect(\":memory:\")\n",
    "baza.execute(\"CREATE TABLE tasks (id INTEGER PRIMARY KEY, title TEXT NOT NULL)\")\n",
    "zadachi = [(\"Купить хлеб\",), (\"Написать тесты\",), (\"Позвонить врачу\",)]\n",
    "baza.executemany(\"INSERT INTO tasks (title) VALUES (?)\", zadachi)\n",
    "baza.commit()\n",
    "\n",
    "vvod_polzovatelya = \"' OR '1'='1\"\n",
    "\n",
    "# TAK NIE ROBI SIĘ — pokazano celowo, aby zobaczyć konsekwencje:\n",
    "opasny_zapros = f\"SELECT * FROM tasks WHERE title = '{vvod_polzovatelya}'\"\n",
    "rezultat_opasny = baza.execute(opasny_zapros).fetchall()\n",
    "\n",
    "print(\"Введённый фильтр:\", repr(vvod_polzovatelya))\n",
    "print(\"Строки, возвращённые уязвимым запросом:\", rezultat_opasny)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "daec72f1",
   "metadata": {},
   "source": [
    "## Sprawdzanie wyniku – filtr jest omijany"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "815634a9",
   "metadata": {},
   "outputs": [],
   "source": [
    "vse_stroki = baza.execute(\"SELECT * FROM tasks ORDER BY id\").fetchall()\n",
    "assert rezultat_opasny == vse_stroki\n",
    "assert len(rezultat_opasny) == len(zadachi) == 3\n",
    "print(f\"Фильтр обойдён: запрос вернул все {len(rezultat_opasny)} строки вместо точного совпадения.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6224352b",
   "metadata": {},
   "source": [
    "## Eksperyment - Zapytanie parametryzowane jest bezpieczne"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6b2ed903",
   "metadata": {},
   "outputs": [],
   "source": [
    "baza2 = sqlite3.connect(\":memory:\")\n",
    "baza2.execute(\"CREATE TABLE tasks (id INTEGER PRIMARY KEY, title TEXT NOT NULL)\")\n",
    "baza2.executemany(\"INSERT INTO tasks (title) VALUES (?)\", zadachi)\n",
    "baza2.commit()\n",
    "\n",
    "vvod_kak_dannye = \"' OR '1'='1\"\n",
    "rezultat = baza2.execute(\"SELECT * FROM tasks WHERE title = ?\", (vvod_kak_dannye,)).fetchall()\n",
    "\n",
    "vse_stroki2 = baza2.execute(\"SELECT * FROM tasks ORDER BY id\").fetchall()\n",
    "print(\"Строки по точному совпадению:\", rezultat)\n",
    "print(\"Все строки по-прежнему в таблице:\", vse_stroki2)\n",
    "\n",
    "assert rezultat == []\n",
    "assert len(vse_stroki2) == len(zadachi) == 3\n",
    "print(\"Верно: параметризованный запрос обработал вредоносный текст как обычное значение и не позволил обойти фильтр.\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Cartesian Python 3.14",
   "language": "python",
   "name": "cartesian-python314"
  },
  "language_info": {
   "name": "python",
   "version": "3.14.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
