본문 바로가기

1. Web hacking (웹 해킹)/2) 개념 정리

[2021.3.20] Server-side Basic

2021.03.13

I.Sly() 드림팀-dreamhack의 Web Hacking 강의를 통한 개념 스터디


 

Server-side Basic

introduction

서버에서는 사용자가 요청 한 데이터를 해석하고 처리한 후 사용자에게 응답함 그 과정에서 웹 어플리케이션이나 데이터베이스와 같은 서버의 자원을 사용해 처리하기도 함

이 과정에서 사용자의 요청 데이터에 의해 발생하는 취약점을 서버 사이드 취약점이라고 함

nc나 telnet과 같은 네트워크 프로그램을 통해 HTTP Request를 보낼 때는 메소드나 요청 헤더처럼 브라우저에서 조작하지 못하는 데이터도 조작하여 전송할 수 있음 ➡ 서버에서는 사용자로부터 받는 모든 입력을 신뢰하지 않도록 해야함

HTTP 요청 시 모든 데이터는 조작하여 전송이 가능하며, 악의적인 사용자는 이를 이용해 서버의 취약점을 확인함

  • Injection(인젝션): 서버의 처리 과정 중 사용자가 입력한 데이터가 처리 과정의 구조나 문법적으로 사용되어 발생하는 취약점
  • File vulnerability: 서버의 파일 시스템에 사용자가 원하는 행위를 할 수 있을 때 발생하는 취약점
  • Business Logic Vulnerability (비즈니스 로직 취약점): 인젝션, 파일 관련 취약점들과는 다르게 정상적인 흐름을 악용하는 것을 의미
  • Language specific Vulnerability (PHP, Python, NodeJS): 웹 어플리케이션에서 사용하는 언어의 특성으로 인해 발생하는 취약점을 다룸
  • Misconfiguration: 잘못된 설정으로 인해 발생하는 취약점을 다룸

Injection

주입

인젝션 공격: 사용자의 입력 값이 어플리케이션의 처리 과정에서 구조나 문법적인 데이터로 해석돼 발생하는 취약점을 의미.

변조된 입력을 주입 ➡ 의도하지 않은 행위 발생시킴

  • SQL Injection: SQL을 사용할 때 공격자의 입력 값이 정상적인 요청에 영향을 주는 취약점
  • Command Injection: OS Command를 사용 시 사용자의 입력 데이터에 의해 실행되는 Command를 변조할 수 있는 취약점
  • Server Side Template Injection (SSTI): 템플릿 변환 도중 사용자의 입력 데이터가 템플릿으로 사용돼 발생하는 취약점
  • Path Traversal: URL / File Path를 사용 시 사용자의 입력 데이터에 의해 임의의 경로에 접근하는 취약점
  • Server Side Request Forgery (SSRF): 공격자가 서버에서 변조된 요청을 보낼 수 있는 취약점

SQL Injection

SQL: 관계형 데이터베이스(RDBMS)의 데이터를 정의하고 질의, 수정 등을 하기 위해 고안된 언어

데이터베이스에 의존하는 상당수의 웹 어플리케이션은 SQL을 사용해 데이터베이스와 상호작용함

웹 어플리케이션에서 로그인/검색과 같이 사용자의 입력 데이터를 기반으로 DBMS에 저장된 정보를 조회하는 기능을 구현하기 위해 SQL쿼리에 사용자의 입력 데이터를 추가하여 DBMS에 요청함

SQL Injection은 SQL 쿼리에 사용자의 입력 값이 삽입돼 사용자가 원하는 쿼리를 실행할 수 있는 취약점

SQL Injection이 발생하게 되면 현재 쿼리를 실행하는 DBMS 계정의 권한으로 공격이 가능하며 일반적으로 데이터베이스의 내용을 추출하거나 변조, 삭제하는 등의 행위가 가능

SQL

  • DDL (Data definition language): 데이터를 정의하기 위한 언어. 데이터를 저장하기 위한 스키마, 데이터베이스의 생성/수정/삭제 등의 행위를 수행.
  • DCL (Data control language): 데이터베이스의 접근 권한 등의 설정을 하기 위한 언어. 데이터베이스내에 사용자의 사용 권한을 부여하기 위한 GRANT와 권한을 박탈하는 REVOKE가 대표적임.

