Theo de Raadt က တိုက်ခိုက်မှုမျက်နှာပြင်ကို လျှော့ချရန်အတွက် OpenBSD တွင် ယန္တရားအသစ်တစ်ခု ထည့်သွင်းရန် အဆိုပြုခဲ့ပြီး openat system call ကို တိုးချဲ့ခြင်းဖြင့် အကောင်အထည်ဖော်ခဲ့သည်။ "/" မှတစ်ဆင့် အထက် directory များသို့ သွားလာနိုင်စွမ်းနှင့် absolute path များကို ဝင်ရောက်နိုင်စွမ်းကို ကန့်သတ်သည့် openat နှင့် open အတွက် အပို flags များကို အကောင်အထည်ဖော်သည့် patch များကို kernel၊ libc နှင့် base system ရှိ application အချို့အတွက် ပြင်ဆင်ထားပြီးဖြစ်သည်။ ပြောင်းလဲမှုများကို OpenBSD-current တွင် မထည့်သွင်းရသေးဘဲ developer များအကြား လက်ရှိတွင် ဆွေးနွေးနေဆဲဖြစ်သည်။
openat(2) system call မိသားစုသည် open(2) ကဲ့သို့ လုပ်ဆောင်သော်လည်း "path" parameter သည် relative ဖြစ်ပါက ဖွင့်မည့်ဖိုင်သည် လက်ရှိအလုပ်လုပ်နေသော directory မဟုတ်ဘဲ "fd" file descriptor နှင့် ဆက်စပ်နေသော directory နှင့် သက်ဆိုင်ပါသည်။ openat သို့ absolute path တစ်ခု ပေးပါက၊ ဥပမာ- int dirfd = open("/tmp", O_RDONLY | O_DIRECTORY); int hfd = openat(dirfd, "/etc/hosts", O_RDONLY);
openat() function သည် "dirfd" ကို လျစ်လျူရှုမည်ဖြစ်ပြီး ရလဒ်အနေဖြင့် absolute path ကို ပုံမှန်အတိုင်း လုပ်ဆောင်ပေးမည်ဖြစ်သည်။
ထို့ကြောင့် open() ကို openat() ဖြင့် အစားထိုးခြင်းသည် ၎င်းကိုယ်တိုင်က ပရိုဂရမ်လုံခြုံရေးကို တိုးတက်ကောင်းမွန်စေမည်မဟုတ်ပါ။ ဤခေါ်ဆိုမှုသည် လမ်းကြောင်းခွဲခြမ်းစိတ်ဖြာခြင်းကို မြန်ဆန်စေနိုင်သော်လည်း ဖိုင်စနစ်ကို ဝင်ရောက်ခွင့်ကို ကန့်သတ်ထားခြင်းမရှိပါ။ absolute paths များကို တားမြစ်သည့် flags (ဥပမာ၊ openat2 အတွက် RESOLVE_BENEATH နှင့်/သို့မဟုတ် RESOLVE_IN_ROOT) Linux): ပရိုဂရမ်မာသည် ၎င်းတို့ကို သင့်လျော်သော ခေါ်ဆိုမှုအားလုံးတွင် ထည့်သွင်းရမည်ဖြစ်ပြီး လုပ်ငန်းစဉ်ကို ထိန်းချုပ်နိုင်သည့်အခါ တိုက်ခိုက်သူသည် ဖိုင်များကို ဖွင့်ရန် အခြားနည်းလမ်းများကို အသုံးပြုနိုင်သည်။
openrsync utility မှာ အလုပ်လုပ်နေစဉ်မှာ Theo ဟာ သူ့ရဲ့ filesystem traversal စွမ်းရည်တွေကို ကန့်သတ်ဖို့ လိုအပ်ခဲ့ပေမယ့် unveil() နဲ့ pledge() function တွေကို အသုံးပြုပြီး ဒီလိုလုပ်လို့မရခဲ့ပါဘူး။ ပြီးတော့ သူဟာ openat() နဲ့ ဆင်တူတဲ့ ယန္တရားတစ်ခုကို တီထွင်ခဲ့ပေမယ့် pledge/unveil ကို ဖြည့်စွက်ပေးမယ့် ဒါမှမဟုတ် သူတို့မရှိတဲ့အချိန်မှာတောင် အလုပ်လုပ်နိုင်တဲ့ လုံခြုံရေးအင်္ဂါရပ်တွေ ပါဝင်ပါတယ်။
အခြေခံအယူအဆကတော့ ကန့်သတ်ချက်တွေကို directory descriptor ရဲ့ အစိတ်အပိုင်းတစ်ခုအဖြစ် ပြုလုပ်ရန်ပါပဲ။ ဒီလိုလုပ်ဖို့အတွက် fcntl() မှတစ်ဆင့် သတ်မှတ်နိုင်တဲ့ F_BELOW flag ဒါမှမဟုတ် open() အတွက် O_BELOW flag ကို ကျွန်တော်တို့ အဆိုပြုထားပါတယ်။ ဒီနည်းနဲ့ ကန့်သတ်ထားတဲ့ "dirfd" descriptor ဟာ directory tree မှာ အောက်ဘက်ကို ဖြတ်သန်းသွားရုံပဲ ခွင့်ပြုပါတယ်- absolute path ရှိတဲ့ openat() call တွေ ဒါမှမဟုတ် ".." မှတစ်ဆင့် အပေါ်ဘက်ကို ဖြတ်သန်းသွားတဲ့အခါ ENOENT error နဲ့ မအောင်မြင်ပါဘူး။ code execution attack တစ်ခုခုဖြစ်ရင် process ရဲ့ file descriptor table မှာ လုပ်ဆောင်ချက်နည်းတဲ့ "dirfd" တွေ ပါဝင်မှာဖြစ်ပြီး attack မျက်နှာပြင်ကို ကန့်သတ်ထားပါတယ်။
source: opennet.ru
