SELECT * FROM users WHERE name=''; DROPTABLE users; --';user input escaped the stringSQL injection

SQL 주입

11 분 읽음보안

SQL 주입은 1990년대 후반 이후 모든 웹 보안 취약점 목록의 최상위에 있거나 그 근처에 있었습니다. 수정 사항(매개변수화된 쿼리)은 알려져 있고 간단하며 20년 동안 권장되었습니다. 그러나 새로운 SQLi 취약점은 여전히 ​​매주 발견되고 있습니다. 오류 모드가 미묘하고 많은 프레임워크의 기본값이 불완전하기 때문에 이 범주가 지속됩니다.

전체 기사 본문은 아래에 영어로 제공됩니다.

SQL 주입(SQLi)는 공격자가 응용 프로그램이 데이터베이스에 보내는 쿼리에 SQL 코드를 주입할 수 있는 취약점 클래스입니다. 성공할 경우 공격자는 액세스 권한이 없는 데이터를 읽거나 수정하거나 삭제할 수 있으며 때로는 데이터베이스 서버에서 코드를 실행하고 때로는 응용 프로그램 자체에 대한 공격으로 전환할 수 있습니다.

전형적인 실수

교과서의 예입니다. 응용 프로그램은 로그인 양식에서 사용자 이름을 받아 이를 조회합니다.

query = "SELECT * FROM users WHERE 사용자 이름='" + input + "';"

inputalice인 경우 쿼리는 다음과 같습니다. 다음과 같이 됩니다:

SELECT * FROM 사용자 WHERE 사용자 이름='alice';

Normal. 그러나 inputalice' OR '1'='1인 경우 쿼리는 다음과 같습니다.

SELECT * FROM users WHERE username='alice' OR '1'='1';

The OR '1'='1'는 항상 참입니다. 쿼리는 테이블의 모든 사용자를 반환합니다. 보다 정교한 페이로드를 사용하면 공격자는 테이블을 덤프하거나 레코드를 수정하거나 추가로 에스컬레이션할 수 있습니다.

공격 범주

  • Classic/in-band SQLi. 삽입된 쿼리의 결과는 애플리케이션의 응답에 나타납니다. 공격자는 데이터를 직접 읽습니다.
  • Blind SQLi. 응답에는 데이터가 나타나지 않지만 주입된 쿼리가 true 또는 false를 반환하는지 여부에 따라 응용 프로그램의 동작이 변경됩니다. 공격자는 "관리자 비밀번호 'a'의 첫 번째 문자는 무엇입니까?"와 같은 질문을 통해 데이터를 한 비트씩 추출합니다.
  • 시간 기반 블라인드 SQLi. 공격자는 SLEEP() 또는 이에 상응하는 방법을 사용하여 조건이 true인 경우 데이터베이스가 느리게 응답하도록 만듭니다. 데이터 유출 속도는 더 느리지만 애플리케이션이 응답 피드백을 제공하지 않을 때 작동합니다.
  • 대역외 SQLi. 공격자는 데이터베이스를 속여 외부 네트워크 연결(DNS 조회, HTTP 요청)을 만들어 자신이 제어하는 서버로 데이터를 유출합니다.
  • 2차 SQLi. 악의적인 입력은 데이터베이스에 저장됩니다. 먼저 읽은 다음 나중에 다른 쿼리에서 안전하지 않게 읽고 사용합니다. 삽입은 입력과 다른 컨텍스트에서 발생합니다.

수정: 매개변수화된 쿼리

사용자 입력으로 데이터베이스를 쿼리하는 올바른 방법은 매개변수 자리 표시자를 사용하는 것이며 문자열을 연결하지 않는 것입니다. 본질적으로 모든 언어에서:

// Python(psycopg2)
커서.execute("SELECT * FROM 사용자 WHERE 사용자 이름=%s", (입력,))

// 자바
stmt = conn.prepareStatement("SELECT * FROM 사용자 WHERE 사용자 이름=?");
stmt.setString(1, 입력);

// 자바스크립트(pg)
client.query("SELECT * FROM users WHERE username=$1", [input]);

드라이버는 SQL과 매개변수 값을 별도로 보냅니다. 데이터베이스는 입력 데이터를 SQL 구문과 혼동하지 않습니다. 입력에 따옴표, 세미콜론, OR 절 또는 기타 SQL 구문이 포함되어 있어도 데이터로 처리됩니다.

이것은 작동합니다. 이는 20년 동안 권장되는 접근 방식이었습니다. 문제는 기술이 아닙니다. 코드베이스의 모든 쿼리가 이를 사용하는지 확인하는 것입니다.

ORM은 자동으로 안전하지 않습니다.

객체 관계형 매퍼(ActiveRecord, Sequelize, Hibernate, SQLAlchemy)는 기본적으로 매개변수화된 쿼리를 사용합니다. 이는 훌륭한 일입니다. 그러나 모든 ORM에는 이스케이프 해치가 있습니다.

  • raw() 임의의 SQL 문자열을 사용하는 메서드
  • 문자열 기반 ORDER BY 절(열 이름은 매개변수화할 수 없음)
  • 쿼리에 삽입된 테이블 이름
  • 자체적으로 저장되는 프로시저 concatenate