DDL (Data definition language)

  • CREATE: 새로운 데이터베이스 또는 테이블을 생성
  • ALTER: 데이터베이스 또는 테이블의 속성을 변경
  • DROP: 데이터베이스 또는 테이블을 삭제

DML (Data manipulation language)

  • INSERT: 테이블에 새로운 데이터를 추가
  • UPDATE: 테이블에 존재하는 데이터를 수정
  • SELECT: 테이블에 존재하는 데이터를 조회
  • DELETE: 테이블에 존재하는 데이터를 삭제

사용자의 입력 데이터가 SQL 쿼리에 들어가는 대표적인 예시로는 로그인 기능

select * from user_table

where uid='{uid}' and upw='{upw}';

 

사용자가 자신의 아이디와 패스워드를 입력하면 웹 어플리케이션에서는 {uid} , {upw} 부분에 사용자가 입력한 문자열을 삽입하고 DBMS로 전달해 실행

1'or'1과 같은 공격 페이로드를 통해 모든 정보를 출력할 수 있음

SQL Injection 취약점을 막기 위해 ➡ 사용자의 입력 데이터가 SQL 쿼리로 해석되지 않아야 함

앞의 실습 문제는 사용자의 입력값에 문자열 구분자(', ")가 삽입되어 본래의 쿼리 형태를 벗어나는 SQL Injection이 발생함

과거에는 문자열 구분자 앞에 백슬래시(\\) 문자를 붙여 사용자의 입력을 escape해 사용하는 방식을 자주 이용 but 최근에는 권장X why? 사용자로부터 입력을 받는 타입은 문자열일 수도 있지만 숫자 타입일 수도 있기 때문

문자열 구분자를 모두 escape 했더라도 숫자 뒤에 공백문자(' ', \\n, ...)를 넣는 것 만으로도 바로 쿼리에 사용자의 입력을 삽입할 수 있기 때문에 SQL Injection이 발생할 수 있음

SQL Injection을 막기 위해 권장하는 방법은 ORM과 같이 검증된 SQL 라이브러리를 사용하는 것

ORM: Object Relational Mapper의 약자로써 SQL의 쿼리 작성을 돕기위한 라이브러리

ORM은 생산성을 위해서도 사용하지만 사용자의 입력 값을 라이브러리 단에서 스스로 escape하고 쿼리에 매핑시키기 때문에 안전하게 SQL 쿼리를 실행함

ORM을 사용하더라도 입력 데이터의 타입 검증이 없으면 잠재적인 위협이 될 수 있습니다. 입력 데이터의 타입 검증이 필요합니다.

Command Injection

웹 어플리케이션에서는 OS Command를 실행하기 위해 PHP(system), Node JS(child_process), **Python(os.system)**과 같은 함수가 존재

OS Command: linux(ls, pwd, ping, zip), windows(dir, pwd, ping) 등의 OS에서 사용하는 명령어

웹 어플리케이션에서 OS Command를 사용하는 이유는 이미 기능을 구현한 OS 실행 파일이 존재할 때 코드 상에서 다시 구현하지 않고 이를 실행하면 더 편리하기 때문

OS Command는 내부적으로 셸(Shell)을 이용해 실행

  • ``명령어 치환: ``안에 들어있는 명령어를 실행한 결과로 치환됨.
  • $() 명령어 치환: $()안에 들어있는 명령어를 실행한 결과로 치환됨. 이 문자는 위와 다르게 중복 사용이 가능되. (echo $(echo $(echo theori)))
  • && 명령어 연속 실행: 한 줄에 여러 명령어를 사용하고 싶을 때 사용. 앞 명령어에서 에러가 발생하지 않아야 뒷 명령어를 실행. (Logical And)
  • || 명령어 연속 실행: 한 줄에 여러 명령어를 사용하고 싶을 때 사용. 앞 명령어에서 에러가 발생해야 뒷 명령어를 실행. (Logical Or)
  • ; 명령어 구분자: 한 줄에 여러 명령어를 사용하고 싶을 때 사용합니다. ;은 단순히 명령어를 구분하기 위해 사용하며, 앞 명령어의 에러 유무와 관계 없이 뒷 명령어를 실행
  • | 파이프: 앞 명령어의 결과가 뒷 명령어의 입력으로 들어감.

Command Injection 취약점을 막기 위해 ➡ 사용자의 입력 데이터가 Command 인자가 아닌 다른 값으로 해석되는 것을 방지해야함

가장 좋은 방법은 웹 어플리케이션에서 OS Command를 사용하지 않는 것 웹 어플리케이션에서 필요한 OS Command가 라이브러리 형태로 구현되어 있으면 해당 라이브러리를 사용하는 것을 권장하며, 없을 경우 직접 프로그램 코드로 포팅해 사용하는 것이 좋음

만약 OS Command에 사용자의 입력 데이터를 사용해야할 경우 필터링을 통해 Command Injection을 방지해야합니다. 방지하는 방법에는 크게 화이트/블랙 리스트 필터링 방식이 있음

 

  • 정규식을 통한 화이트리스트방식 필터링
  • OS Command에서 Meta 문자로 사용되는 값을 필터링 하고 따옴표로 감싸기
  • execve args 인자로 사용
  • 기능에 해당하는 라이브러리 사용

 

Server Side Template Injection(SSTI)

웹 어플리케이션에서 동적인 내용을 HTML로 출력할 때 미리 정의한 Template에 동적인 값을 넣어 출력하는 Template Engine을 사용하기도함

Template 내부에서 사용되는 context가 아닌 Template source에 사용자 입력이 들어가게 된다면 악의적인 입력을 통해 개발자가 의도하지 않은 임의의 Template 기능을 실행할 수 있음

즉, 사용자의 입력 데이터가 Template에 직접 사용될 경우 Template Engine이 실행하는 문법을 사용할 수 있기 때문에 SSTI 취약점이 발생하게 됨.

SSTI 취약점을 막기 위해서는 사용자의 입력 데이터를 Template source에 삽입되지 않도록 해야함

Path Traversal

Path가 사용되는 대표적인 로직으로는 URL/File이 있음. URL/File의 Path에는 Parent Directory(상위 디렉터리)를 의미하는 구분자(..)가 있음. 예를 들어 /tmp/test/../a 경로가 해석되면 /tmp/test/의 상위 폴더인 /tmp/폴더의 하위에 있는 a 파일, 즉 /tmp/a를 나타냄.

사용자의 입력 데이터가 적절한 검증 없이 URL/File Path에 직접적으로 사용될 경우 설계 및 개발 당시에 의도하지 않은 임의의 경로에 접근할 수 있는 Path Traversal 취약점이 발생하게 됨

사용자의 입력 데이터가 경로로 사용되는 경우에는 URL Encoding과 같은 인코딩을 사용해 사용자의 입력 데이터에 포함된 구분 문자를 인식하지 않도록 할 수 있음. 이를 통해 Path Traversal 취약점을 방지할 수 있음.

Server-side Request Forgery(SSRF)

CSRF는 변조된 요청이 웹 클라이언트(브라우저)가 보내며, SSRF는 웹 어플리케이션에서 보내지게됨

웹 어플리케이션에서 요청을 보내기 때문에 웹 어플리케이션이 작동하고 있는 서버 내부의 포트, 서버와 연결된 내부망에 요청을 보낼 수 있고 Server-side에서 변조된 요청 / 의도하지 않은 서버로 요청을 보내는 공격이 SSRF

웹 서비스 인프라를 구성할 때 외부망/내부망을 나누어 설계하고 "내부망에서는 인증된 서버/사용자만이 요청을 보낼 수 있다"고 가정해 별도의 인증 없이 기능을 구현하는 경우가 많이 있습니다. 클라우드 플랫폼들에서도 내부망에서 작동하는 기능들이 있어 SSRF 공격이 발생하면 인프라를 공격하는 취약점이 될 수 있습니다.

SSRF 취약점을 방지하기 위해➡ 사용자가 입력한 URL의 Host를 화이트리스트 방식으로 검증하는 방법

그 외에도 사용자의 URL을 처리하는 서버를 독립적으로 망 분리를 하여 SSRF 취약점이 발생하여도 다른 취약점과 연계를 하지 못하도록 방지하는 방법들도 있습니다.

File Vulnerability

  • 파일 업로드 취약점

    서버의 파일 시스템에 사용자가 원하는 경로 또는 파일 명 등으로 업로드가 가능하여 악영향을 미칠 수 있는 파일이 업로드되는 취약점

  • 파일 다운로드 취약점

    서버의 기능 구현 상 의도하지 않은 파일을 다운로드할 수 있는 취약점

    File Upload

    File Upload(파일 업로드)는 웹 서비스를 통해 파일을 서버에 업로드하는 기능을 의미

    파일 업로드 기능은 사용자의 파일이 서버의 파일 시스템에 저장되어 처리된다는 이유로 인해 취약점이 발생할 수 있음

정상적인 File Upload와 악의적인 File Upload

악의적인 건 filename에 상위 디렉토리로 이동하는 ../문자를 삽입한 요청 ➡ uploads디렉토리를 벗어난 경로에 파일이 업로드 된것을 확인할 수 있음

파일 업로드 취약점을 통해 서버 파일 시스템에 원하는 파일 경로 또는 파일 명을 업로드할 수 있다면 악의적인 공격자는 웹 어플리케이션 또는 서버의 서비스가 참조하는 파일을 업로드하여 공격에 사용할 수 있습니다.

공격에 앞서 웹 서버의 CGI라는 개념을 이해하여야 합니다.

CGI(Common Gateway Interface): 사용자의 요청을 받은 서버가 동적인 페이지를 구성하기 위해 엔진에 요청을 보내고 엔진이 처리한 결과를 서버에게 반환하는 기능

웹 서비스가 동작하는 경로에 사용자가 원하는 파일 내용과 파일 명을 업로드 할 수 있다면 서버가 엔진에 요청하는 확장자를 업로드하여 서버의 웹 어플리케이션에 원하는 코드를 실행 할 수 있음

웹 어플리케이션이 실행하는 코드를 악의적인 공격자가 조작할 수 있다면 웹 어플리케이션 언어에 내장된 OS 명령어 등을 사용할 수 있으며, 해당 서버의 쉘을 웹을 통해 사용한다고하여 WebShell(웹쉘)이라는 악성코드가 등장하게 되었음

File Download

파일 다운로드 기능을 구현하는 방법은 여러가지지만 취약점이 발생하는 가장 흔한 형태는 사용자가 입력한 파일이름을 검증하지 않은 채 그대로 다운로드를 제공하는 행위

개발자는 사용자가 uploads 디렉토리 안에 존재하는 파일만 다운로드할 수 있을 것이라고 생각할 수 있지만, Injection 주제에서 배운 Path Traversal을 이용하면 uploads 경로보다 더 상위 경로에 존재하는 시스템 파일, 설정 파일과 같은 중요한 정보들을 다운로드할 수 있음

파일 다운로드 취약점은 웹 어플리케이션의 소스 코드, 관리자의 패스워드, 서비스 키, 설정 파일 등을 유출할 수 있기 때문에 주로 이차적인 공격을 위한 발판으로 삼을 수 있음

파일 다운로드 취약점을 막기 위해

1️⃣ 기본적으로 인자에 다운로드 받으려는 파일의 경로나 이름을 넘기지 않는 것이 좋음

2️⃣ 반드시 이름을 넘기는 방식으로 구현해야 한다면 상대경로로 접근하는데 사용될 수 있는 .. 과 / 와 \\\\ 를 적절하게 필터링 해야함

3️⃣ 데이터베이스에 다운로드 될 파일의 경로와 그에 해당하는 랜덤 키를 생성해 1대 1로 매칭해서 저장해두고 해당 랜덤 값이 인자로 넘어왔을 때 데이터베이스에 존재하는 파일인지를 먼저 식별하고 다운로드 하는 것이 안전

4️⃣ 만약에 웹 서버가 동작하는 운영 체제가 윈도우 운영체제일 경우 ../외에 ..\\로도 상위 경로에 접근할 수 있기 때문에 둘 다 필터링 하는 것이 필요

Business Logic Vulnerability

Business logic(비즈니스 로직): 규칙에 따라 데이터를 생성·표시·저장·변경하는 로직, 알고리즘 등을 말함

ex) 게시판 서비스: 회원 가입/로그인, 게시물 작성/수정/삭제 등 다양한 로직이 모여 하나의 서비스가 완성됨

