株も歩けば犬に当たる

ブラックSlerで働くSEが株やPythonや思ったことについて書いています。

Pythonで画像処理 〜2枚の画像を重ねてみる〜

pythonのライブラリ、pillowを使って、2つの画像を重ねてみたいと思います。

重ねる画像はこの2つ。

アナログテレビ時代のザザーッって感じのやつ。

微妙にこの2つの画像、違います。

これを重ねてみます。

f:id:doz13189:20170723012946p:plain

f:id:doz13189:20170723013003p:plain


以下が重ねるコードです。

画像のピクセルを配列に入れる関数と画像を重ねる関数の2つを使って、画像を重ねています。

コードと一緒に、コードの動きをコメントで書いています。

#pillowとnumpyをインストール
from PIL import Image
import numpy as np

#画像のピクセルを配列に入れる関数
def pixelGetter(img):
	#画像を開く
	img = Image.open(img)
	
	#画像のサイズ(縦×横)を入れる
	#今回使用する画像は640×480
	size = img.size
	#print(size[0])
	#print(size[1])

	#配列を入れる変数を定義
	img_pixels = []
	for x in range(size[0]):
		for y in range(size[1]):
			#画像の左上から順番にピクセルの情報を取得
			#1ピクセルの情報は(r, g, b, 透過度)
			#この情報をappendで配列に入れている
			img_pixels.append(img.getpixel((x,y)))

	#ピクセル情報が入っている配列をリターン
	return img_pixels

#画像を重ねる関数
def pileUp(pic1, pic2):
	#2枚の画像を開く
	img = Image.open("pic1.png")
	img2 = Image.open("pic2.png")

	#2枚の画像のサイズを入れる
	size = img.size
	size2 = img2.size

	#2枚の画像を重ねるための変数を定義
	#重ねるといっても、実際は2枚の画像から新しい3枚目の画像を作成している
	#そのため、3枚目の画像を入れる変数をここで定義する必要がある
	#サイズは2枚の画像と一緒であるため、640×480を入れる
	new_img = Image.new("RGBA", size)

	#重ねる処理を行う
	#画像を重ねるというのは、中の処理は1つ1つのピクセル同士を足し合わせるということ
	#赤い透明の下敷きを2枚重ねると、濃い赤になる原理と同じ
	#そのため、2枚の同じ位置同士のピクセルの(r, g, b)を足し合わせている
	i = 0
	for x in range(size[0]):
		for y in range(size[1]):
			r = pic1[i][0] + pic2[i][0]
			g = pic1[i][1] + pic2[i][1]
			b = pic1[i][2] + pic2[i][2]

			#ピクセル情報の入った配列では、画像を表示する形式に合わない
			#そのため、putpixelで画像表示の形式に変換
			new_img.putpixel((x, y), (r, g, b, 255))
			i += 1

	#リターンで重ねた画像を表示
	return new_img.show()


pic1 = pixelGetter("pic1.png")
pic2 = pixelGetter("pic2.png")
pileUp(pic1, pic2)

結果的に、重ねると...

f:id:doz13189:20170723013216p:plain

重ねるとちょっとした文字がでてきましたね。(出てきた文字に特に意味はありません)

まとめ

pythonって色々なことができるんだなぁと実感しました。

たまにいつもと違うコードを書くのも楽しいですね。

以上終わり。

パスワードをかけても中身を見られてしまうZIPファイルの脆弱性〜既知平文攻撃〜

目次

ZIPファイルとは

主にWindowsで使用されるデータ圧縮フォーマットです。

#ZIPのフォーマットで圧縮されたファイル
file.zip

データ圧縮によく使用されるフォーマットで、シンプルな暗号化機能も備えています。

圧縮するときにパスワードを設定するのですが、この暗号化には重大な脆弱性があることで知られています。

今回はその脆弱性についての記事をまとめました。

既知平文攻撃

ZIPファイルの暗号化は、設定されるパスワードを元に鍵を生成する共通鍵暗号方式です。

