バランスを取りたい

よくCTFの記事を書きます

RuCTF 2014 Writeup (Crypto 100)

100. MD5

Server (python27.quals.ructf.org:12337) accepts only authorized messages.
It works like this:

	buf = c.recv(4096)
	digest, msg = buf.split(" ", 1)
	if (digest == md5(password+msg).hexdigest()):
		#here I send a secret
	else:
		c.send("Wrong signature\n")

You have intercepted one authorized message: "b34c39b9e83f0e965cf392831b3d71b8 do test connection". Construct your own authorized message! Answer starts with 'RUCTF_'

Length extension attackを知ってるかどうかが勝負の分かれ目らしい。
IRCで変な質問してる人がいたりして面白かったです(真顔


この手の攻撃で知ってるツールはHashPumpだけだったのでそれでなんとかしました。
結果下見たいなコードになったんですが、Pythonほとんど書いたことが無くて文字列の処理周りでめっちゃ大変なことになってます。
あと、文字列周りでエラー吐く可能性があったんですが何事も無く動いたのでそのままです。

import socket
import time
import commands

host = "python27.quals.ructf.org"
port = 12337

known_sig = "b34c39b9e83f0e965cf392831b3d71b8"
known_text = "do test connection"

def test(sign, text):
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM);
  sock.connect((host, port))
  
  data = sign + " " + text
  sock.send(data)
  time.sleep(0.1)
  return sock.recv(4096)

for i in range(1,32):
  cmd = "/Users/rex/CTF/tools/HashPump/HashPump"
  cmd += " -s " + known_sig
  cmd += " -d \"" + known_text + "\""
  cmd += " -k " + str(i)
  cmd += " -a " + "AAAA"
  sign, text = commands.getoutput(cmd).split('\n')
  a, b = text.split('\\x80')
  b = b[:-4].replace('\\x','').decode('hex')

  data = a + '\x80' + b + 'AAAA'
  res = test(sign, data)
  print str(i) + ': ' + res
  if not 'Wrong' in res:
    break

RuCTF 2014 Writeup (Recon)

100. Favourite Book

Have you ever met Olimpiada Balalaykina?
She is a young girl who likes to chat and dreams to meet Pavel Durov.
We'd like to know her favorite book.

これ、だいぶ困りました。
ぐぐってもFacebookでも全く出てこないので放置ゲーしてました。


@lmt_swallowが「やっぱりvk.comかなあ」と言うので二人で見に行ったところ、アカウントを発見。

なんかの文章付きのバッグの写真をアップロードしているのでGoogle画像検索に投げつけました。

すると、"Pride and Prejudice Cotton Book Bag"って名前らしいことがわかるので、
"Pride and Prejudice"をsubmitして100pt。


200. Stolen Camera

Have you ever met Olimpiada Balalaykina?
She is a young girl who likes to chat and dreams to meet Pavel Durov.
Сould name the city where her camera was stolen.

vk.comのpostにある、
"My friend always tells me not to use my relatives' birthdays as a password but he have just tweeted that his own mail had been hacked! Hahaha! :DDD"
がどう考えても怪しい。でもなんだろう。

っていう状態で、Grannyって誰だろうと@akiymさんに聞いたところ、
普通に「おばあちゃん」って意味だとわかったのでそこでひらめきました。

  • 親族の誕生日がパスワード
  • 誕生日は先週の日曜日(写真のアップロード日は2014年3月6日)
  • おそらく80歳を祝っているバースデーケーキ
  • メールアドレスが公開されている

という条件から、メールボックスが見られると推測し、メールアドレスのドメインからMXレコードを引いたところ、GoogleAppsでした。


パスワード19340302とかやってたんですが@akiymさんが地域によって日付の書き方違う、とナイスな指摘をしてくれたので02031934でメールボックスに侵入。


するとGoogleMap付きのメールがあるので、
そのMap上のポイントと、VKのamerican tripのアルバムのコメントの内容から
Day7に行った場所、すなわちGreat Junctionをsubmitして200pt。

200点問題はちゃんと推理可能なように適度にヒントが散りばめられていてすごくいい問題でした

CSAW CTF 2013 Reversing 150 Write-up

f:id:xrekkusu:20130923123414p:plain

見た感じ.NETのアセンブリだからとりあえずILSpyで開いてみます。


f:id:xrekkusu:20130923123205p:plain



あっ…(察し)



なんて騒いでないで.NETの知識を使ってガンガン進んでいきましょう。


