الـ framework اللي بيوصل ملايين المواقع — وبسبب تعقيده وفلكسيبليتهه، هو أكتر مكان بتلاقي فيه bugs بـ severity عالية. من الصفر للاحتراف.
شاهد شرح الفيديو الكامل لمنهجية الـ OAuth وكيفية اكتشاف الثغرات عملياً.
قبل ما نتكلم عن الـ vulnerabilities، لازم نفهم الـ framework نفسه. ليه اخترع، وإيه المشكلة اللي بيحلها.
تخيل إن إنت عندك صور على Instagram وعايز موقع PrintMyPhotos.com يطبعهالك. قبل OAuth كان الموقع ده هيقولك "إديني الـ username والـ password بتاعك على Instagram، أنا هلوج إن واسحب الصور".
طب تفتكر ده آمن؟ لأ إطلاقاً. الموقع ده هياخد الباسورد بتاعك، يقدر يدخل على كل حاجة في حسابك (مش الصور بس)، ولو الموقع ده اتهك، الباسورد بتاعك راح. وأكتر من كده، عشان توقف الموقع من إنه يدخل، لازم تغير الباسورد — وكل المواقع التانية اللي اديتها نفس الباسورد هتقفل.
دي المشكلة اللي OAuth اخترع عشانها. الفكرة الجوهرية: "اديني الـ access من غير ما تديني الباسورد، واسمحلي بحاجة محددة فقط، وممكن تلغي الـ access في أي وقت".
قبل ما تفهم أي flow، لازم تعرف مين بيتكلم مع مين. الـ 4 أدوار دول هما اللي بيلعبوا في كل سيناريو.
صاحب الـ data — غالباً المستخدم نفسه. هو اللي بيقول "أوافق" أو "أرفض" على الـ access request.
في تعريف RFC: "An entity capable of granting access to a protected resource"
الموقع/التطبيق اللي عايز يدخل على بيانات المستخدم. مش بالضرورة client-side — ممكن يبقى server.
مثال: PrintMyPhotos.com اللي عايز يقرا صور Instagram
السيرفر اللي بيتحقق من المستخدم وبيصدر الـ access tokens. ده اللي بيعمل الـ OAuth flow.
مثال: accounts.google.com عند تسجيل الدخول بـ Google
السيرفر اللي عليه الداتا الفعلية. بياخد التوكن من الـ Client وبيرجع البيانات.
مثال: graph.facebook.com اللي بيرجع بيانات الـ profile
الـ Authorization Server والـ Resource Server ممكن يكونوا نفس الـ entity أو يكونوا منفصلين. ده اللي بيلخبط كتير من الـ researchers في الأول.
مثال على دمجهم: لما تعمل "Login with Google"، جوجل هي الاتنين — هي اللي بتورايز (accounts.google.com) وهي اللي عندها الداتا (googleapis.com). كلهم Google.
مثال على فصلهم: في setup داخلي للشركة، Auth0 ممكن يبقى الـ Authorization Server، والـ Resource Server هي الـ API بتاع الشركة على دومين تاني.
✦ ده الـ flow المجرد. كل grant type بيختلف في تفاصيل الخطوات دي — بس الفكرة الكبيرة دي تماماً.
الـ grant type الأكثر استخداماً والأكثر أماناً. لو فهمته كويس، فهمت 80% من OAuth.
الـ Authorization Code Flow بيستخدم حاجتين منفصلتين: أولاً بياخد code عبر البراوزر، وبعدين بيبدله بـ access token عبر back-channel (سيرفر-لسيرفر) آمن.
الميزة هنا: الـ access token ما بيمرش بالبراوزر أبداً. حتى لو في malicious script في البراوزر، أقصى حاجة يقدر يسرقها هو الـ code، والـ code ده مالوش لازمة من غير الـ client_secret اللي مخزن على السيرفر.
مبسط بس فيه مخاطر كبيرة. OAuth 2.1 شيله أصلاً. لكن لسه موجود في تطبيقات كتير قديمة.
الـ Implicit Flow اخترع علشان الـ Single Page Applications (SPAs) اللي ما عندهاش backend. الفكرة كانت: لو ما عندكش server، ما تقدرش تحفظ client_secret آمن، فمالكش لزمة الـ Code. خد التوكن مباشرة.
المشكلة: الـ access_token بيتبعت في الـ URL fragment عبر البراوزر. ده بيخليه عرضة للسرقة من: browser history، malicious extensions، referrer headers، XSS، logs السيرفر.
في حالة كتيرة، الـ implicit flow بيُستخدم في authentication. الـ client بياخد التوكن، يبعت الـ user ID للسيرفر بتاعه، ويطلب session cookie.
المشكلة: لو السيرفر مش بيتحقق إن الـ user ID ده مرتبط فعلاً بالتوكن، الـ attacker يقدر يبعت user ID حد تاني ويلوج إن باسم الضحية. هنشوف ده بالتفصيل في section الـ Implicit Bypass.
في 4 grant types في OAuth 2.0. شفنا اتنين، تعالى نشوف الباقي بسرعة.
المستخدم بيدي الـ username والـ password مباشرة للـ client. الـ client بيبعتهم للـ auth server وبياخد توكن.
مفيش user أصلاً. الـ client بيستخدم الـ credentials بتاعته هو عشان ياخد توكن. مفيد للـ background services.
| Grant Type | الـ Use Case | أمان | OAuth 2.1 | هل لسه شائع؟ |
|---|---|---|---|---|
| Authorization Code | Web apps with backend (الـ default الحديث) | SECURE | REQUIRED | نعم — أكتر استخداماً |
| Auth Code + PKCE | SPAs و mobile apps (الـ default الجديد) | VERY SECURE | REQUIRED | متزايد بسرعة |
| Implicit | SPAs (قديم) — مش مفروض يستخدم | INSECURE | REMOVED | موجود في legacy apps |
| ROPC (Password) | Migration من legacy (متجنبه) | DANGEROUS | REMOVED | للأسف نعم |
| Client Credentials | Machine-to-machine, no user | SECURE | KEPT | نعم — للـ APIs الداخلية |
| Device Code | Smart TVs, IoT devices | CONDITIONAL | KEPT | متخصص |
| Refresh Token | Renew access tokens (مش grant مستقل) | DEPENDS | KEPT | دايماً موجود |
3 أنواع من الـ tokens بتفهم الـ flow كله. لازم تعرف الفرق بينهم.
الـ token اللي بيستخدم في كل API call. بيشهد إن الـ client مسموحله يدخل على الـ resource.
بياخد access token جديد لما القديم بيخلص. ما بيتبعتش لأي resource server — بس للـ auth server.
مش token حقيقي — هو "ticket" يستخدم مرة واحدة عشان يتبدل بـ access token عبر back-channel.
الـ access token ممكن يبقى نوعين:
JWT (Self-contained): بيحتوي كل المعلومات عن الـ user والـ scope جواه. الـ resource server بيقدر يتحقق منه من غير ما يكلم الـ auth server. سريع، scalable، لكن لو اتسرب صعب نلغيه قبل الـ expiry.
Opaque (Reference): string عشوائي مش بيحمل معلومات. الـ resource server محتاج يكلم الـ auth server (introspection endpoint) عشان يعرف هل التوكن valid. أبطأ، لكن قابل للإلغاء فوراً.
OAuth = authorization. OIDC = layer فوق OAuth علشان تعمل authentication. الفرق ده بيغير كتير.
OAuth 2.0 اخترع للـ authorization — يعني "هل المستخدم سامح للموقع ده يقرا الـ photos بتاعته؟". لكن المطورين بدأوا يستخدموه للـ authentication كمان — يعني "Login with Google".
الفرق دقيق لكن مهم: في الـ authorization، إنت بتتحقق إن في توكن صالح للوصول لـ resource. في الـ authentication، إنت محتاج تثبت هوية المستخدم (مين هو فعلاً).
OAuth ما اتصممش للحاجة دي. كان كل client بيعمل workaround بطريقته. النتيجة: implementations مختلفة، vulnerabilities كتيرة، تجربة مستخدم متفاوتة.
id_token: بيقول للـ client "ده المستخدم اللي اتثبت إنه هو" — عبارة عن JWT بيتحقق منه الـ client نفسه.
access_token: بيقول للـ resource server "صاحب التوكن ده مسموحله بكذا" — يستخدم في الـ API calls.
في 2026، الـ industry تحرك للـ OAuth 2.1 — consolidation لكل best practices في 14 سنة. وPKCE بقت إجبارية.
PKCE = Proof Key for Code Exchange (RFC 7636). فكرتها بسيطة جداً وعبقرية: حتى لو الكود اتسرق في رحلته، مش هيشتغل من غير الـ secret اللي بدأ بيه الـ flow.
الـ flow: قبل ما يبدا الـ Auth Code flow، الـ client بيولد code_verifier عشوائي (43-128 chars). يعمل له SHA256 ويحط النتيجة كـ code_challenge في الـ authorization request. لما يجي يستبدل الكود بتوكن، يبعت الـ code_verifier الأصلي. الـ auth server بيعمل SHA256 ويتأكد إنه يساوي الـ challenge اللي اتبعت أولاً.
OAuth 2.1 خلى PKCE إجبارية لكل الـ clients — public أو confidential. ده بيغطي على الـ implicit flow اللي اتشال أصلاً.
عشان تختبر OAuth implementation بشكل صح، لازم الأول تعرف بالظبط إيه الـ flow المستخدم وإيه الـ endpoints.
لو في "Login with Google/Facebook/Apple/GitHub" — في OAuth بنسبة 99%. حتى الزرار اللي بيقول "Continue with Microsoft" أو "Sign in with Twitter" كلها OAuth. افتح Burp وابعت ريكويست واحد على الزرار ده.
دور في الـ /authorize request على response_type:
• code = Authorization Code Flow (آمن)
• token = Implicit Flow (خطر — هاجم!)
• id_token = OIDC implicit (خطر برضو)
• code id_token = OIDC hybrid
الـ host بتاع الـ /authorize request هو الـ Authorization Server. لو خارجي (Google, Facebook) = موثوق. لو الـ company نفسها بتعمله = طبقة جديدة من الـ attack surface.
جرب على الـ auth server دومين: /.well-known/openid-configuration و /.well-known/oauth-authorization-server. الـ JSON اللي بيرجع بيقولك كل الـ endpoints والـ supported features.
في الـ /authorize request، خد screenshot أو احفظ كل القيم: client_id، redirect_uri، scope، state، nonce، code_challenge. كل واحد فيهم vector محتمل.
بعد الـ login، احصل على التوكن من الـ response أو من الـ /userinfo callback. فك الـ JWT في jwt.io. وثق الـ aud، iss، scope. الـ aud claim هو السلاح الأقوى للـ token validation testing.
| الـ Indicator في الـ Recon | إيه اللي بيعنيه | الـ Attack Vector | الأولوية |
|---|---|---|---|
| response_type=token | Implicit flow مستخدم | Token leakage, account takeover via redirect_uri | CRITICAL |
| مفيش state parameter | مفيش CSRF protection | Forced OAuth profile linking, login CSRF | HIGH |
| redirect_uri loose validation | الـ regex/prefix matching مستخدم | Token theft via subdomain or path manipulation | CRITICAL |
| request_uri_parameter_supported | JWT requests مدعومة | SSRF via request_uri parameter | HIGH |
| HS256 signing | Symmetric key — قابل للـ brute force | JWT forge if secret weak/leaked | HIGH |
| "none" alg supported | Bug catastrophic لو الـ client مش بيتحقق | Forge any JWT | CRITICAL |
| Dynamic registration open | أي حد يقدر يسجل client | SSRF via jwks_uri or logo_uri | HIGH |
| token_endpoint_auth_method=none | Public clients مدعومة بدون auth | Confused deputy attacks | MEDIUM |
في الـ implicit flow، التوكن بيمر عبر البراوزر. ده بيخلق فرصة للـ client implementation يكون vulnerable بشكل غريب.
تخيل تطبيق بيعمل authentication عبر OAuth implicit. الـ flow التقليدي:
1. User يدوس "Login with Social". الـ client يعمل
redirect لـ auth server.
2. User يلوج إن في الـ social provider.
3. الـ provider بيرجع access_token في URL
fragment.
4. الـ JS بتاع الـ client بيستخرج التوكن من الـ
fragment.
5. الـ JS بيكلم الـ /userinfo بالتوكن، بياخد user
data.
6. الـ JS بيبعت الـ user data للـ backend بتاع الـ
client (POST request).
7. الـ backend بياخد الـ user data، يدور على المستخدم
في الـ DB، ويعمل session cookie.
الـ backend لازم يستخدم الـ access_token بنفسه عشان يستعلم من الـ provider:
الـ state هو CSRF token للـ OAuth flow. غيابه أو عدم validate له = vulnerabilities خطرة.
تخيل موقع بيسمح للمستخدم يستخدم email/password عادي، أو يربط حسابه بـ social account (Linking). لو الـ flow مش بيستخدم state parameter، الـ attacker يقدر يجبر الضحية تربط حسابها بحساب الـ attacker على الـ provider.
السيناريو:
1. Attacker يبدأ OAuth flow على الـ client بحسابه على الـ provider.
2. Attacker يوصل لمرحلة الـ callback بس ما يكملش — يحتفظ بـ URL الـ callback.
3. Attacker يبعت الـ URL ده للضحية كـ phishing link.
4. الضحية، اللي معاها login session في الـ client، تفتح اللينك.
5. الـ client بياخد الكود ويربطه بحساب الضحية.
النتيجة: حساب الضحية مربوط بـ social account الـ
attacker. الـ attacker يقدر يلوج إن لحساب الضحية بأي وقت عبر الـ social account بتاعه.
⚠️ لو الـ state بـ random value فقط من غير ربط بالـ session، attacker ممكن يولد state من نفسه ويستخدمه. لازم يبقى مربوط بالـ session.
الـ redirect_uri parameter هو الـ trust boundary الأساسي. لو الـ validation ضعيفة، الـ attacker يقدر يسرق الكود/التوكن.
الـ redirect_uri parameter بيقول للـ auth server "بعد ما المستخدم يلوج، رجع الكود/التوكن على العنوان ده". لو الـ attacker قدر يخلي الـ auth server يبعت الكود على دومين بتاع الـ attacker، اللعبة خلصت.
الـ flow بتاع الهجوم:
1. Attacker بيعمل URL يبدا الـ OAuth flow بـ
redirect_uri يخصه.
2. Attacker بيبعت الـ URL ده للضحية.
3. الضحية بتدوس على اللينك (ممكن يكون مخفي في email
أو social).
4. الضحية بتعمل login عادي مع الـ provider (هي بالفعل
عندها session).
5. الـ provider بيرجع الكود/التوكن — لكن للـ
redirect_uri اللي حدده الـ attacker.
6. الـ attacker بياخد الكود، بيستخدمه على الـ
legitimate callback، ويلوج إن باسم الضحية.
حتى لو الـ redirect_uri validation شديدة، open redirect على الدومين الـ legitimate ممكن تتسبب في كارثة.
الـ developer بيكون فاكر إن إنه ضمن الـ redirect_uri = نفس الدومين الـ legitimate يبقى آمن. بس لو في open redirect على الدومين ده، الـ attacker يقدر يستخدمها كـ proxy.
السيناريو الكلاسيكي: الـ application بتقبل redirect_uri لأي subpath على client.com. لكن في endpoint على client.com — مثلاً /redirect?url=... أو /logout?next=... — اللي بيعمل redirect لأي URL بدون validation.
الـ attack ده مش بيحتاج كسر OAuth. بيحتاج بس فهم لمنطق ربط الحسابات. وده بيوجع الشركات كتير.
الـ vulnerability دي بتحصل لما الـ application بتدعم طريقتين للتسجيل: email/password عادي، و OAuth login (مثلاً Login with Google). الـ application بتربط الحسابات على أساس الـ email.
السيناريو الكامل:
1. الـ attacker بيعرف email الضحية (مثلاً victim@gmail.com).
2. الـ attacker بيسجل في الـ application بـ email الضحية + password يخصه. الـ application ما بتبعتش email verification أو الـ verification بيتم asynchronously.
3. الـ attacker مش بيـ verify الـ email — وده مش مشكلة بالنسبة له، الحساب موجود.
4. بعد فترة، الضحية بتيجي تستخدم الـ application. تدوس "Login with Google".
5. Google بترجع للـ application: "ده victim@gmail.com". الـ application
بتلاقي إن في حساب موجود بنفس الـ email. بدل ما تطلب password reset أو
verification، بتربط الحسابين تلقائياً.
6. الضحية تستخدم الـ application عادي — مش حاسة بأي حاجة غريبة.
7. الـ attacker بيلوج إن بـ email الضحية + الـ password الأصلي اللي حطه في step 2. معاه access كامل لحساب الضحية.
عند ربط حساب OAuth بحساب password موجود:
الـ token issued لـ App A لازم ما يشتغلش على App B. لو الـ application مش بتتحقق من الـ aud claim — تطبيقات كتيرة عرضة.
الـ Identity Provider (مثلاً Facebook, Google) بيصدر access tokens. كل token مرتبط بـ application معين (الـ aud / app_id). لما الـ provider يصدر token لـ "App A"، التوكن ده يخص App A فقط.
لكن في كتير من التطبيقات اللي بتدعم social login، الـ flow بيكون:
1. الـ client بياخد access token من Facebook عبر SDK.
2. الـ client بيبعت التوكن لـ backend بتاعه.
3. الـ backend بيستدعي Facebook API بالتوكن، بياخد user info.
4. الـ backend بيلوج إن المستخدم على أساس الـ Facebook user ID.
المشكلة: الـ backend مش بيتحقق إن التوكن ده صادر للـ application بتاعه. أي token Facebook صحيح هيشتغل — حتى لو صادر لتطبيق تاني تماماً.
المستخدم وافق على read-only، لكن الـ attacker يقدر يحصل على write. لو الـ scope validation ضعيفة.
الـ scope parameter بيقول "أنا client بدي الصلاحيات دي". المستخدم بيوافق على scopes معينة، الـ token بيتصدر بالـ scopes دي. لكن في الـ subsequent requests للـ token endpoint، أحياناً الـ server بيقبل scope جديدة من غير ما يتحقق.
السيناريو 1 — Authorization Code Flow:
1. Attacker بيعمل client app يطلب scope "openid email" بس.
2. الضحية توافق — التوكن صادر بـ scope محدودة.
3. عند الـ token exchange، الـ attacker (اللي بيتحكم في الـ client) بيضيف scope جديدة في الطلب:
scope=openid email profile address phone.
4. لو الـ server مش بيقارن مع الـ original consent، بيصدر token بالـ scopes الجديدة.
السيناريو 2 — Implicit Flow:
1. Attacker بيسرق access token بصلاحيات محدودة (read).
2. عند استخدام التوكن للـ /userinfo أو غيره، يضيف scope parameter جديد.
3. لو الـ resource server مش بيتحقق إن الـ scope مفعل في التوكن، بيرجع data أكتر مما المستخدم
وافق عليه.
في scopes كتيرة مش موجودة في الـ docs بس بتشتغل:
تكنيك متطور لسرقة OAuth tokens عبر استغلال "non-happy paths" في الـ flow + postMessage abuse.
الـ "dirty dancing" تكنيك اخترعه Frans Rosén ضد كذا برنامج كبير (Reddit, Mapbox, Zoom). الفكرة الأساسية: تخلي الـ OAuth flow يفشل في مرحلة معينة بحيث يخلي التوكن "stranded" في الـ URL، ثم تستخدم client-side bug عشان تسرّبه.
الخطوات:
1. الـ attacker بيلاعب الـ flow بحيث الـ provider بيصدر token صالح، بس الـ client يفشل في consume
الـ token عشان السبب.
2. ده ممكن يكون عن طريق: تغيير response_type من code لـ token، إرسال state غير متوقع، تغيير
response_mode، أو إضافة prompt=none.
3. الـ provider بيرجع للـ callback، الـ token في الـ URL fragment.
4. الـ client بيلاحظ إن state غلط (أو حاجة تانية فشلت)، بيظهر error page. لكن الـ URL fragment لسه فيه التوكن.
5. لو الـ error page بتلود scripts من 3rd parties (analytics, chat widgets, ads)، الـ scripts دي
ممكن تقرا الـ window.location.hash.
6. الـ attacker بيستغل postMessage listener أو CORS misconfiguration على واحد من الـ scripts دي
عشان يسرّب الـ URL.
OIDC بيضيف complexity فوق OAuth. الـ complexity دي بتجيب معها attack vectors جديدة خاصة بيها.
الـ OIDC specification بتدعم حاجة اسمها Dynamic Client Registration — أي حد يقدر يسجل client جديد عبر /register endpoint.
لو الـ endpoint ده مفتوح بدون authentication، الـ attacker يقدر يسجل client بـ jwks_uri أو logo_uri بيشير لـ internal network — SSRF كلاسيكي.
OIDC بيدعم إرسال الـ authorization parameters كـ JWT عبر request_uri parameter بدل الـ query string العادي.
لو الـ server بيجيب الـ JWT ده من الـ URL، الـ attacker يحط request_uri بيشير لـ internal service.
الـ OIDC provider بيديك claim اسمه email_verified. لو الـ client مش بيتحقق منه، الـ attacker يسجل في الـ provider بـ email الضحية من غير verification ويلوج إن باسمها.
الـ nonce في الـ id_token بيمنع إعادة استخدام التوكن في attacks. لو الـ client مش بيتحقق منه، الـ attacker يقدر يعيد استخدام id_token قديم.
في OIDC، الـ id_token هو JWT. وده بيخليه عرضة لكل JWT attacks المعروفة. أهمها:
Algorithm Confusion (RS256 → HS256): الـ server بيصدر التوكن بـ RS256 (asymmetric). الـ attacker بيغير الـ alg لـ HS256 (symmetric) ويعمل signature بالـ public key كـ secret. لو الـ library مش بتعمل validation صارم على الـ algorithm، هتقبل التوكن الملفق.
alg:none Attack: بعض الـ libraries بتقبل tokens بدون signature لو الـ algorithm اتحدد كـ "none". غالباً مش شغالة على Production لكن لازم تختبرها.
| الـ Vulnerability | الـ Indicator | الـ Test | الأولوية |
|---|---|---|---|
| Dynamic Registration SSRF | registration_endpoint في discovery doc | سجل client بـ jwks_uri/logo_uri يشير لـ internal IP | CRITICAL |
| request_uri SSRF | request_uri_parameter_supported: true | ابعت request_uri لـ internal service | HIGH |
| email_verified bypass | Login with social + email as identifier | سجل في provider بـ email غير verified | CRITICAL |
| Algorithm Confusion | HS256 في supported algorithms | jwt_tool -X s بالـ public key | CRITICAL |
| nonce Replay | OIDC flow بدون nonce validation | أعد استخدام id_token قديم | HIGH |
| alg:none | "none" في id_token_signing_alg_values | jwt_tool -X a | HIGH |
| kid Injection | kid claim في JWT header | SQLi / path traversal في kid value | HIGH |
لما تشوف OAuth implementation، دي الخريطة اللي بتحدد فين تبدأ وايه تختبر أولاً.
كل حاجة محتاجها في الـ testing في مكان واحد — parameters، endpoints، payloads، tools.
| الـ Tool | الاستخدام | الـ Command / URL |
|---|---|---|
| Burp Suite | Intercept كل OAuth flow، modify parameters | Proxy → HTTP History → Filter: oauth |
| jwt_tool | JWT attacks: alg confusion، brute، injection | github.com/ticarpi/jwt_tool |
| jwt.io | Decode وفهم JWT tokens | jwt.io |
| hashcat | Brute force HS256 secret | hashcat -m 16500 token wordlist.txt |
| OAuth Test Suite | Automated OAuth testing | portswigger.net/burp/extensions |
| Interactsh | Out-of-band detection للـ SSRF | app.interactsh.com |
| Firefox DevTools | تحليل postMessage + localStorage | F12 → Console: monitorEvents(window, 'message') |
| الـ Vulnerability | Account Takeover | Data Theft | No User Interaction | Severity |
|---|---|---|---|---|
| redirect_uri = external | ✓ | ✓ | △ | CRITICAL |
| Implicit Flow Bypass | ✓ | ✓ | ✓ | CRITICAL |
| Audience Validation Missing | ✓ | ✓ | △ | CRITICAL |
| JWT alg:none | ✓ | ✓ | ✓ | CRITICAL |
| Pre-Account Takeover | ✓ | ✓ | △ | CRITICAL |
| Missing state / CSRF | △ | ✗ | △ | HIGH |
| Open Redirect + OAuth Chain | ✓ | ✓ | △ | CRITICAL |
| Scope Upgrade | ✗ | ✓ | ✓ | HIGH |
| SSRF via jwks_uri | △ | △ | ✓ | HIGH |
✓ = Yes | △ = Sometimes | ✗ = No
10 أسئلة على كل اللي اتعلمناه. اختبر فهمك قبل ما تبدأ تصطاد.