revise November 2020 security articles
Build and deploy / deploy (push) Successful in 15s

This commit is contained in:
2026-07-31 11:59:30 +03:00
parent 2ffa7a40eb
commit 41c3aca967
7 changed files with 840 additions and 1 deletions
@@ -0,0 +1,55 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 1528" role="img" aria-labelledby="title desc">
<title id="title">Учебная матрица минимальной защиты веб-приложения</title>
<desc id="desc">Вертикальная схема связывает четыре актива учебной админки с угрозой, контролем и наблюдаемым доказательством. Это не отчёт о реальном приложении.</desc>
<style>
.title { fill: #f8fafc; font-family: Arial, sans-serif; font-size: 34px; font-weight: 700; }
.subtitle { fill: #cbd5e1; font-family: Arial, sans-serif; font-size: 22px; }
.label { fill: #475569; font-family: Arial, sans-serif; font-size: 20px; font-weight: 700; letter-spacing: 1px; }
.body { fill: #0f172a; font-family: Arial, sans-serif; font-size: 24px; font-weight: 600; }
.small { fill: #334155; font-family: Arial, sans-serif; font-size: 21px; }
.step { fill: #ffffff; font-family: Arial, sans-serif; font-size: 22px; font-weight: 700; text-anchor: middle; }
</style>
<rect width="720" height="1528" fill="#f8fafc"/>
<rect x="0" y="0" width="720" height="198" fill="#0f172a"/>
<text x="48" y="70" class="title">Минимальный baseline</text>
<text x="48" y="112" class="title">актив → угроза → контроль → evidence</text>
<text x="48" y="156" class="subtitle">Учебная админка, ноябрь 2020</text>
<rect x="48" y="232" width="624" height="70" rx="14" fill="#e2e8f0"/>
<circle cx="82" cy="267" r="20" fill="#2563eb"/>
<text x="82" y="275" class="step">1</text>
<text x="120" y="275" class="label">АКТИВ: ИЗМЕНЕНИЕ ПРОФИЛЯ</text>
<rect x="48" y="320" width="624" height="116" rx="16" fill="#dbeafe"/>
<text x="76" y="360" class="body">Угроза: post приходит не из</text>
<text x="76" y="392" class="body">ожидаемого контекста формы</text>
<rect x="48" y="452" width="624" height="116" rx="16" fill="#dcfce7"/>
<text x="76" y="492" class="body">Контроль: origin + CSRF token</text>
<text x="76" y="524" class="body">до server-side update</text>
<rect x="48" y="584" width="624" height="92" rx="16" fill="#fef3c7"/>
<text x="76" y="625" class="body">Evidence: foreign origin → 403</text>
<text x="76" y="655" class="small">в учебной fixture</text>
<rect x="48" y="710" width="624" height="70" rx="14" fill="#e2e8f0"/>
<circle cx="82" cy="745" r="20" fill="#2563eb"/>
<text x="82" y="753" class="step">2</text>
<text x="120" y="753" class="label">АКТИВ: СЕССИЯ АДМИНИСТРАТОРА</text>
<rect x="48" y="798" width="624" height="102" rx="16" fill="#dbeafe"/>
<text x="76" y="838" class="body">Угроза: cookie доступен script</text>
<text x="76" y="870" class="body">или не привязан к HTTPS-сценарию</text>
<rect x="48" y="916" width="624" height="102" rx="16" fill="#dcfce7"/>
<text x="76" y="956" class="body">Контроль: Secure + HttpOnly</text>
<text x="76" y="988" class="body">и узкий Path=/admin</text>
<rect x="48" y="1034" width="624" height="82" rx="16" fill="#fef3c7"/>
<text x="76" y="1084" class="body">Evidence: Set-Cookie contract</text>
<rect x="48" y="1150" width="624" height="70" rx="14" fill="#e2e8f0"/>
<circle cx="82" cy="1185" r="20" fill="#2563eb"/>
<text x="82" y="1193" class="step">3</text>
<text x="120" y="1193" class="label">АКТИВ: РАЗМЕТКА ADMIN PAGE</text>
<rect x="48" y="1238" width="624" height="70" rx="16" fill="#dbeafe"/>
<text x="76" y="1282" class="body">Угроза: неожиданный content</text>
<rect x="48" y="1322" width="624" height="70" rx="16" fill="#dcfce7"/>
<text x="76" y="1366" class="body">Контроль: encoding + CSP policy</text>
<rect x="48" y="1406" width="624" height="82" rx="16" fill="#fef3c7"/>
<text x="76" y="1456" class="body">Evidence: CSP response contract</text>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

@@ -0,0 +1,63 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 1500" role="img" aria-labelledby="title desc">
<title id="title">Диагностика учебного security baseline</title>
<desc id="desc">Вертикальная схема показывает для четырёх симптомов причину, безопасную проверку и действие: foreign origin, пустой token, недостаточное permission и неполный ответный контракт.</desc>
<style>
.title { fill: #f8fafc; font-family: Arial, sans-serif; font-size: 34px; font-weight: 700; }
.subtitle { fill: #cbd5e1; font-family: Arial, sans-serif; font-size: 22px; }
.title2 { fill: #f8fafc; font-family: Arial, sans-serif; font-size: 30px; font-weight: 700; }
.symptom { fill: #991b1b; font-family: Arial, sans-serif; font-size: 25px; font-weight: 700; }
.label { fill: #475569; font-family: Arial, sans-serif; font-size: 19px; font-weight: 700; letter-spacing: 1px; }
.body { fill: #0f172a; font-family: Arial, sans-serif; font-size: 22px; font-weight: 600; }
.action { fill: #166534; font-family: Arial, sans-serif; font-size: 22px; font-weight: 700; }
.num { fill: #ffffff; font-family: Arial, sans-serif; font-size: 21px; font-weight: 700; text-anchor: middle; }
</style>
<rect width="720" height="1500" fill="#f8fafc"/>
<rect x="0" y="0" width="720" height="190" fill="#0f172a"/>
<text x="48" y="70" class="title">Диагностика без сканера</text>
<text x="48" y="112" class="title2">симптом → причина → проверка → действие</text>
<text x="48" y="156" class="subtitle">Учебные request objects в памяти</text>
<rect x="48" y="226" width="624" height="268" rx="18" fill="#fff1f2"/>
<circle cx="84" cy="264" r="20" fill="#dc2626"/>
<text x="84" y="272" class="num">1</text>
<text x="122" y="270" class="symptom">Foreign origin проходит</text>
<text x="76" y="316" class="label">ПРИЧИНА</text>
<text x="76" y="348" class="body">origin gate отсутствует или поздно</text>
<text x="76" y="388" class="label">ПРОВЕРКА</text>
<text x="76" y="420" class="body">other.example.test должен дать 403</text>
<text x="76" y="460" class="label">ДЕЙСТВИЕ</text>
<text x="76" y="492" class="action">вернуть gate до update</text>
<rect x="48" y="528" width="624" height="268" rx="18" fill="#fff7ed"/>
<circle cx="84" cy="566" r="20" fill="#ea580c"/>
<text x="84" y="574" class="num">2</text>
<text x="122" y="572" class="symptom">Пустой token проходит</text>
<text x="76" y="618" class="label">ПРИЧИНА</text>
<text x="76" y="650" class="body">form field не связан с controller</text>
<text x="76" y="690" class="label">ПРОВЕРКА</text>
<text x="76" y="722" class="body">пустая строка должна дать 403</text>
<text x="76" y="762" class="label">ДЕЙСТВИЕ</text>
<text x="76" y="794" class="action">сравнить token до effect</text>
<rect x="48" y="830" width="624" height="268" rx="18" fill="#fefce8"/>
<circle cx="84" cy="868" r="20" fill="#ca8a04"/>
<text x="84" y="876" class="num">3</text>
<text x="122" y="874" class="symptom">Read-роль меняет профиль</text>
<text x="76" y="920" class="label">ПРИЧИНА</text>
<text x="76" y="952" class="body">session ошибочно заменяет permission</text>
<text x="76" y="992" class="label">ПРОВЕРКА</text>
<text x="76" y="1024" class="body">profile:read должен дать 403</text>
<text x="76" y="1064" class="label">ДЕЙСТВИЕ</text>
<text x="76" y="1096" class="action">поставить profile:write gate</text>
<rect x="48" y="1132" width="624" height="298" rx="18" fill="#ecfdf5"/>
<circle cx="84" cy="1170" r="20" fill="#16a34a"/>
<text x="84" y="1178" class="num">4</text>
<text x="122" y="1176" class="symptom">Response contract неполон</text>
<text x="76" y="1222" class="label">ПРИЧИНА</text>
<text x="76" y="1254" class="body">policy не привязана к route</text>
<text x="76" y="1294" class="label">ПРОВЕРКА</text>
<text x="76" y="1326" class="body">CSP и Set-Cookie есть в карте</text>
<text x="76" y="1366" class="label">ДЕЙСТВИЕ</text>
<text x="76" y="1398" class="action">сверить server version на стенде</text>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

@@ -0,0 +1,66 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 1420" role="img" aria-labelledby="title desc">
<title id="title">Граница учебного запроса к административному маршруту</title>
<desc id="desc">Вертикальный путь POST запроса от браузера к прокси, проверке сессии, origin и token, проверке права, изменению состояния и ответному контракту. Внизу указана учебная fixture.</desc>
<style>
.title { fill: #f8fafc; font-family: Arial, sans-serif; font-size: 34px; font-weight: 700; }
.subtitle { fill: #cbd5e1; font-family: Arial, sans-serif; font-size: 22px; }
.card-title { fill: #0f172a; font-family: Arial, sans-serif; font-size: 27px; font-weight: 700; }
.body { fill: #334155; font-family: Arial, sans-serif; font-size: 23px; }
.gate { fill: #166534; font-family: Arial, sans-serif; font-size: 22px; font-weight: 700; }
.note { fill: #92400e; font-family: Arial, sans-serif; font-size: 21px; font-weight: 700; }
.num { fill: #ffffff; font-family: Arial, sans-serif; font-size: 22px; font-weight: 700; text-anchor: middle; }
</style>
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="5" refY="5" orient="auto-start-reverse">
<path d="M0,0 L10,5 L0,10 z" fill="#64748b"/>
</marker>
</defs>
<rect width="720" height="1420" fill="#f8fafc"/>
<rect x="0" y="0" width="720" height="188" fill="#0f172a"/>
<text x="48" y="72" class="title">Граница одного POST</text>
<text x="48" y="116" class="title">не набор несвязанных headers</text>
<text x="48" y="158" class="subtitle">training origin: admin.example.test</text>
<line x1="360" y1="330" x2="360" y2="370" stroke="#64748b" stroke-width="8" marker-end="url(#arrow)"/>
<line x1="360" y1="524" x2="360" y2="564" stroke="#64748b" stroke-width="8" marker-end="url(#arrow)"/>
<line x1="360" y1="718" x2="360" y2="758" stroke="#64748b" stroke-width="8" marker-end="url(#arrow)"/>
<line x1="360" y1="912" x2="360" y2="952" stroke="#64748b" stroke-width="8" marker-end="url(#arrow)"/>
<line x1="360" y1="1106" x2="360" y2="1146" stroke="#64748b" stroke-width="8" marker-end="url(#arrow)"/>
<rect x="48" y="220" width="624" height="110" rx="18" fill="#dbeafe"/>
<circle cx="86" cy="265" r="21" fill="#2563eb"/>
<text x="86" y="273" class="num">1</text>
<text x="126" y="270" class="card-title">HTML-форма</text>
<text x="126" y="302" class="body">POST, origin, cookie, token</text>
<rect x="48" y="414" width="624" height="110" rx="18" fill="#e0f2fe"/>
<circle cx="86" cy="459" r="21" fill="#0284c7"/>
<text x="86" y="467" class="num">2</text>
<text x="126" y="464" class="card-title">Proxy contract</text>
<text x="126" y="496" class="body">область /admin/ и response policy</text>
<rect x="48" y="608" width="624" height="110" rx="18" fill="#dcfce7"/>
<circle cx="86" cy="653" r="21" fill="#16a34a"/>
<text x="86" y="661" class="num">3</text>
<text x="126" y="658" class="card-title">Session gate</text>
<text x="126" y="690" class="gate">нет session → 401</text>
<rect x="48" y="802" width="624" height="110" rx="18" fill="#dcfce7"/>
<circle cx="86" cy="847" r="21" fill="#16a34a"/>
<text x="86" y="855" class="num">4</text>
<text x="126" y="852" class="card-title">Form context gate</text>
<text x="126" y="884" class="gate">origin + token, иначе 403</text>
<rect x="48" y="996" width="624" height="110" rx="18" fill="#dcfce7"/>
<circle cx="86" cy="1041" r="21" fill="#16a34a"/>
<text x="86" y="1049" class="num">5</text>
<text x="126" y="1046" class="card-title">Permission gate</text>
<text x="126" y="1078" class="gate">profile:write, затем update</text>
<rect x="48" y="1190" width="624" height="182" rx="18" fill="#fef3c7"/>
<text x="80" y="1242" class="card-title">Ответ и evidence</text>
<text x="80" y="1280" class="note">CSP + Set-Cookie contract</text>
<text x="80" y="1314" class="body">fixture: expected request → 204</text>
<text x="80" y="1346" class="body">три изменённых входа → 403</text>
<text x="80" y="1378" class="body">in-memory, без сети и scanner</text>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB