일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- css기초
- 알고리즘
- 익스프레스
- JS
- 다이나믹프로그래밍
- HTML
- 프로그래머스
- JS프로그래머스
- 백준구현문제
- 프로그래머스JS
- 리액트댓글기능
- 자바스크립트
- 백준nodejs
- CSS
- 코테
- 리액트커뮤니티
- HTML5
- 백준골드
- 백준알고리즘
- 백준
- dp알고리즘
- 백준구현
- 프로그래머스코테
- 몽고DB
- 코딩테스트
- 백준js
- 리액트
- 포이마웹
- js코테
- 안드로이드 스튜디오
- Today
- Total
개발새발 로그
웹 보안 공격 이론 - HTTPS의 원리 본문
기초적인 것은 꼭 알자
1. SQL injection
SQL injection은 웹 응용 프로그램에서 발생하는 보안 취약성 중 하나로, 악의적인 사용자가 입력 필드 또는 매개변수를 통해 SQL 쿼리를 주입하여 데이터베이스에 대한 비인가된 액세스를 시도하는 공격입니다.
일반적으로 웹 어플리케이션에서 사용자로부터 입력을 받아 데이터베이스와 상호 작용하는 경우, 사용자의 입력이 안전하게 처리되지 않으면 SQL injection 공격에 취약할 수 있습니다.
일반적인 SQL injection 공격의 예를 살펴보겠습니다.
가령, 사용자 이름과 비밀번호를 확인하는 로그인 폼이 있다고 가정해봅시다.
SELECT * FROM users WHERE username = '사용자입력' AND password = '비밀번호입력';
이 때, 사용자로부터 입력을 받을 때 입력값을 안전하게 처리하지 않고 사용한다면, 악의적인 사용자는 다음과 같은 입력을 사용하여 공격을 시도할 수 있습니다.
사용자이름: ' OR '1'='1'; --
비밀번호: 아무거나
위와 같은 입력을 사용하면 SQL 쿼리가 다음과 같이 변경됩니다.
SELECT * FROM users WHERE username = '' OR '1'='1'; --' AND password = '아무거나';
이렇게 되면 항상 참이 되는 조건 '1'='1'으로 인해 해당 쿼리는 모든 사용자를 반환하게 됩니다.
공격자는 이를 통해 로그인 폼을 우회하고 데이터베이스에 있는 모든 사용자의 정보를 얻을 수 있게 됩니다.
SQL Injection 방어
- SQL에서 특별한 의미를 가지는 문자를 이스케이프 한다. (\n, \t, | , /, &, #...)
- 준비된 선언을 사용 Placeholder을 담은 SQL을 먼저 DB에 보낸 후 PlaceHolder에 해당하는 입력 값을 DB에 보내는 방식
- 요즘 라이브러리, 프레임워크에서는 해당 공격을 잘 막아준다.
Error based SQL injection
- 일부러 SQL에러를 발생시켜 원하는 정보를 얻는다. 쿼리문 추측, DB명, 테이블 명 등을 취득할 수 있다.
Blind SQL Injection
- Query 결과의 참/거짓을 보고 원하는 정보가 존재하는지 알 수 있다.
- DB, Table명을 알 수 있다.
- 너무 수작업이라 SQLMap이라는 자동화된 툴을 이용하기도 한다.
- 데이터 베이스 이름에서 1~2까지 자른 값이 us가 맞으면 true를 반환하는데 이를 통해 알아낸다.
Union SQL Injection
- Union명령을 이용하여 정보를 취득한다.
- Union앞의 명령어는 아무렇게나 두고 뒤의 명령어를 통해 id나 password등을 탈취한다.
2. XSS
- 웹 페이지에 악성 스크립트를 삽입하는 공격
- 사이트 이용자 정보를 탈취한다.
- form에다가 스크립트를 넣어서 해커의 사이트에 cookie값을 보내는 명령어를 적는다면 해커는 자연스럽게 게시판이용자의 토큰을 탈취할 수 있다.
XSS 방어
- HTML 필터링을 한 후 DB에 저장한다.
( <,>,script,html,head,met)와 같은 태그를 필터링한다.
- 프론트에서도 위와 같이 필터링해주는 방법이 있다.
위 XSS 공격은 Stored XSS이다.
3. Reflected XSS
- 검색어 등을 보여주는 곳에 스크립트를 심는 공격
- URL을 사용자에게 누르게 만들면 공격 성공
- 위와같이 입력하고 나타난 URL을 사용자에게 보내서 누르면 공격이 성공된다.
다음은 Reflected XSS의 간단한 예시입니다. URL에 사용자 입력이 반영되는 경우
https://www.example.com/search?query=<script>alert('XSS')</script>
이 경우, 웹 어플리케이션은 사용자의 검색 쿼리를 동적으로 생성하여 페이지에 반영합니다.
그러나 이를 적절하게 처리하지 않으면, 악의적인 사용자는 스크립트 코드를 주입하여 다른 사용자에게 반사될 수 있습니다.
위의 예시에서는 검색 결과 페이지가 로드될 때 "XSS"라는 경고창이 표시됩니다.
4. DOM Based XSS
- DOM에 악의적인 스크립트를 심는 공격
- 브라우저가 해석하는 단계에서 발생되는 공격
5. CSRF Attack
- Cross-Site Request Forgery
- 공격자가 사용자를 이용하여 웹사이트에 요청을 보내는 공격
왼쪽 가짜 사이트에서 사용자가 아이디와 비밀번호를 입력하고 로그인을 누르면
진짜 사이트에 로그인 요청을 보내고,
진짜 사이트에서는 성공여부를 보내서
만약 성공한다면 저장하는 방법
CSRF Attack 방어
- CSRF 토큰 사용: 각 요청에 대해 서버에서 생성한 고유한 CSRF 토큰을 요청에 포함시켜야 합니다. 이 토큰은 악의적인 사이트에서는 얻기 어렵기 때문에 공격을 방지할 수 있습니다.
- SameSite 쿠키 속성 설정: SameSite 쿠키 속성을 설정하여 외부 사이트로의 쿠키 전송을 방지할 수 있습니다.
- Referrer 검증: 요청을 처리할 때 Referer 헤더를 검증하여 유효한 출처에서 온 요청인지 확인할 수 있습니다.
- 쿠키 HttpOnly 속성 사용: 쿠키에 HttpOnly 속성을 사용하여 JavaScript에서 쿠키에 접근하는 것을 방지할 수 있습니다.
- CAPTCHA : 사람이 요청한 것이 맞는지 검증
6. Command Injection
- 애플리케이션에서 사용되는 시스템명령에 악의적인 명령어를 삽입하는 공격(WebShell Attack)
- 서버 root 권한을 취득할 수 있다.
간단한 Command Injection 예시를 살펴보겠습니다.
가령, 웹 어플리케이션이 사용자로부터 입력을 받아서 특정 명령어를 실행하는 상황에서 발생할 수 있습니다.
아래의 예시는 PHP로 작성된 웹 페이지에서 사용자 입력을 받아 시스템 명령어를 실행하는 부분입니다.
<?php
// 사용자 입력을 받아와서 시스템 명령어를 실행하는 PHP 코드
$user_input = $_GET['input_param'];
$result = shell_exec('some_command ' . $user_input);
echo $result;
?>
여기서 some_command는 시스템 명령어를 실행하는 예시일 뿐입니다.
그러나 이 코드에서는 $user_input이라는 사용자 입력을 적절하게 검증하거나 처리하지 않고 그대로 명령어에 사용하고 있습니다.
만약 공격자가 다음과 같은 URL을 이용하여 이 페이지에 악의적인 입력을 주입한다면
https://example.com/page.php?input_param=;ls
위의 예시에서 ;ls는 명령어 구분자(;)를 이용하여 ls 명령어를 주입하는 것을 시도하는 것입니다.
이 입력이 적절하게 처리되지 않으면, some_command ;ls가 실행되어 사용자의 입력에 따라 파일 목록이 출력될 수 있습니다.
이렇게 명령어가 주입되는 것이 Command Injection의 예시입니다.
Command Injection을 방지하려면 사용자 입력을 안전하게 처리하고, 매개변수화된 명령어를 사용하여 외부 입력을 전달해야 합니다.
7. File Upload Attack
- 악성 스크립트 파일을 업로드하는 공격
- 업로드 후 파일 위치를 찾아 실행시키면 공격 성공
File Upload Attack 방어
- 확장자/ 파일 타입 검사
- 업로드 파일을 난수화하여 저장
- 특수 문자가 포함된 경우 업로드 금지
8. javascript injection
- client-side에서 JavaScript를 삽입시키는 공격
- 크롬 console 등을 통해 조작 가능하다.
- Client-Side에 민감한 데이터를 넣을 경우 탈취 가능
위 처럼 간단하게 탈취가 가능하다.
javascript injection - 방어
- Client-Side엔 민감한 정보를 절대 넣지 않는다.
- 데이터 유효성 검사가 필요한 경우 서버와 통신한다.
(중요한 데이터는 Client에서만 검사하면 안된다.)
9. DDoS
- 서버에 비정상적으로 많은 트래픽을 보내는 공격
- 서비스가 마비되고 많은 비용이 소모된다.
DDoS 방어
- 제일 단순한데 제일 막기 어렵다
- 확장 가능한 서비스 구조 설계 - 많은 요청이 들어오더라도 확장가능하도록
- IP 필터링 - 특정 IP를 필터링
- Rate limit - 요청을 제한하는 방법
- 솔루션 구매
10. Dictionary Attack
- 미리 사전에 등록해놓은 문자열을 암호로 대입하는 공격
- Brute Force의 일종
만약 네이버에서 어떤 사용자의 id를 알고 있다면 비밀번호에 무작위의 비밀번호를 계속해서 대입해서 로그인 시도를 하는 것
Dictionary Attack 방어
- 의미가 있는 문자열(apple,banana)는 암호로 등록하지 못하도록 설정
- Account Lockout Policy - 5번 틀리면 잠김
- 2-factor 인증
11. Rainbow Table
- 해시 함수를 이용한 평문을 모두 저장시켜 놓은 표
- 계청 탈취 후 암호 원문을 알아내기 위해 사용
Rainbow Table - 방어
- Salt 사용
- Key Stretching
- PBKDF2, Bcrypt 등의 암호화 알고리즘 사용
알아야 하는 보안 정책
1. CORS
- Cross-Origin Resource Sharing
- 개발자가 지정한 프로토콜, 도메인, 포트가 아니라면 리소스를 가져올 수 없다.
- Response header를 보고 허용 여부를 브라우저가 정한다.
- 브라우저마다 구현이 다를 수 있다
2. CSP
- Content-Security-Policy
- 실행 가능한 리소스에 대한 whitelist를 정하는 정책
- 웹사이트가 허용되지 않은 리소스를 요청하지 못하도록 막는다.
- XSS방지에 도움이된다.
- 기본적으로 imline script는 실행을 막는다.
- 메타 태그 혹은 HTTP Header로 설정 가능
디렉티브(Directives): CSP는 다양한 디렉티브를 사용하여 리소스의 로딩을 제어합니다. 몇 가지 주요 디렉티브는 다음과 같습니다.
- default-src: 기본으로 허용되는 리소스의 소스를 지정합니다.
- script-src: 스크립트 리소스의 허용 소스를 지정합니다.
- style-src: 스타일 시트의 허용 소스를 지정합니다.
- img-src: 이미지 리소스의 허용 소스를 지정합니다.
HTTP 헤더 설정: CSP 정책은 HTTP 헤더인 Content-Security-Policy를 통해 설정되며, 서버 응답 헤더에 이를 포함시켜야 합니다.
- default-src: 기본으로 허용되는 리소스의 소스는 현재 도메인('self')으로 설정됩니다.
- script-src: 스크립트 리소스는 현재 도메인과 example.com에서만 로드할 수 있습니다.
- style-src: 스타일은 현재 도메인에서만 허용되며, 'unsafe-inline'은 인라인 스타일을 허용한다는 의미입니다.
Content-Security-Policy: default-src 'self'; script-src 'self' example.com; style-src 'self' 'unsafe-inline';
3. HTTPS
- HTTP 프로토콜의 암호화된 버전
- 소켓 통신에 암호화된 데이터를 전송한다.
- SSL 인증서를 이용한다.
HTTPS는 중요해서 자세하게 설명해보겠다
1. 왜 사용하나요?
내가 어떤 사이트에 보내는 정보를 다른 누군가가 훔쳐보지 못하게 한다.
-> HTTP로 보내면 입력한 텍스트 그대로 누구든 알아볼 수 있는 형식으로 보내진다.
-> HTTPS는 이 정보를 해당 사이트만 알아볼 수 있는 뒤죽박죽 이 된 텍스트로 변경해서 보낸다.
내가 접속한 사이트가 진짜 사이트인지를 판별해준다.
-> 네이버가아닌 다른 피싱사이트일 수도 있다.
-> 이때 정보를 입력해버리면 피싱사이트는 정보를 알 수 있게 된다.
-> HTTPS는 이런 수상한 사이트를 걸러내준다. - 기관으로부터 검증된 사이트만 HTTPS사용이 허가 됨
-> HTTP를 사용하는 사이트들은 주소창에 경고표시가 뜬다.
2. 그럼 HTTP는 뭔가요?
웹사이트에 접속하면 컴퓨터는 웹사이트 서버에 아래와 같은 메시지를 보낸다.
그럼 웹사이트 서버는 컴퓨터에게 아래와 같은 메시지를 보낸다.
이러한 메시지를 어떻게 읽을지는 컴퓨터도 모른다.
이때 HTTP가 사용된다.
HTTP는 인터넷상의 커뮤니케이션에 사용되는 형식 중 하나다.
웹사이트에 요청을 보낼 때 '이건 HTTP(S) 형식이야~ '하고 주소창에 일일이 명시해줘야
비로소 웹사이트 서버는 이걸 HTTP(S) 형식으로 읽어본 다음
'이런걸 요청한 거구나' 하고
그에 맞는 응답을 작성해서 보내고
내 컴퓨터는 이걸 HTTP 형식에 따라 해독해서 화면에 보여주게 된다.
3. 1번에서 말한 두 가지 보안기능이 어떤 원리로 구현되나요?
이걸 알기 위해서는 대칭키와 비대칭키(공개키)를 알아야한다.
예를 들어
전쟁에서 아군에게 편지를 보낼 때
적군에게 편지가 탈취되어도 이를 알아볼 수 없도록 하려면
편지의 내용을 암호화 해야한다.
그 암호화된 내용은 아군만 읽을 수 있어야 한다.
이때 사용된 것이 대칭키 방식이다.
메시지를 보내는 쪽과 메시지를 받는 쪽이
메시지를 암호화하고,
암화화된 메시지를 다시 메시지로 복호화하는
같은 방식을 공유하는 것이다.
예를 들어
a=27
b=9 ..라는 표를 대칭으로 양쪽이 똑같이 갖고있다면
얼마든지 메시지를 주고받을 수 있다.
이 때 해당 표가 노출되지 않는이상 가능한 일이다.
컴퓨터에서 사용하는 '대칭키'라는 건 이 표와도 같다.
임의의 문자열이 아래와 같이 주어진다.
a0583@$^sf4_2
상대방에게 보내고자하는 메시지를 이 키와함께 어떤 알고리즘에 돌리면
아래와 같이 전혀 알 수 없는 암호문이 만들어진다.
뚜겔덷러휴폳
이를 다시 메시지로 알아내려면
위에서 나온 암호문을 다시 키를 이용해서 알고리즘을 거꾸로 돌리면 된다.
이 과정을 복호화라고 한다.
그래서 컴퓨터와 웹사이트는 이 대칭키를 이용해서 서로 정보를 공유하는 것이다.
근데 문제는 이 '대칭키'라는 것을 양쪽이 어떻게 공유할까?라는 것이다.
결국 한번은 한 쪽에서 다른 한 쪽으로 이 키를 전송해야하는데
중간에 누가 이걸 탈취한다면 말짱 도루묵이 된다.
이게 대칭키의 한계이다.
이를 보완한 새 방식이 1970년대에 개발됐다.
비대칭키(공개키)라 불리는 시스템이다.
여기에는 두개의 키가 사용된다.
A키(공개키)
B키(개인키)
이 둘은 한 쌍이다. 서로 다르기 때문에 비대칭키이다.
비대칭키는
어떤 메시지를 A키로 암호화하면 B키로만 복호화 할 수 있다.
'안녕하세요' - A키 - '뛜빭썅줼훃' - B키 - '안녕하세요'
반대로 B키로 암호화하면 A키로만 복호화할 수 있다.
'안녕하세요' - B키 - $%&^##^&* - A키 - '안녕하세요'
웹사이트 서버는 이 두 키들 중 하나인 B키(개인키)를 비밀로 보관하고,
다른 하나인 A키(공개키)를 누구든 볼 수 있게 모두에게 공개한다.
이제 사용자는 공개키를 이용해 메시지를 암호화해서 웹사이트 서버에 보낸다.
- 누가 가로채면 어떻게 해?
=> 말했듯이 A키로 암호화한 메시지는 B키로만 복호화가 가능하다!
웹사이트 서버는 암호화된 메시지를 B키로 복호화해서 볼 수 있다.
문제는 이 사이트가 어떻게 진짜인지를 증명하는가?이다.
웹사이트에서 보내는 정보들은 개인키로 암호화가 되어있다.
우리가 웹사이트의 공개키로 풀어서 알아볼 수 있는건 웹사이트의 개인키로 암호화된 정보 뿐이다.
만약 피싱사이트에서 온 정보들은 진짜 웹사이트의 공개키로는 풀리지 않기 때문에
오류가 날 것이다.
그리고 신뢰할 수 있는 기관에서 우리에게 웹사이트의 공개키를 진짜라고 검증만 해준다면
우린 이걸 기준으로 안전하게 웹사이트를 이용할 수 있다.
4. HTTPS가 실제로 구현되는 과정은 어떻게 되나요?
일단 웹사이트가 뿌린 공개키를 정품인지 확인해야한다.
이걸 인증해주는 공인된 민간기업 CA들을 이용해야한다.
우리가 사용하는 브라우저는 이 CA 들의 목록들이 내장되어 있다.
그럼 이제 브라우저에서 웹사이트에 접속할 때 어떤 과정이 이루어지는지 알아보자
1. 브라우저, 즉 클라이언트는 서버(웹사이트)를 아직 신회하지 못한다.
2. 그래서 이둘은 일종의 탐색과정을 거치게 되는데 이를 핸드 쉐이크(악수)라고 한다.
3. 클라이언트는 어떤 랜덤 데이터를 생성해서 서버에 보낸다.
4. 이걸 받은 서버는 역시 서버측에서 생성한 무작위의 데이터와 해당 서버의 인증서를 같이 보낸다.
5. 이걸로 둘은 핸드 쉐이크를 했다.
6. 이제 클라이언트는 이 인증서가 진짜인지 확인하기 위해 브라우저에 내장된 CA들의 정보를 통해 확인하게 된다.
7. 어떻게? 비대칭키를 사용해서
8. CA의 인증을 받은 인증서들은 CA의 개인키로 암호화가 되어있다.
9. 인증서가 진짜라면 브라우저에 내장된 CA의 공개키로 복호화 할 수 있어야 한다.
10. 이 공개키로 복호화될 수 있는 인증서를 발급할 수 있는 건 그에 대응하는 개인키를 가진 CA뿐이니까
만약 이 CA리스트 중에 이 인증서가 해당하는 것이 없다면 브라우저 주소창에 경고 표시가 뜬다
11. 그렇게 성공적으로 복호화된 인증서에는 서버의 공개키가 포함되어있다.
'그럼 이 공개키로 메시지를 암호화해서 비대칭키 방식으로 서버와 통신하면 되겠구나' 하지만 아니다!
12. 지금부터 주고받아지는 데이터들은 대칭키 방식과 비대칭키 방식이 함께 혼합되어 사용된다.
=> 좋은 비대칭키 방식을 두고 대칭키 방식을 왜 써요?
=> 비대칭키 방식으로 메시지를 주고받으면 대칭키보다 컴퓨터에 훨씬 큰 부담을 주게된다.
13. 그래서 데이터는 대칭키로 암호화한다.
=> 대칭키는 탈취될 수 있어서 위험하다고 했는데?
=> 그 대칭키를 공유할 때 비대칭키를 사용한다!
14. 클라이언트는 아까 핸드쉐이크에서 주고받은 무작위 데이터와 랜덤데이터를 혼합해서 어떤 임시키를 만든다.
15. 이 임시키를 아까 인증서로 받은 공개키로 암호화해서 서버로 보낸다.
16. 서버는 이 임시키를 서버의 개인키로 복호화한다.
17. 그럼 이 임시키는 서버와 클라이언트의 대칭키가 된다.
18. 이제 이 대칭키는 서버와 클라이언트 둘만 갖고있으니까 이후 서로 주고받아지는 메시지들은 제3자가 알아볼 수 없다.
'자바스크립트' 카테고리의 다른 글
D3.js 첫 시작하기 - 기본 메서드들 사용 (1) | 2024.01.23 |
---|---|
D3를 사용하기 위한 SVG에 대해 알아보기 (1) | 2024.01.23 |
JS - intersection observer, 커스텀 이벤트 (0) | 2023.12.06 |
fetch의 에러처리 문제 (0) | 2023.11.30 |
Vue의 문제점 - 렌더링 최적화장점이면서 단점 (0) | 2023.11.30 |