سیکیورٹی اولین

SQL انجیکشن سے بچاؤ

صارف کی فراہم کردہ ویلیوز کبھی SQL ٹیکسٹ میں انٹرپولیٹ نہیں کی جاتیں — ویلیوز پیرامیٹر پلیس ہولڈرز کے ذریعے بائنڈ کی جاتی ہیں (ڈائلیکٹ کے لحاظ سے، مثلاً $1 یا ?)

پیرامیٹر بائنڈڈ
100%
صارف کی تمام فراہم کردہ ویلیوز پلیس ہولڈرز استعمال کرتی ہیں
ویلیو انٹرپولیشن
صفر
صارف کا ڈیٹا کبھی SQL ٹیکسٹ میں ظاہر نہیں ہوتا
ترتیب کا تحفظ
یقینی
پلیس ہولڈرز پیرامیٹرز سے 1:1 میپ ہوتے ہیں
سیکیورٹی ٹیسٹ
موجودہ
انجیکشن کی کوششوں کی کوریج

SQL انجیکشن کو سمجھنا

SQL انجیکشن آج بھی ویب ایپلیکیشنز کی سب سے سنگین کمزوریوں میں سے ایک ہے

SQL انجیکشن تب ہوتا ہے جب ناقابلِ اعتماد ڈیٹا کو محفوظ پیرامیٹر بائنڈنگ کے بغیر SQL ٹیکسٹ میں شامل کیا جائے۔ حملہ آور کوئری کا مطلب بدل کر غیر مجاز ڈیٹا تک رسائی حاصل کر سکتے ہیں، ریکارڈز میں ترمیم کر سکتے ہیں، یا غیر ارادی آپریشنز چلا سکتے ہیں۔

حملوں کے عام پیٹرنز

تصدیق کو بائی پاس کرنا

admin' OR '1'='1

WHERE شرط کو ہمیشہ درست بنا کر لاگ اِن بائی پاس کرنے کی کوشش

ڈیٹا کی چوری

' UNION SELECT password FROM users--

دوسرے ٹیبلز سے ڈیٹا نکالنے کی کوشش کے لیے UNION کا استعمال

تباہ کن کمانڈز

'; DROP TABLE users; --

ڈیٹا حذف کرنے کے لیے اضافی اسٹیٹمنٹس جوڑنے کی کوشش

پیرامیٹر ترتیب کے بگ کا غلط استعمال

استحصال: اگر پلیس ہولڈرز اور پیرامیٹرز میں مطابقت نہ ہو تو اجازت کی جانچ غلط ویلیوز استعمال کر سکتی ہے

مثال: WHERE userId=$1 AND isAdmin=$2، لیکن [123, true] کی بجائے params=[true, 123] غلطی سے ایڈمن رسائی دے سکتا ہے

کثیر سطحی تحفظ کی حکمتِ عملی

