OWASP API सुरक्षा के शीर्ष 10 जोखिमों का शमन
टूटी हुई प्रमाणीकरण व्यवस्था, BOLA और मास असाइनमेंट जैसे सामान्य API खतरों को ठोस FastAPI सुरक्षा उपायों से संबद्ध कीजिए।
OWASP API सुरक्षा के शीर्ष 10 जोखिमों का शमन, CoddyKit पर FastAPI बैकएंड डेवलपमेंट बूटकैंप का एक निःशुल्क पाठ है। यह 4 में से 1वाँ पाठ है। इस अध्ययन पथ के 3 तक कोई भी पाठ पूरा पढ़ना निःशुल्क है — इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ व्यावहारिक अभ्यास भी उपलब्ध कराता है। यह FastAPI बैकएंड डेवलपमेंट बूटकैंप सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। FastAPI बैकएंड डेवलपमेंट बूटकैंप पाठ्यक्रम में कुल 4 पाठ शामिल हैं।
OWASP API Security Top 10 क्यों महत्वपूर्ण है
OWASP API Security Top 10 आधुनिक API के सामने मौजूद सबसे गंभीर सुरक्षा जोखिमों की चुनी हुई सूची है। वेब ऐप्स के लिए बने पारंपरिक OWASP Top 10 से अलग, यह सूची विशेष रूप से API के आक्रमण-क्षेत्रों पर केंद्रित है — जिनमें प्रमाणीकरण का दुरुपयोग, अत्यधिक डेटा उजागर होना और सामूहिक असाइनमेंट की कमज़ोरियाँ शामिल हैं।
FastAPI एक शक्तिशाली रूपरेखा है, लेकिन यह आपके API को डिफ़ॉल्ट रूप से सुरक्षित नहीं बनाती। आपको हर परत पर जानबूझकर सुरक्षा उपाय लागू करने होंगे: रूटिंग, सत्यापन, प्रमाणीकरण और क्रमांकन।
इस पाठ में हम तीन उच्च-प्रभाव वाली श्रेणियों पर ध्यान देंगे:
- API1 — टूटा हुआ ऑब्जेक्ट-स्तरीय प्राधिकरण (BOLA)
- API2 — टूटा हुआ प्रमाणीकरण
- API6 — सामूहिक असाइनमेंट
प्रत्येक की आक्रमण-विधि अलग है और उसके लिए FastAPI में एक ठोस शमन उपाय है, जिसे आप आज लागू कर सकते हैं।
टूटा हुआ प्रमाणीकरण: आक्रमण-क्षेत्र
टूटा हुआ प्रमाणीकरण (API2) तब होता है जब API यह ठीक से सत्यापित नहीं कर पाता कि कॉल करने वाला वही व्यक्ति है होने का दावा कर रहा है। आम विफलताओं में ये शामिल हैं:
- हस्ताक्षर सत्यापन के बिना समाप्त या छेड़छाड़ किए गए JWT स्वीकार करना
- टोकन पर हस्ताक्षर करने के लिए कमज़ोर या अनुमान लगाने योग्य गुप्त मानों का उपयोग करना
- टोकन की समय-सीमा लागू न करना (
expदावा) - असीमित लॉगिन प्रयासों की अनुमति देना (अनुरोध दर की कोई सीमा नहीं)
FastAPI में सबसे विश्वसनीय तरीका है कि प्रत्येक सुरक्षित रूट पर python-jose या PyJWT जैसी लाइब्रेरी से JWT का सत्यापन किया जाए — और Depends() के माध्यम से डाली गई निर्भरता का उपयोग किया जाए।
निर्भरता वाला तरीका प्रमाणीकरण तर्क को एक जगह केंद्रित करता है, इसलिए नए रूट पर इसे गलती से छोड़ देने की संभावना नहीं रहती।
JWT प्रमाणीकरण निर्भरता लागू करना
नीचे FastAPI के लिए उत्पादन-शैली की JWT निर्भरता दी गई है। यह टोकन के हस्ताक्षर की पुष्टि करती है, exp दावे की जाँच करती है और किसी भी विफलता पर 401 उत्पन्न करती है। इसे प्रमाणीकरण की आवश्यकता वाले प्रत्येक रूट में डालें।
सुरक्षा मजबूत करने के मुख्य बिंदु:
algorithms=[ALGORITHM]— केवल HS256 (या RS256) को स्पष्ट रूप से अनुमत करें; कभी भीalgorithms=Noneन दें- गुप्त मान पर्यावरण चर से आना चाहिए, उसे कभी हार्ड-कोड न करें
- अनुपस्थित या गलत स्वरूप वाले
subदावे को अमान्य टोकन माना जाता है
import os
from datetime import datetime, timezone
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt
SECRET_KEY = os.environ["JWT_SECRET_KEY"] # never hardcode
ALGORITHM = "HS256"
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/token")
def get_current_user_id(token: str = Depends(oauth2_scheme)) -> int:
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
user_id: str = payload.get("sub")
if user_id is None:
raise credentials_exception
return int(user_id)
except JWTError:
raise credentials_exceptionBOLA: टूटा हुआ ऑब्जेक्ट-स्तरीय प्राधिकरण
BOLA (API1) दुनिया भर में API की सबसे बड़ी कमज़ोरी है। यह तब होता है जब कोई कॉल करने वाला केवल उसकी ID का अनुमान लगाकर किसी भी ऑब्जेक्ट तक पहुँच सकता है — क्योंकि सर्वर स्वामित्व की जाँच ही नहीं करता।
एक पारंपरिक असुरक्षित तरीका:
GET /orders/9871यदि सर्वर केवल order_id के आधार पर ऑर्डर लाता है और उसे लौटा देता है, तो कोई भी प्रमाणित उपयोगकर्ता केवल ID बढ़ाकर डेटाबेस का कोई भी ऑर्डर पढ़ सकता है।
समाधान हमेशा एक ही है: संसाधन लाने के बाद संसाधन के स्वामी की तुलना प्रमाणित कॉल करने वाले से करें। यदि दोनों मेल नहीं खाते, तो 403 Forbidden लौटाएँ — 404 नहीं, क्योंकि कुछ संदर्भों में उससे संसाधन के अस्तित्व की जानकारी उजागर हो सकती है।
FastAPI रूट में BOLA ठीक करना
तरीका यह है: ऑब्जेक्ट लाएँ और फिर स्वामित्व की पुष्टि करें। स्वामित्व की जाँच कभी न छोड़ें, यह सोचकर कि ID का अनुमान लगाना कठिन है — UUID सुरक्षा नियंत्रण नहीं हैं।
ध्यान दें कि पिछले दृश्य का get_current_user_id Depends() के माध्यम से डाला गया है। स्वामित्व की पुष्टि एक ही if कथन है, लेकिन फ़ंक्शन की यह सबसे महत्वपूर्ण पंक्ति है।
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from app.auth import get_current_user_id
from app.db import get_db
from app.models import Order
router = APIRouter()
@router.get("/orders/{order_id}")
async def get_order(
order_id: int,
current_user_id: int = Depends(get_current_user_id),
db: AsyncSession = Depends(get_db),
):
order = await db.get(Order, order_id)
if order is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Order not found")
# BOLA fix: verify the caller owns this resource
if order.user_id != current_user_id:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Access denied")
return orderपुनः उपयोग योग्य BOLA सुरक्षा लिखना
जब आपके API में दर्जनों संसाधन रूट हों, तो स्वामित्व की जाँच को हर जगह सीधे दोहराना त्रुटि-प्रवण होता है। इसे ऐसे पुनः उपयोग योग्य सहायक में निकालें, जो अपने-आप अपवाद उत्पन्न करे। इससे नए रूट पर जाँच भूल जाने की संभावना कम हो जाती है।
यह सहायक इतना सामान्य है कि user_id विशेषता वाले किसी भी SQLAlchemy मॉडल के साथ काम कर सकता है। अधिक जटिल स्वामित्व नियमों (जैसे टीम-आधारित पहुँच) के लिए इस फ़ंक्शन में भूमिका/अनुमति वाली क्वेरी जोड़ें।
from fastapi import HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
async def get_owned_resource(model_class, resource_id: int, user_id: int, db: AsyncSession):
"""
Fetch a resource and assert ownership in one call.
Raises 404 if not found, 403 if the caller does not own it.
"""
resource = await db.get(model_class, resource_id)
if resource is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"{model_class.__name__} not found",
)
if resource.user_id != user_id:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="You do not have permission to access this resource",
)
return resourceसामूहिक असाइनमेंट: आक्रमण
Mass Assignment (API6) तब होता है जब कोई API अनुरोध बॉडी के फ़ील्ड को बिना जाँच के डेटाबेस मॉडल पर मैप कर देती है और हमलावर उन फ़ील्ड को भी सेट कर पाता है जिन्हें उपयोगकर्ता द्वारा नियंत्रित किया जाना कभी अपेक्षित नहीं था।
पारंपरिक उदाहरण: कोई उपयोगकर्ता अपनी प्रोफ़ाइल अपडेट करते समय JSON बॉडी में "is_admin": true या "balance": 99999 शामिल कर देता है। यदि सर्वर बिना फ़िल्टर किए user.__dict__.update(request_data) चलाता है, तो ये फ़ील्ड डेटाबेस में लिख दिए जाते हैं।
FastAPI में Pydantic इनपुट स्कीमा आपकी प्राथमिक सुरक्षा हैं। ये एक स्पष्ट अनुमति-सूची की तरह काम करते हैं: क्लाइंट से केवल वही फ़ील्ड स्वीकार किए जा सकते हैं जो स्कीमा में घोषित हों। किसी भी अतिरिक्त फ़ील्ड को चुपचाप अनदेखा कर दिया जाता है या कॉन्फ़िगरेशन के अनुसार अस्वीकार कर दिया जाता है।
इनपुट और आउटपुट स्कीमा को अलग रखना
Mass Assignment को रोकने का सबसे महत्वपूर्ण पैटर्न इनपुट और आउटपुट के लिए अलग-अलग Pydantic मॉडल का उपयोग करना है:
- इनपुट स्कीमा — केवल वे फ़ील्ड जिन्हें उपयोगकर्ता सेट कर सकता है
- आउटपुट स्कीमा — कॉल करने वाले को लौटाने के लिए सुरक्षित सभी फ़ील्ड
- DB मॉडल — संवेदनशील फ़ील्ड सहित पूरा रिकॉर्ड, जैसे
is_admin,hashed_passwordआदि
यदि इनपुट और आउटपुट की सुरक्षा आवश्यकताएँ अलग हों, तो दोनों के लिए कभी भी एक ही स्कीमा का उपयोग न करें।
from pydantic import BaseModel, EmailStr
from typing import Optional
# What the client is ALLOWED to send when updating a profile
class UserUpdateInput(BaseModel):
display_name: Optional[str] = None
bio: Optional[str] = None
email: Optional[EmailStr] = None
# NOTE: is_admin, balance, role, hashed_password are NOT here
# What we return to the client (read-only fields visible but not settable)
class UserPublicOutput(BaseModel):
id: int
display_name: str
email: EmailStr
is_admin: bool
model_config = {"from_attributes": True}अपडेट रूट में इनपुट स्कीमा लागू करना
अलग स्कीमा तैयार होने के बाद, अपडेट रूट model_dump(exclude_unset=True) का उपयोग करके केवल वे फ़ील्ड प्राप्त करता है जिन्हें क्लाइंट ने वास्तव में भेजा है। फिर इन्हें डेटाबेस मॉडल पर एक-एक करके लागू किया जाता है — कभी भी सामूहिक __dict__ अपडेट के ज़रिए नहीं।
exclude_unset=True PATCH के अर्थ के लिए अत्यंत महत्वपूर्ण है: यह सुनिश्चित करता है कि किसी फ़ील्ड का न होना "इसे न बदलें" माना जाए, न कि "इसे null पर सेट करें"।
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from app.auth import get_current_user_id
from app.db import get_db
from app.models import User
from app.schemas import UserUpdateInput, UserPublicOutput
router = APIRouter()
@router.patch("/users/me", response_model=UserPublicOutput)
async def update_profile(
payload: UserUpdateInput,
current_user_id: int = Depends(get_current_user_id),
db: AsyncSession = Depends(get_db),
):
user = await db.get(User, current_user_id)
if user is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
# Only apply fields the client actually provided
update_data = payload.model_dump(exclude_unset=True)
for field, value in update_data.items():
setattr(user, field, value)
await db.commit()
await db.refresh(user)
return userअतिरिक्त फ़ील्ड को अस्वीकार करना लागू करना
डिफ़ॉल्ट रूप से, Pydantic v2 अज्ञात फ़ील्ड को चुपचाप अनदेखा कर देता है। सुरक्षा-संवेदनशील स्कीमा के लिए आप मॉडल को इस तरह कॉन्फ़िगर कर सकते हैं कि कोई अप्रत्याशित फ़ील्ड भेजे जाने पर वह सत्यापन त्रुटि उत्पन्न करे। इससे Mass Assignment के प्रयास लॉग में दिखाई देते हैं और टाइपिंग की गलतियों से होने वाली चुपचाप डेटा-हानि रुकती है।
अपने इनपुट स्कीमा पर model_config = ConfigDict(extra='forbid') सेट करें। यदि क्लाइंट स्कीमा में घोषित न किया गया कोई फ़ील्ड भेजता है, तो आपका API 422 Unprocessable Entity लौटाएगा।
from pydantic import BaseModel, EmailStr, ConfigDict
from typing import Optional
class StrictUserUpdateInput(BaseModel):
model_config = ConfigDict(extra="forbid") # reject unknown fields
display_name: Optional[str] = None
bio: Optional[str] = None
email: Optional[EmailStr] = None
# Demonstration (runs standalone)
if __name__ == "__main__":
import json
from pydantic import ValidationError
# Valid input
valid = StrictUserUpdateInput(display_name="Alice")
print("Valid:", valid.model_dump(exclude_unset=True))
# Attacker tries to escalate privileges
try:
evil = StrictUserUpdateInput(display_name="Alice", is_admin=True)
except ValidationError as e:
errors = json.loads(e.json())
print("Blocked:", errors[0]["type"], "-", errors[0]["loc"])एक ही प्रवाह में तीनों सुरक्षा उपायों को जोड़ना
तीनों सुरक्षा उपाय परतों की तरह मिलकर काम करते हैं। किसी एक दस्तावेज़-अपडेट एंडपॉइंट में उनका संयोजन इस प्रकार होता है:
- Auth dependency — JWT का सत्यापन करती है और
current_user_idनिकालती है (Broken Authentication को रोकती है) - BOLA जाँच — दस्तावेज़ प्राप्त करती है और
doc.owner_id == current_user_idसुनिश्चित करती है (BOLA को रोकती है) extra='forbid'वाला इनपुट स्कीमा — केवलtitleऔरcontentसेट करने की अनुमति देता है (Mass Assignment को रोकता है)
हर परत स्वतंत्र है। इनमें से कोई एक हटाने पर बाकी दो आंशिक सुरक्षा देती रहेंगी — लेकिन पूरी सुरक्षा के लिए तीनों आवश्यक हैं।
from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel, ConfigDict
from typing import Optional
from sqlalchemy.ext.asyncio import AsyncSession
from app.auth import get_current_user_id
from app.db import get_db
from app.models import Document
router = APIRouter()
class DocumentUpdateInput(BaseModel):
model_config = ConfigDict(extra="forbid")
title: Optional[str] = None
content: Optional[str] = None
@router.patch("/documents/{doc_id}")
async def update_document(
doc_id: int,
payload: DocumentUpdateInput, # Layer 3: mass assignment guard
current_user_id: int = Depends(get_current_user_id), # Layer 1: auth
db: AsyncSession = Depends(get_db),
):
doc = await db.get(Document, doc_id)
if doc is None:
raise HTTPException(status_code=404, detail="Document not found")
if doc.owner_id != current_user_id: # Layer 2: BOLA guard
raise HTTPException(status_code=403, detail="Access denied")
for field, value in payload.model_dump(exclude_unset=True).items():
setattr(doc, field, value)
await db.commit()
await db.refresh(doc)
return docज्ञान-जाँच: BOLA को रोकना
एक FastAPI एंडपॉइंट किसी इनवॉइस को उसकी ID से प्राप्त करके कॉल करने वाले को लौटाता है। एंडपॉइंट पहले से ही एक मान्य JWT आवश्यक करता है। BOLA (Broken Object Level Authorization) हमले को रोकने के लिए कौन-सा अतिरिक्त कदम आवश्यक है?
पाठ का पुनरावलोकन: तीन सुरक्षा उपाय, एक सुरक्षित API
इस पाठ में आपने OWASP API Security Top 10 के तीन खतरों को ठोस FastAPI सुरक्षा उपायों से जोड़ा:
- Broken Authentication (API2) — JWT सत्यापन को
Depends()dependency में केंद्रीकृत करें; हस्ताक्षर करने वाले एल्गोरिदम की अनुमति-सूची बनाएँ; secrets को environment variables से लोड करें। - BOLA (API1) — किसी भी resource को प्राप्त करने के बाद हमेशा
resource.owner_id == current_user_idसुनिश्चित करें। असंगति होने पर403लौटाएँ। जाँच को दोबारा उपयोग किए जा सकने वाले helper में निकालें ताकि यह छूट न जाए। - Mass Assignment (API6) — अलग-अलग इनपुट और आउटपुट Pydantic स्कीमा का उपयोग करें; इनपुट स्कीमा पर
extra='forbid'सेट करें;exclude_unset=Trueके साथ फ़ील्ड-दर-फ़ील्ड अपडेट लागू करें।
ये तीनों पैटर्न स्वतंत्र हैं और एक साथ संयोजित किए जा सकते हैं। FastAPI की dependency injection प्रणाली के माध्यम से इन्हें साथ लागू करने पर, बिज़नेस लॉजिक की एक भी पंक्ति चलने से पहले ही, फ़्रेमवर्क स्तर पर सबसे आम API हमले के रास्ते समाप्त हो जाते हैं।
एआई शिक्षक के साथ FastAPI बैकएंड डेवलपमेंट बूटकैंप सीखें — निःशुल्क
अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।
- पाठ्यक्रम
- 21
- पाठ
- 84
अक्सर पूछे जाने वाले प्रश्न
क्या “OWASP API सुरक्षा के शीर्ष 10 जोखिमों का शमन” पाठ निःशुल्क है?
हाँ — FastAPI बैकएंड डेवलपमेंट बूटकैंप अध्ययन पथ के 3 तक कोई भी पाठ, जिसमें “OWASP API सुरक्षा के शीर्ष 10 जोखिमों का शमन” भी शामिल है, यहाँ वेब पर पूरा पढ़ना निःशुल्क है। इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ इंटरैक्टिव अभ्यास भी उपलब्ध कराता है। FastAPI बैकएंड डेवलपमेंट बूटकैंप पाठ्यक्रम में कुल 4 पाठ शामिल हैं।
“OWASP API सुरक्षा के शीर्ष 10 जोखिमों का शमन” में मैं क्या सीखूँगा?
टूटी हुई प्रमाणीकरण व्यवस्था, BOLA और मास असाइनमेंट जैसे सामान्य API खतरों को ठोस FastAPI सुरक्षा उपायों से संबद्ध कीजिए। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ FastAPI बैकएंड डेवलपमेंट बूटकैंप का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।
क्या FastAPI बैकएंड डेवलपमेंट बूटकैंप शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?
पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर FastAPI बैकएंड डेवलपमेंट बूटकैंप शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 1वाँ पाठ है।
“OWASP API सुरक्षा के शीर्ष 10 जोखिमों का शमन” पाठ पूरा करने में कितना समय लगता है?
CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।
क्या मैं इस FastAPI बैकएंड डेवलपमेंट बूटकैंप पाठ में कोड लिख और चला सकता हूँ?
हाँ। हर FastAPI बैकएंड डेवलपमेंट बूटकैंप पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।
इस पाठ्यक्रम के सभी पाठ
- OWASP API सुरक्षा के शीर्ष 10 जोखिमों का शमन
- दर-सीमांकन और बॉट दुरुपयोग सुरक्षा
- गुप्त जानकारी प्रबंधन और कुंजी रोटेशन
- CORS, CSP और सुरक्षित हेडर नीतियाँ