JSON(JavaScript Object Notation)

:: JavaScript에서 객체를 만들 때 사용하는 표현식

:: 다른 언어에서도 사용해서 서로 다른 언어들끼리 객체는 객체 그대로, 배열은 배열 그대로 전송이 가능

 

JavaScript 에서 객체와 배열 각각을 나타내는 방법

객체 {키1:값1, 키2:값2}

배열 [값1,값2,값3]

 

서버 어플리케이션-클라이언트 어플리케이션(자바스크립트 애플리케이션)이

서로 통신하며 작업해야 한다면 JSON을 꼭 사용해야 한다.

 

 

◇ JavaScript : JSON.stringify(), JSON.parse() => JSON을 만들고 JSON을 해석해서 다시 객체로 만들어냄(직렬화)

 

- JSON API 

ECMAscript 5에는 JSON을 공식적으로 지원하는 API가 포함되어 있음

 

- JSON.parse()

인자로 전달된 문자열을 자바스크립트의 데이터(객체)로 변환

 

- JSON.stringify()

인자로 전달된 자바스크립트의 데이터(객체)를 문자열로 변환

 

PHP : JSON.encode(), JSON.decode() => JSON 데이터를 만들고 해석함

 

- JSON.encode()

전달받은 값을 JSON 형식의 문자열로 변환하여 반환

 

- JSON.decode()

전달받은 JSON 형식의 문자열을 PHP 변수로 변환

 

 

php와 JavaScript는 서로 다른 언어임에도 불구하고 JSON의 포맷을 이용하게 되면 데이터를 서로 전송할 수 있게 된다.

 

 

'WEB > JavaScript' 카테고리의 다른 글

Open API 활용  (0) 2021.05.02
라이브러리 & 프레임워크  (0) 2021.01.27
웹 브라우저 제어  (0) 2020.11.08
콘솔  (0) 2020.11.05
이벤트  (0) 2020.11.05

Front-end : 우리가 보는 화면

Back-end : 화면에 보여줄 정보를 처리하는 곳

 

Front-end가 Back-end에 요청을 할 때 특정 규칙에 맞게 요청을 해야함

 

API(Application Programming Interface) = 사용 규칙을 제공하는 것

 

Open API : 누군가 Back-end를 만들어놓고 주소와 사용 규칙을 공개한 것을 의미

= "Back-end의 주소와 사용 규칙을 알고 있다면 Front-end만 만들어도 얼마든지 요청하고 데이터를 가져와서  쓸 수 있다는 것"

+) Front-end만 만들어 쓰는 것을 'serverless' 라고 부르기도 함

 

Front-end 의 요청(Request)과 Back-end의 응답(Response)은 API 마다 정해진 형식에 맞춰서 전달되고 이런 형식이 적혀진 문서API 가이드라고 한다.

 

공통적으로 요청과 응답에 대한 정보가 나와 있다.

<요청>

1. 주소 : 어디로 전달해야 할지

2. 전송방식 : GET/POST

3. 보낼 데이터 (API 요청에서 필요한 정보들)

 

<응답>

1. 형식 : JSON // 어떤 형식으로 날아오는지(요즘은 거의 대부분이 JSON 형태)

2. 응답 의미 설명 : JSON으로 날아온 응답에 어떤 것들이 포함되어 있는지 

 


1. jQuery CDN 이용

jQuery CDN 사이트에서 가져온다.

 

CDN (Content Delivery Network)

::특정 서버에 트래픽이 집중되지 않고 컨텐츠를 자동으로 가장 가까운 서버에서 다운받도록 하는 기술

<script
  src="https://code.jquery.com/jquery-3.6.0.js"
  integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk="
  crossorigin="anonymous"></script>

 

2. jQuery AJAX 이용

Examples에서 예시 하나를 복사해온다. (나중에 사용할 API 가이드에 맞춰서 수정할 예정)

 

Ajax

:: JavaScript의 라이브러리중 하나이며 Asynchronous Javascript And Xml(비동기식 자바스크립트와 xml)의 약자.

브라우저가 가지고 있는 XMLHttpRequest 객체를 이용해서 전체 페이지를 새로 고치지 않고도 페이지의 일부만을 위한 데이터를 로드하는 기법 (기본적으로 HTTP프로토콜은 클라이언트쪽에서 Request를 보내고 Server쪽에서 Response를 받으면 이어졌던 연결이 끊기게 되어있음)

$.ajax({
  method: "POST",
  url: "some.php",
  data: { name: "John", location: "Boston" }
})
  .done(function( msg ) {
    alert( "Data Saved: " + msg );
  });

 

 

<카카오 API 사용>