ہر کوئری کئی سیکیورٹی توثیقی لیئرز سے گزرتی ہے

  1. لیئر 1: خودکار پیرامیٹر بائنڈنگ

    صارف کی تمام فراہم کردہ ویلیوز بائنڈڈ پیرامیٹرز میں تبدیل کی جاتی ہیں۔ ویلیوز لٹرلز کے طور پر SQL ٹیکسٹ میں داخل نہیں ہوتیں۔

    • صارف کی ویلیوز ڈائلیکٹ کے مخصوص پلیس ہولڈرز (مثلاً $1 یا ?) سے ظاہر کی جاتی ہیں
    • ارے ان پٹس پیرامیٹرائزڈ ہوتے ہیں (ڈائلیکٹ/حکمتِ عملی کے مطابق پھیلائے گئے پلیس ہولڈرز یا ارے پیرامیٹرز)
    • NULL اور اختیاری ویلیوز کو صارف کا ان پٹ SQL ٹیکسٹ میں جوڑے بغیر ہینڈل کیا جاتا ہے
    • تاریخ/وقت کی ویلیوز پیرامیٹرائزڈ ہوتی ہیں
    • JSON ویلیوز پیرامیٹرائزڈ ہوتی ہیں
  2. لیئر 2: فیلڈ نام کی توثیق

    کوئری تیار ہونے سے پہلے ہر فیلڈ نام کی Prisma اسکیما میٹا ڈیٹا کے مقابل توثیق کی جاتی ہے۔

    • صرف اسکیما میں متعین فیلڈز کی اجازت ہے
    • ریلیشن فلٹرز کی توثیق اسکیما میٹا ڈیٹا کے ذریعے ہوتی ہے
    • کوئی من مانا فیلڈ نام قبول نہیں کیا جاتا
    • جہاں لاگو ہو، غیر معاون/کمپیوٹڈ فیلڈز مسترد کیے جاتے ہیں
    • پروٹوٹائپ پولوشن پے لوڈز مسترد کیے جاتے ہیں (مثلاً __proto__, constructor)
  3. لیئر 3: آئیڈینٹیفائر سینیٹائزیشن

    ٹیبل نام، کالم نام اور ایلیاسز کی توثیق کی جاتی ہے اور ضرورت کے مطابق انہیں محفوظ طریقے سے کوٹ/ایسکیپ کیا جاتا ہے۔

    • کنٹرول کریکٹرز مسترد کیے جاتے ہیں
    • ضرورت پڑنے پر مخصوص کلیدی الفاظ (reserved keywords) کوٹ کیے جاتے ہیں
    • جہاں کنفیگر ہو، اسکیما کوالیفیکیشن سپورٹ ہوتی ہے
    • آئیڈینٹیفائرز کے لیے ڈبل کوٹ ایسکیپنگ (یا ڈائلیکٹ کا مساوی طریقہ)
    • ہر ڈائلیکٹ کے مطابق آئیڈینٹیفائر کی زیادہ سے زیادہ لمبائی نافذ کی جاتی ہے
  4. لیئر 4: آپریٹر کی توثیق

    ہر فیلڈ ٹائپ کے لیے صرف معلوم اور محفوظ آپریٹرز کی اجازت ہے۔

    • اسٹرنگ آپریٹرز: contains, startsWith, endsWith
    • عددی آپریٹرز: lt, lte, gt, gte
    • ارے آپریٹرز: in, notIn، ٹائپ کی توثیق کے ساتھ
    • منطقی آپریٹرز: AND, OR, NOT کی ساختی توثیق
    • نامعلوم آپریٹرز فوراً مسترد کیے جاتے ہیں
  5. لیئر 5: پیرامیٹر ترتیب کی ضمانت

    سخت ترتیب یقینی بناتی ہے کہ ہر پلیس ہولڈر اندراج کی ترتیب میں بالکل ایک پیرامیٹر سے میپ ہو، جس سے عدم مطابقت نہیں ہوتی۔

    • ترتیب وار کاؤنٹر ترتیب بدلنے سے روکتا ہے
    • SQL کی تیاری اور پیرامیٹر ارے کی تعمیر ساتھ ساتھ (lockstep) ہوتی ہے
    • کوئی درمیانی بفر یا ترتیب بدلنے والے آپریشنز نہیں
    • ٹیسٹ سے تصدیق: تیار کردہ SQL اور پیرامیٹرز ہمیشہ ہم آہنگ رہتے ہیں
    • یک بہ یک مطابقت: پلیس ہولڈر N → params[N-1] (یا ڈائلیکٹ کے لیے مساوی میپنگ)

باضابطہ سیکیورٹی ضمانتیں

بیان کردہ ڈیزائن مفروضات (پیرامیٹر بائنڈنگ، خام SQL سے کوئی بائی پاس نہیں، ڈرائیور کا درست استعمال) کے تحت انجیکشن مزاحمت کے ثبوت کے خاکے

تھیورم 1: ویلیو کی علیحدگی

صارف کی فراہم کردہ تمام ویلیوز V کے لیے، ایسا کوئی ایگزیکیوشن پاتھ موجود نہیں جہاں V تیار کردہ کوئری اسٹرنگ میں SQL ٹیکسٹ کے طور پر ظاہر ہو۔

ساخت کے لحاظ سے، صارف کی ویلیوز ہینڈل کرنے والے تمام کوڈ پاتھس addParameter(value) کال کرتے ہیں، جو: 1. ویلیو کو ایک الگ params ارے میں محفوظ کرتا ہے 2. SQL ٹیکسٹ کے لیے ایک پلیس ہولڈر ٹوکن واپس کرتا ہے 3. SQL اسٹرنگ میں صرف پلیس ہولڈر ٹوکن جوڑا جاتا ہے 4. ڈیٹابیس ڈرائیور SQL ٹیکسٹ اور پیرامیٹر ویلیوز الگ الگ وصول کرتا ہے ∴ صارف کی ویلیوز SQL سنٹیکس کے طور پر پارس نہیں ہوتیں