当然ながら、第3者にパスワードが知られてしまえばZIPファイルの中身を見られてしまいます。

ZIPファイルに長〜いパスワードをかける人はあまりおらず、しかもZIPファイルはパスワード入力制限もないので、かなり貧弱なランダム数生成器によるブルートフォースアタックでも簡単にパスワードを特定できそうですね。

しかし今回はそういった力技ではなく既知平文攻撃というちょっとスマートな攻撃方法を見てみます。


この既知平文攻撃では、条件が揃えばパスワードを知らなくても中身をみることができてしまいます。

既知平文攻撃は条件が揃った場合のみに有効です。

その条件とは、暗号化されたZIPファイルの中に1つでも中身のわかるファイルが存在する場合です。

もし、1つでも中身のわかるファイルが存在していれば、暗号化されたそのファイルと暗号化されていないファイルを比較して、パスワードを割り出すことができます。

パスワードがわかってしまえば、ZIPの暗号が解けるため他のファイルの閲覧も可能になります。

ゆえに既知平文攻撃と呼ばれています。


中身のわかるファイルが暗号化されたZIPファイルの中にある場合なんて少ないのでないかとも思うのですが、例えばネットに落ちている画像なんかをZIPファイルに置いていたりすると、既知平文攻撃が可能となります。

攻撃者はネットからその画像を拾ってきて、暗号化された画像と拾ってきた画像と比較してパスワードを割り出そうとします。

このような形でZIPファイルのパスワードをクラックされてしまうのが既知平文攻撃です。

実演

2つのファイルを用意します。

  • password.txt
  • hello.txt
#password.txtはこんな中身
password is 43jJKqqT
#hello.txtはこんな中身
hello world!!

この2つのファイルをZIPして、暗号化します。

zip -P 43jJKqqT hatena.zip password.txt hello.txt

パスワードは、43jJKqqT。

8文字のランダムな英数字です。

この時、hello.txtのファイルの中身は既知という設定です。(hello.txtと言えば、中身の推測も容易ですしね)

そして、読まれたくないファイルはpassword.txtです。

これで環境は整いました。


ここで既知平文攻撃をするために使用するツールがpkcrackです。

pkcrackは既知平文攻撃を行うツールで、Windowsは32bit版、UbuntuなどのLinux系はソースからビルドすることで使用することが出来ます。。

wget https://www.unix-ag.uni-kl.de/~conrad/krypto/pkcrack/pkcrack-1.2.2.tar.gz
pkcrack-1.2.2/src
make

無事にビルドできたら、次はpkcrackを使って既知平文攻撃を開始します。

./pkcrack-1.2.2/src/pkcrack -C hatena.zip -c hello.txt -p hello.txt -d hatena2.zip

pkcrackの使い方は以下です。

 -C [暗号化されたzipファイル]
 -c [暗号化されたzipファイルの中で平文がわかるファイル]
 -p [平文のファイル]
 -d [出力先(復号したzipファイルの名前)]


pkcrackの処理が終了すると、hatena2.zipにパスワードが解除された状態で出力されています。

これでpassword.txtの中身が見れてしまいます。

まとめ

既知平文攻撃という攻撃でした。

大事なのは、ZIPの暗号化を信用しないことです。

あくまでもZIPの暗号化をしてもローカルにとどめておくことが大事なのではないでしょうか。

暗号化したからと言って、ネットに上げるとこういった攻撃に晒され、クラックされる危険性が高くなります。

暗号化と言ってもZIPの場合は、極めて重大な脆弱性があるということを覚えておく必要がありそうです。

以上終わり!

The Sleuth Kitの使い方メモ

The Sleuth Kitは、ファイルシステム周りの調査をするためのツールです。

使い方

fls file.img

これでfile.imgの中身の一覧を表示してくれる。

icat target.jpg 14 > sample.jpg

これで対象となるファイルを参照。

【参考サイト】

qiita.com

カーネルパニック(kernel panic)でUbuntuが起動しない問題

