آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

آموزش اسکریپت نویسی

آموزش اسکریپت نویسی پوسته گنو-لینوکس

پرسش و پاسخ شماره ۷۸

پرسش و پاسخ شماره ۷۸

من می‌خواهم با استفاده ازفرمان passwd یونیکس یک کلمه عبور کاربر را تنظیم کنم، اما چطور آن را اسکریپت کنم؟ ورودی استاندارد را نمی‌خواند!

خوب، اول از همه، من میدانم ممکن است افردای نیز هم اکنون درحال خواندن این مطلب ‌باشند که حتی پرسش را متوجه نمی‌شوند. اینجا، این کد کار نمی‌کند:

{ echo oldpass; echo newpass; echo newpass; } | passwd
# !این کار نمی‌کند

اصلاً کاری نمی‌توانید بکنید که بتواند در bash عملی بشود. ‎passwd(1)‎ از ورودی استاندارد نمی‌خواند. این مطلب تعمدی است. برای حراست از شماست. هرگز کلمات عبور برای قرار گرفتن در برنامه‌ها یا تولید شدن توسط برنامه‌ها در نظر گرفته نشده‌اند. آنها برای آن در نظر گرفته شده‌اند که با انگشتان یک انسان حقیقی، با یک ذکاوت عملیاتی وارد بشوند، و هرگز اصلاً در جایی نوشته نشوند. بنابراین قبل از اینکه ادامه بدهید، احتمالی را که مؤلفین ‎passwd(1)‎ در فکر آن بودند، درنظر بگیرید، و شاید شما نباید سعی در اسکریپت نمودن ورودی ‎passwd(1)‎ بنمایید.

با این وجود، انبوهی پرسش از کاربران به دست ما می‌رسد که آنها چگونه می‌توانند 35 سال امنیت یونیکس را خنثی کنند. و همکاری اشخاصی با راه حل‌های مطلوبِ حذف امنیت را با این صفحه مشاهده می‌کنیم. اگر شما بازهم فکر می‌کنید آنچه می‌خواهید این است، ادامه دهید.

طرح ریزی کلمه عبور درهم ریخته خودتان و نوشتن آن در فایل

اولین رویکرد، ساختن کلمه عبور بهم ریخته خودتان(DES، MD5، Blowfish‎، یا هر چیزی که سیستم عامل شما استفاده می‌کند) با استفاده از ابزارهای غیر استانداردی از قبیل ‎http://wooledge.org/~greg/crypt/‎ یا بسته mkpasswd دبیان/اوبونتو، را شامل می‌شود. سپس باید آن کلمه عبور درهم ریخته را همراه با فیلدهای اضافی در یک سطر از فایل ‎password-hash‎ سیستم محلی خودتان (شاید ‎/etc/passwd‎، یا ‎/etc/shadow‎، یا ‎/etc/master.passwd‎، یا ‎/etc/security/passwd‎، یا ... باشد) بنویسید. این کار نیاز به آن دارد که شما صفحات man در سیستم خود را بخوانید، تا دریابید پسورد بهم‌ریخته کجا قرار می‌گیرد، فایل چه قالب‌بندی نیاز دارد، و سپس کُدی ایجاد کنید که آنرا در آن قالب به تفصیل بنویسد.

یک گونه فرعی آن، مستلزم استفاده از یک ابزار سیستمی خاص برای نوشتن سطرِ کلمه عبور درهم ریخته طراحی شده شما، می‌باشد. برای مثال، در دبیان/اوبونتو، ‎useradd -m joe -s /bin/bash -p "$(mkpasswd "$password")"‎ به طوری که ما فهمیده‌ایم، می‌تواند کارکند.

فریب کامپیوتر به تصور آن که با یک انسان طرف است

دومین رویکرد استفاده از expect یا معادل python آن است. من گمان می‌کنم expect حتی دقیقاً این موضوع را به عنوان یکی از مثالهای رسمی‌اش دارد.

یافتن ابزار سیستمی مخصوص