홈페이지(developers.kakao.com/)에 들어가서 로그인 -> 내 애플리케이션 만들기 ->  키 확인 가능

 

[도구] - [REST API 테스트] - 자신이 사용하고자 하는 API의 [개발 가이드 보러가기]

 

실제 제공하는 책 검색 API

 

 

<전체 코드>

<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>API 연습</title>
</head>

<body>
    <h1>내 사이트임</h1>
    <script src="https://code.jquery.com/jquery-3.6.0.js"
        integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>

    <script>
        $.ajax({ //코드 상단 : 요청에 대한 정보
            method: "GET", // 전송 방식
            url: "https://dapi.kakao.com/v3/search/book?target=title", // 전송 URL
            data: { query: "미움받을 용기" }, //전송 정보 JSON 형식
            headers : { Authorization: "KakaoAK 'REST API 키'"}
        })
            .done(function (msg) {//요청에 대한 응답이 올 때 처리하는 코드
                console.log(msg);
            });
    </script>
</body>

</html>

 

코드 실행 후 개발자 도구 확인

요청에 대한 응답(Response) 정보 - [F12] 키를 이용해 확인(console.log 사용했으므로)

=> API 가이드를 참고해 비교해보면 필수 정보들이 잘 담겨져 있는 것을 확인할 수 있다

 


<JSON 데이터 JavaScript 접근 방법>

dog = {
    "name": "식빵",
    "family": "웰시코기",
    "age": 1,
    "weight": 2.14,
    "specialty" : ["솜사탕","부리부리"],
    "friend" : {"name": "젤리", "family": "푸들", "age": 7, "weight": 3.1}
}

"식빵"을 가져오려면? dog.name 혹은 .name

"솜사탕"을 가져오려면? dog.specialty[0]

"젤리"를 가져오려면? dog.friend.name

 

 

<실습>

아까 봐뒀던 개발자 도구 탭을 활용한다.

※ 'Object' -[마우스 오른쪽] - [Store object as global variable]

(응답 받은 JSON을 console 창에서 다루기 위해 따로 저장해두는 것)

 

 

그러면 temp1이라는 곳에 Object가 잘 저장이 된 것이 확인가능하다. 

"미움받을 용기"라는 책 제목과 썸네일을 불러올 것이기 때문에 

temp1.documents[0].title

temp1.documents[0].thumbnail

를 사용할 것이다.

 

<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>API 연습</title>
</head>

<body>
    <h1>내 사이트임</h1>
    <script src="https://code.jquery.com/jquery-3.6.0.js"
        integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>

    <script>
        $.ajax({ //코드 상단 : 요청에 대한 정보
            method: "GET", // 전송 방식
            url: "https://dapi.kakao.com/v3/search/book?target=title", // 전송 URL
            data: { query: "미움받을 용기" }, //전송 정보 JSON 형식
            headers : { Authorization: "KakaoAK 'REST API 키'"}
        })
            .done(function (msg) {//요청에 대한 응답이 올 때 처리하는 코드
                console.log(msg.documents[0].title);
                console.log(msg.documents[0].thumbnail);
            });
    </script>
</body>

</html>

위의 코드와 똑같지만, console.log 함수를 통해서 console 창을 통해 데이터 확인이 가능하다.

 

실행 결과

console 창에서 올바르게 값을 불러왔다는 것을 확인할 수 있다.

 

<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>API 연습</title>
</head>

<body>
    <h1>내 사이트임</h1>
    <p></p>
    <script src="https://code.jquery.com/jquery-3.6.0.js"
        integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>

    <script>
        $.ajax({ //코드 상단 : 요청에 대한 정보
            method: "GET", // 전송 방식
            url: "https://dapi.kakao.com/v3/search/book?target=title", // 전송 URL
            data: { query: "미움받을 용기" }, //전송 정보 JSON 형식
            headers: { Authorization: "KakaoAK 'REST API 키'" }
        })
            .done(function (msg) {//요청에 대한 응답이 올 때 처리하는 코드
                console.log(msg.documents[0].title);
                console.log(msg.documents[0].thumbnail);
                $("p").append("<strong>" + msg.documents[0].title + "</strong><br>");
                $("p").append("<img src='"+ msg.documents[0].thumbnail + "'/>");
            });
    </script>
    </script>
</body>

</html>

<p>태그를 추가한 후

append를 통해 (jQuery add html 검색하면 쉽게 방법을 알 수 있음)

<p>태그에 들어갈 내용을 추가해주었다.

 

 

최종 실행 화면

 

 

www.youtube.com/watch?v=QPEUU89AOg8

 

'WEB > JavaScript' 카테고리의 다른 글

JSON  (0) 2021.05.02
라이브러리 & 프레임워크  (0) 2021.01.27
웹 브라우저 제어  (0) 2020.11.08
콘솔  (0) 2020.11.05
이벤트  (0) 2020.11.05

Business Logic 

:: 규칙에 따라 데이터를 생성. 표시. 저장. 변경하는 로직, 알고리즘

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

 

ⓐ Business Logic Vulnerability

- 비즈니스 로직 취약점은 정상적인 비즈니스 로직을 악용하는 것

- 서비스의 기능에서 적용되어야 할 로직이 없거나 잘못 설계된 경우 발생

 

ex) 상품 후기를 작성시 포인트를 주는 이벤트가 있다. 

후기를 작성한 후, 100 포인트를 받았는데

글을 삭제한 후 다시 후기를 작성하니 100 포인트를 또 받을 수 있었다..

 

※ 비즈니스 로직 취약점을 방어하기 위해선?

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

 

 

ⓑ IDOR (Insecure Direct Object Reference) Vulnerability

:: 안전하지 않은 객체 참조

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

 

ex) 금액을 조회하고 송금할 수 있는 페이지에서 

사용자가 자신의 계좌번호를 다른 사용자의 것으로 바꿀 때 서버가 이를 검증하지 않는다면 조회, 송금이 가능하다.

 

※ IDOR 취약점을 방어하기 위해선?

- 사용자의 권한을 검증하는게 가장 중요

즉, 사용자가 의도한 권한을 벗어나서 행동할 수 없도록 권한 등을 분리해서 관리해야 한다.

 

- 사용자 인증을 거친 후 사용하는 서비스에서는 사용자가 요청 시 전달하는 세션을 통해 서버 내에서 처리하는 것이 안전

 

- 객체 참조 키를 단순한 숫자가 아닌 무작위 문자 생성 등을 통해 악의적 공격자가 이를 추측하기 어렵게 하는 방법도 있다.

 

 

 

ⓒ Race Condition

:: 공유 자원 처리 과정에서 해당 자원에 대한 동시 다발적인 접근으로 인해 발생하는 취약점

 

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

- 주로 검증 과정에서의 데이터와 수정 과정의 데이터의 차이로 인해 웹 어플리케이션에서 의도하지 않은 흐름으로 진행한다.

- 비즈니스 로직의 잘못된 순서로 인해 발생하기도 한다.

 

ex) 사용자의 잔액 확인 과정과 차감하는 과정 사이, 재고 확인 과정에서 시간 지연이 발생하며, 

잔액 확인 과정 이후에 잔액이 차감된다는 점을 이용하여 현재 잔액보다 더 많은 금액의 상품을 구매할 수 있다.

 

※ 레이스 컨디션 취약점을 방어하기 위해선?

- 하나의 접근이 끝난 후 다음 접근을 처리하도록 하는 쓰레드 락 등을 통해 동시 다발적 접근을 방지해야 한다.

- CSRF 토큰, 캡차 등을 통해 다량의 접근을 방지하는 방법도 있다.

File Vulnerability 

:: 파일을 업로드/다운로드 하는 기능에서 발생할 수 있는 취약점

 

ⓐ File Upload

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

이때 서버가 아무런 검증이 없다면 서버의 파일 시스템에 원하는 파일을 저장할 수 있다.

 

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

ex) Apache 웹 서버, php 웹 어플리케이션 사용하는 서버에 사용자가 요청을 보내면

Apache는 사용자의 요청을 해석하고,

사용자가 요청하는 리소스의 확장자가 .php와 같이 php 엔진을 사용하기로 설정되어 있는 확장자라면

mod_php(CGI)를 통해 사용자의 요청을 php 엔진이 처리 및 실행하도록 요청한다.

 

 

웹 서비스가 동작하는 경로에 사용자가 원하는 파일 내용과 파일 명을 업로드할 수 있다면

서버가 엔진에 요청하는 확장자를 업로드하여 서버의 웹 어플리케이션에 원하는 코드를 실행할 수 있다.

 

웹 어플리케이션이 실행하는 코드를 악의적 공격자가 조작할 수 있다면

웹 어플리케이션 언어에 내장된 OS 명령어 등을 사용할 수 있으며, 해당 서버의 쉘을 웹을 통해 사용한다고 하여

WebShell(웹쉘)이라는 악성코드가 등장하게 되었다.

 

<?php
if(!empty($_FILES['file'])){
  $filename = generateRandomString(); // custom function
  $ext = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
  $path = "./uploads/" . $filename . "." . $ext;
  if(move_uploaded_file($_FILES['file']['tmp_name'], $path)) {
    return true; // upload success
  } else {
    return false; // upload fail
  }
}
?>