Submitボタンを押すとClickイベントが走るのでそこに何かがあるはずです。

Clickイベントといえば (object sender, EventArgs e)ですね。

private void eval_ᜀ(object obj, EventArgs eventArgs)
{
	string strB = null;
	Assembly executingAssembly = Assembly.GetExecutingAssembly();
	ResourceManager resourceManager = new ResourceManager(executingAssembly.GetName().Name + ".Resources", executingAssembly);
	DateTime now = DateTime.Now;
	string arg_65_0 = this.eval_ᜀ.Text;
	string value = string.Format("{0}", now.Hour + 1);
	string text = "NeEd_MoRe_Bawlz";
	this.eval_ᜀ(text, Convert.ToInt32(value), ref strB);
	if (string.Compare(arg_65_0.ToUpper(), strB) == 0)
	{
		this.eval_ᜂ.Text = "";
		this.eval_ᜀ(this.eval_ᜀ(107));
		this.eval_ᜁ();
		this.eval_ᜂ.Text = string.Format(this.eval_ᜂ.Text, this.eval_ᜀ(resourceManager));
		this.eval_ᜃ.Image = (Bitmap)resourceManager.GetObject("Sorry You Suck");
	}
	else
	{
		this.eval_ᜃ.Image = (Bitmap)resourceManager.GetObject("Almost There");
		this.eval_ᜀ();
	}
}


if(string.Compare(...))なんてのが見えます。
この条件をtrueにすればフラグが表示されそうです。


ifの1行前を見ると、ref付きで何かの関数に処理を投げています。

private void eval_ᜀ(string text, int num, ref string ptr) {
  int num2 = 0;
  if (0 < text.Length) {
    do {
      char c = text[num2];
      int num3 = 1;
      if (1 < num) {
        do {
          c = Convert.ToChar(this.eval_ᜀ(Convert.ToInt32(c), num3));
          num3++;
        }
        while (num3 < num);
      }
      ptr += c;
      num2++;
    }
    while (num2 < text.Length);
  }
  ptr = this.eval_ᜀ(ptr);
}

中盤、終盤のevalはそれぞれこんな感じになってます。

private int eval_ᜀ(int num, int num2) {
  return (new int[] {
    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113
  })[num2] ^ num;
}
private string eval_ᜀ(string s) {
  byte[] bytes = Encoding.ASCII.GetBytes(s);
  return BitConverter.ToString(new MD5CryptoServiceProvider().ComputeHash(bytes)).Replace("-", "");
}


NeEd_MoRe_Bawlzを暗号化した文字列と、ユーザーから入力された文字列が一致してればいいみたいな空気です。
しかもそれは1時間ごとに変わるらしい。


ということなので手っ取り早く上のコードをうまく繋ぎあわせて入力すべき文字列が表示されるようなプログラムを作ります。



そしてフラグをゲットします。

f:id:xrekkusu:20130923131456p:plain



でもこのフラグは通りませんでした…


というのも、途中に出てくるNeEd_MoRe_BawlzをGoogleで検索すると大量のideoneがヒットして、そこを見るだけで解けてしまうっぽいです。


[追記]

実際は元の文字列が文字化けして????????...なってたのをコンバートした結果?????...のハッシュ値になってしまっていたという情報。

通らないからここからもう一捻りかと思って調べたら?????...のハッシュであることは理解してたんだけどねえ…。

======


なので"If your key isn't working PM ColdHeat on IRC"に従ってPMを送ってみると、


"how did you get the key?"


あっ…あっ…(英語ができない)


"i used ILSpy"

"describe more. go in depth"


あっ…あっ…



ってな感じで時間かけてやりとりした結果30分後にフラグを入手、150ポイントが手にはいりました。



というわけで "how did you get the key?" に対する答えでした。

WordPressへの大規模攻撃のまとめ

追記しました

@KOBA789版のまとめを参照の上この記事を読むことをおすすめします。


バージョンが最新版の3.6でも不正アクセスが発生していることを考えると、
未修正の脆弱性に対するゼロデイ攻撃、もしくはWordPressのバージョンに縛られない箇所からの攻撃であると考えられる。


ロリポップの情報によると、 http://lolipop.jp/info/news/4149/
この攻撃の対策にwp-config.phpパーミッションを400にして一般ユーザーからのファイル読み込みを防止した模様。


