بيرل في وضع العيب:الحفاظ على suid عند تشغيل برنامج خارجي عبر النظام ()
سؤال
أحاول إضافة ميزة إلى البرنامج النصي القديم.البرنامج النصي suid، ويستخدم Perl -T (وضع العيب:man perlsec)، لمزيد من الأمان.الميزة التي أحتاج إلى إضافتها مطبقة في بايثون.
مشكلتي هي أنني لا أستطيع إقناع perlsec بالحفاظ على أذونات suid، بغض النظر عن مقدار غسل البيئة وأسطر الأوامر الخاصة بي.
وهذا أمر محبط، لأنه يحافظ على suid للثنائيات الأخرى (مثل /bin/id).هل هناك حالة خاصة غير موثقة لـ /usr/bin/Perl؟هذا يبدو غير محتمل.
هل يعرف أحد طريقة لجعل هذا العمل؟(كما هي:ليس لدينا الموارد اللازمة لإعادة هندسة هذا الأمر برمته.)
حل: (حسبgbacon)
# use the -p option to bash
system('/bin/bash', '-p', '-c', '/usr/bin/id -un');
# or set real user and group ids
$< = $>;
$( = $);
system('/usr/bin/python', '-c', 'import os; os.system("/usr/bin/id -un")');
يعطي النتائج المرجوة!
إليك نسخة مختصرة من البرنامج النصي الخاص بي، والتي لا تزال تظهر مشكلتي.
#!/usr/bin/perl -T
## This is an SUID script: man perlsec
%ENV = ( "PATH" => "" );
##### PERLSEC HELPERS #####
sub tainted (@) {
# Prevent errors, stringifying
local(@_, $@, $^W) = @_;
#let eval catch the DIE signal
$SIG{__DIE__} = '';
my $retval = not eval { join("",@_), kill 0; 1 };
$SIG{__DIE__} = 'myexit';
return $retval
}
sub show_taint {
foreach (@_) {
my $arg = $_; #prevent "read-only variable" nonsense
chomp $arg;
if ( tainted($arg) ) {
print "TAINT:'$arg'";
} else {
print "ok:'$arg'";
}
print ", ";
}
print "\n";
}
### END PERLSEC HELPERS ###
# Are we SUID ? man perlsec
my $uid = `/usr/bin/id --user` ;
chomp $uid;
my $reluser = "dt-pdrel";
my $reluid = `/usr/bin/id --user $reluser 2> /dev/null`;
chomp $reluid;
if ( $uid ne $reluid ) {
# what ? we are not anymore SUID ? somebody must do a chmod u+s $current_script
print STDERR "chmod 4555 $myname\n";
exit(14);
}
# comment this line if you don't want to autoflush after every print
$| = 1;
# now, we're safe, single & SUID
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# BEGIN of main code itself
print "\nENVIRON UNDER BASH:\n";
run('/bin/bash', '-c', '/bin/env');
print "\nTAINT DEMO:\n";
print "\@ARGV: ";
show_taint(@ARGV);
print "\%ENV: ";
show_taint(values %ENV);
print "`cat`: ";
show_taint(`/bin/cat /etc/host.conf`);
print "\nworks:\n";
run('/usr/bin/id', '-un');
run('/usr/bin/id -un');
print "\ndoesn't work:\n";
run('/bin/bash', '-c', '/usr/bin/id -un');
run('/bin/bash', '-c', '/bin/date >> /home/dt-pdrel/date');
run('/bin/date >> /home/dt-pdrel/date');
run('/usr/bin/python', '-c', 'import os; os.system("/usr/bin/id -un")');
run('/usr/bin/python', '-c', 'import os; os.system("/usr/bin/id -un")');
sub run {
my @cmd = @_;
print "\tCMD: '@cmd'\n";
print "\tSEC: ";
show_taint(@cmd);
print "\tOUT: ";
system @cmd ;
print "\n";
}
وهنا الإخراج:
$ id -un
bukzor
$ ls -l /proj/test/test.pl
-rwsr-xr-x 1 testrel asic 1976 Jul 22 14:34 /proj/test/test.pl*
$ /proj/test/test.pl foo bar
ENVIRON UNDER BASH:
CMD: '/bin/bash -c /bin/env'
SEC: ok:'/bin/bash', ok:'-c', ok:'/bin/env',
OUT: PATH=
PWD=/proj/test2/bukzor/test_dir/
SHLVL=1
_=/bin/env
TAINT DEMO:
@ARGV: TAINT:'foo', TAINT:'bar',
%ENV: ok:'',
`cat`: TAINT:'order hosts,bind',
works:
CMD: '/usr/bin/id -un'
SEC: ok:'/usr/bin/id', ok:'-un',
OUT: testrel
CMD: '/usr/bin/id -un'
SEC: ok:'/usr/bin/id -un',
OUT: testrel
doesn't work:
CMD: '/bin/bash -c /usr/bin/id -un'
SEC: ok:'/bin/bash', ok:'-c', ok:'/usr/bin/id -un',
OUT: bukzor
CMD: '/bin/bash -c /bin/date >> /home/testrel/date'
SEC: ok:'/bin/bash', ok:'-c', ok:'/bin/date >> /home/testrel/date',
OUT: /bin/bash: /home/testrel/date: Permission denied
CMD: '/bin/date >> /home/testrel/date'
SEC: ok:'/bin/date >> /home/testrel/date',
OUT: sh: /home/testrel/date: Permission denied
CMD: '/usr/bin/python -c import os; os.system("/usr/bin/id -un")'
SEC: ok:'/usr/bin/python', ok:'-c', ok:'import os; os.system("/usr/bin/id -un")',
OUT: bukzor
CMD: '/usr/bin/python -c import os; os.system("/usr/bin/id -un")'
SEC: ok:'/usr/bin/python', ok:'-c', ok:'import os; os.system("/usr/bin/id -un")',
OUT: bukzor
المحلول
تحتاج إلى تعيين معرف المستخدم الحقيقي الخاص بك على المعرف الفعال (suid-ed).ربما تريد أن تفعل الشيء نفسه بالنسبة لمعرف مجموعتك الحقيقي:
#! /usr/bin/perl -T
use warnings;
use strict;
$ENV{PATH} = "/bin:/usr/bin";
system "id -un";
system "/bin/bash", "-c", "id -un";
# set real user and group ids
$< = $>;
$( = $);
system "/bin/bash", "-c", "id -un";
تشغيل العينة:
$ ls -l suid.pl -rwsr-sr-x 1 nobody nogroup 177 2010-07-22 20:33 suid.pl $ ./suid.pl nobody gbacon nobody
ما تراه موثق bash
سلوك:
-p
قم بتشغيل الوضع المميز.في هذا الوضع،
$BASH_ENV
و$ENV
لا تتم معالجة الملفات، ولا يتم توريث وظائف الصدفة من البيئة، ولا تتم معالجةSHELLOPTS
,BASHOPTS
,CDPATH
وGLOBIGNORE
يتم تجاهل المتغيرات، إذا ظهرت في البيئة.إذا تم بدء تشغيل الصدفة بمعرف المستخدم (المجموعة) الفعال الذي لا يساوي معرف المستخدم الحقيقي (المجموعة)، و-p
لم يتم توفير الخيار، ويتم اتخاذ هذه الإجراءات وتعيين معرف المستخدم الفعال إلى معرف المستخدم الحقيقي.إذا-p
يتم توفير الخيار عند بدء التشغيل، ولا تتم إعادة تعيين معرف المستخدم الفعال.يؤدي إيقاف تشغيل هذا الخيار إلى تعيين معرفات المستخدم والمجموعة الفعالة على معرفات المستخدم والمجموعة الحقيقية.
هذا يعني أنه بإمكانك أيضًا
#! /usr/bin/perl -T
use warnings;
use strict;
$ENV{PATH} = "/bin:/usr/bin";
system "/bin/bash", "-p", "-c", "id -un";
تحصل
nobody
تذكر أن تمرير وسائط متعددة إلى system
يتجاوز القشرة.حجة واحدة تذهب إلى الصدفة، ولكن ربما لا bash
-انظر إلى إخراج perl -MConfig -le 'print $Config{sh}'
.