WordPress 4.2のXSS脆弱性

WordPress4.2.1になってやっとfixされた、Wordpress4.2の脆弱性。ゼロデイ攻撃というやつですねえ。
今回は4.2、4.1.2、4.1.1、3.9.3が対象ということで、かなり大規模じゃないんですかね。
「WordPress 4.2」の更新版公開、全バージョンに深刻な脆弱性が存在 – ITmedia エンタープライズ

WordPress 4.2 Stored XSS

WordPressの現在のバージョンでは、XSSの脆弱性が存在します。認証されていない攻撃者は、WordPressのコメントにJavaScriptを注入することができます。 コメントが表示されると、スクリプトがトリガされます。 ログインした管理者によってトリガすると、デフォルトの設定で、攻撃者は、プラグインとテーマエディタを介してサーバ上で任意のコードを実行する脆弱性を利用することができます。 あるいは攻撃者は、管理者のパスワードの変更や新しい管理者アカウントを作成したり、 現在ログインしている管理者がシステム上で行うことができるものは何でも行うことができます。

原理としては、
WordpressのコメントのデータベースはMySQLのTEXT型として登録するため、
64KB(65,535B)以上だと途中で文章が切り捨てられ、そのままhtmlタグとして動作する。
といった感じですか?
実際自分で自鯖を攻撃して試してみるのも良かったかもしれない、がその前にアップデートしちまった。

動画DEMOでは、コメントでexploit.jsを流し込んで、バックドアを仕掛けてます。
これ見る限りやはり管理者権限と同等のことが出来るようです。怖いなあ。こんなもん放置してたのかよ・・・
4.2またはその他対象のバージョン使用者は、早急にアップデートしたほうがよろしいと思います。

node.jsなんかでオンラインなゲームを作る(5) ルーム機能(socket.io)

Websocketを利用して、特定の処理や通知などをそのルーム、またはその人にだけ行う。

WebSocket – Wikipedia
Websocketは双方向通信のプロトコルです。html5と対応ブラウザなら動作します。
双方向通信なので、つまりは、サーバ側からクライアントにプッシュ通知、クライアントからサーバ側にデータ送信、といったことが可能になります。
connectionが成立した後は後ろでプロトコルが動いてくれますので、動的なWebサイトとして、しかもサーバとのやり取りをずっと行えます。
この技術を応用すれば、オンラインゲームに必須なチャット機能的なこと、ダメージ処理とかそういうの、が全部ブラウザ上で動くってことですね。
Ajax(XMLHttpRequest)なんかだとクライアントから問い合わせは出来てもサーバから受け取ることは難しいので、Ajaxの上位互換みたいな感じらしいです。
socket.ioは、Websocketを使うためのnode.jsモジュールです。

まずは、初期設定的な何か。
サーバ(app.js)
socketio = require('socket.io')
var server = http.createServer(app);
var io = socketio.listen(server);
これで、websocketプロトコルをlistenします。一応独自プロトコルなのですがTCP 80/443で動作しますので、そのままhttp(TCP 80)に乗っける形になるのでこう書きます。

クライアント(main.js)
var socket = io.connect();
クライアントは、事前にhtmlから/socket.io/socket.io.jsをロードして使用します。
(socket.ioサーバーを立てた段階で、自動的にサイトからロードできるようになります)
前回作成したejsに書いておきます。
そうすれば、この一行を書くだけで使えるようになります。
socket.ioは、socket.emit(送信する値)で送信、socket.onで受け取りの処理(callback)大体この二つを使います。

socket.ioでのROOM処理は、この辺を参照。
既にjoinメゾットというのが準備されていて、同じ部屋にjoinしたクライアントだけ、emit(送る)ことが出来ます。
参考:Socket.IO — Rooms and Namespaces
Node.js – Socket.IO覚え書き(Room、joinまわり) – Qiita

順を追って書いていくと、
クライアントが接続するので、その接続をサーバ側が受け取り、サーバ側はRoomIDにしたがってjoinメゾットで部屋を振り分けます。
その後、to(room).emitメゾットでその部屋のみ送ります。

クライアント(main.js)

socket.on('connected', function() {
            //部屋番号送信・初期表示
            socket.emit('init', {'room': RoomID});
        });
        //文章受け取り
        socket.on("logmessage", function (data) {
            logpush(data); //dataを文章を表示する関数
        });

s.on(‘connected’,[callback])はWebsocket接続完了時に自動的に呼び出されます。それに、RoomIDをinitとしてサーバに送信。

