webshell

この記事は約8分で読めます。
とりあえず作ってみたオリジナルのwebshell画面 そこそこ本物っぽい

webshellと言えば、悪意を持った攻撃者がweb経由でサーバーのシェルコマンドを実行できるバックドアの一種である。要は管理人のサーバーアクセス権限を得て何でもできてしまうものだ。管理人に気がつかれずにwebサーバーに侵入して設置するものだが、実際ものすごい被害があり問題になっている。

さくらインターネットのライトプランでは、通常は使えるサーバーのシェルコマンド(コンソール画面)を使うことができないのだ。上位のスタンダードプランからだと可能で、普通の人はまずいらないと思うのだが、サーバー管理の勉強をするには必要だ。
そうか、webshellってスタンダードプランが契約できない貧乏人がコンソール画面を使うにも便利そうだな。意図的に設置したら便利かもしれない!と思って、知っている情報だけでシコシコと15年ぶり位にPHPでWEBプログラムを作り始めた。

とりあえず、半日位でそれらしき物ができあがった。ちょっと制限はあるけど、かなり便利にシェルコマンドを打てるようになった。さくらインターネットのライトプランでも9割以上の操作はカバーできるんじゃないかと思う。全く出来なかったのが出来るようになったのは、かなり大きい。今後色々遊べそうだ。

うーん、なるほど。。。自分で作ってみて良くわかった。こいつはヤバい。ヤバい代物である。こんなものを密かに設置されたら大問題だ。余裕で情報を抜き取れるね。個人ならまだしも企業の担当者は大変そうである。知らない方が幸せだったかもしれない。

折角作ったので自分のサイトに恒久的に設置することにした。
ただ一応以下の制限をかけてみた。

  • nouno.comとは違うドメインに設置する。ルートでは無く、謎のディレクトリに設置する
  • とりあえずBASIC認証は必須にする。SSLも必須
  • IPv4でのアクセス禁止。IPv6での特定アドレスに限定する

とあるサイトに本物とは別にメンテナンス用の専用ドメインを設置しているという記事を見つけた。本物のドメインにメンテナンス用のプログラムを設置すると、万が一の攻撃があった場合に対処できないとのことだ。確かにその通りだ。
nouno.comのwordpressは念のため標準のwwwディレクトリには設置していない。なのでこのwebshellプログラムもnouno.comには存在しない。nouno.comから見れば存在しないが、とあるサイトから見るとnouno.comのメンテナンスが可能だ。さくらインターネットは、サブドメインとして62種類のドメインから自分用として追加することができるのだが、一時的に使う「捨てメールアドレス」以外には使っていなかったドメインがある。このドメインからのみアクセスが可能としてみた。ルートディレクトリは全アクセス禁止にしているのだが、とあるディレクトリのみ穴を開けてアクセス可能にしたので、見つけるのはそこそこ難しいと思われる。

もちろんこのフォルダにアクセス制限するために認証機能も追加した。
BASIC認証を使うのは今時セキュリティ的にどうかとも思うが、個人のWEBサイトだ。まぁハッキングされたら、それはそれで勉強になるのでよしとした。最低限SSLでのアクセスがなければ拒否されるようにはしてみた。

何故か未だにIPv6は不人気だ。自宅は既にIPv6対応済みで、V6プラスというプランなのでIPv4は固定IPではある。ただ共有IPなので近所の人はアクセスできてしまう。今のところログを見る限り攻撃スクリプトもIPv4が大半なのでIPv4でのアクセスは一切禁止にしてみた。ただIPv6はどのようにIPの払い出しをされているのかは謎なのだが、おそらく契約回線ごとに前半64bitが固定で払い出しと思われた。違ってもおそらく近所の方のみだろう。そこで自宅のIPv6の前半64bitのみ合致をアクセス許可としてみた。.htaccessの書き方もほぼIPv4と同じだ。

Order Deny,Allow
Deny from all
Allow from 1234:5678:789A:BCDE::/64

