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

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

AunimedaAunimeda
📋 Мазмуну

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 Кыргызстан бизнеси үчүн коопсуз веб тиркемелерди иштеп чыгат.

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

Kitty Girlfriend: Бишкектеги студия Google Play-га оюн чыгардыaunimeda
Оюн иштеп чыгуу

Kitty Girlfriend: Бишкектеги студия Google Play-га оюн чыгарды

Kitty Girlfriend — Бишкектеги Aunimeda командасы иштеп чыгып, Google Play-га жарыяланган мобилдик оюн. Unity кыймылдаткычы, дизайн жана монетизация жөнүндө айтып беребиз.

Auni Kitchen: Бишкектен тамак-аш темасындагы мобилдик оюнaunimeda
Оюн иштеп чыгуу

Auni Kitchen: Бишкектен тамак-аш темасындагы мобилдик оюн

Auni Kitchen — Aunimeda командасы тарабынан Бишкекте иштелип чыгылган жана Google Play-да жарыяланган казуалдык тамак-аш оюну. Unity, оюн дизайны жана монетизация жөнүндө айтып беребиз.

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

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

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

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

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

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