サーバ(app.js)

var chat = io.sockets.on('connection', function(socket) {
    socket.emit('connected');
    console.log(socket.id+" connected");
    //room別に管理
    socket.on("init",function(req){
        //join(room)で部屋を作る
        socket.setRoominfo=req.room;
        socket.join(req.room); //roomIDごとに登録
        socket.join(socket.id); //個別に識別するためにクライアント識別子であるsocketidを登録

        console.log(req.room+" join");

    });
    socket.on('msg post', function(msg) { //Room内にメッセージ送信
        chat.to(socket.setRoominfo).emit("logmessage", msg);
    });
});

簡単なチャットとしての機能が出来ました。
socket.setRoominfoに、一時的なデータを格納するためRoomIDを入れています。
これで、各クライアントが’msg post’と文字列をemitすると、同じルームに入っているクライアント全てに表示されます。
その後、Disconnection(ブラウザから離れた時)の処理、gameをstartした時の処理、などでログを表示するようにします。
game
まあ、ゲームの道のりは遠い。次はmongoDBです。


githubにソースがあります。製作中。ソースは自由に。

前:node.jsなんかでオンラインなゲームを作る(4) ルーム機能

[node.js]HTTPS通信に対応させてみる(SSL-リバースプロキシ環境を構築する)

タイトルの通り。httpsのこともこれから勉強していかなければならないのかなーと思い。

きっかけはこの記事です。

『証明書を無料で発行、HTTPSの導入を支援する「Let’s Encrypt」』は何に使え、何に使えないのか – いろいろやってみるにっき

HTTPS普及を推進するプロジェクト「Let’s Encrypt」、Linux Foundation傘下に

これを見ながら10年後くらいはWeb全てがhttpsになってんじゃねーかなと思えてきて。

無料なら個人でも気兼ねなく使えますもんね。商用には辞めたほうがいい感じですけれど・・・

 

当然、証明書は所謂オレオレ証明書です。

・・・オレオレ証明書って言い方はどうなんだろうとちょっと思います。別に偽サイトじゃないのにニュアンスからそう思わせてしまうじゃないかと。

ソースコード。

var https = require('https');
var fs = require('fs');

var ssloptions={key: fs.readFileSync('server.key', 'utf8'),
    cert: fs.readFileSync('server.crt', 'utf8')};

var serverhttps = https.createServer(ssloptions,function ( req, res ) {
        res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('SSL Connection');
});

serverhttps.listen(443);

URL:https://potproject.net/

※オレオレ証明書なので当然https通信に関する警告が各ブラウザで出ます。

node.jsには標準モジュールとして既にhttpsが存在します。これでencrypt関連のことは全く知らなくても使えます。

なので、最小限のコードであれば通常のhttp通信と違うところは証明書の登録をしなくてはならないという点だけです。

証明書(秘密鍵・公開鍵)に関してはopensslで生成。ここに公的機関が発行した証明書を入れ替えればすぐに使えます。

これで通信は暗号化されたわけですが、最近はSSL絡みの脆弱性がいっぱい出てきてますし、規格に関してはまだまだ変わっていくのでしょうかねー・・・

このブログもhttpsに対応させよう

せっかくなのでブログも対応させよう。

httpsに対応することで、ログイン時に盗聴されて乗っ取られることはなくなると思います。そもそもまずそんなことは起きない・・・というツッコミはさておき。
鯖自体、リバースプロキシサーバでサブドメインごとに振り分けているため、設定は結構複雑になってきます。