Business Logic Vulnerability(비즈니스 로직 취약점)은 정상적인 비즈니스 로직을 악용하는 것을 의미합니다. 인젝션, 파일 관련 취약점들은 사용자의 악의적인 데이터가 서버의 시스템 상에서 악영향을 미치는 공격을 수행하지만, 비즈니스 로직 취약점은 서비스의 기능에서 적용되어야 할 로직이 없거나 잘못 설계된 경우 발생

  • Business Logic Vulnerability: 정상적인 흐름에서 검증 과정의 부재 및 미흡으로 인해 정상적인 흐름이 악용되는 취약점
  • IDOR (Insecure Direct Object Reference): 변조된 파라미터 값이 다른 사용자의 오브젝트 값을 참조할 때 발생하는 취약점
  • Race Condition: 비즈니스 로직의 순서가 잘못되거나, 한 오브젝트에 여러 요청이 동시에 처리되는 상황에서 발생하는 취약점

비즈니스 로직 취약점은 어플리케이션의 검증 부재 또는 미흡의 이유로 발생

비즈니스 로직 취약점을 방어하기 위해➡ 비즈니스 로직을 확실하게 이해하고, 설계 및 개발 단계에서 어떤 위협이 발생할 수 있는지 위협을 파악하고 방어하는 것이 중요합니다.

