سلام دوستان
تعریف ها :
وظیفه ی suid این است که در صورت فعال بودن بر روی فایلی . آن فایل را با پرمیشن سازنده یا همان Owner فایل اجرا می کند مثلا یک فایل اجرایی را فرض کنید که مقدار suid دارد و سازنده ی این فایل اجرایی root است . حال اگر یوزر دیگری این فایل اجرایی را اجرا کند ( در صورت داشتن پرمیشن execute ) . آن فایل با یوزر root به اجرا در می آید .
وظیفه ی sgid دقیقا همانند وظیفه ی suid است با تفاوت که با گروه و یا Group فایل سرو کار دارد . یعنی در صورت فعال بودن بر روی فایلی . در صورت اجرا توسط هر یوزر . فایل با گروه سازنده ی فایل به اجرا در می آید .خب حالا همین تعریف های بالا رو برای برنامه ی خودمون امتحان می کنیم . برنامه ی ما در این جا یک ضرب ساده است که به زبان cpp نوشده شده است :
#include <iostream>
#include <fstream>
using namespace std;
int main ()
{
int i;
cout << "Adade khodeton ro vared konid : ";
cin >> i;
ofstream myfile;
myfile.open ("/etc/out.txt");
myfile << "Out is : " << i*2 << "\n";
myfile.close();
return 0;
}
روند اجرای این برنامه به این صورت است که ابتدا متنی برای شما با مضمون "عدد خودتون رو وارد کنید" نمایش داده می شود و منتظر می ماند تا عدد خودتون را وارد کنید . سپس عدد وارد شده در 2 ضرب می شود و خروجی در فایل out.txt واقع در مسیر etc/ ذخیره می شود .
در مرحله ی اول کد بالا را در فایلی ذخیره کنید ( به عنوان مثال code.cpp ) :
user@elab:~/test$ su root
root@elab:/home/user/test# nano code.cpp
حال برای کامپایل این برنامه به صورت زیر عمل می کنیم :
root@elab:/home/user/test# g++ code.cpp -o exe
نکته : با استفاده از سویچ o نام کامپایل شده ی برنامه را انتخاب کردیم .
در مرحله ی بعد بایستی پرمیشن SGID و suid را برای فایل exe ست کنیم . پس به صورت زیر عمل می کنیم :
root@elab:/home/user/test# chmod 6755 exe
دلیل استفاده از عدد 6 به شرح زیر است :
(1 x 2^2) + (1 x 2^1) + (0 x 2^1) = 4 + 2 + 0 = 6
توجه داشته باشید که می خواهیم پرمیشن suid و SGID را برای فایل ست کنیم لذا 2 بیت اول را مقدار 1 و از آن جا که با sticky کاری نداریم , بیت آخر را مقدار 0 اختیار می کنیم .
حال برای مشاهده ی خروجی دستوراتی که زدید کافیست یک stat از فایل exe بگیریم . یعنی :
root@elab:/home/user/test# stat exe
نتیجه ی اجرای این برنامه :
1. از آن جا که پرمیشن suid را برای این برنامه ست کردیم , اگر با یوزر معمولی و جاری سیستم خود , این برنامه را اجرا کنیم . در پشت پرده خواهیم دید که این برنامه توسط یوزر root اجرا شده است .
2. از آن جایی که پرمیشن SGID هم به برنامه اضافه کردیم , فایل out.txt با uid و gid کاربر root ایجاد خواهد شد . علت داشتن uid کاربر root , ست کردن پرمیشن suid و علت داشتن gid کاربر root , ست کردن پرمیشن SGID است .
اما برای اجرای این برنامه ابتدا از یوزر root خارج شده و با یوزر معمولی فایل کامپایل شده را بدین شکل اجرا می کنید :
user@elab:~/test$ ./exe
http://bayanbox.ir/view/3763644508951137558/001.pngقبل از وارد کردن عدد مورد نظر اگر پروسه های فعال را مشاهده کنیم , خواهیم دید که این برنامه با استفاده از یوزر root اجرا شده است . این در حالی است که برنامه با یوزر user اجرا شده است . ( مطابق عکس )
http://bayanbox.ir/view/8275785320512998364/003.pngاگر به خط اول دقت کنید , یوزر root را در ابتدای خط خواهید دید .
اما بعد از اجرا برنامه یک بار از فایل ساخته شده stat می گیریم :
user@elab:~/test$ stat /etc/out.txt
http://bayanbox.ir/view/7721757452966217281/002.pngملاحظه می شود که دو مقدار uid و gid فایل out.txt کاربر root است ! در صورتی که همان طور که از عکس اول پیداست , کاربری که فایل اجرایی را اجرا کرده root نیست .
نکته : اسکریپتی bash ای و یا ... را فرض کنید که درون آن به برنامه ای داخل توزیع اشاره شده باشد . به عنوان مثال :
#! /bin/bash
touch /etc/out.txt
حال حتی اگر 2 پرمیشن suid و SGID را هم به این اسکریپت بدهید , فایل out.txt ساخته نخواهد شد و با ارور نداشتن پرمیشن مواجه خواهد شد ( اجرا با یوزر معمولی و جاری سیستم ) . دلیل این موضوع مشخص است چرا که داخل اسکریپت از یک برنامه ی دیگر جهت ساخت یک فایل استفاده کردیم . برنامه ای که خود فاقد پرمیشن suid و SGID است . این نتیجه در صورتی که 2 پرمیشن suid و SGID را به فایل اجرایی برنامه ی touch دهید , تغییر خواهد کرد و نتیجه ی مطلوب بدست خواهد آمد .
اگر جایی رو اشتباه گفتم و یا مشکلی دیدید و ... حتما مطرح کنید . با تشکر
منبع