이러한 코드를 가지는 업로드 페이지가 있다면,

php 파일을 업로드하여 php를 실행시키거나 html 파일 등을 업로드하여 Stored XSS 취약점을 발생시킬 수 있다.

 

 

이런식으로 .php, .php3/4/5/7, .pht, .phtml 등의 파일 확장자를 업로드하여 php 엔진이 처리하도록 유도할 수 있다.

 

 

 

ⓑ File Download

파일 다운로드 기능을 구현할 때 발생하는 취약점의 형태는 사용자가 입력한 파일이름을 검증하지 않은 채 그대로 다운로드를 제공하는 형태이다.

 

...
@app.route("/download")
def download():
    filename = request.args.get("filename", "")
    return open("uploads/" + filename, "rb").read()
...

위와 같은 코드를 가지는 다운로드 페이지가 있다고 하면

Path Traversal과 같은 Injection 공격을 통해 uploads 경로보다 더 상위 경로에 존재하는 시스템 파일, 설정 파일과 같은 중요한 정보들을 다운로드 할 수 있다.

 

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

- 기본적으로 인자에 다운로드 받으려는 파일의 경로나 이름을 넘기지 않은 것이 좋다.

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

- 또 다른 방법으로, 데이터베이스에 다운로드 될 파일의 경로와 그에 해당하는 랜덤키를 생성해 1대 1로 매칭해서 저장해두고 해당 랜던 값이 인자로 넘어왔을 때 데이터베이스에 존재하는 파일인지를 먼저 식별하고 다운로드 하는 방법이 있다.

Injection"주입". 변조된 입력을 주입해 의도하지 않은 행위를 발생시킴

 

ⓐ SQL Injection : SQL 문 사용 시 공격자의 입력 값이 정상적인 요청에 영향을 주는 취약점

ⓑ Command Injection : OS Command 사용 시 사용자의 입력 데이터에 의해 실행되는 Command를 변조 할 수 있는 취약점

ⓒ Server Side Template Injection(SSTI) : 템플릿 변환 도중 사용자의 입력 데이터가 템플릿으로 사용돼 발생하는 취약점

ⓓ Path Traversal : URL / File Path를 사용 시 사용자의 입력 데이터에 의해 임의의 경로에 접근하는 취약점

ⓔ Server Side Request Forgery(SSRF) : 공격자가 서버에서 변조된 요청을 보낼 수 있는 취약점

 

 

 

ⓐ-1 SQL Injection 

웹 어플리케이션에서 로그인/검색과 같이 사용자의 입력 데이터를 기반으로 DBMS에 저장된 정보를 조회하는 기능 등을 구현하기 위해 SQL 쿼리에 사용자의 입력 데이터를 추가하여 DBMS에 요청하는데, 그 과정에서 사용자의 입력이 SQL 쿼리에 삽입되어 SQL 구문으로 해석되거나 문법적으로 조작하게 되면 개발자가 의도하지 않은 임의의 쿼리가 실행될 수 있다.

 

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

 

대표적인 예시로, 로그인 시

SELECT * FROM users WHERE uid = '{uid}' and upw='{upw}'; 라는 쿼리가 실행될 때

 

'를 기준으로 문자열을 구분하고 있다는 점을 집중해서 보자.

만약 사용자가 입력에 ' 문자를 포함해 해당 문자열을 탈출하고 뒷 부분에 새로운 쿼리를 작성하여 전달하면 DBMS는 사용자가 직접 작성한 쿼리를 실행시키는 것이다.

 

'{uid}'admin을 , '{upw}'1'or'1 을 작성한다면, or 연산을 이용해 참의 조건이 만족되므로 admin의 데이터에 접근이 가능하게 된다.

+ (or 연산은 A or B와 같은 구조일 경우 A와 B 중 하나라도 참(True)인 경우 결과는 참이된다.)

 

ⓐ-2 SQL Injection 방어

SQL Injection을 막기 위해 권장하는 방법

:: ORM(Object Relational Mapper의 약자로써 SQL의 쿼리 작성을 돕기위한 라이브러리)과 같이 검증된 SQL 라이브러리 사용

 

이를 통해 개발자가 직접 쿼리를 작성하는 Raw 쿼리를 사용하지 않아도 기능 구현이 가능하여, SQL Injection으로부터 상대적으로 안전하다.

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

 

 

ⓑ-1 Command Injection 

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

:: 이러한 명령어를 실행하기 위해 PHP, NodeJS, Python과 같은 함수들이 존재한다.

 

OS Command는 내부적으로 셸(Shell)을 이용해 실행하는데, 셸은 사용자 편의성을 위해 한 줄에 여러 명령어를 실행하는 특수 문자가 여럿 존재한다.