Insecure Direct Object Reference (IDOR) 취약점은 안전하지 않은 객체 참조라는 의미와 같이 객체 참조 시 사용하는 객체 참조 키가 사용자에 의해 조작됐을 때 조작된 객체 참조 키를 통해 객체를 참조하고, 해당 객체 정보를 기반으로 로직이 수행되는 것을 의미

IDOR 취약점이 발생하는 주된 원인은 사용자의 입력 데이터에 의해 참조하는 객체가 변하는 기능에서 사용자가 참조하고자 하는 객체에 대한 권한 검증이 올바르지 않아 발생

IDOR 취약점은 비즈니스 로직에 따라 조회/삭제/수정/추가 등의 다양한 형태를 다른 사용자의 객체로 수행할 수 있음

IDOR 취약점을 방어하기 위해

1️⃣ 객체 참조 시 사용자의 권한을 검증하는게 가장 중요합니다. 즉 사용자가 의도한 권한을 벗어나서 행동 할 수 없도록 권한 등을 분리해서 관리하여야함

2️⃣ 로그인 등의 기능을 통해 사용자 인증을 거친 후 사용하는 서비스에서는 사용자 식별을 위한 정보를 사용자의 입력 데이터로 구분하기 보다는 사용자가 요청 시 전달하는 세션을 통해 서버 내에서 처리하는 것이 안전

3️⃣ 객체를 참조하기 위해 사용하는 객체 참조 키를 단순한 숫자가 아닌 무작위 문자 생성 등을 통해 악의적인 공격자가 객체에 참조하기 위한 객체 참조 키를 추측하기 어렵게 만드는 방법

숫자 만을 이용한 해쉬 함수로 객체 참조 키를 사용하면 레인보우 테이블(rainbow table)에 의해 사실상 평문으로 사용하는 것과 같습니다. 해쉬 함수를 이용해 객체 참조 키를 사용할 경우 솔트(Salt)를 사용해 해쉬 함수를 안전하게 사용해야 합니다.

 

Race Condition

Race Condition(레이스 컨디션): 공유 자원 처리 과정에서 해당 자원에 대한 동시 다발적인 접근으로 인해 발생하는 취약점

1️⃣ 레이스 컨디션 취약점으로 부터 안전하게 보호되어야하는 로직들은 하나의 접근이 끝난 후 다음 접근을 처리하도록 쓰레드 락 등을 통해 동시 다발적인 접근을 방지하여야함

2️⃣ 레이스 컨디션 취약점을 발생시키기 위해 다량의 접근이 필요하다는 점을 이용하여 특정한 행위에 요청을 할 시에는 CSRF 토큰, 캡차 등을 통해 다량의 접근을 방지하는 방법을 통해 웹 어플리케이션을 보호할 수 있음

