MyBatis

이 코드는 SQL Injection 공격에 매우 취약합니다.


🔥 취약한 이유 요약

@Select("select * from user where ${column} = #{value}")
User findByColumn(@Param("column") String column, @Param("value") String value);
  • ${column}: SQL 문에 문자열 그대로 치환됨 (동적 SQL 템플릿)

  • #{value}: PreparedStatement 바인딩 변수 (바인딩으로 안전)

👉 ${}문자열 치환 방식이기 때문에, 사용자가 악의적인 SQL을 삽입할 수 있음 → 이게 바로 SQL Injection의 경로입니다.


🧨 공격 예시

요청 예시:

findByColumn("1=1 --", "irrelevant");

실행되는 쿼리:

SELECT * FROM user WHERE 1=1 -- = 'irrelevant'
  • 1=1은 항상 참

  • -- 이후는 주석 처리됨

  • 따라서 필터 조건이 없어지고 모든 유저가 조회됨


⚠️ @Select에서 ${} vs #{} 차이

표현 방식
동작 방식
안전성
설명

${var}

SQL 문자열에 직접 치환

❌ 위험

쿼리 문법 구조 자체가 변함

#{var}

PreparedStatement로 바인딩

✅ 안전

값만 바인딩되어 문법은 고정됨


✅ 안전한 대안

  1. 동적 SQL 대신 @SelectProvider 또는 XML <where> 사용

  2. 열 이름은 if/switch 또는 whitelist로 고정

예:


💡 핵심 요약

  • ${}직접 문자열 삽입이므로, SQL Injection에 취약

  • 열(column)은 사용자 입력을 그대로 받으면 안 됨

  • 안전하게 하려면 열 이름을 하드코딩 / 화이트리스트로만 구성해야 함


당신이 작성한 XML 기반의 MyBatis 설정 예시는 다음과 같은 중요한 개념들을 포함하고 있습니다. 아래에 각 내용을 정리하고 설명드릴게요:


✅ 1. <sql><include>: 재사용 가능한 SQL 조각

📌 목적:

반복되는 SQL 코드(예: 컬럼 목록, 테이블명 등)를 재사용하기 위해 사용합니다.

📄 예시 1: 컬럼 조각 재사용

🧠 설명:

  • <sql> 태그로 컬럼 리스트를 정의

  • <include refid="..."/>로 불러와서 사용

  • <property>를 이용해 ${alias}에 값을 주입


📄 예시 2: 중첩 include와 매개변수 전달

🧠 설명:

  • <include refid="someinclude">에 전달된 property는 내부에서 다시 <include>를 통해 사용 가능

  • prefix = "Some""SomeTable"로 치환됨

  • 동적으로 테이블명 구성 가능


✅ 2. Result Mapping: DB 컬럼명과 자바 필드명이 다를 때


📄 방법 1: SQL에서 직접 alias 사용

✅ 장점:

  • 간단하고 직관적

❌ 단점:

  • SQL 문이 길어지고 복잡해질 수 있음


📄 방법 2: <resultMap> 사용

✅ 장점:

  • SQL은 컬럼 그대로 가져오고,

  • 자바 필드와의 매핑은 외부에서 정의

  • 재사용 가능, 가독성 증가


🔁 총 정리

항목
설명

<sql> / <include>

반복되는 SQL 조각을 템플릿처럼 재사용

<property>

<include> 내부에서 사용할 변수에 값 주입

${}

문자열 치환 방식이므로 SQL 문 구조 바꾸는 데 사용

#{}

값 바인딩, SQL Injection 방어에 사용

resultType

DB 컬럼명이 자바 객체 필드와 같을 때 자동 매핑

resultMap

컬럼명 ≠ 필드명일 때 명시적으로 매핑 정의


필요하시면 <choose>, <if> 등 조건문 처리 방식이나 <foreach>를 통한 IN 조건 리스트 처리도 이어서 설명드릴 수 있어요.

Last updated