こんな感じで鯖の構造も変更しました。
http-node-proxy(リバースプロキシサーバ | port 80/443[外部ポート番号])
—potproject.net(Node.js | port 8080(http/https)
—blog.potproject.net(Apache | port 8081(http)/8443(https))
別途、ApacheにSSLの設定をしなくてはならないです。

と思ったんですが、リバースプロキシからの通信は暗号化する必要ないので(同じ鯖で内部ルーティングしているため)、
ネットワークからリバースプロキシまでをSSLで暗号化、
リバースプロキシからapacheの受付内部ポートまでは暗号化せずhttpで渡すようにしました。
なので、バーチャルホスト設定で8443ポートを内部ルーティングできるようにして、ApacheのSSL設定は停止しました。
Apache ssl.conf設定。ssl.confだけどSSL切ってます

Listen 8443 https

<VirtualHost _default_:8443>

# General setup for the virtual host, inherited from global configuration
DocumentRoot "/var/www/wordpress"
ServerName blog.potproject.net
SetEnv HTTPS on

#   SSL Engine Switch:
#   Enable/Disable SSL for this virtual host.
SSLEngine off

---中略---

</VirtualHost>

node.jsプロキシサーバの設定。

var https = require('https');
var fs = require('fs');

var httpsoptions={target:'http://127.0.0.1:8443',secure:false};

var ssloptions={key: fs.readFileSync('server.key', 'utf8'),
    cert: fs.readFileSync('server.crt', 'utf8')};

var serverhttps = https.createServer(ssloptions,function ( req, res ) {
        if (req.headers.host == 'potproject.net') {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('SSL Connection');
    }else if (req.headers.host == 'blog.potproject.net') {
        Proxy.web( req, res ,httpsoptions);

    }

});
serverhttps.listen(443);

こんな形に変更しました。

options[secure]はhttps -> httpsでプロキシをする時にtrueにします。今回はhttps -> httpなのでfalseです。

そしてhttpsでつながった・・・のはいいのですが、デザインが崩れて明らかにCSSやJSが読み込めていない。
調べたところ、こういう問題があるようです。
WordPress をSSL運用すると管理画面でアップロードした画像が見れない
こんな問題があるらしい。ってことはまだ治っていないのだろうか?それともテーマの問題か?
ということでSetEnv HTTPS onをssl.confに追加し、コードを組むことででちゃんと表示されるようになりました。
その後、WordPress HTTPS(SSL)プラグインを導入し、管理者ログインと画面をhttps通信化。
ちゃんと管理者画面だけhttpsにリダイレクトしてくれますのでいいですね。

https://blog.potproject.net/
※オレオレ証明書なので当然https通信に関する警告が(以下略
これでこのブログもhttpsの仲間入りですね。オレオレ証明書だしまあ多分ほとんど意味ない気がしますが・・・
Let’s Encryptの無料証明書がきたらぜひ使ってみようと思います。まあその時までこのままで。
無料のSSLならStartSSLなんか使えるという声もありますが登録めんどそうなので・・・

node.jsなんかでオンラインなゲームを作る(4) ルーム機能

オンラインゲームには不可欠な存在だと思える、ルーム機能を実装していきます。
内容は、そのままルーム機能です。チャットで個別の部屋みたいなのを実装するためのもの。
同じ部屋同士で対戦できます。逆に同じ部屋に入っていないと対戦できません。これがちゃんと機能しないとえらいこっちゃです。

この機能には、express,ejs,socketを利用します。
ということで、requireで指定します。おまじないという奴です。
var express = require('express')
, http = require('http')//標準モジュール http
, path = require('path') //標準モジュール path
, fs = require('fs') //標準モジュール filesystem
, socketio = require('socket.io')
, mongoose = require('mongoose')
, ejs=require('ejs');

ルーム機能の実装には、socket.ioが不可欠です。ほぼこいつに頼りきり。
流れとしては、

  1. form.htmlからPOSTでルーム番号を送る
  2. ルーム番号を受け取り、ejsで表示、その部屋に入る(index.ejsへ遷移)
  3. emitで通知する場合、そのルーム内だけ通知するようになる(socket.io)

これが一連の流れとなります。
3はsocket.ioを含む処理のため、次の記事で。1,2を実装していきましょう。

ejsについて
ejsはテンプレートエンジンというもので、htmlに変数を流しいれるために使うファイルみたいなものです。VIEWに当たるもの。
書き方としては、PHPやJSPと似てます。htmlにejsタグを付けて、変数を入れていきます。
ついでに、デフォルトでエスケープ処理をしてくれたりもします。
[index.ejs]

<%=room_id %>に送った変数[room_id]が挿入されます。JSPと書き方ほぼ一緒だし見分けがつかない
これで、POSTで送った値を取得したら、ejsで流し込み、タイトルに表示・javascriptの値として登録します。

<html>
  <head>
    <meta charset="utf-8">
    <title>RoomID:<%=room_id %></title>
    <script type="text/javascript">
    var RoomID = "<%=room_id %>";
    </script>
  </head>
  <body>
  </body>
</html>

[form.html]
送信する方のPOSTはこんな感じです。特に何も考えずシンプルに実装。こっちはhtmlです。

<!DOCTYPE html>
  <head>
    <meta charset="utf-8">
    <title>title</title>
  </head>
  <body>
  <form action="./" method="post">
    <p>部屋ID:<input type="text" name="room" size="10"></p>
      <p>
    <input type="submit" value="入室"><input type="reset" value="リセット">
      </p>
</form>
  </body>
</html>

[app.js]
app.jsはサーバーサイドのjavascriptとして。サーバーの処理を記述します。
httpサーバのlisten、expressの初期設定などは省略します。
POSTで送った値はreq.bodyに格納されているということが割と重要です。覚えていないと変なところで躓くかも。

//入室
app.get('/', function(req,res){ //アクセスされたら
      fs.readFile('form.html',function(err, data){ //form.html読み込んで送る
        if (err) {
            console.error("console:"+err);
            res.send(404); // エラーで404を返す
            return;
        }
        res.set('Content-Type', 'text/html');
        res.send(data);
      });
});
//index.htmlのGET
app.post('/', function(req,res){ //postで送られて来たら
        if(req.body.room==null){
            res.send(500); // 値なしならエラーで500を返す
            return;
        }
        res.render('index.ejs',{room_id:req.body.room}); //ejsをレンダリングして送る
        });

});

