10. 不正SQL文の動作
なぜパスワードが表示されたのか?
SELECT * FROM articles A JOIN users U ON U.id=user_id WHERE title LIKE '%'
UNION SELECT 0,0,name,pass,0,'a','a','a' from users where name like '%%' ORDER BY 1
+----+---------+-------+---------+----+------+----------+------------------+
| id | user_id | title | body | id | name | pass | email |
+----+---------+-------+---------+----+------+----------+------------------+
| 5 | 1 | sss | dfdsfsa | 1 | hata | hatahata | h.hata@olt.tokyo |
+---+---+--------------+----------+---+---+---+---+
| 0 | 0 | name | pass | 0 | a | a | a |
+---+---+--------------+----------+---+---+---+---+
| 0 | 0 | hata | hatahata | 0 | a | a | a |
| 0 | 0 | hiro | hiro | 0 | a | a | a |
| 0 | 0 | hata2 | hahata | 0 | a | a | a |
| 0 | 0 | hata2 | hahata | 0 | a | a | a |
| 0 | 0 | hata2 | hahata | 0 | a | a | a |
1個目のSELECTで生成された表(もともと意図していた表=8カラムを持ち、うち3カラムを使う)
2個目のSELECTで生成された表
+----+---------+---------+------------+----+------+----------+-----------+
| id | user_id | title | body | id | name | pass | email |
+----+---------+---------+------------+----+------+----------+-----------+
| 0 | 0 | hata | hatahata | 0 | a | a | a |
| 0 | 0 | hiro | hiro | 0 | a | a | a |
| 0 | 0 | hata2 | hahata | 0 | a | a | a |
| 0 | 0 | rrr | 8888 | 0 | a | a | a |
| 0 | 0 | trew | 5555 | 0 | a | a | a |
| 0 | 0 | hhaat | 11111 | 0 | a | a | a |
UNION
10
14. プログラミング対策
String sql = "SELECT * FROM articles A JOIN users U ON U.id=user_id"+" WHERE title LIKE '%" + word +"%' ORDER BY 1";
ResultSet rs = st.executeQuery(sql);
String sql = "SELECT * FROM articles JOIN users ON user_id=users.id"+" WHERE title LIKE ? ORDER BY 1";
PreparedStatement st = con.prepareStatement(sql);
st.setString(1, "%" + word + "%");
ResultSet rs = st.executeQuery();
修正されたコード
言語で用意されているSQLインジェクション対策機能を利用する
Stringの結合ではなく、PreparedStatementクラスのsetStringを使う
(注意)PreparedStatementを使えばいいのではなく、
プレースホルダに値をセットするのにsetStringを使うことで初めて対策になる
特殊文字をエスケープする。ただし、手動ではなく言語ごとに用意されている
PreparedStatementクラスを使う
14