と書けば良い。アドレスの最後が「::」となるのがポイントだ。IPv4やv6対応の携帯回線からのアクセスは拒否されたので、多分大丈夫である。

以上の設定をすることにより、間違いがなければNounoの自宅以外はアクセス禁止だし、アクセスできたとしても認証が必要だ。自分でバックドアを設置したけど多分大丈夫だろう。

と、ここまでして思いついた。webshellが猛威を振るっているのであれば、そのソースコードを手に入れられれば、より高機能でより便利になるのではないのか?

早速検索をしてみると、githubに沢山のソースコードが普通にあった。これを使えばかなり便利そうだ。今までの苦労は何だったのかと思う位だ。。。
しかしながら試しにダウンロードしてみると、全てのソースコードがウイルス検知ソフトに引っかかり、危険だと警告がでまくった。
おそらくだけど、出回っているソースコードが既にバックドアとして使われているのだと思う。。。

無理矢理ダウンロードしてソースを確認してみると、他のサイトのJavaScriptを読み込んでいたりして、安全なのかどうか確認することができなかった。。。
この手のプログラムは面倒でも自分で実装すべきなのを、この歳になって身をもって知ったのだった。

折角なので、シコシコと作ったオリジナルのwebshellプログラムを公開してみる。15年ぶりのPHPでもなんとかなるもんだ。
構文から思い出すのは大変だったけど、まだまだ若い者には負けない(つもり)

作ってみて初めて気がついたのだが、gccをはじめ多くのコマンドは標準エラーに吐かれるのね。この歳まで知らなかった。。。
サンプルは一応これにも対応しています。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>WebShell - www.nouno.com</title>
<style>
*{
  color:white;
  font-size:16px;
  font-family:monospace;
}
body{
  background-color:black;
}
input{
  border:1px solid transparent;
  outline:none;
  border-bottom-color:gray;
  background-color:transparent;
}
.directory{
  color:lime;
  font-weight:bold;
}
</style>
</head>
<body>
<?php
  session_start();

  if(empty($_SESSION["currentDirectory"])) {
    $_SESSION["currentDirectory"] = getcwd();
  }
  if(empty($_SESSION["outputList"])) {
    $_SESSION["outputList"]="";
  }

  chdir($_SESSION["currentDirectory"]);
  $_SESSION["currentDirectory"] = getcwd();

  $exec_command = htmlspecialchars(mb_convert_encoding($_POST["command"],"utf-8"),ENT_QUOTES,"utf-8",true);

  if($exec_command) {
    if (preg_match("/^cd\s.+/",$exec_command)) {
      $new_directory=explode(" ",$exec_command,2);
      chdir($new_directory[1]);
      $_SESSION["currentDirectory"] = getcwd();
      $_SESSION["outputList"].=$exec_command."<pre></pre>";
      echo $_SESSION["outputList"];
    }
    elseif($exec_command === "exit") {
      echo "<a href='./'>bye!</a>";
      $_SESSION = [];
      $session_destroy();
    }
    elseif($exec_command === "cls") {
      $_SESSION["outputList"]="";
    } else {
      $output = "<pre>".htmlspecialchars(shell_exec($exec_command." 2>&1"))."</pre>";
      $_SESSION["outputList"].=$exec_command.$output;
      echo $_SESSION["outputList"];
    }
  } else {
    $_SESSION["outputList"]="<pre><span class=directory>Login:".date("Y-m-d H:i:s")." from ".$_SERVER['REMOTE_ADDR']."</span></pre>";
    echo $_SESSION["outputList"];
  }
?>
<form method="post">
<span class=directory>
<?php
  $_SESSION["outputList"].="<span class=directory>".$_SESSION["currentDirectory"]."</span>$&nbsp;";
  echo $_SESSION["currentDirectory"];
?>
</span>$
<input size="64" type="text" name="command" autofocus>
</form>
</body>
</html>

※勉強の為に適当に作ったもので、全く検証もしていません。とりあえず動いたレベルです。興味があればどうぞ。

コメント