Биз жөнүндөБлогБайланыш
Коопсуздук2026-ж., 18-апрель 4 мин 13

Веб коопсуздугу: OWASP Top 10 - реалдуу чабуулдар жана коргоо

AunimedaAunimeda
📋 Мазмуну

Веб коопсуздугу: OWASP Top 10 - реалдуу чабуулдар жана коргоо

OWASP Top 10 - веб тиркемелердин коопсуздугун баалоонун дүйнөлүк стандарты. Ар бир пункт - миңдеген тиркемелерди бузуу үчүн колдонулган конкреттүү ыкма. Бул - практикалык колдонмо, Node.js разработчиктери үчүн.


A01: Сынган мүмкүндүктү башкаруу

Эң кеңири таралган аялуулук. Колдонуучу башкалардын маалыматына мүмкүндүк алат.

IDOR чабуулу:

GET /api/orders/my-order-id      ← менин заказым
GET /api/orders/victim-order-id  ← башкасынын заказы (эгер текшерүү жок болсо!)
// ❌ Авторизацияны гана текшерет, ресурска ким ээлигин - жок
router.get('/api/orders/:orderId', authenticate, async (req, res) => {
  const order = await db.order.findUnique({ where: { id: req.params.orderId } });
  res.json(order); // каалаган авторизацияланган колдонуучу каалаган заказды алат
});

// ✅ Учурдагы колдонуучуга гана чектөөбүз
router.get('/api/orders/:orderId', authenticate, async (req, res) => {
  const order = await db.order.findUnique({
    where: {
      id: req.params.orderId,
      userId: req.user.id, // колдонуучу өзүнүн заказдарын гана көрөт
    },
  });
  if (!order) return res.status(404).json({ error: 'Табылган жок' });
  res.json(order);
});

Admin эндпоинттери үчүн - роль текшерүү:

function requireRole(role: string) {
  return (req: Request, res: Response, next: NextFunction) => {
    if (!req.user?.roles.includes(role)) {
      return res.status(403).json({ error: 'Уруксат жок' });
    }
    next();
  };
}

router.delete('/api/admin/users/:id', authenticate, requireRole('admin'), deleteUser);

A02: Криптографиялык каталар

Сырсөздөрдү туура эмес сактоо - эң кеңири таралган катанын бири.

// ❌ MD5 - сырсөз хэштөө алгоритми эмес
const hash = crypto.createHash('md5').update(password).digest('hex');

// ✅ bcrypt - атайылап жай иштеген алгоритм
import bcrypt from 'bcrypt';

async function hashPassword(password: string): Promise<string> {
  return bcrypt.hash(password, 12); // cost factor 12 ≈ 250мс
}

async function verifyPassword(password: string, hash: string): Promise<boolean> {
  return bcrypt.compare(password, hash);
}

// ✅ Сырсөзду калыбына келтирүү үчүн коопсуз токен
import crypto from 'crypto';

async function createResetToken(userId: string): Promise<string> {
  const token = crypto.randomBytes(32).toString('hex');
  const hash = crypto.createHash('sha256').update(token).digest('hex');
  
  await db.passwordReset.create({
    data: {
      userId,
      tokenHash: hash,
      expiresAt: new Date(Date.now() + 15 * 60 * 1000), // 15 мүнөт
    },
  });
  
  return token; // колдонуучуга жиберебиз, хэшти гана сактайбыз
}

A03: Инъекциялар (SQL, NoSQL)

// ❌ SQL инъекция - классикалык аялуулук
const users = await db.query(
  `SELECT * FROM users WHERE email = '${req.body.email}'`
);
// Чабуул: email = "admin'--" → сырсөзсүз системага кирет

// ✅ Параметрлештирилген суроо
const users = await db.query(
  'SELECT * FROM users WHERE email = $1',
  [req.body.email]
);

// ✅ ORM - автоматтык параметрлештирүү
const user = await prisma.user.findUnique({
  where: { email: req.body.email },
});

NoSQL (MongoDB) инъекциясы:

// ❌ Аялуу
// Чабуул: { "email": {"$gt": ""}, "password": {"$gt": ""} } → авторизацияны айланып өтөт
const user = await User.findOne({ email: req.body.email });

// ✅ Zod менен валидация
import { z } from 'zod';
const LoginSchema = z.object({
  email: z.string().email(),
  password: z.string().min(1),
});
const { email, password } = LoginSchema.parse(req.body);
// email милдетте string - инъекция мүмкүн эмес

A05: Туура эмес конфигурация

Коопсуздук headers - ар кандай веб тиркеме үчүн милдеттүү:

