linuxtnt(linux tips and tricks)
5.75K subscribers
1.59K photos
137 videos
531 files
1.24K links
https://t.me/+AL7RKhKS6b4zNzY8

آموزش لینوکس- گروه مکمل برای پرسش و پاسخ
linux tips and tricks
ارتباط با من
@seilany
seilany.ir
Download Telegram
Forwarded from OS Internals (Abolfazl Kazemi)
مقدار صفر برای argc در برنامه‌های لینوکسی. چرا و چگونه؟

همه چیز از بررسی CVE-2021-4034 و کامپایل مجدد PolKit بر روی Ubuntu 22.04 شروع شد! تصمیم داشتم یک نسخه‌ی آسیب‌پذیر PolKit رو با فعال کردن Debug Symbols کامپایل کرده و مراحل کامل این CVE رو در GDB بررسی کنم. به صورت خلاصه بگم که این آسیب‌پذیری در باینری pkexec وجود دارد و به کمک آن می‌توان LPE انجام داد. یکی از شرایط استفاده از این آسیب‌پذیری این است که در زمان اجرای pkexec شرط argc==0 برقرار باشد که از طریق آن متغیرهای محلی خوانده شده و بتوان یک library مخرب را بارگذاری نمود.

از آنجایی که pkexec علاوه بر لینوکس بر روی Solaris, BSD هم قابل استفاده است، در مقاله‌ی اصلی این CVE که توسط Qualys Security منتشر شده است متن زیر مشاهده می‌شود که از الزام argc==0 برای امکان‌پذیر بودن این LPE خبر می‌دهد.
OpenBSD is not exploitable, because its kernel refuses to execve() a program if argc is 0

پس فرض من این بود که در نسخه‌های اخیر لینوکس هم با کامپایل PolKit باید بتوان این آسیب‌پذیری را تست کرد. این بود که بر روی Ubuntu 22.04 یک نسخه‌ی آسیب‌پذیر را کامپایل کرده و یک کد ساده به صورت زیر نوشتم که pkexec را اجرا کرده و argc==0 برقرار باشد.

void main() {
char *args[] = { NULL };
char *envs[] = {"SHELL=/bin/bash", 0};
execve("pkexec", args, envs);
}

با اجرای برنامه و زدن strace مشاهده شد که فراخوانی در سطح user طبق انتظار انجام شد.
execve("pkexec", [], 0x7ffe3883b200 /* 1 var */)

ولی دو تا مورد عجیب رخ داد. اول اینکه برنامه در gdb بر خلاف انتظار با argc==1‌ اجرا شده و argv[0] که اسم برنامه در آن قرار می‌گیرد و طبق مدل فراخوانی باید NULL می‌بود برابر “” شده بود. مورد دومی که عجیب بود پیام زیر در dmesg بود.
process 'exploit' launched 'pkexec' with NULL argv: empty string added

با رسیدن به این مرحله به سراغ Ubuntu 20.04 رفتم و همین کد را بر روی آن اجرا کردم که همه چیز طبق انتظار رخ داده و در gdb با رسیدن به main برنامه‌ی pkexec مقدار argc==0 برقرار بوده و امکان تست CVE وجود داشت. اینجا واضح بود که در کرنل‌های جدید لینوکس در فراخوانی سیستمی execve تغییراتی اعمال شده است که جلوی اجرای برنامه‌ها با argc==0 گرفته شود. اینجا دیگه لازم بود کد کرنل چک شود!

با رفتن به github‌ و بررسی فایل fs/exec.c کرنل لینوکس مشاهده شد که در تابع اجرای فراخوانی سیستمی execve کد زیر در March 2022 اضافه شده که جلوی اجرای برنامه‌ها با argc==0 را می‌گیرد.

/*
* When argv is empty, add an empty string ("") as argv[0] to
* ensure confused userspace programs that start processing
* from argv[1] won't end up walking envp. See also
* bprm_stack_limits().
*/
if (bprm->argc == 0) {
retval = copy_string_kernel("", bprm);
if (retval < 0)
goto out_free;
bprm->argc = 1;
}

پس از این به بعد علاوه بر OpenBSD بر روی لینوکس نیز امکان اجرای آسیب‌پذیری‌های این مدلی وجود نخواهد داشت! :-D
پ.ن: در آینده‌ یک ویدئو از شیوه‌ی کامل اجرای این CVE منتشر می‌کنم.

#linux #kernel #CVE #PolKit #pkexec #execve
Forwarded from OS Internals (Abolfazl Kazemi)
جزئیات پروسه و نخ در لینوکس

به صورت خلاصه از دید ویندوز پروسه فقط یک container می‌باشد که اجرا نشده و فضایی برای اجرای Threadها فراهم می‌کند و در سطح کرنل نیز دو ساختار EPROCESS, ETHREAD برای این دو تعریف شده‌اند. اما در لینوکس ماجرا متفاوت است و Process, Thread هر دو قابلیت اجرا داشته و در سطح کرنل نیز یک ساختار task_struct برای آن‌ها تعریف شده است. در دنیای شی‌گرایی مثل این است که در لینوکس یک کلاس برای این دو وجود دارد و فقط در زمان ایجاد شی خصوصیات متفاوتی برای آن‌ها تنظیم می‌شود.

اگر به سراغ برنامه‌نویسی سیستمی در لینوکس برویم، تابع fork برای ایجاد پروسه استفاده شده و از تابع pthread_create نیز برای ایجاد نخ در لینوکس استفاده می‌شود. در سطحی کمی پایین‌تر، هر دوی این توابع syscallای به نام clone را فراخوانی می‌کنند و با ست‌کردن فلگ‌هایی مشخص می‌کنند که قصد ایجاد پروسه یا نخ را دارند. در زمان بررسی برنامه‌ها، در خروجی دستور ps برای یک برنامه‌ی چند پروسه‌ای pidهای مختلفی خواهیم دید ولی در یک برنامه‌ی چند نخی pidها یکسان بوده ولی عددهای متفاوتی در فیلد Light-Weight Process-LWP می‌بینیم.

نکته‌ی جالب دیگر این است که در سطح کرنل پروسه‌ها یک لیست پیوندی تشکیل می‌دهند. هم شیوه‌ی ایجاد لیست پیوندی Generic در سطح کرنل و در زبان C موضوع جالبی است و هم اینکه به کمک فیلدی به اسم tasks می‌توانیم یک لیست پیوندی از پروسه‌ها تشکیل دهیم که به پروسه‌های قبلی و بعدی اشاره می‌کند.

این موارد و موارد دیگری از جزئیات پروسه‌ها و نخ‌های لینوکس مواردی هستند که در این ویدئو به آن می‌پردازیم.

لینک ویدئو در یوتیوب:
https://youtu.be/0fxYtyFn8Jc
لینک ویدئو در آپارات:
https://aparat.com/v/cnytp55

#ShortLinuxInternals #linux #internals #syscalls #kernel #process #thread #gdb #qemu #clone #LWP