慎重にやれとあれほど言ったのに...

Ubuntuのアップデートと石橋は叩いて渡れ。

愚か者の私が叩かずに渡った結果、カーネルパニック(Kernel panic)が発生しました。

kernel panic not syncing unable to mount root fs on unkonown-block(0,0)

こんな素敵なメッセージがリブート時(電源ON)に表示されました。

今日は、カーネルパニックが起きた時の対処法をサラッとまとます。

対処法の流れ

  • 無事にリブートできる

カーネルパニックとは

カーネルとは、OSの核となるソフトウェアです。

ハードウェアとアプリケーションを繋ぐ橋渡しのような存在です。

つまり、カーネルがなければハードウェアとアプリケーションを繋ぐものがないので、システムとして機能しなくなります。

カーネルパニックは、Ubuntuの起動時に何らかの原因でカーネルが起動しなくなってしまうことを指します。

異なるカーネルUbuntuを起動しよう

OSがアップデートされるのと同じように、カーネルはしょっちゅうアップデートされます。

Windowsは基本的にOSなどの更新があれば自動アップデートされますが、Linuxは使用用途などの都合から自動アップデートはされません。(自動アップデートなんかされたらシステム管理者ブチ切れです)

現在、どのバージョンのカーネルを使用しているかは以下のコマンドで確認可能です。

uname -r

#4.4.0-79-generic

表示されたのが現在使用中のカーネルで、使用可能なカーネルの一覧は以下のコマンドで確認可能です。

dpkg -l | grep linux-image

ズラズラーッと出てきたら、それらがカーネルたちです。

そして、カーネルパニックを起こしているのは、uname -rで表示された使用中のカーネルです。

そのため、使用可能なカーネルの一覧の中から使用中以外のものを選択して、Ubuntuをリブートすれば、起動します。

その方法は、起動画面で以下の画面に行きます。

f:id:doz13189:20170709022032j:plain

通常、「Ubuntu」と表示された部分を選択して、使用中のカーネルUbuntuをリブートします。

しかし、それがカーネルパニックを起こしているので起動しません。

「Advanced options for Ubuntu」と表示されている部分を選択すると、どのカーネルで起動するかを選択することが出来ます。

ここには基本的には2つ以上のバージョンのカーネルがあるはずです。

Ubuntuでは、最新のカーネルを使っている場合でも1つ前のバージョンのカーネルは削除されません。(意図的に削除しなければ)

そのため、「Advanced options for Ubuntu」の画面を選択してからカーネルパニックを起こしてるカーネル以外を選択して、Ubuntuをリブートします。

これで無事にリブートできます。

トラブルを起こしているカーネルを削除

Ubuntuのリブートは、使用中のカーネルが自動で選択されてリブートされます。

なので、カーネルパニックを起こしているカーネルが選択されるとずーっとリブートできません。

ということで、カーネルパニックを起こしているカーネルを削除します。(リブート時にトラブったカーネルを削除します)

dpkg -l | grep linux-image

これでカーネルパニックを起こしてるカーネルのバージョンを確認します。

sudo apt-get autoremove --purge linux-image-extra-4.4.0-21-generic

linux-image-extra-4.4.0-21-genericがカーネルパニックを起こしていた場合は、これでlinux-image-extra-4.4.0-21-genericを消します。

カーネルパニックを起こしているカーネルを削除すれば、無事にリブートできるようになるはずです。

まとめ

こういうのが起こるとUbuntuをキライになりそうです。

ただ、復旧のための情報はたくさんネットに落ちているので何とかなるのですが...

とりあえず、今回思ったのはバックアップをとっといてよかったということです。

バックアップをとっているだけで、データは失われないという安心感からとても落ち着いていられます。

カーネルパニックと一緒に自分もパニックになると、焦りから解決できる問題も解決できなくなってしまいますしね。

ふぅ、とりあえず復旧出来てよかったです。

リクルートのTalk APIをubuntuとpythonで使ってみた

リクルートAPIを公開したので使ってみる

