さくらのレンタルサーバー(ライトプラン)でもbuildしたい


ライトプランではSSHで接続できないのでソースコードから build することができない……ことはないのです。

――そう、CGIならね!

はじめに

さくらが想定した使い方ではないので、すべて自己責任でお願いします。

危険なラッパーを作る

どんなスクリプトでもCGIとして動かせるラッパーを作ります。いうまでもなく危険なので build するときだけ置くようにしましょう。

danger.sh
#!/bin/sh

export USER=`echo -n $DOCUMENT_ROOT | awk -F/ '{print $3}'`
export HOME=/home/$USER
export QUERY_STRING=`echo $QUERY_STRING | awk '/^[[:alnum:]\._-]+$/ {print}'`

IFS=$'\n'
for line in `cat .htaccess`
do
    directive=`echo -n $line | awk '{print $1}'`
    if [ "$directive" = "SetEnv" ]; then
        export `echo -n $line | awk '{print $2"="$3}'`
    fi
done

echo "Content-Type: text/plain"
echo ""

exec ./$QUERY_STRING

CGIなのでUSERHOMEといった基本的な環境変数もセットされていません。使うことも多いので準備します。

whileの中で .htaccess のSetEnvディレクティブを読み込んで環境変数にセットしています。
CGIはsuEXECで実行される都合上、環境変数を親プロセスから引き継いでくれないため、.htaccess で SetEnv しても反映されません。それをここで無理やり反映させています。

危険な .htaccess の配置

標準では .sh のファイルはCGIとして認識されないので .htaccess で設定します。

<Files "*.sh">
    Options +ExecCGI
    SetHandler cgi-script
</Files>

上で説明したようにSetEnvも使えます。

一般的なWebサーバ同様、さくらのレンタルサーバーでも .htaccess はブラウザでアクセスすることはできません。秘密の情報を書くならここに書くのが安全かもしれませんね。

(※SetEnvでは、環境変数と値の区切りはスペースです)

<Files "*.sh">
    Options +ExecCGI
    SetHandler cgi-script
    SetEnv TOP_SECRET I_AM_A_CAT
</Files>

危険な方法で動かすスクリプトの用意

動作させるスクリプトの名前には英数字、アンダースコア(_)、ハイフン(-)、ピリオド(.)しか使えません。引数を与えることもできません。

スクリプト自体はexecで実行できるものならなんでもOKです。(条件さえそろえばバイナリもいけます)

テストはこんな感じにしました。

bomber.sh
#!/bin/sh
env

危険な実行

レンタルサーバーのコントロールパネルから「ファイルマネージャー」を使って危険なラッパーと動作させたいスクリプト、.htaccess をアップロードします。

危険なラッパーがdanger.sh、スクリプトがbomber.shという名前だったら、以下のURLにブラウザでアクセスします。

https://www.example.com/danger.sh?bomber.sh

危険な理由

……わかるな?

(追記: QUERY_STRINGの文字チェックをするようになったので下のは動かなくなりました。よかったよかった)

https://www.example.com/danger.sh?ls
https://www.example.com/danger.sh?yes

危険でもやりたい人向けの注意点

CGIならではの注意点がいくつかあります

  • 処理に時間がかかると強制終了(KILL -9)させられてしまいます。大きなものを build するのは難しいです。(Python 3.7 を入れようとしたら make test で止まった)
  • 標準エラー出力はサーバのコントロールパネルから「アクセスログの確認」→「エラーログ」で見ることができます。ただし1000行までなので、長くなりそうな場合はリダイレクトしたほうがいいと思います。

  • 終わったら消すのを、くれぐれも忘れずに!

危険ついでのおまけ

せっかくなのでPerlでも書いてみました。

danger.pl
#!/usr/bin/perl

if ( $ENV{DOCUMENT_ROOT} =~ m|^(/home/([^/]+))/| ) {
    $ENV{HOME} = $1;
    $ENV{USER} = $2;
}
my $qs = $ENV{QUERY_STRING} if ( $ENV{QUERY_STRING} =~ m|^[a-zA-Z0-9\._-]+$| );

open(FIN, '<', '.htaccess');
while ( <FIN> ) {
    chomp;
    s/^\s*//;
    my @items = split(/\s+/);
    if ( $items[0] eq 'SetEnv' ) {
        $ENV{$items[1]} = $items[2];
    }
}
close(FIN);
print "Content-Type: text/plain\n\n";

exec("./$qs")

.htaccess のシェルスクリプトとPerlの両対応バージョンは、スマートにFilesMatchにしました。

<FilesMatch "\.(sh|pl)$">
    Options +ExecCGI
    SetHandler cgi-script
    SetEnv TOP_SECRET I_AM_A_CAT
</FilesMatch>

ここに掲載しているすべてのスクリプトは GitHub にも置いています。
https://github.com/keioni/qiita-sample/tree/master/201908_sakura_lightplan_hack