次はsocket.ioについて理解していかないと・・・。


githubにソースがあります。製作中。ソースは自由に。

前:node.jsなんかでオンラインなゲームを作る(3) express設定
次:node.jsなんかでオンラインなゲームを作る(5) ルーム機能(socket.io)

node.jsなんかでオンラインなゲームを作る(3) フレームワークであるExpressの設定

Expressはnode.jsで動作するフレームワークです。多分nodeの中では一番有名で、これを使うことでWebサーバの操作がぐっと楽になると思います。
Express Fast, unopinionated, minimalist web framework for Node.js
これがなくてもhttpサーバは立てられますが、変数を入れたりPOSTを処理したりなど複雑な操作は、コードを書いて処理しないといけません。
そういうのを一括で解決してくれるものをフレームワークと呼びます。
元々Androidアプリばっかり作ってたのでWebフレームワークというものをほとんど使ったことが無かった私なのですが、
これを使うとWeb開発がめちゃくちゃ楽になり、やらないといけない作業も数段減るため、
最近のWeb開発においてはフレームワークはほぼ必須なんだなあと使ってると思います。
Express設定
一部抜粋。全文はソースにて。

var express = require('express')
  , http = require('http')
  , path = require('path')
  , socketio = require('socket.io')
  , fs = require('fs')
  , mongoose = require('mongoose')
  , ejs=require('ejs');
var app = express();
var server = http.createServer(app);
var io = socketio.listen(server);

//expressの設定(socket.ioは関係ないです)
app.set('port', process.env.PORT || 8080); //portを指定(デフォルト:8080)
app.set('view engine', 'ejs'); //ejsを使用
app.use(express.favicon()); //標準faviconを出力
app.use(express.logger('dev')); //logger:開発用に詳細ログが表示されるようになります
app.use(express.json()); //bodyParser絡み
app.use(express.urlencoded()); //bodyParser絡み
app.use(express.methodOverride()); //methodOverride ミドルウェア
app.use(app.router); //パス名絡み
app.use(express.static(path.join(__dirname, 'img'))); //staticなディレクトリ

expressの設定は結構いろいろあってこれはこれで覚えるところ多くて大変。
コメントで簡単な説明を付けましたが、自分も完全な中身は知らないので各自ググってください。
app.use(express.favicon());
は、別にfaviconいらないし付ける必要もないのですが、これがないとコンソールさんにfaviconねーぞと怒られるので付けました。
app.use(express.json());
app.use(express.urlencoded());
は、前話したbodyparser絡みの設定。これを入れておかないとpostした時とかエラー吐きますのでとりあえず入れておきましょう。
app.use(express.static(path.join(dirname, 'img')));
Express.staticは、指定したファイル/ディレクトリをスタティックなファイルとして公開します。
つまり、http上でディレクトリ内の画像やjsファイルなど、誰でもアクセスが可能になります。
ディレクトリの指定も可能です。(ディレクトリ内のファイルが全て公開されます)
path.joinは、絶対パスで指定しなければならないために使用します。
dirnameは、実行しているjsファイルのディレクトリパスを表します。

この後は、アクセスされた時の処理を書いていきます。


githubにソースがあります。製作中。ソースは自由に。

前:node.jsなんかでオンラインなゲームを作る(2)
次:node.jsなんかでオンラインなゲームを作る(4) ルーム機能