今日、こんなハッカソンに参加してきました。(会社以外のエンジニアと交流するのは久々で楽しかったです)

www.xn--78j2ayab5gxloexbxg1q.com

機械学習 × ハッカソンで、機械学習を使ったWebアプリをチームで作るのですが、機械学習を一から構築するのも大変なのでAPI使ったらいいですよーってな感じでリクルートAPIGoogleAPIのURLがサイトに貼っつけてありました。

私のチームではAPIは使用しなかったのですが、せっかくなのでハッカソンが終わった後に使ってみることにしました。

ちょっとだけチャットボットに興味があったので、選んだのはリクルートTalk API

リクルートのサイト。

a3rt.recruit-tech.co.jp

Github

github.com

使い方がなんせ簡単

APIkeyというのをサイトで取得する必要がありますが、それを含めてもとっても簡単でした。

使い方は、Talk APIのあるサーバにPOSTでメッセージ付きのリクエストを送ると、レスポンスにメッセージの返信付きで返ってきます。

curlコマンドで、メソッドはPOST形式、そして、POSTの中身にapikeyと、queryというパラメーター名で送りたいメッセージを送信します。

#リクエスト
curl -X POST https://api.a3rt.recruit-tech.co.jp/talk/v1/smalltalk -F "apikey=AAAAAAAAAAAAAAAAAAAAAAAAAAAA" -F "query=おはよう"

#レスポンス
{"status": 0, "message": "ok", "results": [{"perplexity": 0.07743213382788067, "reply": "\u304a\u306f\u3088\u3046\u3054\u3056\u3044\u307e\u3059"}]}

!!??。

レスポンスのメッセージの返信はreplyに格納されているはずですが、そこがなぜか文字コード。笑

見た感じASCIIコードですが、いちおうチェック。

#text.txtにレスポンスを出力。
curl -X POST https://api.a3rt.recruit-tech.co.jp/talk/v1/smalltalk -F "apikey=AAAAAAAAAAAAAAAAAAAAAAAAAAAA" -F "query=おはよう" > text.txt

#何のエンコード方式かチェック
file text.txt

チェックした結果、やっぱりASCII。

エラーの9割は文字コードとはよく言ったものです。

replyをUTF-8に変換するのが手っ取り早そう。

レスポンスはjson形式なので、pythonで開いてUTF-8に変換するかってな感じでコードを書きました。

#text.jsonにレスポンスを出力。(json形式)
curl -X POST https://api.a3rt.recruit-tech.co.jp/talk/v1/smalltalk -F "apikey=AAAAAAAAAAAAAAAAAAAAAAAAAAAA" -F "query=おはよう" > text.json

#text.jsonを開く
import json
f = open("text.json")
data = json.load(f)
f.close()
print(data)

#この時点でprintしてみると...
{'message': 'ok', 'results': [{'reply': 'おはようございます', 'perplexity': 0.07743213382788067}], 'status': 0}

??。

あれ?まだASCIIからUTF-8に変換してないのに、replyが見れる...

きっと、python自体がUTF-8で動くからかな。


ここまでやって、なんかlinuxのコマンドでリクエスト送って、pythonで開くの面倒だなぁ、pythonで全部書いちゃうかとか思っていたら、なんとpythonライブラリで提供されていることが判明したので、そちらも掲載します。

pythontalk APIを使ってみる

pipで入ります。

pip install pya3rt

さっそくコードを書きます。

import pya3rt
apikey = "AAAAAAAAAAAAAAAAAAAAAA"
client = pya3rt.TalkClient(apikey)
print(client.talk("おはよう"))

#{'message': 'ok', 'results': [{'reply': 'おはようございます', 'perplexity': 0.07743213382788067}], 'status': 0}

print(client.talk("ギャンブル大好き"))
#{'message': 'ok', 'results': [{'reply': '良さそうですね', 'perplexity': 2.592985171811111}], 'status': 0}
>>> 

おはようにはおはようございますを。

ギャンブル大好きには良さそうですねを。

