بيرل في وضع العيب:الحفاظ على suid عند تشغيل برنامج خارجي عبر النظام ()

StackOverflow https://stackoverflow.com/questions/3313855

سؤال

أحاول إضافة ميزة إلى البرنامج النصي القديم.البرنامج النصي 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}'.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top