
RuoYi-Vue의 generator 모듈에서 발생하는 인증된 SQL 인젝션인 CVE-2024-57521에 대한 정적 코드 감사로, 소스-투-싱크 분석과 %0b 필터 우회 PoC를 포함합니다.
본 저장소는 보안 연구 및 교육 목적으로만 사용됩니다. 본 문서의 기술을 이용하여 비인가 공격 행위를 해서는 안 됩니다. 모든 테스트는 로컬 정적 코드 감사 환경에서 완료되었습니다.
ruoyi-generator 모듈)ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java핵심 코드:
@PostMapping("/createTable")
public AjaxResult createTableSave(@RequestParam("sql") String sql, @RequestParam("tplWebType") String tplWebType)
{
try
{
SqlUtil.filterKeyword(sql); // 비즈니스 로직 진입 전 필터 호출
분석: 백엔드 관리자는 HTTP POST 요청의 sql 파라미터를 통해 임의의 데이터베이스 테이블 생성 구문을 전달할 수 있습니다. 진입점에서 사용자 입력에 대한 충분한 제한이 이루어지지 않으며, 이후 필터로 직접 전달됩니다.
스크린샷 증거:

· 파일 위치: ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
핵심 결함 코드:
// 16번째 줄: 블랙리스트 정의, 키워드에 【후행 공백】이 포함되어 있음에 주목
public static String SQL_REGEX = "\u0008|%0A|and |extractvalue|updatexml|sleep|information_schema|exec...";
// 61-66번째 줄: 필터링 로직
String normalizedValue = value.replaceAll("\\p{Z}|\\s", ""); // 먼저 입력 내 모든 공백 문자를 제거
String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
for (String sqlKeyword : sqlKeywords)
{
if (StringUtils.indexOfIgnoreCase(normalizedValue, sqlKeyword) > -1)
{
throw new UtilException("요청 파라미터에 민감한 키워드 " + sqlKeyword + "가 포함되어 있어 보안 위험이 존재할 수 있습니다");
}
}
결함 분석: 필터는 먼저 replaceAll("\p{Z}|\s", "")를 실행하여 입력 내 모든 공백 문자를 제거합니다. 그러나 블랙리스트 SQL_REGEX의 키워드(예: "and ", "select ")는 후행 공백을 포함하고 있습니다. 이로 인해 매칭이 반드시 실패하게 되며, 공격자가 키워드 뒤에 %0b(수직 탭 문자)를 사용하여 공백을 대체하기만 하면 블랙리스트 검사를 완벽하게 우회할 수 있습니다.
스크린샷 증거:
· 파일 위치: ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
핵심 코드:
<update id="createTable">
${sql}
</update>
분석: MyBatis에서 ${}는 안전한 사전 컴파일 #{}를 사용하지 않고 문자열을 직접 연결합니다. 이로 인해 필터를 우회한 악성 SQL이 데이터베이스로 전달되어 실행됩니다. 이는 전형적인 "블랙리스트 필터링 + 안전하지 않은 문자열 연결" 조합 취약점입니다.
스크린샷 증거:
· 방법: 공격자는 %0b(MySQL의 수직 탭 문자로, \s 매칭 범위에 속함)를 사용하여 SQL 구문 내의 공백을 대체합니다.
· 탐지 원리: IF(<조건>, 1, 1/0)를 불리언 블라인드 인젝션의 탐지기로 활용합니다. · 조건이 거짓인 경우: 0으로 나누기 오류가 발생하여 서버가 HTTP 500을 반환합니다. · 조건이 참인 경우: 정상적으로 오류가 발생하지 않습니다. · 추출 방식: 이분법을 사용하여 데이터베이스 데이터를 비트 단위로 추측할 수 있습니다.
이 취약점은 전형적인 "불완전한 수정"으로 인한 우회입니다. 개발자는 이전의 동일 유형 SQL 인젝션을 수정할 때 블랙리스트 메커니즘을 도입했지만, 블랙리스트가 공백에 의존한다는 점을 간과했고, 공백을 제거하는 선행 로직이 블랙리스트의 매칭 조건을 파괴하여 결국 새로운 우회(CVE-2024-57521)를 초래했습니다.
· 블랙리스트 메커니즘 폐지: 블랙리스트에 의존하지 말고, 화이트리스트 메커니즘이 안전의 근간이 되어야 합니다. · 사전 컴파일 사용: MyBatis의 ${sql}을 #{} 사전 컴파일 방식으로 변경해야 합니다. SQL을 동적으로 전달해야 하는 경우(예: 테이블 생성, Order By)에는 엄격한 추상 구문 트리(AST) 파싱 또는 엄격한 파라미터 검증을 사용해야 합니다. · 필터 개선: 블랙리스트를 반드시 사용해야 하는 경우, 블랙리스트 키워드의 후행 공백을 제거하고 비교 전에 통일된 정규화(예: 모두 소문자로 변환, %0b 등을 공백으로 대체)를 수행해야 합니다.
· NVD - CVE-2024-57521 · RuoYi-Vue Gitee 저장소