ハッカソンで使えばよかったなと思えるほど、使い方は簡単でした。

まとめ

チャット形式ってすごく良いUIだと個人的に思っているので、いずれ自分が作っているwebアプリにもチャット機能を追加したいなぁなんて思っていますが、きっとまだまだ先のことでしょう。

以上終わり!

HTTPリクエストの改ざんをBurp Suiteでやってみた

目次

セキュリティについて少し勉強しました

浅い知識なので、メモ程度です。

今日の記事でやることを軽くまとめると、自分のはてなブログの通信を傍受して、改ざんしてみようというものです。

こんな記事を投稿して、それを途中で改ざんして。

f:id:doz13189:20170602221738p:plain

こうなります。

f:id:doz13189:20170602221838p:plain

htmlのbodyを改ざんしました。

(記事の内容に「ほげほげほげ」と投稿されるはずが、「あなたのリクエストを改ざんしました」となっています)

これが他人のものだと不正アクセス禁止法に抵触します。

ということで本題へ。

リクエストとレスポンス

簡単な言葉のおさらいをすると...

  • リクエスト:クライアント(自分のPCなど)からサーバーに送る通信
  • レスポンス:サーバーからクライアントに返ってくる通信

今日はリクエストの内容を改ざんしてみます。

攻撃の分類で言うと、HTTPヘッダインジェクションなんかが近いと思います。(今回はヘッダではなくボディを改ざんしています)

使用するツール

Burp SuiteというHTTPプロキシを使用します。

portswigger.net

このツールでHTTP通信を閲覧、改ざんをすることができます。

脆弱性診断で広く使われるツールで、他の有名なツールにfiddlerなどがあげられます。


重要なポイントとして、これはHTTP通信なら改ざん可能というところです。

HTTPS通信の改ざんは行えません。(基本的には)

HTTPSSSLを使用して、通信内容を暗号化しているので、通信内容は見ることはできません。

また、サーバー証明書も持っていないので復号化もできませんし、しても改ざんが検知されます。


逆にHTTPは、通信は平文です。

なので、通信さえ傍受してしまえば、改ざんが可能というわけです。

HTTP通信を使ってるWebサービスないかなぁ

HTTPSは改ざんはできないので、HTTPを使用しているwebサービスを探していました。

すると、すごく身近にHTTP通信を使用しているWebサービスがありました。

はてなブログです笑


そう言えば、ブラウザのURLのところに鍵マークがありません。(むしろビックリマークがついています)

ということは、記事の更新等も平文で行われているわけですね(驚愕)

HTTP通信を使用しているのは、ECサイトみたいな金銭が発生するWebサービスではないので、そこまで厳格なセキュリティは求められないからでしょうか。

一昔前まえはLINEも平文でメッセージの通信を送っていたようなので、案外そんなもんなのかな。(現在はLINEの通信は暗号化していたはずです)


なので、自分のアカウントで新しい記事をアップロードし、そのアップロードしようとしている通信を改竄してみます。

成功すれば、記事の内容が変わってアップロードされることになります。

改ざんする手順

プロキシサーバーをたてます。

自PC(クライアント)>>>>> プロキシサーバー >>>>>> はてなサーバ

こんな感じに自分PCとはてなサーバーの間にひとつプロキシをはさみます。

このプロキシで、自PCから送られたレスポンスを傍受して、改ざんしてから、はてなサーバーに送りつけます。


Proxy SwitchySharp というChromeのアドオンを追加して、プロキシサーバーを立てます。

こうすることによってBurp Suiteは、立てたプロキシサーバーを通る通信をみることができます。

Proxy SwitchySharpの設定はこんな感じ。

f:id:doz13189:20170602225625p:plain


プロキシサーバーの設定が終わったら、Burp Suiteを開いて、通信をみます。

f:id:doz13189:20170602225757p:plain

HTTP historyにプロキシを通っている通信が表示されます。

Interceptをのタブの Intercept is off をクリックすると、インターセプトが開始されます。

