RƏSƏDXANA

Həftə 5 · 09/23

İnterfeys kilid deyil

6 dəqiqəlik oxu

Klubun qapısında nəzarətçi var. Amma arxa qapı açıqdır və zalın içində heç kim bilet soruşmur. Qapıdakı nəzarətçi zalı qorumur — sadəcə qapını.

İnterfeys qapıdır, server isə zal. Düyməni gizlətmək kimsəni saxlamır: istənilən adam birbaşa serverə sorğu göndərə bilər. Qayda serverdə tətbiq olunmalıdır.

// the browser hides the button...
{isMember && <PostButton />}

// ...and the server lets anyone in
app.post("/api/post", async (req) => save(await req.json()));
İki fayl, bir boşluq. Birinci sətir rahatlıqdır; ikinci sətir isə qaydadır — və orada qayda yoxdur.

Çox deyilən söz: Düymə görünmürsə, istifadəçi o işi edə bilməz.

İstənilən adam istənilən HTTP sorğusunu istənilən məzmunla göndərə bilər. İnterfeys yalnız dürüst istifadəçiyə rahatlıq verir. Vacib olan hər qayda serverdə tətbiq olunur. Kimlik isə client-in özü haqqında dediklərindən deyil, yalnız yoxlanılmış sessiyadan gəlir.

Hər sorğuda: authn, sonra authz

Əvvəl «sən kimsən» (sessiya → 401), sonra «buna haqqın var» (sahiblik və ya rol → 403). İkisi də serverdə, hər endpoint-də.

Sən bunu istə

const me = await requireSession(req);              // 401
const post = await db.getPost(id);
if (!post) return notFound();
if (post.authorId !== me.id) return forbidden();   // 403

Client istənilən şeyi göndərə bilər

Gizli düymə, söndürülmüş input, brauzerdə validasiya — bunlar rahatlıqdır, qoruma yox. Hər endpoint-i curl ilə sına.

AI belə yazır

curl -X POST https://api.example.com/vote \
  -d '{"postId":"p1","voterId":"someone-else"}'
# 200 OK  <- the server believed the body

Ehtiyat yol da koddur

Əsas yol düzəlir, «?? query» ehtiyatı açıq qalır. Kimliyin hesablandığı hər yeri axtar, təkcə birini yox.

AI belə yazır

const uid = session?.id ?? url.searchParams.get("uid");

Sən bunu istə

const uid = session?.id ?? null;   // signed out = nobody

Diff oxuyanda soruş: Hər endpoint üçün soruş: sessiya yoxdursa nə qaytarır? Başqasının id-si ilə çağırsam nə olur? Cavabı curl ilə al.

Terminlər

authentication / authorization
Birincisi «sən kimsən?», ikincisi «bunu etməyə haqqın var?» sualıdır.
broken access control
OWASP Top 10:2025 siyahısında 1-ci yer: icazə yoxlamasının olmaması və ya səhv olması.
IDOR / BOLA
Sorğudakı id-ni dəyişib başqasının məlumatına çatmaq, çünki server sahibliyi yoxlamır.
identity spoofing
Özünü başqası kimi təqdim etmək — məsələn, gövdədə başqasının id-sini göndərmək.
401 / 403
401: kim olduğun bilinmir. 403: kim olduğun bilinir, amma icazən yoxdur.

İndi sən yoxla

1Bu endpoint-də nə səhvdir?

app.post("/api/vote", async (req) => {
  const { postId, voterId } = await req.json();
  await db.toggleVote(postId, voterId);
});

2Bu təhlükəsizdirmi?

// GET /api/classes/:id/report
const session = await requireSession(req);   // 401 if none
return json(await db.classReport(params.id));

Hazır prompt

İngiliscədir, çünki terminlər ingiliscədir. Tərcümə etsən də terminləri saxla.

prompt
Act as a security reviewer. For every API endpoint in <path>:

- Who is allowed to call it? Where is that checked (file:line)?
  If it is only checked in the UI, flag it.
- Where does the caller's identity come from? Flag any id, key, role
  or owner taken from the body, the query string, or any header other
  than the verified session. Include fallback paths.
- For endpoints that take a resource id: is ownership or membership
  checked on the server?

Output a table: endpoint | authn | authz | identity source | verdict.

Öz kodunda

  1. 1Prompt-u öz API-ində işlət.
  2. 2Qeyd olunan hər endpoint üçün curl ilə sessiyasız sorğu göndər (401 gözlənilir), sonra başqa hesabla göndər (403 gözlənilir).
  3. 3Düzəlt, deploy et, eyni curl əmrlərini yenidən işlət.

Bunu görəndə bitib: Hər qorunan endpoint üçün 401/403 qaytaran curl əmrin var və onları canlı serverə qarşı işlətmisən.

Daha dərinə

Oxumaq üçün