mojo's Blog

SQL injection / SQL vs NoSQL 본문

Computer Science/데이터베이스

SQL injection / SQL vs NoSQL

_mojo_ 2022. 1. 20. 00:12

SQL injection

 

SQL Injection 이란?

 

해커에 의해 조작된 SQL 쿼리문이 데이터베이스에 그대로 전달되어 비정상적인 명령을 실행시키는 공격 기법을 의미한다.

 

※ 공격 방법

인증 우회 방법 : 보통 로그인을 할 때, 아이디와 비밀번호를 입력 창에 입력한다.

예를 들어서 아이디를 xyz, 비밀번호를 1234 라고 할 때, 다음과 같은 쿼리로 전송되는 것을 떠올릴 수 있다.

SELECT * FROM USER WHERE ID = "xyz" AND PASSWORD = "1234";

 

SQL Injection 으로 공격할 때, 입력 창에 비밀번호를 입력함과 동시에 다른 쿼리문을 함께 입력하는 것이다.

1234; DELETE * USER FROM ID = "1"; 

 

보안이 완벽하지 않을 경우, 비밀번호가 아이디와 일치해서 True가 되고 비밀번호 뒤에 작성한 DELETE 문도 데이터베이스에 영향을 줄 수도 있게 되는 치명적인 상황이 될 수 있다.

이 밖에도 기본 쿼리문의 WHERE 절에 OR 문을 추가하여 '1' = '1' 과 같은 true 문을 작성하여 무조건 적용되도록 수정한 뒤 DB를 마음대로 조작할 수도 있다. 

1234; OR '1' = '1';

 

데이터 노출 방법 : 시스템에서 발생하는 에러 메시지를 이용해 공격하는 방법이다.

보통 에러는 개발자가 버그를 수정하는 방법에서 도움을 받을 수 있다.

해커들은 이를 역으로 이용하여 악의적 구문을 삽입하여 에러를 유발시킨다.

 

예를 들어서 해커는 GET 방식으로 동작하는 URL 쿼리 스트링을 추가하여 에러를 발생시킨다.

이에 해당하는 오류가 발생하면, 이를 통해 해당 웹앱의 데이터베이스 구조를 유추할 수 있고 해킹을 할 수 있다.

 

 

※ 방어 방법

① 입력 값을 받을 때(비밀번호), 특수문자 여부를 검사한다.

로그인 전에 검증 로직을 추가하여 미리 설정한 특수문자들이 들어올 경우(DELETE * FROM ..., OR '1' = '1' 등) 요청을 막아낸다.

 

② SQL 서버 오류 발생 시, 해당하는 에러 메시지를 감춘다.

view를 활용하여 원본 데이터베이스 테이블에는 접근 권한을 높인다.

일반 사용자는 view로만 접근하여 에러를 볼 수 없도록 만든다.

 

preparestatement 를 사용한다.

preparestatement를 사용하면 특수문자를 자동으로 escaping 해준다. (statement와는 다르게 쿼리문에서 전달인자 값을 ?로 받는 것)

이를 활용하여 서버 측에서 필터링 과정을 통해 공격을 방어한다.

 

 

SQL vs NoSQL

 

웹 앱을 개발할 때, 데이터베이스를 선택할 때 다음과 같은 고민을 할 수 있다.

MySQL과 같은 SQL 또는 MongoDB와 같은 NoSQL ... 뭐가 더 좋지?

 

보통 Spring에서 개발할 때는 MySQL, Node.js에서는 MongoDB를 주로 사용한다고 한다.

하지만 단순히 프레임워크에 따라 데이터베이스를 결정하는 것이 아니다.

프로젝트 진행에 앞서 적합한 데이터베이스를 선택해야 한다.

 

 

※ SQL (Relational DB)

관계형 데이터베이스에는 핵심적인 두 가지 특징이 존재한다.

  • 데이터는 정해진 데이터 스키마에 따라 테이블에 저장된다.
  • 데이터는 관계를 통해 여러 테이블로 분산된다.

 

스키마란?

 

컴퓨터 과학에서 데이터베이스 스키마(database schema)는 데이터베이스에서 자료의 구조, 자료의 표현 방법, 자료 간의 관계를 형식 언어로 정의한 구조이다. 

데이터베이스 관리 시스템(DBMS)이 주어진 설정에 따라 데이터베이스 스키마를 생성하며, 데이터베이스 사용자가 자료를 저장, 조회, 삭제, 변경할 때 DBMS는 자신이 생성한 데이터베이스 스키마를 참조하여 명령을 수행한다.

스키마는 3층 구조로 되어있다.

  • 외부 스키마(External Schema) : 프로그래머나 사용자의 입장에서 데이터베이스의 모습으로 조직의 일부분을 정의한 것
  • 개념 스키마(Conceptual Schema) : 모든 응용 시스템과 사용자들이 필요로하는 데이터를 통합한 조직 전체의 데이터베이스 구조를 논리적으로 정의한 것
  • 내부 스키마(Internal Schema) : 전체 데이터베이스의 물리적 저장 형태를 기술하는 것

 

데이터는 테이블에 레코드로 저장되는데, 각 테이블마다 명확하게 정의된 구조가 있다.

해당 구조는 필드의 이름, 데이터 유형으로 정의된다.

따라서 스키마를 준수하지 않은 레코드는 테이블에 추가할 수 없다.

즉, 스키마를 수정하지 않는 이상은 정해진 구조에 맞는 레코드만 추가가 가능한 것이 관계형 데이터베이스의 특징 중 하나이다.

 