따라서 이를 사용할 때 사용자의 입력 값을 검증하지 않고 함수의 인자로 전달한다면?

여러 특수 문자를 이용해 사용자가 원하는 명령어를 함께 실행할 수 있다.

` ` 명령어 치환 `` 안에 들어있는 명령어를 실행한 결과로 치환된다.
$( ) 명령어 치환 $( ) 안에 들어있는 명령어를 실행한 결과로 치환. 중복 가능
&& 명령어 연속 실행 한 줄에 여러 명령어를 사용하고 싶을 때.
앞 명령어에서 에러가 발생하지 않아야 뒷 명령어 실행 가능
|| 명령어 연속 실행 한 줄에 여러 명령어를 사용하고 싶을 때.
앞 명령어에서 에러가 발생해야 뒷 명령어 실행 가능
명령어 구분자 한 줄에 여러 명령어를 사용하고 싶을 때.
단순 구분자. 앞 명령어의 에러 유무 상관없이 뒷 명령어도 실행
| 파이프 앞 명령어의 결과가 뒷 명령어의 입력으로 들어감
ex) $echo id | /bin/sh

 

예를 들어, 사용자가 입력한 주소로 ping 명령어를 실행하는 코드가 있다고 가정해보자.

@app.route('/ping')
def ping():
	ip = request.args.get('ip')
	return os.system(f'ping -c 3 {ip}')

콘솔 환경에서 

ping -c 3 1.1.1.1; id 혹은 ping -c 3 1 && id 이런식으로 입력하게 되면 id 명령어도 실행이 된다.

 

 

ⓑ-2 Command Injection 방어

:: 사용자의 입력 데이터가 Command인자가 아닌 다른 값으로 해석되는 것을 방지해야 한다.

:: OS Command를 사용할 경우 해당 Command 내부에서 다른 취약점이 발생하는 등 잠재적 위협이 될 수 있으므로 OS Command를 되도록이면 사용하지 않는 것이 가장 좋은 방법이다.

 

그럼에도 불구하고 이를 사용해야 한다면, 필터링 과정을 거쳐야 한다.

 

→ 정규식을 통한 화이트리스트방식 필터링

#사용자가 입력한 IP가 정상적인 IP 형식인지 검증

import re, os, ...
...
chk_ip = re.compile('^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$')
if bool(chk_ip.match(ip)):
    return run_system(f'ping -c 3 {ip}')
else:
    return 'ip format error'

→ OS Command에서 Meta 문자로 사용되는 값을 필터링 하고 따옴표로 감싸기

if '\'' in ip:
    return 'not allowed character'
return run_system(f'ping -c 3 \'{ip}\'')

→ execve args 인자로 사용

#shell meta 문자로 해석되지 않도록 입력 값을 넣음
subprocess.Popen(['ping', '-c', '3', ip]) # B

기능에 해당하는 라이브러리 사용

# 사용하고자하는 기능을 OS 커맨드가 아닌 구현한 라이브러리로 대체 사용
#! pip install ping3 
# https://github.com/kyan001/ping3/blob/master/ping3.py
import ping3
ping3.ping(ip)

 

ⓒ Server Side Templete Injection(SSTI)

:: 웹 어플리케이션에서 동적인 내용을 HTML로 출력할 때 미리 정의한 templete에 동적인 값을 넣어 출력하는 Templete Engine을 사용할 때 발생하는 취약점

※ 따라서, 사용자가 입력한 데이터가 templete에 직접 사용될 경우 templete Engine이 이를 해석하여 실행하는 과정에서 예상치 못한 공격을 당할 수 있다.

 

- 대부분의 Templete Engine은 {{user.uid}}, ${user.uid}와 같은 문법을 지원한다.

더보기

<각 언어별 많이 사용되는 Templete Engine>

Python : Jinja2, Mako, Tornado..

PHP : Smarty, Twig..

JavaScript : Pug, Marko, EJS... 

...
class Secret(object):
    def __init__(self, username, password):
        self.username = username
        self.password = password
secret = Secret('admin', secret_password)
...
@app.route('/board')
def board():
    title = request.form['title']
    content = request.form['content']
    template = '''<html>
    <body>
        <h3 id="title">{{title}}</h3>
        <h3 id="content">%s</h3>
    </body>
</html>''' % content
    return render_template_string(template, title=title, secret=secret)

사용자가 페이지에서 content 부분을 입력하면 %s 바로 저 부분에 들어가게 되는데,

이때 {{secret.password}} 와 같은 문자열을 입력하여 templete Engine이 해석하는 {{Data}} 형태를 이용, 공격에 사용할 수 있다.

 

 

