やられました。1412 発の spam post をくらいました。
あと気になる点は、数日前に同じアドレス (およびその周辺) から
という嗅ぎ回るようなアクセスがありました。
対策としては、IP アドレスと User-Agent (前者も後者も) で Deny したうえで、ダサいけどこんなプラグインで /./ が含まれるアクセスをエラーにしました (本当は mod_rewrite で拒否したいけれど、正規化されてしまうようでうまくいかない)。
raise 'Permission Denied' if %r|/\./| =~ ENV['REQUEST_URI']
で、とにかく面倒だったのはその後の復旧です。'![ ... http://...zenno...' みたいな荒しだったので、こんなプラグインを書いて '?c=cleanup' で呼び出しました。
def cleanup
print @cgi.header( 'type' => 'text/plain' )
@db.page_info.collect{ |i| i.keys[0] }.each do |page|
keyword = []
@db.get_attribute(page, :keyword).each do |k|
if /^!\[/ !~ k
keyword << k
else
puts "#{page} - #{k}"
end
end
@db.set_attribute(page, :keyword => keyword)
if /^!\[.*zenno/ =~ @db.load( page )
backup = @db.load_backup( page )
if backup.nil? || backup.empty?
@db.delete( page )
delete_proc
puts "d:#{page}"
else
md5 = @db.md5hex( page )
save( page, backup, md5 )
puts "u:#{page}"
end
end
end
end
add_plugin_command( 'cleanup', nil )
今回の経験で、tDiary のようなフィルタ機構の必要性がわかりましたし、よりシンプルなデータ構造が望ましいこともわかりました。
そんなわけで、互換性をそれなりに残しながらもかなりの部分を再設計したい熱が高まってまいりました。
RewriteCond %{THE_REQUEST} "^\S+ .*/\./" みたいなのはどうでしょう。
おぉ、うまくいきました。%{THE_REQUEST} は初耳でした。ありがとうございます!