インターセプトとは、一つの通信を傍受して、他の通信をせき止めている状態です。

傍受した通信は、テキストベースなので改竄し放題です。

こんな感じで、HTTP通信を傍受して改竄を行います。

はてなの記事を改ざんしてみる

f:id:doz13189:20170602221738p:plain

適当にほげほげ、と入力して、Burp Suiteのインターセプト機能をオンにしてから公開します。

すると、リクエストをBurp Suiteでキャッチできます。

キャッチしたHTTP通信のheadとbodyを見るとこんな感じ。

title=%E3%81%BB%E3%81%92%E3%81%BB%E3%81%92&body=%E3%81%BB%E3%81%92%E3%81%BB%E3%81%92%E3%81%BB%E3%81%92

一瞬、暗号化されているように見えますが、これはただのエンコードです。

ちなみにURLエンコード

URLでは、日本語などを送信できないのでURLエンコードという方法でエンコードします。

エンコードなので、もちろんデコードが可能です。

エンコードとデコードができるWebサービスもあります。

Web便利ツール/URLエンコード・デコードフォーム/処理完了 - TAG index

ここでデコードすると...

%E3%81%BB%E3%81%92%E3%81%BB%E3%81%92

#デコード結果
ほげほげ

なので、「あなたのリクエストを改ざんしました」という文章をURLエンコードして、傍受した通信のbody部にはっつけます。

body部の編集が終わったら、Burp Suiteで送ります(フォワード)。

すると...

f:id:doz13189:20170602221838p:plain

改ざん完了ということになります。

まとめ

HTTP通信は平文で送っているので、傍受されている危険性を考えなければいけないです。

なので、フリーWiFi(スタバやマクド等)でHTTP通信を行う際は、傍受されているものとしたほうが良いですね。

傍受されても問題ない程度の通信しかおこなっちゃいかんということですね。

以上終わり。

Ubuntu16.04にJAVAの開発環境を整える

おそらく一番手っ取り早い方法で、さっさと環境を整える

手順

  1. JREをインストー
  2. JDKをインストー
  3. 終了

必要最低限を整えて、今日のところは終わります。

JDKJREは一体何?

javaを実行するには、まずコンパイルが必要です。

#javacでコンパイル
javac Java_file.java

このjavacで動くのが、JDKです。(おそらく)

次に、必要なのがコンパイルしたjavaファイルを実行するJREです。

#javaファイルを実行
java Java_file

この2つさえあれば、javaの開発環境はとりあえず整います。

あとは適当なテキストエディタさえあれば、大丈夫。

私はいつも使っているSublime Textで書くことにします。

JREJDKをインストー

JREの略は、Java Runtime Environment。

JDKの略は、Java Development Kit

この2つをインストールします。

#何をインストールするときの儀式をとりあえずします。
sudo apt-get update
sudo apt-get upgrade

#容量に不安があるならこちらも。
sudo apt-get autoremove

そして。

sudo apt-get install default-jre 
sudo apt-get install default-jdk

これでインストールは終わり

Hello Worldしてみよう

適当なディレクトリにHello.javaのファイルを作成。

public class Hello {
	public static void main(String[] args) {
		System.out.println("Hello");
	}
}

これを端末上でコンパイルからの実行。

#コンパイル
javac Hello.java

#実行
java Hello

これでコンパイルも実行エラーもでなければ、Helloと表示されるはず。

まとめ

研修でjavaをやっているので、急遽javaの開発環境を自PCに整える必要がありました。

研修ではeclipsを使用していますが、作業中にあのマウスを離せない感じがなんともストレスなので、普通にテキストエディタを使おうと思い、今回はデフォルトの開発環境を整えました。

Webアプリケーションを作ると、eclipsの便利さなども実感できたのですが、eclipsでやっていると内部の動きがほとんど理解できません。

ちゃんと理解できるまでは、大変ですがテキストエディタで頑張ろうかと。

というか今までpythonでずっとそうだったので、それが続くだけですが。


以上、終わり!