또한, 데이터의 중복을 피하기 위해 "관계"를 이용한다.

 

 

하나의 테이블에서 중복 없이 하나의 데이터만을 관리하기 때문에, 다른 테이블에서 부정확한 데이터를 다룰 위험이 없어지는 장점이 존재한다.

 

 

※ NoSQL (Non-Relational DB)

관계형 DB의 반대로 스키마, 관계가 없다.

 

NoSQL에서는 레코드를 문서(documents)라고 부른다.

SQL과 차이는 다음과 같다.

  • SQL : 정해진 스키마를 따르지 않을 경우 데이터 추가가 불가능하다.
  • NoSQL : 다른 구조의 데이터를 같은 컬렉션에 추가가 가능하다.

 

문서(documents)Json과 비슷한 형태로 가지고 있으며 관계형 데이터베이스처럼 여러 테이블에 나누어 담지 않고, 관련 데이터를 동일한 "컬렉션"에 넣는다.

따라서 위 사진에 SQL에 진행한 Orders, Users, Products 테이블로 나눈 것을 NoSQL에서는 Orders에 한꺼번에 포함해서 저장할 수 있다.

따라서 여러 테이블에 조인할 필요없이 이미 필요한 모든 것을 갖춘 문서를 작성하는 것이 NoSQL 이다. (NOSQL에는 조인이라는 개념이 존재하지 않음!)

 

NoSQL에서 조인을 하고 싶을때 어떻게 해야 할까?

 

컬렉션을 통해 데이터를 복제하여 각 컬렉션의 일부분에 속하는 데이터를 정확하게 산출하도록 한다.

하지만 이러면 데이터가 중복되어 서로 영향을 줄 위험이 존재한다.

따라서 조인을 잘 사용하지 않고 자주 변경되지 않는 데이터일 때 NoSQL을 쓰면 상당히 효율적이다.

 

♠ 확장 개념

두 데이터베이스를 비교할 때 중요한 Scaling 개념도 존재한다.

데이터베이스 서버의 확장성은 "수직적", "수평적" 확장 두개로 나뉜다.

  • 수직적 확장 : 단순히 데이터베이스 서버의 성능을 향상시키는 것이다. (ex : CPU 업그레이드)
  • 수평적 확장 : 더 많은 서버가 추가되고 데이터베이스가 전체적으로 분산됨을 의미한다. (하나의 데이터베이스에서 작동하지만 여러 호스트에서 작동)

 

데이터 저장 방식으로 인해 SQL 데이터베이스는 일반적으로 수직적 확장만 지원하며 수평적 확장은 NoSQL 데이터베이스에서만 가능하다.

 

SQL 장점

  • 명확하게 정의된 스키마, 데이터 무결성을 보장한다.
  • 관계는 각 데이터를 중복없이 한번만 저장한다.

 

 SQL 단점

  • NoSQL에 비해 덜 유연하며 데이터 스키마를 사전에 계획하고 알려줘야 한다. (수정이 힘듬)
  • 관계를 맺고 있어서 조인문이 많은 복잡한 쿼리가 만들어질 수 있다.
  • 대체적으로 수직적 확장만 가능하다.

 

NoSQL 장점

  • 스키마가 없어서 유연하며 언제든지 저장된 데이터를 조정하고 새로운 필드 추가도 가능하다.
  • 데이터는 애플리케이션이 필요로 하는 형식으로 저장되며 데이터를 읽어오는 속도가 빨라진다.
  • 수직 및 수평 확장이 가능해서 애플리케이션이 발생시키는 모든 읽기/쓰기 요청 처리가 가능하다.

 

NoSQL 단점

  • 유연성으로 인해 데이터 구조 결정을 미루게 될 수 있다.
  • 데이터 중복을 계속 업데이트 해야 한다.
  • 데이터가 여러 컬렉션에 중복되어 있기 때문에 수정 시 모든 컬렉션에서 수행해야 한다. (SQL에서는 중복 데이터가 없으므로 한번만 수행이 가능)

 

SQL 데이터베이스 사용이 언제 더 좋을까?

 

1. 관계를 맺고 있는 데이터가 자주 변경되는 애플리케이션의 경우 (NoSQL에서는 여러 컬렉션을 모두 수정해야 하기 때문에 비효율적)

2. 변경될 여지가 없고, 명확한 스키마가 사용자와 데이터에게 중요한 경우

 

NoSQL 데이터베이스 사용이 언제 더 좋을까?

 

1. 정확한 데이터 구조를 알 수 없거나 변경/확장 될 수 있는 경우

2. 읽기를 자주 하지만, 데이터 변경은 자주 없는 경우

3. 데이터베이스를 수평으로 확장해야 하는 경우 (막대한 양의 데이터를 다루는 경우)

 

참고 : gyoogle/tech-interview-for-developer: 👶🏻 신입 개발자 전공 지식 & 기술 면접 백과사전 📖 (github.com)

 

GitHub - gyoogle/tech-interview-for-developer: 👶🏻 신입 개발자 전공 지식 & 기술 면접 백과사전 📖

👶🏻 신입 개발자 전공 지식 & 기술 면접 백과사전 📖. Contribute to gyoogle/tech-interview-for-developer development by creating an account on GitHub.

github.com

 

'Computer Science > 데이터베이스' 카테고리의 다른 글

Anomaly, Index  (0) 2022.03.02
데이터베이스  (0) 2022.03.02
Redis  (0) 2022.03.01
Transaction  (0) 2022.02.28
Normalization  (0) 2022.01.21
Comments