Modern SQLi 버그는 일반적으로 기본 CRUD 코드 경로가 아닌 이러한 극단적인 경우에 나타납니다.

NoSQL 주입

패턴은 SQL에 고유하지 않습니다. MongoDB, Redis, ElasticSearch, GraphQL — 입력이 검증되지 않으면 사용자의 구조화된 입력을 받아들이는 모든 쿼리 언어를 삽입할 수 있습니다. MongoDB의 $ne, $gt, $regex 연산자는 JSON 페이로드가 엄격하게 스키마 검사되지 않은 경우 일반적인 주입 벡터입니다.

깊이 있는 방어

매개변수화된 쿼리 너머:

  • Least-privilege 데이터베이스 계정. 애플리케이션은 필요한 권한만 가진 사용자와 연결해야 합니다. 읽기 전용 경로는 읽기 전용 자격 증명을 사용합니다. SQLi가 악용될 때 피해를 제한합니다.
  • 입력 유효성 검사. 예상 형식으로 입력을 제한합니다. 도움이 되지만 그 자체만으로는 충분하지 않습니다.
  • 웹 애플리케이션 방화벽(WAF). 패턴 일치 명백한 SQLi 시도. 우회할 수 있지만 공격자의 속도가 느려집니다.
  • 정적 분석. 문자열 연결 쿼리에 대한 소스를 검색하는 도구입니다. 최신 IDE에서는 이러한 항목을 표시합니다.
  • 데이터베이스 강화. 불필요한 기능을 비활성화합니다(MSSQL의 xp_cmdshell, PostgreSQL의 위험한 확장).

유명한 SQLi 사고

  • 2007 TJX — 9,400만 개의 신용카드. Wi-Fi 손상으로 시작되었지만 내부 데이터베이스에서 유출하는 데 SQLi가 사용되었습니다.
  • 2008 Heartland — 1억 3천만 개의 카드 기록. SQLi는 네트워크에 대한 초기 액세스 권한을 부여했습니다.
  • 2012 LinkedIn — SQLi를 통해 1억 1700만 개의 비밀번호 해시가 유출되었습니다.
  • 2017 Equifax — Apache Struts 취약점이지만 SQLi는 침해 후 데이터의 일부였습니다. exfiltration.
  • 2020년대 내내 — SaaS 회사, 전자 상거래 사이트, 정부 기관에서 셀 수 없이 많은 소규모 침해가 발생했습니다.

이 범주는 수십 년이 되었지만 여전히 살아 있습니다.

자주 묻는 질문

SQL 주입이 여전히 일반적인가요?
예. OWASP의 상위 10개 항목에는 매년 상위 3개 범주에 주입(SQLi 포함)이 포함되어 있습니다. 버그 현상금 프로그램은 매주 SQLi 보고서를 확인합니다. 최신 프레임워크는 기본 코드 경로에서 빈도를 줄였지만 레거시 앱, 엣지 케이스 및 ORM 이스케이프 해치는 카테고리를 유지합니다.
웹 애플리케이션 방화벽이 모든 SQL 주입을 막을 수 있나요?
아니요. WAF는 명백한 패턴을 포착하고 정교하지 않은 공격자를 차단하지만, 지식이 풍부한 공격자는 다양한 인코딩, 주석 삽입, 대체 SQL 구문 등의 우회 방법을 만들 수 있습니다. WAF는 유용한 계층입니다. 이는 애플리케이션의 안전한 쿼리 구성을 대체할 수 없습니다.
HTTPS는 SQL 삽입을 방지하나요?
아니요. SQLi는 애플리케이션 계층 취약점입니다. HTTPS는 전송 중인 데이터를 보호하지만 콘텐츠의 유효성을 검사하지는 않습니다. 공격자의 악의적인 입력은 다른 모든 사람과 마찬가지로 HTTPS를 통해 도착합니다. 응용 프로그램은 응용 프로그램을 안전하게 처리하거나 처리하지 않는 것입니다.
NoSQL 데이터베이스는 면역되어 있나요?
아니요. NoSQL 주입은 자체 범주입니다. MongoDB, Elasticsearch 등은 엄격하게 검증되지 않으면 조작될 수 있는 구조화된 쿼리 입력을 허용합니다. 보호 패턴은 유사하지만(사용자 입력을 쿼리 구조로 처리하지 않고 데이터로 처리) 구체적인 공격은 다릅니다.
내 사이트에서 SQL 삽입을 어떻게 테스트하나요?
sqlmap과 같은 도구는 일반적인 SQLi 패턴에 대한 테스트를 자동화합니다. OWASP ZAP 및 Burp Suite에는 스캐너가 포함되어 있습니다. 개발자에게 가장 신뢰할 수 있는 검사는 문자열 연결 쿼리에 대한 코드 검토 및 정적 분석입니다. 침투 테스트 계약에는 특히 SQLi 평가가 포함됩니다.
SQL 주입 설명: 결코 사라지지 않는 웹 취약점