Perl ソースコードを用いて suidperl を構築する
SETUP
.style1 {
background-color: #FFFFFF;
}
.style2 {
white-space: nowrap;
}
suidperl
Qmail-Scanner というプログラムをインストールしていたときのこと、UID の切り替えに対応した suidperl が必要になりました。
ディストリビューションによっては追加インストール可能になっている場合もあるようでしたけど、Slackware 10.2 では、提供されていないような感じです。C-wrapper があればなくても良いような記載もありましたけど、その C-wrapper の情報も、なかなか見つかりませんでした。
そんな中、Perl をソースコードからコンパイルすれば、UID の切り替えに対応させることができるような情報が見つかりましたので、その方法で suidperl を作成してみることにしました。
suidperl を構築する
suidperl を構築するに当たって、まずは http://www.cpan.org/src/README.html から、Perl のソースコードを取得します。
現時点での最新版である Perl 5.8.9 のソースコード (perl-5.8.9.tar.gz) を /usr/local/src ディレクトリへダウンロードしたら、展開し、コンパイルの準備を進めます。
tar xvzf perl-5.8.9.tar.gz
cd perl-5.8.9
次のコマンドを実行すると、Perl の構築に必要な事項の確認を行うことになります。
./Configure
確認される内容については、ほとんどが既定値のままで良いのですけど、一部だけ、特別な設定を行います。
具体的には suidperl として振舞うために "Do you want to do setuid/setgid emulation?" に "y" と回答することと、既存のバージョンの Perl を残しておくために "What shall I put after the #! to start up perl ("none" to not use #!)?" に対して "/usr/local/bin/suidperl" と答える感じです。
質問内容 | 既定値 | 設定値 |
---|---|---|
Which of these apply, if any? | linux | 既定値の通り |
Operating system name? | linux | 既定値の通り |
Operating system version? | 2.4.31 | 既定値の通り |
Installation prefix to use? (~name ok) | /usr/local | 既定値の通り |
What installation prefix should I use for installing files? (~name ok) | /usr/local | 既定値の通り |
Build Perl for SOCKS? | n | 既定値の通り |
Use the PerlIO abstraction layer? | y | 既定値の通り |
Build a threading Perl? | n | 既定値の通り |
Build Perl for multiplicity? | n | 既定値の通り |
Use which C compiler? | cc | 既定値の通り |
Directories to use for library searches? | /usr/local/lib /lib /usr/lib | 既定値の通り |
What is the file extension used for shared libraries? | so | 既定値の通り |
Try to use long doubles if available? | n | 既定値の通り |
What libraries to use? | -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc | 既定値の通り |
What optimizer/debugger flag should be used? | -O2 | 既定値の通り |
Any additional cc flags? | -fno-scrict-aliasing -pipe -I/usr/local/include | 既定値の通り |
Any additional ld flags (NOT including libraries)? | -L/usr/local/lib | 既定値の通り |
Try to use 64-bit integers, if available? | n | 既定値の通り |
Try to use maximal 64-bit support, if available? | n | 既定値の通り |
What is your architecture name | i686-linux | 既定値の通り |
Pathname where the public executables will reside? (~name ok) | /usr/local/bin | 既定値の通り |
Use relocatable @INC? | n | 既定値の通り |
Pathname where the private library files will reside? (~name ok) | /usr/local/lib/perl5/5.8.9 | 既定値の通り |
Where do you want to put the public architecture-dependent libraries? (~name ok) | /usr/local/lib/perl5/5.8.9/i686-linux | 既定値の通り |
Other username to test security of setuid scripts with? | none | 既定値の通り |
Does your kernel have *secure* setuid scripts? | n | 既定値の通り |
Do you want to do setuid/setgid emulation? | n | y |
Installation prefix to use for add-on modules and utilities? (~name ok) | /usr/local | 既定値の通り |
Pathname for the site-specific library files? (~name ok) | /usr/local/lib/perl5/site_perl/5.8.9 | 既定値の通り |
List of earlier versions to include in @INC? | none | 既定値の通り |
Do you wish to wrap malloc calls to protect against potential overflows? | y | 既定値の通り |
Do you wish to attempt to use the malloc that comes with perl5? | n | 既定値の通り |
Pathname for the site-specific architecture-dependent library files? (~name ok) | /usr/local/lib/perl5/site_perl/5.8.9/i686-linux | 既定値の通り |
Do you want to configure vendor-specific add-on directories? | n | 既定値の通り |
Colon-separated list of additional directories for perl to search? | none | 既定値の通り |
Install any extra modules (y or n)? | n | 既定値の通り |
Directory for the main Perl5 html pages? (~name ok) | none | 既定値の通り |
Directory for the Perl5 module html pages? (~name ok) | none | 既定値の通り |
Do you want to install perl as /usr/bin/perl? | n | 既定値の通り |
Shall I use /usr/bin/nm to extract C symbols from the libraries? | n | 既定値の通り |
Do you wish to use dynamic loading? | y | 既定値の通り |
Source file to use for dynamic loading | ext/DynaLoader/dl_dlopen.xs | 既定値の通り |
Any special flags to pass to cc -c to compile shared library modules? | -fPIC | 既定値の通り |
What command should be used to create dynamic libraries? | cc | 既定値の通り |
Any special flags to pass to cc to create a dynamically loaded library? | -shared -O2 -L/usr/local/lib | 既定値の通り |
Any special flags to pass to cc to use dynamic linking? | -Wl,-E | 既定値の通り |
Build a shared libperl.so (y/n) | n | 既定値の通り |
Where do the main Perl5 manual pages (source) go? (~name ok) | /usr/local/share/man/man1 | 既定値の通り |
What suffix should be used for the main Perl5 man pages? | 1 | 既定値の通り |
Where do the perl5 library man pages (source) go? (~name ok) | /usr/local/share/man/man3 | 既定値の通り |
What suffix should be used for the perl5 library man pages? | 3 | 既定値の通り |
Your host name appears to be "********". Right? | y | 既定値の通り |
What is your domain name? | *****.***.JP | 既定値の通り |
What is your e-mail address? | ***@****.***.JP | 既定値の通り |
Perl administrator e-mail address | ***@****.***.JP | 既定値の通り |
Do you want to install only the version-specific parts of perl? | n | 既定値の通り |
What shall I put after the #! to start up perl ("none" to not use #!)? | /usr/local/bin/perl | /usr/local/bin/suidperl |
Where do you keep publicly executable scripts? (~name ok) | /usr/local/bin | 既定値の通り |
Pathname where the add-on public executables should be installed? (~name ok) | /usr/local/bin | 既定値の通り |
Pathname where the site-specific html pages should be installed? (~name ok) | none | 既定値の通り |
Pathname where the site-specific library html pages should be installed? (~name ok) | none | 既定値の通り |
Pathname where the site-specific manual pages should be installed? (~name ok) | /usr/local/share/man/man1 | 既定値の通り |
Pathname where the site-specific library manual pages should be installed? (~name ok) | /usr/local/share/man/man3 | 既定値の通り |
Pathname where add-on public executable scripts should be installed? (~name ok) | /usr/local/bin | 既定値の通り |
Use the "fast stdio" if available? | y | 既定値の通り |
Try to understand large files, if available? | y | 既定値の通り |
What is the extension of dynamically loaded modules | so | 既定値の通り |
Shall I ignore gethostname() from now on? | n | 既定値の通り |
Shall I ignore gethostname() from now on? | n | 既定値の通り |
Do you still want to use vfork()? | n | 既定値の通り |
Doubles must be aligned on a how-many-byte boundary? | 4 | 既定値の通り |
Use which function to generate random numbers? | drand48 | 既定値の通り |
What type pointer is the second argument to getgroups() and setgroups()? | gid_t | 既定値の通り |
What pager is used on your system? | /usr/bin/less | 既定値の通り |
Which compiler compiler (byacc or yacc or bison -y) shall I use? | /usr/bin/byacc | 既定値の通り |
What extensions do you wish to load dynamically? | B ByteLoader Cwd ... threads/shared | 既定値の通り |
What extensions do you wish to load statically? | none | 既定値の通り |
Press return or use a shell escape to edit config.sh: | 既定値の通り | |
Run make depend now? | y | 既定値の通り |
なお、注意点として、既存のバージョンを残すようにしたとしても、インストール時に /usr/local/bin/perl のバイナリも併せて更新するようです。
既存の Perl は旧バージョンの処理系が維持されるようなのですけど、バイナリが更新されるせいなのか、旧バージョンでも UID の切り替えが可能でした。
コンパイル前に念のため、既にインストールされている Perl のバックアップを取っておくと安心かもしれません。
ともあれこれで、コンパイルのための準備は完了です。
具体的には、config.sh 内の d_dosuid の値が 'define' となっていれば大丈夫です。
後は次のようにして、Perl のコンパイルを行います。
make
make test
make install
これで、/usr/local/bin/suidperl として、Perl がインストールされました。
最後に、インストールされた suidperl に対して、s ビットを付加すれば完成です。
chmod +s /usr/local/bin/suidperl
suidperl の動作を確認する
suidperl は、Perl スクリプトに設定されている s フラグとそのファイルの所有者情報を元に、実行時の UID を切り替えるようになっています。
正しく動作しているかを確認する方法としては、まず、次のような Perl スクリプトを作成します。
#!/usr/local/bin/suidperl
print `whoami`;
このスクリプトを、たとえば "test.pl" というファイル名で保存したとします。
これに次のようにして、ファイルの所有者を "user1" に変更し、パーミッションとして s ビットを付加します。"user1" というところには、Linux に登録されているユーザ名を指定する必要がありますので、登録済みのユーザ名に置き換えてください。
chown user1 test.pl
chmod +s test.pl
これで準備完了です。
次のようにしてスクリプトを実行すれば、実行時のユーザー名として、ファイルに設定した所有者名が取得されるのを確認できると思います。
./test.pl