ⓓ Path Traversal

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

 

- URL 필터링 또는 인코딩이 부재하면 ../ 와 같은 구분 문자를 통해 의도한 경로가 아닌 상위 경로에 접근해 다른 API를 호출할 수 있다.

 

/ 경로 구분자
..  부모 디렉토리
? 쿼리 구분자 (? 뒤는 query로 해석됨)
# 프래그먼트 구분자 (# 뒤는 Server로 전달되지 않음)
& 파라미터 구분자 (여러 정보를 함께 전달할 때 사용)

 

 

ⓔ Server-side Request Forgery(SSRF)

URL을 통해 사용자가 입력한 사진을 업로드하는 기능을 구현하면 사용자가 입력한 URL을 웹 어플리케이션에서 접근해야 하는 경우처럼, 웹 어플리케이션에서 사용자가 입력한 URL에 요청을 보내는 기능이 구현되어야 하는 경우가 있다.

 

:: SSRF는 웹 어플리케이션에서 요청을 보내는 것

(웹 어플리케이션이 작동하고 있는 서버 내부의 포트, 서버와 연결된 내부망에 요청을 보냄)

 

:: Server-side에서 변조된 요청/의도하지 않은 서버로 요청을 보내는 공격

 

- 웹 인프라를 구성할 시 외부망/내부망을 나누어 설계하고 "내부망에서는 인증된 서버/사용자만이 요청을 보낼 수 있다"고 가정해 별도의 인증 없이 기능을 구현하는 경우가 많다.

- 클라우드 플랫폼들에서도 내부망에서 작동하는 기능들이 있어 SSRF 공격의 대상이 될 수 있다.

 

※ 취약점 방지를 위해선?

- URL HOST 화이트리스트 방식 필터링 : 미리 신뢰할 수 있는 Domain Name, IP Address 등을 리스트에 등록하고 사용자가 입력한 URL에서 HOST 부분을 파싱해 화이트리스트에 있는지 확인하여 사용

 

<SSRF 예시>

이미지 URL을 입력받아 Externel Server에서 Internal Server로 접근하는 예시

 URL 주소 입력 부분에 HOST를 127.0.0.1로, 그리고 외부 서버의 코드를 확인하여 코드 속의 config 함수를 활용하면

이런 식으로 내부 서버로 들어갈 수 있는 URL을 얻을 수 있다. 

내부 서버로 들어간 후, 코드를 확인해 여러 함수를 악용하면 특정한 사용자의 권한을 높인다던지 등의 악위적 행위를 할 수 있게 된다.

 

SSRF 공격에 대한 자세한 설명은 여기에서..

https://medium.com/naver-cloud-platform/ssrf-%EA%B3%B5%EA%B2%A9%EC%9D%98-%ED%94%BC%ED%95%B4-%EC%82%AC%EB%A1%80%EC%99%80-%EB%8C%80%EC%9D%91-1-d0be4b12d10a

'WEB > WEB Hacking' 카테고리의 다른 글

Server - side Vulnerability ③ Business Logic  (0) 2021.03.09
Server - side Vulnerability ② File  (0) 2021.03.09
Server - side Vulnerability  (0) 2021.03.06
Dreamhack | 워게임 | <csrf-1> 문제  (0) 2021.01.26
Client-side Attack  (0) 2021.01.25

'웹 서비스를 제공하는 서버'를 대상으로 공격할 때 발생하는 웹 취약점

 

:: 주 목적 = 서버 내에 존재하는 사용자들의 정보 탈취, 서버 권한 획득

:: 종류

1. Injection(인젝션) - 서버의 처리 과정 중 사용자가 입력한 데이터가 처리 과정의 구조나 문법으로 사용되어 발생

2. File vulnerability - 서버의 파일 시스템에 사용자가 원하는 행위를 할 때 발생

3. Business Logic Vulnerability - 정상적인 흐름을 악용할 때 발생

4. Language specific Vulnerability(PHP, Python, NodeJS 등) - 언어의 특성으로 인해 발생

5. Misconfiguration - 잘못된 설정으로 인해 발생

'WEB > WEB Hacking' 카테고리의 다른 글

Server - side Vulnerability ② File  (0) 2021.03.09
Server - side Vulnerability ① Injection  (0) 2021.03.08
Dreamhack | 워게임 | <csrf-1> 문제  (0) 2021.01.26
Client-side Attack  (0) 2021.01.25
Flask, HTTP 요청 방식  (0) 2021.01.24

Filtering : 사용자가 입력한 정보에서 문제가 될만한 것을 차단하는 것