웹 해킹에서는 데이터베이스 또는 파일 시스템과 같이 웹 어플리케이션에서 공유하는 자원들에 대한 접근 과정에서 데이터를 참조하는 타이밍의 차이로 인해 취약점이 발생하게 됨

Language specific Vulnerability

해당 언어만의 특성, 함수에서 발생할 수 있는 취약점

의도한 기능을 제공하는 함수를 잘못 사용해서 문제가 발생할 수도 있으며, 사용자의 입력 데이터가 함수의 인자로 사용되어 취약점이 발생하기도 함

Common

  • 코드 실행 함수 (eval)
  • OS command function
  • Filesystem function
  • serialize / deserialize

PHP

  • include
  • Wrappers
  • extract
  • Type Juggling
  • Comparison
  • session
  • Upload Logic

Javascript

자바스크립트는 클라이언트 사이드에서는 웹 브라우저의 내장 언어로 사용되며, 서버 사이드에서는 자바스크립트를 기반으로 만들어진 NodeJS로 사용될 수도 있습니다.

  • Comparison Problem
  • Prototype Pollution

eval

인자로 입력된 문자열을 어플리케이션 코드로 실행

➡ eval의 인자로 사용자의 입력 데이터가 사용될 경우 악의적인 데이터를 입력해 원하는 프로그램 코드를 실행할 수 있기 때문에 사용자의 입력 데이터가 eval의 인자로 사용되지 않아야함

OS Command Function

OS Command를 실행하기 위한 어플리케이션 함수 사용 시 실행하는 명령어에 사용자의 입력 데이터가 포함될 경우 Command Injection 취약점이 발생할 수 있음

Filesystem function

어플리케이션에서 파일 시스템에 접근할 수 있는 함수들의 인자가 사용자의 입력 데이터 또는 변조될 가능성이 있는 변수들을 사용할 경우 서버의 파일 시스템을 공격하거나, 다른 취약점으로 악용될 수 있음

  • File Read

    -어플리케이션 코드, 설정 파일 정보 등의 노출

  • File Write

    -WebShell 생성을 통한 원격 코드 실행 공격

    -기존 설정 파일을 덮는 공격을 통해 운영체제 또는 어플리케이션 설정 변경

  • Etc

    -파일 복사를 통해 File Write와 유사한 상황 발생

    -설정 파일을 삭제하여 운영체제 또는 어플리케이션 서비스 무력화

serialize / deserialize (직렬화 / 역직렬화)

serialize(직렬화)는 Object 또는 Data의 상태 또는 타입을 특정한 형태의 포맷을 가진 데이터로 변환하는 것을 의미

deserialize(역직렬화)는 직렬화된 데이터를 원래의 Object 또는 Data의 상태 또는 타입으로 변환하는 것을 의미

직렬화는 오브젝트, 데이터의 현재 상태와 타입들을 저장하고, 원하는 상황에 역직렬화를 통해 동일한 상태와 타입을 가진 오브젝트 또는 데이터들을 사용할 수 있음

ex)

# ClassA 직렬화

ClassA_dump = pickle.dumps(ClassA)

print(ClassA_dump)

# ClassA 역직렬화, ClassB로 할당

ClassB = pickle.loads(ClassA_dump)

print(ClassB.A, ClassB.B)

 

파이썬에서 직렬화/역직렬화를 사용하는 대표적은 모듈은 pickle과 yaml

주로 Python Object의 reduce 메소드를 공격에 사용

NodeJS의 대표적인 직렬화/역직렬화 모듈은 node-serialize

PHP deserialize 공격에서는 Object의 특수한 상황에서 실행되어지는 Magic Methods를 이용합니다.

주로 사용하는 Magic Methods는 아래와 같습니다.

__destruct() ==> 소멸자의 개념으로 오브젝트 소멸 시 호출됨.__wakeup() ==> 역직렬화 시 호출됨.

 

include 함수는 파일의 확장자 또는 파일의 타입과는 상관없이 파일의 내용에 php 태그가 포함될 경우 php 코드가 실행되기 때문에 사용 시 주의해야함.

서버 로컬 파일을 Include 하는 취약점을 Local File Inclusion(LFI), 외부 자원을 Include 하는 취약점을 Remote File Inclusion(RFI)라 부름.

