[모의해킹 스터디] 5주차 정리

바울·2024년 11월 21일
0

모의해킹 스터디

목록 보기
9/40

SQL Injection이란?

SQL 인젝션(SQL Injection)은 웹 애플리케이션이 사용자 입력값을 적절히 검증하지 않고 데이터베이스 쿼리에 삽입하는 취약점을 악용하는 해킹 기법입니다.
공격자는 SQL 쿼리를 조작하여 데이터베이스를 무단으로 조회, 수정, 삭제하거나, 시스템에 불법적인 접근을 시도할 수 있습니다.


Bypass란?

Bypass는 보안 시스템이나 제약 조건을 우회하여 이를 피하는 행위를 말합니다. 보안 시스템에서는 일반적으로 접근 제어, 인증 절차, 또는 필터링 기능 등을 설정하여 특정 작업이나 리소스에 대한 접근을 제한하는데, 이 제약을 우회하는 방법이 bypass입니다. 이 용어는 다양한 보안 분야에서 사용됩니다.

주요 사용 예시

1. 인증 우회 (Authentication Bypass)

  • 사용자가 정상적인 인증 절차를 거치지 않고 시스템에 접근할 수 있도록 하는 공격입니다.
  • 예: SQL 인젝션을 사용하여 로그인 시스템을 우회하거나, 세션 고정(Session Fixation)을 이용해 인증을 우회하는 경우.

2. 권한 우회 (Privilege Escalation)

  • 일반 사용자 계정이 시스템에서 제한된 작업을 수행하기 위해 관리자 권한을 얻는 것입니다.
  • 예: 일반 사용자가 취약한 시스템을 통해 관리자 권한을 얻고 중요한 데이터를 삭제하거나 수정하는 경우.

3. 방화벽 우회 (Firewall Bypass)

  • 네트워크 보안 장치인 방화벽을 우회하여 외부에서 내부 네트워크로의 불법적인 접근을 시도하는 것입니다.
  • 예: 특정 포트를 열지 않고, 정상적인 웹 트래픽처럼 보이게끔 만들어 방화벽을 통과하는 방법.

4. 웹 필터링 우회 (Web Filtering Bypass)

  • 네트워크에서 웹 필터링 기능을 우회하여 차단된 웹사이트나 콘텐츠에 접근하는 것입니다.
  • 예: VPN, 프록시 서버 또는 Tor 네트워크를 사용해 웹 필터를 우회하는 방법.

SQL Injection의 동작 원리

SQL 인젝션은 사용자가 제공한 입력값을 서버가 신뢰하여 그대로 SQL 쿼리에 포함하면서 발생합니다.

$sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
  • 위 쿼리에서 사용자가 비밀번호 대신 1' OR '1'='1을 입력하면, 아래처럼 쿼리가 조작됩니다
SELECT * FROM users WHERE username = 'admin' AND password = '1' OR '1'='1';
  • 결과적으로, 데이터베이스는 비밀번호 확인 없이 조건이 항상 참(1='1')인 행을 반환합니다.
    이는 인증 절차를 우회하거나 민감한 정보를 노출시키는 결과를 초래합니다.

식별인증 동시 SQL Injection

식별 인증을 동시에 수행하는 로그인 로직에서 SQL Injection을 진행해 보자

login.php

// ID와 비밀번호를 동시에 확인
$sql = "SELECT * FROM members WHERE id = '$input_id' AND pass = '$input_pass'";

$result = mysqli_query($conn, $sql);

if (mysqli_num_rows($result) > 0) {
    echo "로그인 성공";
} else {
    echo "아이디 또는 비밀번호가 잘못되었습니다.";
}

식별과 인증을 동시에 수행하는 로직이다.

Database

members라는 테이블에 총 3명에 정보가 있다.

login test

DB에 존재하는 값으로 로그인 시 로그인 성공이 나오고 아닐 경우 로그인이 실패하는 걸 볼 수 있다 SQL Injection을 이용해 로그인을 해보자

' and '1'='1

만약 bawool이라는 계정에 대한 정보만 알고 있다고 가정하고 ' and '1' ='1을 사용해 보자

and '1'='1'이 항상 참이므로 아무 영향도 주지 않지만 기존 조건을 그대로 유지하면서 동작을 테스트하거나, 추가된 조건이 애플리케이션에 어떤 영향을 미치는지 확인할 수 있다. 이로 인해 알 수 있는 사실은 이 페이지에서 SQL Injection을 사용할 수 있다는 거다.

' or '1'='1

위에 정보를 토대로 admin으로 로그인을 시도해 보자

쿼리문을 보면 알 수 있듯이 admin의 비밀번호가 아닌 아무 비밀번호를 입력했지만 로그인이 되는 걸 확인할 수 있다. 그 이유는 '1'='1'은 항상 참이므로, OR 연산자를 통해 기존의 모든 조건을 무시하고 결과를 반환하기 때문이다. 쉽게 설명하면 연산에는 우선순위가 존재한다. 현재 쿼리문을 볼 경우 AND, OR 두 개의 연산자가 있지만 AND 연산자가 우선순위이기 때문이다.

id = 'admin' or ('1'='1' AND pass = 'bndkfjlnb')

이런 식으로 괄호 부분을 먼저 연산한다고 생각하면 된다. 우리는 패스워드를 모르는 상태에서 아무거나 입력했기 때문에 AND 부분은 참이 아니라 거짓이 될 것이다. 하지만 admin이 존재하는 아이디이기 때문에 그리고 OR은 둘 중 하나만 참일 경우 참이 되기 때문에 로그인에 성공하는 걸 볼 수 있다.


식별인증 분리 SQL Injection

이번에는 식별 인증을 분리해서 수행하는 로그인 로직에서 SQL Injection을 진행해 보자 DB 정보는 위와 같다.

login.php

// 1단계: ID 확인 (식별)
$sql_id = "SELECT * FROM members WHERE id = '$input_id'";
$res = mysqli_query($conn, $sql_id);

if ($row = mysqli_fetch_array($res)) {
    // 2단계: 비밀번호 확인 (인증)
    if ($row['pass'] == $input_pass) {
        echo "로그인 성공";
    } else {
        echo "비밀번호가 잘못되었습니다.";
    }
} else {
    echo "아이디가 존재하지 않습니다.";
}

식별과 인증을 분리해서 수행하는 로직은 기존과 같은 or 같은 조건문만 이용해서는 우회할 수 없기 때문에 두 개 이상의 SELECT 쿼리의 결과를 하나로 결합할 때 사용하는 명령어인 union을 사용해 줘야 한다.

Union 동작 방식

사진과 같이 id가 admin이라는 값을 찾는 select 문 뒤에 union으로 select 문을 하나 더 추가해 주었다. 이런 식으로 column의 개수를 맞춰서 사용할 경우 다음 행에 추가되어서 값이 출력된다. 식별 인증 분리 코드를 보면 WHERE id = '$input_id'로 되어있다. 만약 input_id를 입력하지 않고 password도 입력하지 않고 union을 이용하면 어떻게 될까?

앞에 값이 없을 경우 우리가 사용한 union select 문에서 값이 들어간다. 현재 우리가 admin, 1234라는 정보를 알고 있고 bawool이라는 id를 알고 있지만 password를 모르는 상태에서 bawool이라는 id로 접속하고 싶다고 가정하고 코드를 살펴보면 $row['pass'] == $input_pass 내가 입력한 비밀번호랑 row['pass']랑 같아야 로그인을 성공할 수 있는 것이다. 위와 같이 id에 아무 값도 입력하지 않고 union을 사용하면 우리가 입력한 값이 첫 번째 행으로 들어가기 때문에

id: ' union select 'bawool', '1234
passwd: 1234

위와 같이 입력할 경우

$row = mysqli_fetch_array($res) 는 첫 번째 행을 반환
$row = array('id' => 'bawool', 'pass' => '1234');

if ($row['pass'] == $input_pass)

- $row['pass']'1234'.
- $input_pass는 사용자가 입력한 '1234'.

로그인 우회에 성공하는 걸 볼 수 있다. 로직마다 우회 방식이 다르기 때문에 여러 로직을 만들어 보는 것도 중요한 것 같다!

0개의 댓글