Escaping : 저장되어 있는 정보를 사용자에게 표시할 때(출력) 문제가 될만한 것을 차단하는 것

 

 

Filtering

사용자가 입력하는 정보는 모두 불신해야 한다.

mysqli_real_escape_string( ) : 인자로 들어온 데이터 중에서 sql 공격 관련 기호들을 문자로 바꾸는 함수

=> SQL Injection 방어 가능 

SQL Injection문 시도
왼쪽은 mysqli_real_escape_string( )를 사용하지 않았을 때, 오른쪽은 사용하였을 때의 결과이다.

 

Escaping

오염된 데이터 출력을 막아야 한다.

htmlspecialchars( ) : HTML 특수 문자가 일반 문자로 인식되어 그대로 출력되도록 해주는 함수

=> XXS 방어 가능

& &amp;
" &quot;
' &#039;
< &lt;
> &gt;

 

<?php
	echo '<script>alert("hi");</script>'; //1번
	echo htmlspecialchars('<script>alert("hi");</script>');//2번
?>

 

왼쪽부터 차례로 1번, 2번

1번의 경우는 대표적인 XXS 공격으로, hi라는 경고창이 뜨게 되지만

2번의 경우는 함수를 이용해 특수문자들을 문자열 그대로 출력하고 있다.

 

<!--사용 예시-->
...
$escaped_title  = htmlspecialchars($row['title']);
echo "<li><a href=\"index.php?id={$row['id']}\">{$escaped_title}</a></li>"
...

'WEB > PHP' 카테고리의 다른 글

PHP와 MySQL_연동 후 데이터 출력  (0) 2021.01.31
PHP와 MySQL 연동  (0) 2021.01.31
PHP & DATABASE  (0) 2021.01.30
form과 GET, POST  (0) 2021.01.29
PHP 문법 기초  (0) 2021.01.28

데이터베이스에서 가져온 데이터를 php에서 실행하고자 할 때, 
데이터베이스와 php는 서로 완전히 다른 기술이기 때문에 우리가 php라는 컴퓨터 언어를 통해서 그 데이터를 활용하기 위해서는 php 데이터 타입으로 전환하는 과정을 거쳐야 한다.

 

그 때 사용하는 api가 mysqli_fetch_... 들이다.

<!-- SELECT 문으로 하나의 행만 확인 -->
<?php
$conn = mysqli_connect('localhost','root','1111','mysqls');

$sql = "SELECT * FROM topic WHERE id=1";
$result = mysqli_query($conn, $sql);

$row = mysqli_fetch_array($result);
echo '<h1>'.$row['title'].'</h1>';
echo $row['description'];
?>

위 코드를 이해하기 위해 연관배열을 잠깐 언급하겠다.

 

 

현재 topic 테이블

$row = mysqli_fetch_array($result);
print_r($row);
echo $row[1]; 
echo $row['title']; 

mysqli_fetch_array($result) 는 result문이 가리키는 쿼리문의 결과를 하나씩 하나씩 배열로 리턴한다.

+) 더 이상 가져올 행이 없다면 NULL을 리턴한다.

 

따라서 $row 변수에는 php에 맞는 데이터 타입으로 전환된 배열이 들어가 있다.

 

실제 Array 배열을 출력

배열 = 키 값이 숫자, 연관배열 = 키 값이 문자

echo $row[1];  // MySQL =>데이터의 인덱스를 이용해서 데이터를 가져온다 : 배열
echo $row['title'];  // MySQL =>데이터의 컬럼의 이름을 이용해서 데이터를 가져온다 : 연관배열

 

 

우리는 해당 데이터의 배열의 인덱스를 하나하나 다 알 수 없기 때문에

연관배열 방법을 이용해서 원하는 데이터의 결과를 가져온 것이다.

echo '<h1>'.$row['title'].'</h1>';
echo $row['description'];

 

 

<!-- SELECT 문으로 모든 행 확인 -->
<?php
$conn = mysqli_connect('localhost','root','1111','mysqls');

$sql = "SELECT * FROM topic";
$result = mysqli_query($conn, $sql);

while($row = mysqli_fetch_array($result)){
  echo '<h1>'.$row['title'].'</h1>';
  echo $row['description'];
}
?>

while문을 활용해서 모든 행의 결과를 불러올 수 있다.

 

결과화면


+ PHP while문

<?php while(A)
B
C
?>

// A에 있는 코드는 무조건 실행. 그 결과가 true라면 B와 C를 순차적 실행. 더 이상 실행시킬 코드가 없으면 다시 A로 돌아감. 결과가 NULL(flase)라면 while문 종료

 

'WEB > PHP' 카테고리의 다른 글