سرانجام، ابزارهای سیستمی طراحی شده برای این مقصود ممکن است از قبل در سیستم شما موجود باشد. برای مثال، بعضی از سیستمهای گنو-لینوکس دارای فرمان ‎newusers(8)‎ هستند که به طور خاص برای این منظور طراحی شده‌اند، یا ابزار ‎ chpasswd(8)‎ که می‌تواند وادار به انجام انواعی از این کارها بشود. یا ممکن است یک پرچم ‎ --stdin‎ در فرمان passwd خود داشته باشند. همچنین فرمانهایی از قبیل ‎ apropos users‎ یا ‎man -k account‎ را برای دیدن مورد دیگری که شاید وجود داشته باشد امتحان کنید. خلاق باشید.

همچنین پرسش و پاسخ 69 -- می‌خواهم یک ارتباط ssh (یا scp، یا sftp) را خودکار نمایم، اما نمی‌دانم چطور کلمه عبور را ارسال کنم را ببینید.


برای امنیت به ‎ /dev/tty‎ استناد نکنید

در کنار این مطلب، عکس این پرسش نیز مشکلی است. حداقل تحت لینوکس ، پنهان کردن برنامه به نحوی که ترمینال کنترل کننده وادار شود به طور انتزاعی به هر نوع ورودی و خروجی دلخواه شما متصل بشود، امری بدیهی است. این به معنای آنست که از نطر امنیتی بسیار دشوار است تضمین شود که واقعاً یک کاربر با دسترسی محلی است که به طور مستقیم از صفحه کلید، ورودی را به برنامه شما می‌دهد. غالباً اشخاص این کار را با خواندن از‎ /dev/tty ‎ انجام می‌دهند. این درست مانند روشی است که برنامه passwd عمل می‌کند، فقط قدم کوچکی در سست کردن عادات امنیتی نا مناسبی نظیر ذخیره کلمات عبور در فایلهای متن ساده است. کد زیر Bash را اجرا می‌کند، که برنامه‌ای در‎ FD 3 ‎را می‌خواند که به طور غیر هوشمندانه ورودی‌اش را از طریق یک لوله (که به آسانی می‌توانست دقیقاً یک فایل باشد)، با استفاده از یک تابع کتابخانه استاندارد پایتون می‌خواند.

 ~ $ { echo 'o hi there' | python -c 'import pty; pty.spawn(["bash", "/dev/fd/3"])'; } <<"EOF" 3<&0- <&2  
  # ممانعت می‌کند، اثر واقعی ندارد  echo از قطع ارتباط ورودی استاندارد ‎<&2‎ ‎
{
    stty -echo
    read -p 'Password: ' passw
    printf '\n%s\n' "password is: $passw"
    stty echo
} </dev/tty
EOF

o hi there
Password:
password is: o hi there
# نگارش بدون استفاده از پایتون‎

#{ echo 'o hi there' | script -c "bash /dev/fd/3" /dev/null; } <<"EOF" 3<&- 3<&0- <&2   # لینوکس‎
{ echo 'o hi there' | script -q /dev/null bash /dev/fd/3; } <<"EOF" 3<&- 3<&0- <&2      # FreeBSD و Mac OS X در‎
{
    stty -echo
    read -p 'Password: ' passw
    printf '\n%s\n' "password is: $passw"
    stty echo
} </dev/tty
EOF

علاوه بر این، خواندن از ‎ /dev/tt‎y کمی رنجش آور است زیرا طریقه‌ای که کاربران انتظار دارند تغییر مسیرهایشان عمل کنند را نقض می‌کند. پس این کار را انجام ندهید. بهتر است از ‎[[ -t 0 ]]‎ جهت بازرسی tty و رفتار کردن بر طبق موقعیت استفاده کنید. حتی موقعی که یک مدیر سیستم رفتار معینی را انتظار دارد که بر اساس آن I/O را تغییر می‌دهد، این مطلب می‌تواند رنجش آور باشد. اگر شما باید یکی از این ترفندها را به کار ببرید، آن را مستند کنید، و گزینه‌ای برای غیر فعال نمودن رفتار مشروط I/O فراهم نمایید.


پرسش و پاسخ 78 (آخرین ویرایش ‎2013-03-28 10:54:50‎ توسط p54A33276)