Edited at

Perlプログラムにsetuid

More than 3 years have passed since last update.


setuid

まず、setuidというのが有ります。

あるコマンドをそのコマンドの所有者の権限で実行する場合に使用します。

例えばmkdirコマンドの所有者はrootです。

$ ls -la /bin/mkdir

-rwxr-xr-x 1 root root 44744 6月 22 20:46 2012 /bin/mkdir

このmkdirを適当にコピーしてsetuidします。

$ sudo cp -a /bin/mkdir .

$ ll
-rwxr-xr-x 1 root root 44K 2012/06/22 20:46:14 mkdir*
$ sudo chmod +s ./mkdir
$ ll
-rwsr-sr-x 1 root root 44K 2012/06/22 20:46:14 mkdir*

パーミッションのところに's'が付いたのがわかります。このmkdirを一般ユーザで使用すると、root権限で実行されます。

$ ./mkdir test

$ ll
-rwsr-sr-x 1 root root 44K 2012/06/22 20:46:14 mkdir*
drwxr-xr-x 2 root root 4.0K 2016/02/12 13:20:36 test/

作成したtestディレクトリの所有者がrootになってます。


perlプログラムに実行する

setuidをperlプログラムにも付与してみます。

$ cat a.pl

$file = $ARGV[0];
system("touch $file");

↑引数でパスを指定して、そのパスにファイルを作るプログラムです。

所有者をrootにして、setuidします。

$ sudo chown root.root  ./a.pl

$ sudo chmod +s ./a.pl

一般ユーザで実行してみます。

$ ./a.pl /test

Can't do setuid (cannot exec sperl)

何かが足りない。 調べた結果、perl-suidperlをインストール。

$ sudo yum install perl-suidperl

改めて実行

$ ./a.pl /a

Insecure $ENV{PATH} while running setuid at ./a.pl line 3.

どうも"$ENV{PATH}"を指定しなくてはいけないようです。

セキュリティの為にも使うコマンドだけ集めてそのディレクトリを指定すべきでしょうが、

とりあえず/binに。

$ cat a.pl

#!/usr/bin/perl
$ENV{PATH} = "/bin";
$file = $ARGV[0];
system("touch $file");

改めて実行。

$ ./a.pl /a

Insecure dependency in system while running setuid at ./a.pl line 4.

またエラー。。。

外から指定される値を、そのままsystem()等で使う場合に上記の警告がでるようです。

以下のように適当なif文を入れました。

本来は不正なコードが指定されないようにチェックする必要があります。

$ cat a.pl

#!/usr/bin/perl
$ENV{PATH} = "/bin";
$file = $ARGV[0];

if ($file =~ /^([\/\w]+)$/) {
$file = $1;
} else {
print("error\n");
exit(1);
}

system("touch $file");

改めて実行。

$ ./a.pl /a

$
$ ls -la /a
-rw-r--r-- 1 root root 0 2月 12 14:24 2016 /a

できました。