SQLインジェクションについて

## はじめに
自分が作成したwebサイトについて、SQLインジェクションが対策されているのか指摘があったので、調べてみることにしました。

## SQLインジェクションとは
WebサイトやWebアプリケーションの脆弱性を利用し、不正なSQL文をWebサイトなどからデータベースへ送ることで個人情報の窃盗やデータ改ざんなどを行うサイバー攻撃手法。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760632/9163639b-29f5-2c5c-c28a-10f2f9a0e142.png)
【引用】[SQLインジェクションとは？手口や被害リスク・5つの対策までわかりやすく解説](https://www.lanscope.jp/blogs/cyber_attack_pfs_blog/20230913_33347/#:~:text=SQL%E3%82%A4%E3%83%B3%E3%82%B8%E3%82%A7%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E6%94%BB%E6%92%83%E3%81%A8%E3%81%AF,%E8%A1%8C%E3%81%86%E3%82%B5%E3%82%A4%E3%83%90%E3%83%BC%E6%94%BB%E6%92%83%E6%89%8B%E6%B3%95%E3%81%A7%E3%81%99%E3%80%82)

## 仕組み
「user」というテーブルから「id」を基にデータを抽出
```sql
SELECT * FROM user WHERE id = '$ID'
```

「$ID」に「taro’ or ‘1’=‘1」が注入された場合
```sql
SELECT * FROM user WHERE id = 'taro' or '1'='1'
```
id='taro'が成立した場合はtaroの情報が出力されるが、
成立しない場合は、'1'='1'で全ての場合において成立してしまうので、「user」の全てのデータが出力されてしまう。

## 対策
### 1. プレースホルダの利用
SQL文に置く変動箇所を示す記号のこと
この例では「?」のこと

```sql
SELECT * FROM user WHERE id = ?
```
変動箇所に入力された文字がSQL文の一部でなく、文字列として処理されます。それによって、不正SQL文の実行を防ぐことができます。

### 2. エスケープ処理
エスケープ処理とは、ユーザーから入力された特定の文字や記号を安全な形に変換する処理です。例えば、SQL文において特別な意味を持つシングルクォート「’」をダブルクォート「”」に変更することなどがあります。

エスケープ処理を行うことで、SQLインジェクションを受けても、攻撃コードの中の特定の文字列や記号を削除したり置き換えたりするので、攻撃を無効化することができます。

### 3. Webアプリケーションを常に最新のバージョンに保つ
OSやアプリケーションのバージョンアップには、発見された脆弱性を修正したものが含まれることが多いので、常に最新のバージョンにしておくことで攻撃を受けるリスクを軽減できます

### 4. WAFの導入で本格的なセキュリティ対策
WAFとは、Web Application Firewall（ウェブアプリケーションファイアウォール）の略称で、Webサイトを含めたWebアプリケーションの脆弱性を狙ったサイバー攻撃を防御する、セキュリティ対策ツールのひとつです。

## 実践
正しい名前とパスワードを入力し、送信すると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760632/b42be07d-8ee0-8088-3fe6-ddd3908668b9.png)

ログインできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760632/8601d580-d559-4fec-7b8c-0ec18e8e3bb5.png)


### HTML
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form method="post" action="/login">
        <p>名前</p>
        <input type="text" name="id">
        <p>パスワード</p>
        <input type="text" name="pass">
        <input type="submit">
    </form>
</body>
</html>
```
### データベース
テーブル名：user
|カラム|値|
|--|--|
|id|taro|
|pass|password|

### 対策していない場合
```app.js
app.post("/login", (req, res) => {
  connection.query(
    `SELECT * FROM user WHERE id='${req.body.id}' AND pass='${req.body.pass}'`,
    (error, results) => {
      if (results[0] != undefined) {
        login_check(req, res, results);
      } else {
        res.redirect("/");
      }
    }
  );
});

function login_check(req, res, results) {
  for (choice of results) {
    if (choice.id === req.body.id) {
      res.redirect(`/resp?id=${choice.id}`);
      break;
    }
  }
}
```
送信…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760632/36da76c1-207c-068a-bed8-adeaecd0a12a.png)
データが取れてしまう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760632/50e6d819-af0d-e56a-2055-5f498004daf8.png)


### プレースホルダーによる対策をした場合
```app.js
app.post("/login", (req, res) => {
  connection.query(
    'SELECT * FROM user WHERE id=? AND pass=?',
    [req.body.id,req.body.pass],
    (error, results) => {
      if (results[0] != undefined) {
        login_check(req, res, results);
      } else {
        res.redirect("/");
      }
    }
  );
});

function login_check(req, res, results) {
  for (choice of results) {
    if (choice.id === req.body.id) {
      res.redirect(`/resp?id=${choice.id}`);
      break;
    }
  }
}
```
送信…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760632/4dfae902-b03b-7c21-f5c5-4232ebcf9526.png)
送信されない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760632/fed0989b-e4ba-f9e1-27ac-a3c2ea0d4721.png)

## 参考にしたサイト
https://www.shadan-kun.com/waf_websecurity/sql_injection/

## おわりに
SQLインジェクションは割と簡単に対策できることが分かりました。
今回はSQLインジェクションだけを対策しましたが、他にもさまざまなセキュリティ対策があると思うので、機会があれば調べてみようと思います。