flawopen.com/Go의 SQL 인젝션/GORM Raw SQL과 SQL 인젝션
GORM Raw()는 SQL 인젝션을 막나요? Go 매개변수 바인딩
placeholder를 값이 담긴 봉인된 봉투라고 생각해 보세요. 데이터베이스 드라이버는 값을 SQL 명령과 분리해 보냅니다. placeholder를 쿼리에 남기고 값을 별도 인수로 전달하면 GORM Raw()가 안전하게 바인딩할 수 있습니다. 사용자 입력을 SQL 문자열에 format하면 봉투와 명령이 섞여 쿼리가 바뀔 수 있습니다.
// 사용자 제어 문자열이 SQL 구문이 됨 db.Raw(fmt.Sprintf( "SELECT * FROM users WHERE id = %s", userID, )).Scan(&user)
// 드라이버가 userID를 값으로 바인딩 db.Raw( "SELECT * FROM users WHERE id = ?", userID, ).Scan(&user)
안전한 GORM Raw SQL과 매개변수 바인딩
placeholder가 SQL에 남고 인수를 별도로 전달되면 GORM과 Go database/sql은 값을 바인딩합니다. 예: db.Where("name = ?", userInput), db.Raw("SELECT ... WHERE id = ?", userID). placeholder는 값이지 SQL 구문이 아닙니다. 테이블명, 컬럼명, 정렬 방향, 연산자는 값 바인딩으로 안전해지지 않습니다. 동적 식별자는 고정 allowlist에서 선택하세요. 사용자 입력을 SQL 조각에 연결하면 Order, Select, Table, Raw 같은 메서드에 주입 위험이 생길 수 있습니다.
- ✓SQL 구조를 고정하고 사용자 제어 값은 별도 placeholder 인수로 전달하세요.
- ✓동적 테이블명, 컬럼명, 정렬 옵션은 애플리케이션이 소유한 고정 allowlist에서 선택하세요.
- ✓
Raw,Exec,Order,Select,Table등 SQL 조각 메서드의 연결과 format을 검토하세요. - ✓쿼리 전에 숫자 식별자를 예상 Go 타입으로 변환하고 오류를 처리하세요.
코드베이스 확인 방법
rg -n --glob '*.go' '\.(Raw|Exec|Order|Select|Table)\s*\(' .
rg -n --glob '*.go' 'fmt\.(Sprintf|Sprint)' .GORM Raw SQL 및 매개변수 FAQ
아닙니다. Where("name = ?", input)처럼 값을 별도로 전달하면 매개변수 바인딩을 사용합니다. 입력을 조건 문자열에 연결하거나 raw SQL 구문으로 전달하면 여전히 쿼리 주입이 가능합니다. 일부 메서드는 이스케이프되지 않는 식별자나 SQL 조각을 받으므로 인수를 확인하고 동적 구조는 allowlist로 제한하세요.
아니요. placeholder는 데이터 값을 나타냅니다. 동적 식별자나 정렬 방향은 애플리케이션에서 정한 고정 옵션으로 선택하고 검증된 상수만 SQL 구조에 넣으세요.