보안  (0) 2021.01.31
PHP와 MySQL 연동  (0) 2021.01.31
PHP & DATABASE  (0) 2021.01.30
form과 GET, POST  (0) 2021.01.29
PHP 문법 기초  (0) 2021.01.28

PHP와 MySQL 연동 원리

MySQL 서버를 제어하기 위해선 MySQL 모니터가 필요했다.

 

대표적 MySQL Monitor

MySQL 모니터에서 sql문을 입력하면 MySQL 서버가 처리한 후 결과를 보여준다.

MySQL 모니터는 MySQL에 대해서 클라이언트인 셈이다.

(MySQL 클라이언트에는 Workbench, phpMyAdmin 등이 있다.)

 

이때, PHP 도 MySQL 서버에 대해서 클라이언트로서 동작이 가능하다. 

 

PHP와 MySQL 연동을 위해

php mysql api를 검색 후, 이후 진행되는 실습에서는 mysqli api 방식을 사용하기로 하였다.

 

<?php
$conn = mysqli_connect('localhost','root','1111','mysqls'); 
$sql = "INSERT INTO topic
    (title, description, created)
    VALUES(
      '{$_POST['title']}',
      '{$_POST['description']}',
      NOW()
    )";
$result = mysqli_query($conn,$sql);
    
if ($result === false){
  echo mysqli_error($conn);
  echo '저장하는 과정에서 문제가 생겼습니다. 관리자에게 문의해주세요';
  error_log(mysqli_error($conn)); 
} else {
  echo '성공했습니다.';
}

if(mysqli_connect_error()){
	printf("Connect failed: %s\n",mysqli_connect_error()); 
	exit();
};
?>


① $conn = mysqli_connect('localhost','root','1111','mysqls');

// 데이터베이스에 PHP 접속
//함수에 들어가는 인자 : 호스트(데이터베이스의 서버 주소), 사용자 네임, 비밀번호, 데이터베이스(스키마) 이름

 

② $sql = "INSERT INTO topic
    (title, description, created)
    VALUES(

      '{$_POST['title']}',
      '{$_POST['description']}',

       NOW()

     )

";

// sql 문 작성. html에서 POST 방식으로 작성할 것이기 때문에 $_POST['name'] 방식 사용

 

③ $result = mysqli_query($conn,$sql);
//mysqli_query( ): php가 클라이언트가 되어 데이터베이스 서버에 sql문 실행

//실패 시 false, 성공 시 객체 리턴

// 함수에 들어가는 인자 : (데이터베이스 접속 정보 변수, sql문)

 

④ if ($result === false){
  echo mysqli_error($conn);

// mysqli_error( ) :저장하는 과정에서 어떤 에러가 발생했는지 알려주는 함수

// 그러나 사용자에게 그대로 보여주면 보안 위협이 있으므로 아래와 같이 진행
  echo '저장하는 과정에서 문제가 생겼습니다. 관리자에게 문의해주세요';
  error_log(mysqli_error($conn)); //error_log( ): 아파치 error log 디렉토리에 에러사항이 기록됨
} else {
  echo '성공했습니다.';
}

 

⑤ if(mysqli_connect_error()){

printf("Connect failed: %s\n",mysqli_connect_error());

exit();

}; // 접속 에러일 때 사용하는 함수
?>

'WEB > PHP' 카테고리의 다른 글

보안  (0) 2021.01.31
PHP와 MySQL_연동 후 데이터 출력  (0) 2021.01.31
PHP & DATABASE  (0) 2021.01.30
form과 GET, POST  (0) 2021.01.29
PHP 문법 기초  (0) 2021.01.28

PHP & DATABASE 원리

 

데이터베이스가 갖는 '데이터를 효율적으로 관리할 수 있다'라는 장점과 이 갖는 '접근성'이라는 장점.

PHP의 '미들웨어'적 장점 등 이렇게 웹 서버, PHP, 데이터베이스 각각의 장점에 따라 역할을 분담하게 되는 것이다.

(PHP는 웹이라는 부품과 MySQL이라는 데이터베이스 부품을 붙이는 본드같은 기능을 한다.

따라서 이를 미들웨어 라고도 부른다.)

 

여기서 PHP는 웹 서버의 서버로서 동작하고, MySQL의 클라이언트로서 동작하고 있다는 것을 기억해야 한다.

 

'WEB > PHP' 카테고리의 다른 글

PHP와 MySQL_연동 후 데이터 출력  (0) 2021.01.31
PHP와 MySQL 연동  (0) 2021.01.31
form과 GET, POST  (0) 2021.01.29
PHP 문법 기초  (0) 2021.01.28
PHP의 이해  (0) 2021.01.28

+ Recent posts