[Laravel8.x] bcryptのストレッチングが10以外のパスワードでログインする

まずストレッチング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とは

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?

[AWS] IAMでユーザのEC2操作権限を制御したい

まずユーザ作成

続いて、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アカウントを変えるしかない。

どういう風に制御しているのか理解できれば、間接的にセキュリティ方針を俯瞰して観れるようになりますね。

EC2をprivate subnetに移し、SSH用のbastionサーバの構築

### 既存の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/
-> レスポンスが返るようになる。

EC2のKey Pairs作成(mac編)

### Key Pairs作成
– EC2のleft paneのNetwork & Security -> Key Pairsを選択
– Create key pair
– Name: aws-dev(file formatはpem)

### macの.sshに保存
$ pwd
/Users/${username}
$ ls -a
$ cd .ssh
$ ls
aws-dev.pem

アクセス権限の変更: オーナーのみ読み出しができる400(所有者:R)
$ sudo chmod 400 aws-dev.pem 
$ ls -l
-r——–@

pemファイルは秘密鍵
流れとしては
1. ssh接続要求
2. aws側でランダムデータを生成し、公開鍵を使ってクライアントに送る
3. 受け取ったクライアント側は秘密鍵でデータを復号化して送り返す
4. aws側でランダムデータと受け取った復号化データを比較して認証する

このような仕組みから、key parisはAWSで生成するのではなく、ローカルマシンでの生成が望ましい。
$ ssh-keygen -t rsa -f hoge.pem

LaravelのDB::rawのエスケープとSQLインジェクション

SQL Injectionとは?
->アプリケーションが想定しないSQL文を実行させること

公式: https://readouble.com/laravel/6.x/ja/queries.html

rawメソッドはクエリを文字列として挿入するため、SQLインジェクションの脆弱性を生まないように十分気をつけてください。

DB::rawメソッド使用時にはエスケープされない。

 User::where(DB::raw('CONCAT(last_name, first_name)'), 'like', '%'.$text.'%')->get();

mysqlのlike演算子では、% と _ 特別な意味を持つが、DB::rawではエスケープされないので、$textに’%’や’_’が入っていた場合など、SQLインジェクションの脆弱性を生む。
$textの値は、¥%、¥¥、¥_と言うようにエスケープしないといけない。

以下のような使い方の場合は問題なしか。

User::select(DB::Raw('concat(last_name, first_name) as name'), 'id')

NATとSTUN・TURNサーバー

WebRTC通信
– Peer to Peer、ブラウザ間で直接通信
– UDP/IPを使用、オーバーヘッドが少ない
– 鍵交換で暗号化通信を行う
-> 相手のIPアドレス、動的なUDPポート番号を知る必要がある
-> 通信経路の仕組みがInteractive Connectivity Establishment、その候補がICE Candidate
–> NATを通過するためのSTUNサーバから取得したポートマッピング
–> Firewallを越えるための、TURNによるリレーサーバーを介した中継通信
–> このやりとりをシグナリングと言う。WebSocketなど複数の方法がある
-> 複数人通信の場合には、それぞれのユーザとSDP/IPのconnectionをつくる必要がある

NATとは
 グローバルIPとローカルのネットワークIPとの変換
 複数のPC/デバイスが同時に通信できるよう、ポートマッピングによるポート変換
 →ブラウザはローカルのIP、UDPポートはわかるが、グローバルのIP、UDPはわからない
 →→Peer to Peerはグローバルの情報を交換する必要がある

STUN(Session Traversal Utilities for NATs)
NATで変換されたIP/UDPを外のSTUNサーバーから教えてもらう
→グローバル情報をシグナリングサーバーけいゆうで相手に渡す
STUNサーバーはGoogleのstun.l.google.com:19302など

TURN(Traversal Using Relays around NAT)
ストリームデータの受け渡しにリレーする
TURNサーバが入ると厳密にはPeer to Peerではなくなる
データのデコード、エンコードは行わないので、ネットワーク負荷が高くなる

あれ、Bitcoinって、P2Pだけど、STAN, TURN使ってるんだっけ?
否、BitcoinはTCP😂

nonce

暗号学では、一度しか使わないランダムな数値の事をnonceと呼ぶ
メッセージにnonceを追加した上で、そのハッシュ値を計算し、メッセージとハッシュ値を公開した場合、nonceを知っている者だけしかハッシュ値を計算できない
ビットコインのマイニングは、nonceを変更しながらブロックのデータのハッシュ値を繰り返し計算する
ターゲットよりも小さいハッシュ値を最初に得たものが勝利者となる
ハッシュチェーンの一つにマークル木がある
SHA-256とRIPEMD-160をハッシュ関数として標準利用、SHA-1の衝突耐性は失われている

暗号鍵と公開鍵の作成

require 'ecdsa'
require 'securerandom'

group = ECDSA::Group::Secp256k1
n = group.order

private_key = 1 + SecureRandom.random_number(n-1)

# print private_key

pubKey = group.generator.multiply_by_scalar(private_key)
print pubKey.x
print pubKey.y

vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ ruby main.rb
7200274859625909218305600661424454855533433802141920888525182327364340449554183445379063984485161576009152500901248299335294365713023890298728510086562018

ECDSA

ECDSA(Elliptic Curve Digital Signature Algorithm)
楕円曲線デジタル署名アルゴリズム
ビットコインの電子証明などに利用されている
ECDSAは公開鍵の暗号化技術の名前
RSAに比べ約1/10のコンパクトな容量

require 'ecdsa'
require 'securerandom'

group = ECDSA::Group::Secp256k1
n = group.order

private_key = 1 + SecureRandom.random_number(n-1)

print private_key

vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ ruby main.rb
106515493506888278075922016172190811663525618981292515102301206639235796458599

ビットコインの暗号技術

OpenSSL
-> インターネット上で標準的に利用される暗号通信プロトコルであるSSLおよびTLSの機能を実装したオープンソースライブラリ

require 'openssl'

data = '*secret data*'

key = 'a' * 32
iv = 'i' * 16

enc = OpenSSL::Cipher.new('AES-256-CBC')
enc.encrypt
enc.key = key
enc.iv = iv
encrypted_data = enc.update(data) + enc.final
# print encrypted_data

dec = OpenSSL::Cipher.new('AES-256-CBC')
dec.decrypt
dec.key = key
dec.iv = iv 
decrypted_data = dec.update(encrypted_data) + dec.final
print decrypted_data

vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ ruby main.rb
5????
g`??Ա?

vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ ruby main.rb
*secret data*

IntelのIvy Bridge以降のCPUやRaspberry Pi, Apple A7以降のプロセッサには、熱雑音を利用して物理的に乱数を発生させるハードウェア乱数生成器が備わっている

rubyの安全な乱数: securerandom

require 'securerandom'
hex = SecureRandom.hex(32)
print hex

vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ ruby main.rb
1fbd11b0d5588de19571e3679ee86387d2449b6d376f6211498e4dbd2557fabd