import helmet from 'helmet';

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'"],
      imgSrc: ["'self'", 'data:', 'https:'],
    },
  },
  hsts: {
    maxAge: 63072000, // 2 жыл
    includeSubDomains: true,
  },
}));

// Production'до stack trace жок
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  logger.error({ err, url: req.url });
  res.status(500).json(
    process.env.NODE_ENV === 'production'
      ? { error: 'Ички ката' }
      : { error: err.message, stack: err.stack }
  );
});

A07: Аутентификациянын бузулушу

Brute-force коргоо - rate limiting:

import rateLimit from 'express-rate-limit';

const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 мүнөт
  max: 10,                   // бир IP'дан 10 аракет
  handler: (req, res) => {
    res.status(429).json({ error: '15 мүнөттөн кийин кайра аракет кылыңыз' });
  },
});

app.post('/api/auth/login', loginLimiter, loginHandler);

// Email'дин базада бар-жогун ачпаңыз
// ❌ Колдонуучу аттарды чогултууга жардам берет
if (!user) return res.status(404).json({ error: 'Колдонуучу табылган жок' });

// ✅ Бирдей жооп
if (!user || !await bcrypt.compare(password, user.passwordHash)) {
  return res.status(401).json({ error: 'Туура эмес email же сырсөз' });
}

A10: SSRF - сервердик суроолорду жасалмалоо

// ❌ Аялуу - ички сервистерге суроо жибере алат
app.post('/api/preview', async (req, res) => {
  const response = await fetch(req.body.url);
  // Чабуул: url = 'http://169.254.169.254/' → AWS credentials агылуусу
});

// ✅ Жеке IP диапазондорду блокторбуз
import dns from 'dns/promises';
import ipRangeCheck from 'ip-range-check';

const BLOCKED = ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', '127.0.0.0/8', '169.254.0.0/16'];

async function isSafeUrl(urlString: string): Promise<boolean> {
  try {
    const url = new URL(urlString);
    if (!['http:', 'https:'].includes(url.protocol)) return false;
    const ips = await dns.resolve4(url.hostname);
    return ips.every(ip => !ipRangeCheck(ip, BLOCKED));
  } catch { return false; }
}

Минималдуу коопсуздук чеклисти

[ ] Бардык колдонуучу ввод валидацияланат (Zod)
[ ] SQL: параметрлештирилген суроолор гана
[ ] Сырсөздөр: bcrypt cost factor 10+
[ ] Security headers: Helmet
[ ] Rate limiting: /login жана /register
[ ] JWT: 15 мүнөт жашоо + refresh token
[ ] npm audit CI/CD'да
[ ] Production'до stack trace жок
[ ] Ар бир суроо ресурсун ийелигин текшерет
[ ] HTTPS + HSTS

Aunimeda Кыргызстан бизнеси үчүн коопсуз веб тиркемелерди иштеп чыгат.

Ошондой эле: Telegram Bot webhook жана FSM, Git продвинутый workflow

Ошондой эле окуңуз

WebSockets vs SSE vs Long Polling: realtime технологиясын кантип тандоо керекaunimeda
Иштеп чыгуу

WebSockets vs SSE vs Long Polling: realtime технологиясын кантип тандоо керек

Чат, кабарлар, заказ статусу — булардын баары реалдуу убакытта жаңыртууну талап кылат. WebSocket, Server-Sent Events жана Long Polling ар башка иштейт. Кайсын качан колдонуу керегин Node.js код мисалдары менен карайбыз.

Node.js vs Bun vs Deno 2026: кайсы JavaScript runtime тандоо керекaunimeda
Иштеп чыгуу

Node.js vs Bun vs Deno 2026: кайсы JavaScript runtime тандоо керек

Bun 1.x продакшн стабилдүү. Deno 2.0 npm колдойт. Node.js 22 TypeScript'ти нативдүү иштетет. Реалдуу benchmark'тар, экосистема салыштыруусу жана Кыргызстандагы долбоорлор үчүн конкреттүү сунуштамалар.

Node.js'теги таза архитектура: бизнес логиканы инфраструктурадан бөлүп алууaunimeda
Иштеп чыгуу

Node.js'теги таза архитектура: бизнес логиканы инфраструктурадан бөлүп алуу

Алты айдан кийин Node.js долбоору спагетти кодго айланбасын десеңиз — Use Cases, Repository Pattern жана Dependency Inversion. Маалымат базасыз тестирленген бизнес логика — реалдуу код мисалдары менен.

Бизнесиңизге IT иштеп чыгуу керекпи?

Веб-сайттарды, мобилдик тиркемелерди жана AI чечимдерин иштеп чыгабыз. Акысыз консультация.

Консультация алуу Бардык макалалар