PHP의 allow_url_include 설정은 외부 자원에 대한 접근을 방지하는 옵션입니다. 대부분의 기본 설정에서는 해당 옵션이 off된 상태입니다.

PHP - Wrapper

PHP는 include(), fopen(), copy(), file_exists(), filesize() 와 같은 파일 시스템 함수에서 URL style 프로토콜을 위한 wrapper들이 존재

PHP - Extract

PHP의 extract 함수는 배열에서 변수를 가져옴

extract 함수 시 기존에 사용되고 있는 변수의 데이터를 덮을 수 있기 때문에 extract 함수에 사용자의 입력($_GET, $_POST, $_FILES)과 같은 신뢰할 수 없는 데이터가 사용되면 다른 변수를 변조하여 공격에 사용될 수 있음

php extract 문서에서는 사용자의 데이터처럼 신뢰할 수 없는 데이터를 사용하지 않는 것을 권고하고 있음

PHP - Type Juggling

PHP에서 서로 다른 타입인 변수를 비교 또는 연산 시 자동으로 형변환이 발생하며 의도치 않은 결과가 발생할 수 있음

PHP - Comparison

서로 다른 타입이 비교 연산자에서 사용될 경우 type-juggling에 의해 의도치 않은 결과가 발생할 수도 있음

비교 연산자(Equal, ==)를 사용할 때 비교하는 두 변수의 타입이 다르면 type-juggling에 의해 타입이 변환된 후 비교합니다. 정확한 비교를 하기 위해서는 동일한 타입인지도 비교하는 비교연산자(Identical, ===)를 사용해야함

PHP에서 문자열을 비교하는 strcmp 함수는 다음과 같은 형식으로 사용됩니다.

strcmp ( string $str1 , string $str2 ) : int

 

인자를 비교했을 때 같으면 0, $str1이 작으면 음수 $str2가 작으면 양수가 반환되고 string이 아닌 array를 인자로 전달할 경우 NULL을 반환

❌PHP에서는 NULL == 0 와 같은 식으로 비교하게 될 경우 단순 Equal 연산이기 때문에 Type Juggling이 발생해 0 == 0으로 비교하게 되어 문제가 발생할 수 있음

strcmp 함수로 문자열을 비교할 때 Equal이 아닌 Identical을 사용해야 함

PHP - Session

PHP에서 session(세션)의 가장 기본적인 사용 형태는 다음 코드와 같습니다.

<?php

session_start(); // session 사용을 위해 필수적으로 사용되어야 함.

$_SESSION['uid'] = 1234; // 해당 유저의 session['uid']에 int 1234 로 할당

 

PHP의 기본 세션 관리는 다음과 같은 로직을 가짐.

  1. session_start()
    • HTTP Request에서 쿠키를 가져와 PHPSESSID(php 기본 Session ID, 쿠키를 통해 서버와 사용자가 주고받는 php session의 이름)의 값을 가져옴.
    • PHPSESSID값이 존재하지 않으면 랜덤한 값의 PHPSESSID를 생성하고 세션 변수에($_SESSION) 빈 array를 할당.
    • PHPSESSID값이 있으면 해당 PHPSESSID에 해당하는 값을 세션 변수에($_SESSION) 로드.
  2. $_SESSION 변수에 접근하여 값을 읽거나 변경.
  3. session_start로 시작된 해당 페이지(PHP)가 종료될 때 자동으로 세션 변수를 serialize한 값을 파일 시스템에 저장합니다.
    • 기본적으로 파일 시스템의 {세션기본경로}/sess_{PHPSESSID값} 경로에 저장.

세션에 사용자의 입력 데이터가 들어가게 된다면 다른 공격과 연계하여 사용될 수 있음.

예를 들어 include 함수의 인자를 조작 가능하고 인자에 대한 검증이 없는 페이지에서 세션 파일을 include 인자로 넘겨 원하는 PHP 코드를 실행할 수 있음.

  • session.php

<?php

session_start();

$_SESSION['name'] = 

$_GET['name']; // 사용자 입력 데이터를 세션에 저장.

 

위와 같은 파일이 존재할 때 /session.php?name=<?php system('id');?>와 같이 입력하여 php 코드를 세션에 삽입할 수 있음.