const addParameter = (params: any[], value: any) => {
  params.push(value)
  const index = params.length
  return `$${index}`
}

تھیورم 2: فیلڈ ناموں کی بندش

کسی بھی تیار کردہ کوئری میں فیلڈ ناموں کا سیٹ F، اسکیما میں متعین فیلڈز S کا ذیلی سیٹ ہے، یعنی F ⊆ S۔

ہر فیلڈ ریفرنس کے لیے: 1. کوئری آبجیکٹ سے فیلڈ نام نکالا جاتا ہے 2. اسکیما میٹا ڈیٹا میں تلاش کی جاتی ہے 3. اگر فیلڈ اسکیما میں موجود نہ ہو تو ایرر پھینکا جاتا ہے 4. صرف توثیق شدہ فیلڈز SQL کی تیاری تک پہنچتے ہیں ∴ من مانے فیلڈ نام SQL میں ظاہر نہیں ہو سکتے

const validateField = (field: string, model: Model) => {
  if (!model.fields.has(field)) {
    throw new Error(`Field ${field} does not exist`)
  }
  return model.fields.get(field)
}

تھیورم 3: آپریٹر کی حفاظت

فیلڈ F پر لاگو کسی بھی آپریٹر O کے لیے، O فیلڈ F کی ٹائپ T کے لیے اجازت یافتہ آپریٹرز میں شامل ہے۔

آپریٹر کی توثیق کا الگورتھم: 1. اسکیما سے فیلڈ ٹائپ T نکالیں 2. allowed_ops(T) = { ٹائپ T کے درست آپریٹرز } متعین کریں 3. کوئری میں آپریٹر O کے لیے: - اگر O ∉ allowed_ops(T)، تو ایرر پھینکیں - ورنہ پیرامیٹر بائنڈنگ کے ساتھ آپریٹر لاگو کریں ∴ صرف ٹائپ کے مطابق آپریٹرز استعمال ہو سکتے ہیں

const ALLOWED_OPS: Record<string, string[]> = {
  String: ['contains', 'startsWith', 'endsWith'],
  Int: ['lt', 'lte', 'gt', 'gte']
}
if (!ALLOWED_OPS[fieldType]?.includes(operator)) {
  throw new Error('Invalid operator')
}

تھیورم 4: آئیڈینٹیفائر کی حفاظت

تمام SQL آئیڈینٹیفائرز I کی توثیق کی جاتی ہے تاکہ کنٹرول کریکٹرز روکے جائیں اور ہر ڈائلیکٹ کے مطابق محفوظ کوٹنگ/ایسکیپنگ یقینی ہو۔

آئیڈینٹیفائر پروسیسنگ: 1. کنٹرول کریکٹرز ہوں تو مسترد کریں 2. اندرونی کوٹ کریکٹرز کو ڈائلیکٹ کے اصولوں کے مطابق ایسکیپ کریں 3. ضرورت ہو تو آئیڈینٹیفائرز کو کوٹ کریں (مخصوص کلیدی الفاظ یا خاص کریکٹرز) 4. ہر ڈائلیکٹ کی آئیڈینٹیفائر لمبائی کی حد نافذ کریں ∴ آئیڈینٹیفائرز SQL سنٹیکس نہیں توڑ سکتے اور نہ ہی انجیکٹ شدہ ٹوکنز شامل کر سکتے ہیں

