티스토리 뷰

1. 개요
데이터베이스(DB)와 연동된 웹 응용프로그램에서 입력된 데이터에 대한 유효성 검증을 하지 않을 경우, 공격자가 입력 폼 및 URL 입력란에 SQL 문을 삽입하여 DB로부터 정보를 열람하거나 조작할 수 있는 보안약점
2. 보안대책
- 정적 쿼리 사용: PreparedStatement 객체를 이용하여 컴파일 된 정적 쿼리문(상수)으로 쿼리문의 구조가 외부의 값을 통해 바뀌지 않도록 한다. C#에서는 @, MyBatis에서는 #, JAVA 에서는 ?을 이용하여 파라미터 바인딩을 사용한다.
- 유효성 검사: 동적 쿼리를 사용해야 한다면, 입력값에 대하여 쿼리문의 구조를 변경할 수 있는 특수문자 및 쿼리 예약어를 검사(필터링)한 후 쿼리문 생성에 사용한다.
- 보안 모듈 사용: 스트러츠(Struts), 스프링(Spring) 등과 같은 프레임워크를 사용하는 경우에는 외부입력값 검증모듈 및 보안모듈을 상황에 맞추어 적절하게 사용한다.
- 불필요한 정보 노출 방지: 서버의 오류 정보가 노출되지 않도록 한다.
- 권한 관리: 웹 애플리케이션의 데이터베이스 사용자 권한을 최소화한다.
3. 코드예제
※ 아래 예제들은 KISA의 소프트웨어 개발보안 가이드, SW 보안약점 진단가이드의 예제를 옮겨놓았습니다.
[안전하지 않은 코드 - JDBC API]
- 외부에서 입력 받은 값을 별도 조치 없이 사용, SQL 질의문에 직접 데이터가 입력되고 있음
//외부로부터 입력받은 값을 검증 없이 사용할 경우 안전하지 않다.
String gubun = request.getParameter("gubun");
......
String sql = "SELECT * FROM board WHERE b_gubun = '" + gubun + "'";
Connection con = db.getConnection();
Statement stmt = con.createStatement();
//외부로부터 입력받은 값이 검증 또는 처리 없이 쿼리로 수행되어 안전하지 않다.
ResultSet rs = stmt.executeQuery(sql);
[안전한 코드 - JDBC API]
- 외부에서 전달 받은 값을 PreparedStatement 사용을 위해 ?로 바인딩하여 사용
String gubun = request.getParameter("gubun");
......
//1. 사용자에 의해 외부로부터 입력받은 값은 안전하지 않을 수 있으므로, PreparedStatement 사용을 위해 ?문자로 바인딩 변수를 사용한다.
String sql = "SELECT * FROM board WHERE b_gubun = ?";
Connection con = db.getConnection();
//2. PreparedStatement 사용한다.
PreparedStatement pstmt = con.prepareStatement(sql);
//3. PreparedStatement 객체를 상수 스트링으로 생성하고, 파라미터 부분을 setString 등의 메소드로 설정하여 안전하다.
pstmt.setString(1, gubun);
ResultSet rs = pstmt.executeQuery();
[안전하지 않은 코드 - MyBatis]
- MyBatis에서 외부의 값을 $기호로 받을 경우 문자열이 쿼리에 반영되어 취약
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN“
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
......
<select id="boardSearch" parameterType="map" resultType="BoardDto">
//$기호를 사용하는 경우 외부에서 입력된 keyword값을 문자열에 결합한 형태로 쿼리에 반영되므로 안전하지 않다.
select * from tbl_board where title like '%$ {keyword }%' order by pos asc
</select>
[안전한 코드 - MyBatis]
- # 기호로 외부의 값을 받는 경우, 쿼리에 바인딩되어 양호
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
......
<select id="boardSearch" parameterType="map" resultType="BoardDto">
//$ 대신 #기호를 사용하여 변수가 쿼리맵에 바인딩 될 수 있도록 수정하는 것이 안전하다.
select * from tbl_board where title like '%'||# {keyword }||'%' order by pos asc
</select>
[안전하지 않은 코드 - Hibernate]
import org.hibernate.Query
import org.hibernate.Session
......
//외부로부터 입력받은 값을 검증 없이 사용할 경우 안전하지 않다.
String name = request.getParameter("name");
//Hiberate는 기본으로 PreparedStatement를 사용하지만, 파라미터 바인딩 없이 사용 할 경우 안전하지 않다.
Query query = session.createQuery("from Student where studentName = '" + name + "' ");
[안전한 코드 - Hibernate]
import org.hibernate.Query
import org.hibernate.Session
......
String name = request.getParameter("name");
//1. 파라미터 바인딩을 위해 ?를 사용한다.
Query query = session.createQuery("from Student where studentName = ? ");
//2. 파라미터 바인딩을 사용하여 외부 입력값에 의해 쿼리 구조 변경을 못하게 사용하였다.
query.setString(0, name);
import org.hibernate.Query
import org.hibernate.Session
......
String name = request.getParameter("name");
//1. 파라미터 바인딩을 위해 명명된 파라미터 변수를 사용한다.
Query query = session.createQuery("from Student where studentName = :name ");
//2. 파라미터 바인딩을 사용하여 외부 입력값에 의해 쿼리 구조 변경을 못하게 사용하였다.
query.setParameter("name", name);
[안전하지 않은 코드 - C#]
public void ButtonClickBad(object sender, EventArgs e){
string connect = "MyConnString";
string usrinput = Request["ID"];
// 외부로부터 입력받은 값을 SQL 쿼리에 직접 사용하는 것은 안전하지 않다.
string query = "Select * From Products Where ProductID = " + usrinput;
using (var conn = new SqlConnection(connect)){
using (var cmd = new SqlCommand(query, conn)){
conn.Open();
cmd.ExecuteReader(); /* BUG */
}}}
[안전한 코드 - C#]
-외부의 값을 파라미터 바인딩을 위해 @사용
void ButtonClickGood(object sender, EventArgs e){
string connect = "MyConnString";
string usrinput = Request["ID"];
//파라미터 바인딩을 위해 @ 을 사용합니다. 외부입력 값에 의해 쿼리 구조 변경을 할 수 없습니다.
string query = "Select * From Products Where ProductID = @ProductID";
using (var conn = new SqlConnection(connect)){
using (var cmd = new SqlCommand(query, conn)){
cmd.Parameters.AddWithValue("@ProductID",
Convert.ToInt32(Request["ProductID"]);
conn.Open();
cmd.ExecuteReader();
}}
'Information Security > Compliance' 카테고리의 다른 글
(SW 보안약점) 경로 조작 및 자원 삽입 (0) | 2024.09.25 |
---|---|
(SW 보안약점) 코드 삽입 (0) | 2024.09.25 |
(SW 보안약점) 설계단계 보안설계 기준 - 구현단계 보안약점 제거 기준 맵핑 (2) | 2024.09.10 |
인프라 최신 보안 패치 (0) | 2024.08.02 |
기업 신용 평가(등급) (0) | 2024.07.30 |
- Total
- Today
- Yesterday
- 크로스 사이트 스크립트
- 취약점분석평가
- 점검항목분류
- 전자금융기반시설취약점분석평가
- 전자금융기반시설
- SAP
- 접근제어취약점
- 전자금융취약점분석평가
- cve
- linguisticlumberjack
- neural compressor
- 사용자권한상승취약점
- 점검가이드
- 언젠가공개하려나
- 정보보안기획
- 디렉터리트레버셜
- sw보안약점
- 프리미엄베개
- 명령어주입
- 금취분평
- ip전화기
- 무선해킹탐지시스템
- awssap
- AWS
- 취약점
- 테크노젤
- 구현기준
- 링귀스틱럼버잭
- 항목가이드
- RCE
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |