sql注入を効果的に防止する方法の実証
前言
SQL注入攻撃はハッカーがデータベースを攻撃する際によく使われる手段の一つであり、B/Sモードのアプリケーション開発の発展に伴い、このようなモードを使ってアプリケーションを作成するプログラマーも増えてきました。しかし、プログラマのレベルや経験がまちまちなため、かなりの一部のプログラマーがコードを作成する際に、ユーザーがデータを入力する合法性を判断していないため、アプリケーションにセキュリティ上の問題があります。ユーザはデータベースクエリコードの一部を提出することができ、プログラムの結果によって、彼が取得したいデータを得ることができます。これはSQL Injectionと呼ばれるSQL注入です。
一つの背景
もしある大学がネット授業システムを開発したら、学生に授業を選んでから学習を完成させるように要求します。データベースの中に表
データは以下の通りです
このシステムはmysqlをデータベースにして、Jdbcを使ってデータベースの関連操作を行います。システムは、次のコードの学生のコースの完了状況を調べるための機能を提供します。
1.通常の状況で、学生の選択した授業と完成状況を調べるには、student_に入る必要があります。IDなら、関連データを調べることができます。
応答の結果によって、私達はすぐに対応するsqlを書くことができます。
3.mysqlバージョン番号を調べ、unionでsqlを接続する。
4.クエリーデータベース名
5.mysql現在のユーザーのすべてのライブラリを調べます。
これらのプレゼンテーションを見てから、怖くなりましたか?あなたのすべてのデータの配置はすべて完全に暴露して、この以外、また多くの操作を完成することができて、データを更新して、削除して、時計などを削除します。
三どのようにsql注入を防止しますか?
1.コード層がsql注入攻撃を防止する一番いい方法はsqlプリコンパイルです。
2.各データの種類を確認します。たとえば、数字であれば、データベースはintタイプを使って記憶しなければなりません。
3.データ長を規定し、ある程度sql注入を防ぐことができます。
4.データベースの権限を厳しく制限し、sql注入の危害を最大程度減らすことができる。
5.sql異常情報に直接応答しないでください。sqlに異常が発生したら、カスタム異常に応答します。
6.フィルタパラメータに含まれるいくつかのデータベースのキーワード
ここでsql注入を防止する効果的な文章について紹介します。これまでの文章を検索したり、次の関連記事を見たりしてください。これからもよろしくお願いします。
SQL注入攻撃はハッカーがデータベースを攻撃する際によく使われる手段の一つであり、B/Sモードのアプリケーション開発の発展に伴い、このようなモードを使ってアプリケーションを作成するプログラマーも増えてきました。しかし、プログラマのレベルや経験がまちまちなため、かなりの一部のプログラマーがコードを作成する際に、ユーザーがデータを入力する合法性を判断していないため、アプリケーションにセキュリティ上の問題があります。ユーザはデータベースクエリコードの一部を提出することができ、プログラムの結果によって、彼が取得したいデータを得ることができます。これはSQL Injectionと呼ばれるSQL注入です。
一つの背景
もしある大学がネット授業システムを開発したら、学生に授業を選んでから学習を完成させるように要求します。データベースの中に表
course
があります。この表には各学生の選択情報と完成状況が保存されています。具体的な設計は以下の通りです。データは以下の通りです
このシステムはmysqlをデータベースにして、Jdbcを使ってデータベースの関連操作を行います。システムは、次のコードの学生のコースの完了状況を調べるための機能を提供します。
@RestController
public class Controller {
@Autowired
SqlInject sqlInject;
@GetMapping("list")
public List<Course> courseList(@RequestParam("studentId") String studentId){
List<Course> orders = sqlInject.orderList(studentId);
return orders;
}
}
@Service
public class SqlInject {
@Autowired
private JdbcTemplate jdbcTemplate;
public List<Course> orderList(String studentId){
String sql = "select id,course_id,student_id,status from course where student_id = "+ studentId;
return jdbcTemplate.query(sql,new BeanPropertyRowMapper(Course.class));
}
}
二注入攻撃のデモ1.通常の状況で、学生の選択した授業と完成状況を調べるには、student_に入る必要があります。IDなら、関連データを調べることができます。
応答の結果によって、私達はすぐに対応するsqlを書くことができます。
select id,course_id,student_id,status
from course
where student_id = 4
2.この表のすべてのデータを取得するには、上記のsqlのwhere条件が恒真であればいいです。
select id,course_id,student_id,status
from course
where student_id = 4 or 1 = 1
インターフェースを要求する時、studedIdを4 or 1=1に設定します。このsqlのwhere条件は恒真です。sqlは次のようなものです。
select id,course_id,student_id,status
from course
要求の結果は以下の通りです。私たちはこの表のすべてのデータを手に入れました。3.mysqlバージョン番号を調べ、unionでsqlを接続する。
union select 1,1,version(),1
4.クエリーデータベース名
union select 1,1,database(),1
5.mysql現在のユーザーのすべてのライブラリを調べます。
union select 1,1, (SELECT GROUP_CONCAT(schema_name) FROM information_schema.schemata) schemaName,1
これらのプレゼンテーションを見てから、怖くなりましたか?あなたのすべてのデータの配置はすべて完全に暴露して、この以外、また多くの操作を完成することができて、データを更新して、削除して、時計などを削除します。
三どのようにsql注入を防止しますか?
1.コード層がsql注入攻撃を防止する一番いい方法はsqlプリコンパイルです。
public List<Course> orderList(String studentId){
String sql = "select id,course_id,student_id,status from course where student_id = ?";
return jdbcTemplate.query(sql,new Object[]{studentId},new BeanPropertyRowMapper(Course.class));
}
このようにして私たちが送ってきたパラメータ4 or 1 = 1
はstudent_id
として扱われますので、sql注入は発生しません。2.各データの種類を確認します。たとえば、数字であれば、データベースはintタイプを使って記憶しなければなりません。
3.データ長を規定し、ある程度sql注入を防ぐことができます。
4.データベースの権限を厳しく制限し、sql注入の危害を最大程度減らすことができる。
5.sql異常情報に直接応答しないでください。sqlに異常が発生したら、カスタム異常に応答します。
6.フィルタパラメータに含まれるいくつかのデータベースのキーワード
@Component
public class SqlInjectionFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req=(HttpServletRequest)servletRequest;
HttpServletRequest res=(HttpServletRequest)servletResponse;
//
Enumeration params = req.getParameterNames();
String sql = "";
while (params.hasMoreElements()) {
//
String name = params.nextElement().toString();
//
String[] value = req.getParameterValues(name);
for (int i = 0; i < value.length; i++) {
sql = sql + value[i];
}
}
if (sqlValidate(sql)) {
throw new IOException(" ");
} else {
chain.doFilter(servletRequest,servletResponse);
}
}
/**
*
* @param str
* @return
*/
protected static boolean sqlValidate(String str) {
//
str = str.toLowerCase();
// sql ,
String badStr = "'|and|exec|execute|insert|select|delete|update|count|drop|*|%|chr|mid|master|truncate|" +
"char|declare|sitename|net user|xp_cmdshell|;|or|-|+|,|like'|and|exec|execute|insert|create|drop|" +
"table|from|grant|use|group_concat|column_name|" +
"information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|*|" +
"chr|mid|master|truncate|char|declare|or|;|-|--|+|,|like|//|/|%|#";
String[] badStrs = badStr.split("\\|");
for (int i = 0; i < badStrs.length; i++) {
if (str.indexOf(badStrs[i]) >= 0) {
return true;
}
}
return false;
}
}
締め括りをつけるここでsql注入を防止する効果的な文章について紹介します。これまでの文章を検索したり、次の関連記事を見たりしてください。これからもよろしくお願いします。