const quoteIdentifier = (id: string) => {
  if (/[\x00-\x1F]/.test(id)) {
    throw new Error('Invalid characters')
  }
  const escaped = id.replace(/"/g, '""')
  const needsQuoting = /[^a-z0-9_]/i.test(id) || isReservedKeyword(id)
  return needsQuoting ? `"${escaped}"` : id
}

تھیورم 5: پیرامیٹر ترتیب کی یکسانیت

SQL ٹیکسٹ میں شامل ہر پلیس ہولڈر پوزیشن N کے لیے، params[N-1] میں بالکل وہی ویلیو ہوتی ہے جو اس پوزیشن کے لیے مقصود ہے، بغیر کسی ترتیب کی تبدیلی یا عدم مطابقت کے۔

پیرامیٹر ترتیب کی ضمانت: 1. ایک ہی ٹریکر اندراج کی ترتیب برقرار رکھتا ہے 2. ہر add() کال ویلیو کو params میں جوڑتی ہے اور فوراً اگلا پلیس ہولڈر ٹوکن جاری کرتی ہے 3. SQL ٹیکسٹ اور params کی تعمیر ساتھ ساتھ (lockstep) ہوتی ہے 4. کوئی درمیانی ترتیب بدلنے والا آپریشن نہیں ہوتا ∴ پورے عمل میں یک بہ یک مطابقت برقرار رہتی ہے

class ParameterTracker {
  private params: any[] = []

  add(value: any): string {
    this.params.push(value)
    return `$${this.params.length}`
  }

  getParams(): any[] {
    return this.params
  }
}

const tracker = new ParameterTracker()
const sql = `WHERE email = ${tracker.add(email)} AND age > ${tracker.add(age)}`
const params = tracker.getParams()

جامع سیکیورٹی ٹیسٹ کوریج

موجودہ سوٹ SQL انجیکشن کے عام طریقوں اور ایج کیسز کے خلاف تحفظ کی توثیق کرتا ہے

ویلیو پیرامیٹرائزیشن (basic.test.ts)

  • کوٹس والی اسٹرنگز: user'with'quotes
  • سیمی کالن والی اسٹرنگز: user;extra
  • SQL کلیدی الفاظ بطور ویلیو: DROP TABLE users
  • پیچیدہ انجیکشن: '; DROP TABLE users; --
  • Union حملے: ' UNION SELECT * FROM users--
  • Boolean حملے: admin' OR '1'='1
  • کمنٹ انجیکشن: test@example.com' -- comment

فیلڈ نام کی توثیق (identifiers.test.ts)

  • SELECT میں نقصان دہ فیلڈ نام مسترد کریں
  • WHERE میں نقصان دہ فیلڈ نام مسترد کریں
  • ORDER BY میں نقصان دہ فیلڈ نام مسترد کریں
  • فیلڈ ناموں میں SQL انجیکشن مسترد کریں
  • غیر موجود فیلڈز مسترد کریں
  • پروٹوٹائپ پولوشن مسترد کریں: __proto__, constructor

LIKE پیٹرن کی حفاظت (like-patterns.test.ts)

  • وائلڈ کارڈ انجیکشن: %' OR '1'='1
  • انڈر اسکور انجیکشن: test_' OR '1'='1
  • بیک سلیش ہینڈلنگ: test\\'; DROP--
  • متعدد وائلڈ کارڈز: %_%'; DROP--
  • کیس اِن سینسیٹو انجیکشن: '; UNION SELECT--

ارے آپریٹر کی حفاظت (array-operators.test.ts)

  • نقصان دہ اریز کے ساتھ IN: ['; DROP--', 'UNION SELECT--']
  • انجیکشن کے ساتھ NOT IN: ['; TRUNCATE--', 'DELETE FROM--']
  • خالی ارے کی ہینڈلنگ
  • بڑی ارے کی توثیق (100+ آئٹمز)
  • مخلوط ٹائپ ارے کی ہینڈلنگ

ایج کیسز (edge-cases.test.ts)

  • یونیکوڈ انجیکشن: \u0027 OR \u00271\u0027=\u00271
  • ہیکس انکوڈڈ انجیکشن: 0x31=0x31--
  • URL انکوڈڈ: %27%3B%20DROP%20TABLE
  • اسٹیکڈ کوئریز: '; DROP TABLE users; SELECT
  • ٹائم بیسڈ بلائنڈ (ڈائلیکٹ کے لحاظ سے): WAITFOR DELAY '00:00:05'--
  • UNION پر مبنی: UNION ALL SELECT null, password
  • سیکنڈ آرڈر انجیکشن کی کوششیں

پیرامیٹر ترتیب کی تصدیق (basic.test.ts)

  • ترتیب وار پلیس ہولڈر پوزیشنز
  • پیرامیٹر ارے پلیس ہولڈر کی ترتیب سے میل کھاتی ہے
  • پیچیدہ کوئریز تمام شرائط میں ترتیب برقرار رکھتی ہیں
  • نیسٹڈ OR/AND شرائط پیرامیٹر کی ترتیب محفوظ رکھتی ہیں
  • ریلیشن فلٹرز درست پیرامیٹر میپنگ برقرار رکھتے ہیں

محفوظ بمقابلہ غیر محفوظ: کوڈ کا موازنہ

❌ غیر محفوظ: اسٹرنگز جوڑنا
unsafe.ts
const email = req.body.email
const sql = "SELECT * FROM users WHERE email = '" + email + "'"
✅ محفوظ: خودکار پیرامیٹر بائنڈنگ
safe.ts
const email = req.body.email
const { sql, params } = toSQL('User', 'findMany', {
  where: { email }
})

const result = { sql, params }

عمل درآمد کی تفصیلات

پیرامیٹر مینجمنٹ

مرکزی پیرامیٹر ٹریکنگ یقینی بناتی ہے کہ صارف کی ہر فراہم کردہ ویلیو پیرامیٹر بائنڈڈ ہو اور اس کی ترتیب مستحکم رہے

class ParameterTracker {
  private params: any[] = []

  add(value: any): string {
    this.params.push(value)
    return `$${this.params.length}`
  }

  getParams(): any[] {
    return this.params
  }
}

فیلڈ کی توثیق

اسکیما پر مبنی توثیق من مانی فیلڈ رسائی کو روکتی ہے

function validateField(
  fieldName: string,
  model: ModelInfo
): FieldInfo {
  const field = model.fields.get(fieldName)
  if (!field) {
    throw new Error(
      `Field "${fieldName}" does not exist`
    )
  }
  return field
}

آئیڈینٹیفائر کوٹنگ

ڈائلیکٹ سے آگاہ آئیڈینٹیفائر توثیق اور کوٹنگ آئیڈینٹیفائر پر مبنی سنٹیکس انجیکشن کو روکتی ہے

function quoteIdentifier(identifier: string): string {
  if (/[\x00-\x1F]/.test(identifier)) {
    throw new Error('Invalid control characters')
  }

  const escaped = identifier.replace(/"/g, '""')
  const needsQuoting = /[^a-z0-9_]/i.test(identifier) || isReservedKeyword(identifier)

  if (needsQuoting) {
    return `"${escaped}"`
  }

  return identifier
}

سیکیورٹی کے بہترین طریقے

توثیق کبھی غیر فعال نہ کریں

اسکیما کی توثیق یا فیلڈ کی جانچ کو بائی پاس نہ کریں۔ یہ اہم سیکیورٹی لیئرز ہیں۔

کریں
لائبریری کو مکمل توثیق کے ساتھ اسی طرح استعمال کریں جیسے اسے ڈیزائن کیا گیا ہے
نہ کریں
اسکیما کی توثیق بائی پاس کرنا یا کوئری ٹیکسٹ میں خام SQL انجیکٹ کرنا

اسکیما اپ ڈیٹ رکھیں

یقینی بنائیں کہ آپ کا Prisma اسکیما آپ کے ڈیٹابیس کی ساخت کی درست عکاسی کرتا ہے۔

کریں
اسکیما میں تبدیلی کے بعد prisma db pull اور prisma generate چلائیں
نہ کریں
پرانی DMMF یا اسکیما تعریفیں استعمال کرنا

ان پٹ ٹائپس کی توثیق کریں

TypeScript کمپائل ٹائم سیفٹی دیتا ہے، لیکن رن ٹائم توثیق دفاع کی ایک اور تہہ شامل کرتی ہے۔

کریں
کوئری آرگیومنٹس کے لیے Prisma کی تیار کردہ ٹائپس استعمال کریں
نہ کریں
کوئریز کو دینے سے پہلے صارف کے ان پٹ کو any میں کاسٹ کرنا

کوئری پیٹرنز کی نگرانی کریں

بے ضابطگیوں اور غلط استعمال کا پتا لگانے کے لیے پروڈکشن میں تیار کردہ SQL اور پیرامیٹرز کو لاگ کریں اور ان کی نگرانی کریں۔

کریں
کوئری لاگنگ فعال کریں اور پیٹرنز کا جائزہ لیں
نہ کریں
نگرانی کے بغیر پروڈکشن میں چلانا

ڈیزائن کے ذریعے سیکیورٹی

SQL انجیکشن سے تحفظ اس لائبریری کی ہر لیئر میں شامل ہے۔ سیکیورٹی ٹیسٹس اور عمل درآمد کی تفصیلات کا براہِ راست جائزہ لیں۔