この情報が出た時間帯に攻撃が一度止むも、つい先程(11:30過ぎ)からまた攻撃が再開されている。
wp-config.phpパーミッションが変えられても攻撃が続行されているところが気になる。


とまぁここらへんで時間がなくなったので突然のおわり。


帰ってきたら解決してるといいですね


----


中途半端に投げておくのもアレなのできちんとまとめます。


攻撃対象はロリポップに集中しているようなのでロリポップメインの話になるかと思います。


ロリポップにて逐次情報が発信されています。
「ロリポップ!レンタルサーバー」ユーザーサイトへの第三者による大規模攻撃について


19:33時点の情報によると、午前中に確認された被害件数よりも更に多くの被害が確認されたそうですが、HACK DB等を見る限り情報の追加も止まっているようなので攻撃は止んだと思われます。


攻撃の状況について

/wp-login.phpに対するブルートフォース攻撃が確認されています。
ブルートフォースの頻度は様々であるものの、十分な強度を持ったパスワードを攻略するほどの試行回数には見えません。


パスワードの強度が弱かったアカウントが不正アクセスの被害に遭っているだけであるならば、管理者の問題だということで終わってしまうのですが、これだけ大規模となると他に何かあるのではないかと考えるのが自然だと思います。


データベースへのクラッキングの噂

@KOBA789 の指摘にもある通り、一部にはロリポップ以外のサーバーが含まれていることと、
基本的にレンタルサーバーでは外部からのアクセスを拒否しているはずなのでこの可能性は低いと考えられます。


ロリポップ公式のwp-config.phpパーミッション変更について

最初に不正アクセスを受けたアカウント上のwp-config.phpパーミッションが変更されました。
不正アクセスを受けてから変更したところであまり効果がないような気もしますが、
サーバー上のすべてのWordPressのwp-config.phpパーミッションが変更された頃からは攻撃の情報が少なくなったように思います。


この対策がどう働いたかは詳しく分からないものの、サーバーを管理している側が講じた対策なので、
不正アクセスの原因はwp-config.phpが何らかの方法で読み出されたことが原因であるのかもしれません。




妄想

(※あくまでなんとなく思いついたことをくっつけただけなので完全な妄想です。)

この一連の問題では、wp-login.phpへのブルートフォース攻撃やwp-config.phpパーミッション変更という対策が取られているため、これらの事実を強引につなげると、

WordPressへのブルートフォース攻撃をして、成功したアカウントから他ユーザーのwp-config.phpを読みだして他のWordPressへと広がっていく

ような攻撃の形式だったのかもしれません。

誰かロリポップのどのサーバーに攻撃が集中してるとか調べたりしてないのかなあ。

Project EulerをC#+LINQで解くだけ。

数学ガール1巻買いました。読み終わりました。


以前友人に借りてサクッと読んでたので、ストーリーはなんとなく覚えてたんですが、
サクッと読んだだけあってやっぱり数式の部分では忘れてるところが多かったので、新鮮な感じで読めました。


その中でオイラー先生の話が度々登場してて、そういえばProject Eulerなんてのがあったなあと思ったので、C#+LINQでProblem1,2を解いてみました。


Probrem 1

問題:1000未満の自然数で3または5で割り切れる数の総和を求めよ

int ans = Enumerable.Range(1, 999)
	.Where(x => (x % 3 == 0) || (x % 5 == 0))
	.Sum();
Console.WriteLine("The answer is " + ans);

LINQだけでサクッと書けて良い感じ。



Problem 2

問題: 400万以下の範囲のフィボナッチ数列で値が偶数の項の総和を求めよ。

long ans = Util.GetSequence(1, 1, (x, y) => x + y)
	.TakeWhile(x => x <= 4000000)
	.Where(x => x % 2 == 0)
	.Sum();
Console.WriteLine("The answer is " + ans);
public static class Util {
	public static IEnumerable<long> GetSequence(long first, long second, Func<long, long, long> relation) {
		Queue<long> q = new Queue<long>(new long[2] { first, second });
		while (true) {
			long n = q.Dequeue();
			q.Enqueue (relation(n, q.Peek()));
			yield return n;
		}
	}
}


LINQだけじゃ数列は生成できないので3項間漸化式から値を順番に返す関数を作ってUtilに突っ込みました。
ついでに2項間漸化式のも作ったり。

数列が生成できたら400万以下まで取得して奇数潰してSumするだけですね。


Problem 3以降…

素数問題がバリバリ出てきてるので素数列を生成する綺麗なコードが書けるまで保留。