PHP - Upload Logic

php 파일 업로드 내부 로직은 다음과 같습니다.

  1. 임시 디렉토리에 임시 파일 생성
  2. php 로직 중 업로드 파일 처리 로직 존재 시 임시파일 참조($_FILES['file']['tmp_name'])
  3. php 로직 처리 후 임시 파일 삭제

php 코드에서 로직 처리등의 이유로 지연이 발생한다면 임시 파일은 지연이 발생하는 시간동안 존재하게 됨

php 파일 업로드 내부 로직에서 문제가 발생할 수 있는 점은 다음과 같음.

  1. php 코드상에서 업로드 기능을 구현하지 않아도 사용자가 서버의 임시 디렉토리에 업로드 가능.
  2. 예측 가능한 임시 파일 생성 규칙.

Javascript Specific Vulnerability

Comparison Problem

자바스크립트도 PHP와 마찬가지로 변수의 타입을 동적으로 정할 수 있는 Dynamic 언어

자바스크립트는 두 값을 비교할 때 두 값 모두 객체가 아닐경우 valueOf, toString 함수를 이용해 원시 값(primitive value)을 가져와 비교하게 됨

Prototype Pollution

자바스크립트는 프로토타입을 사용하는 언어.

객체를 생성할 때 초기화 할 프로토타입을 지정해주지 않으면 Object.prototype의 속성과 정의된 함수(method)를 상속 받음

Prototype Chain Lookup

Bracket notation

객체에 접근할 때 사용하는 방법은 .을 이용하거나 [xyz]를 사용하는 방법이 있습니다. 전자는 dot notation, 후자는 bracket notation이라고 부름

Misconfiguration

잘못된 설정으로 인해 공격자는 허가되지 않은 동작을 수행할 수 있습니다. 다른 웹 취약점처럼 소스 코드 상에 존재하는 복잡한 로직에 의해 발생하는 취약점이 아닌 간단한 설정 오류로 인해 발생

➡ 따라서 검수할 때는 기본 메뉴얼에 존재하는 룰을 잘 따랐는지만 확인하면 돼 자동화된 도구로 발견하기 쉬움

  • 부주의로 인해 발생하는 문제점

    메뉴얼에 존재하지 않은 설정이거나 개발자의 부주의로 인해 설정 유무를 알지 못한 상태에서 서비스를 할 경우

  • 편의성을 위한 설정에 의해 발생하는 문제점

    개발자를 위한 설정이 서비스 환경에서도 켜져있어 공격자가 이를 통해 시스템 내부의 정보를 알아내 추가적인 공격에 사용될 수 있습

  • 메뉴얼과 실제 구현체의 차이로 인해 발생하는 문제점

    메뉴얼에 설명되어있는 대로 사용했지만 중의적 표현이 존재하거나 잘못 설명되어있을 때 발생

  • 해당 코드나 설정에 대한 이해 없이 사용해 발생하는 문제점

    취약점이 존재하는 예제코드, StackOverflow 답변등을 이해 없이 복사 붙여넣기 해 사용하거나 메뉴얼에 존재하는 권고 설정을 무시한 채 사용해 발생

기본 서비스

서비스 요소들 운용 시 사용하는 시스템 또는 어플리케이션에서 개발자가 설정하지 않아도 기본적으로 제공되는 기능에 의해 문제가 발생할 수 있습니다.

대부분 개발 당시에 필요한 기능이거나, 내부적으로 사용해야 하는 기능들입니다. 즉, 운영 시에 의도하지 않은 경로 또는 기능이 노출되는 위협이 발생할 수 있습니다.

  • 관리 서비스
    • Tomcat - Web Application Manager
    • Docker Registry API
  • 모니터링 서비스
    • Spring Boot Actuator - metrics
    • Apache mod_status

 

Debug

디버그 모드 설정 또는 디버그 목적으로 코드 상에서 특정 정보를 사용자에게 제공할 경우 해당 정보를 기반으로 서버의 환경 및 정보가 노출될 수 있습니다.

 

 


2021.03.20 구글문서 보고서 작성

docs.google.com/document/d/1ee25k8qyrNItAmAWmVVDpzhOn0KWqxw4zQ1_izvtybo/edit?usp=sharing