Entries Tagged as Security

엄청나게 오랜만에 새로운 글하나 남깁니다. ColdFusion에 대한 새소식은 아니고,, 그동안 여러 경로를 통해 ColdFusion 개발시 보안이슈에 대한 이야기를 듣고 나름 반영해 왔는데 간단하지만 하나로 문서화된게 있어서 공유차원에서 전해드립니다. 

Foundeo Inc.의 Pete Freitag가 쓴 문서인데 SQL인젝션, XSS 등 웹개발시 반드시 고려해야 하는 보안위협을 피하는 코딩기법에 대해 간단히 소개하고 있습니다. 특히 파일 업로드, 세션하이재킹 등 놓치기 쉬운 부분도 간략하게 소개하고 있으니 참고해 보세요. 모든 ColdFusion 응용서버(Adobe, Railo, Open BlueDragon 등)에 공통적으로 적용됩니다. 

PDF 다운로드 : http://www.adobe.com/content/dam/Adobe/en/products/coldfusion/pdfs/cf11/cfml-developer-security-guide.pdf
여기에서 받기 : cfml-developer-security-guide.pdf

이전의 Post에서 암호화에 대한 글을 쓰면서 대칭키암호화 방식에서 쓰이는 일종의 열쇠인 "보안키(비밀키)"의 저장에 대해서 고민해 봤습니다. 국내 모 기업의 DB암호화 솔루션 등의 개념을 교육받으면서 이런 보안비밀키의 요청에대해 자체적으로 정책서버라는 인증도구를 사용하는 것과 그냥 단순 텍스트 파일로 저장하는 것과는 분명 차이는 있겠습니다만, 어쨋든 Local에서 정책서버가 구동되어 인증해 주던, 단순 텍스트파일에 보안비밀키를 두던 시스템의 모든 권한이 넘어가는 보안사고가 나면 무슨의미가 있을까? 하는 생각을 하게 된거죠.

어쨋든 시스템의 모든 권한이 넘어가지 않는다는 전제로 간단하게 대칭키 암호화방식에서 쓰이는 보안비밀키와 Salt를 나름 안전하게 시스템상에 저장해 두고(웹 루트가 아닌 경로) 필요시 ColdFusion 또는 PHP 등에서 해당 파일을 불러와 키값을 쓴다면 나름은 할 건 한 셈이 아닌가.. 하는 생각으로 몇자 적습니다.

우선 ColdFusion(PHP 등)에서 쉘을 실행시킬 수 있다는 것이 좀 위험스럽지만 ColdFusion의 실행 런레벨을 최소화하고 일반계정으로 실행하게끔 설치하고 보안비밀키가 저장된 sh파일을 실행하여 그 값을 받아와 처리하면 되지 않을까.. 하는 생각말입니다. 물론 쉘에 어떤 값을 전달하고 그 값이 정상일때 쉘에서 보안비밀키를 토해내는 것 도 나쁘진 않을 것 같네요.

하지만 보통의 경우 sh는 스크립트 파일이므로 vi 등으로 얼마든이 소스를 열어볼 수 있습니다. 그래서 찾아본게 sh의 컴파일화.

sh파일을 컴파일하게 되면 (암호화하는것이 아니므로) 바로 실행할 수 있고, 소스는 볼 수 없는 장점이 생깁니다. 몇 종의 sh컴파일 솔루션이 있는데 무료로 쓸 수 있는 것이 SHC(SHell script Compiler)라는 것이 있습니다. (참조 : http://www.datsi.fi.upm.es/~frosal/)  

Ubuntu에서 APT로 설치하고자 하는 경우 8.04버전까지의 패키지가 존재하고 이후에는 없어서 구글링 해본 결과 wagung이란 개발자가 개인적 목적으로 deb 패키지를 만들어 두었네요. 원저작자 홈페이지에서는 tar.gz파일로 받아 컴파일 설치해야 합니다만 전 그냥 wagung의 패키지를 쓰기로 했습니다.

Ubuntu용 shc - 3.8.9 패키지 다운로드 : https://launchpad.net/~wagungs/+archive/personal/+packages

위 경로에서 shc패키지를 자신의 OS와 아키텍쳐(32/64bit)에 맞춰 다운로드 합니다. 그런 다음 본인의 서버로 옮겨 dpkg -i 옵션으로 설치합니다. 정말 간단하게 설치됩니다. 

SHC의 장점으로는 일단 실행가능한 형태로 컴파일 되면서 일정기간동안만 쉘을 실행하거나 하는 등의 약간의 옵션을 지원한다는 것 입니다. SHC의 Manpage을 보시면 옵션에 대한 설명이 있습니다.(참조 : http://www.datsi.fi.upm.es/~frosal/sources/shc.html) 간단하게 다음과 같이 sample.sh파일을 만들고 이를 컴파일해 봅시다.

#!/bin/sh 
echo "This is sample shell script!!" 
exit 0;
root@testServer:~# shc -f sample.sh

컴파일 결과 두개의 새로운 파일이 생성되었습니다. 하나는 sample.sh.x이고 하나는 sample.sh.x.c입니다. 전자는 실행파일이고, 후자는 C로 작성된 파일인데 두개의 파일이 같이 존재해야 sample.sh.x가 실행됩니다. vi로 열어보면 sample.sh.x는 소스를 확인할 수 없고 sample.sh.x.c는 컴파일된 실행파일을 실행하는 C코드입니다. 즉 원본 소스는 노출되지 않는다는 것 입니다.

따라서 쉘을 실행해서 어떤 값을 argument로 전달하면 쉘 내부에서 인증을 처리하고 정상적인 보안비밀키의 문자열을 출력해주도록 작성하고 컴파일해서 만들어 두고, ColdFusion에서 이 어떤값(쉘 내부로 전달할 비밀번호)을 전달하고 실행하도록 작성하면 비교적 안전하게 대칭키방식을 구현할 수 있지 않을까 생각하는데요. 

해당 ColdFusion파일 소스를 분석하면 금방 탄로날 것이지만 그 경우 시스템에서 해당 CFML파일을 원본그대로 유출해 가야하거나 시스템을 해킹해야하니까.. 비교적?이라는 단서를 붙힌 겁니다. 

물론, ColdFusion에서는 제품에 따라 약간 차이가 있지만 Java byte코드로 실행되도록 CFML소스 자체를 컴파일해버리는 기능이 있습니다. (자바 역시 디컴파일이 가능하다는 점에서 100% 안전한건 아니지만) 이 경우 소스를 전혀 볼 수 없으니까 역시나 비교적 안전하다고 할 수 있을 거 같습니다.

어쨋든 자체적으로 이런 여러 방법을 통해서 보안에 신경쓰다보면 자체적으로 취약점을 확인하거나 새로운 아이디어가 떠오를 수 있으니까 재밌는 것 같습니다. 혹시 이 글을 읽으시는 분 중에서 관련분야에 대한 조언을 해주실 수 있으신 분 있을까요? (웹 개발에 한정해서 말이죠)

참조한 글 : [기초강좌] shc를 이용한 쉘 스크립트 암호화하기 (Encrypting Shell Scripts)

최근에 개인정보보호와 관련하여 관련법이 강화되고 의무적으로 보안관련 이슈를 해결해야 하는 과정에서 DB암호화에 관한 부분이 홈페이지 분야에서 많이 대두 되고 있는 것 같습니다.

사실 DB암호화 솔루션의 경우 MySQL, MSSQL 등에 Plugin방식 등으로 탑재되는게 일반적이라고 할 수 있지만 전 그 역시 ActiveX적 사고에서 벗어나지 못한 일부 보안솔루션 회사들의 한계가 아닌가 싶어 아쉽습니다. 일단 뭔가를 열심히 서버에 설치해야 한다는 것. 

사실 DB를 암호화하는 가장 큰 이유는 유출된 데이터가 알 수 없는 코드로 암호화되어 개인정보 등이 노출되지 않도록 하기 위함입니다. 따라서 대부분의 개인정보는 암호화해서 저장되어야 하는데 암호화를 하는 방향에서 두가지로 나뉠 수 있습니다.

하나는 단방향암호화로서 일단 암호화를 하면 다시는 복호화가 불가능?하도록 하는 암호화와 또 하나는 암호화를 하되 필요시 복호화를 해서 내용을 확인해야 하는 암호화가 바로 그것이죠.

전자의 경우는 패스워드와 같이 일단 암호화를 하면 복호화가 안되도록 하는 곳에 주로 사용할 것 이고, 후자의 경우엔 이름이나 주소 등 다시 복호화해서 화면에 출력하거나 확인을 해야 하는 경우가 그 예가 될 수 있습니다.

사실 KISA에서도 이와 관련한 암호화방법에 관련된 기술자료를 오래전에 배포한 적이 있습니다.(참조 : http://seed.kisa.or.kr/iwt/ko/guide/EgovGuideDetail.do?bbsId=BBSMSTR_000000000011&nttId=37&pageIndex=1&searchCnd=&searchWrd=

위 자료의 요지는 앞에서 설명드린 단방향 암호화기법과 양방향암호화, 그리고 주로 쓰이는 ASP, JSP에서의 구현방법에 대한 내용입니다만, 여기서는 ColdFusion에서의 기법에 대해 몇자 적어보려 합니다.

타 웹 개발 언어와 마찬가지로 ColdFusion(CFML)에서도 Hash()함수등의 암호화 함수와 여러 국제적 표준의 알고리즘을 지원합니다. 그중 몇가지를 소개하고자 합니다.

Hash()

ColdFusion에서 사용하는 해시함수입니다. 대부분의 언어와 마찬가지로 사용법은 비슷합니다. 예제를 하나 만들어 보죠.

"안녕하세요?" 라는 평문을 Hash()함수로 암호화하면 다음과 같이 할 수 있습니다. Adobe ColdFusion의 Standard버전에서는 CFMX_COMPAT, MD5, SHA, SHA-256, SHA-384, SHA-512의 알고리즘을 지원하며 Enterprise버전에서는 좀 더 강화된 알고리즘을 지원합니다.(참조 : http://help.adobe.com/en_US/ColdFusion/10.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7c52.html)

<cfset hashDemo = Hash("안녕하세요?", "SHA-512", "UTF-8")>
<cfoutput>#hashDemo#</cfoutput>

위 실행 결과는

9F7384FE6552F1C7A9871C487B1760D011528BC58F556E3F27C6450C7FEB0C15C59AFDF13AB01
8E565764CB5AA35E15A9B7F48EDB745F92A33522FC57C3B6BA6

와 같은 문자열로 암호화 되어서 반환됩니다. 

위와 같이 해시함수로 암호화하면 이 암호를 푸는 인증키가 없기 때문에 해독이 불가능?합니다. (모든 알고리즘은 언젠가는 해독되게 마련이라 99%라고 할 수 있겠네요.)  이와같은 해시함수로 암호화된 데이터는 비밀번호 등 다시는 확인이 불가능한 데이터를 처리할 때 주로 사용합니다. 이 경우 사용자에게 입력받은 데이터를 해시함수로 암호화하여 저장된 데이터와 비교하여 정확한 값입력을 비교할 수 있습니다. 

Encrypt() Decrypt()

Encrypt()함수는 Decrypt()함수와 함께 보안키기반 암호화 함수입니다. 함수에 사용할 보안키를 임의로 생성한 후 해당 보안키로 문자열을 암호화 또는 복호화 합니다. 따라서 해당 보안키를 모르면 복호화가 불가능합니다. 두 함수 역시 다양한 알고리즘을 지원합니다만 각 Adobe ColdFusion에서 지원하는 알고리즘이 다르므로 기술문서를 참조해야 합니다. 보안키를 생성할 때는 GenerateSecretKey()함수를 이용해 임의로 난수 생성합니다. 역시 예제를 하나 살펴보죠.

Encrypt 함수참조 : http://help.adobe.com/en_US/ColdFusion/10.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7c2f.html

Decrypt 함수참조 : http://help.adobe.com/en_US/ColdFusion/10.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7c1c.html

예제 데모보기 : 암호화데모

<!--- AES 알고리즘 사용 --->
<cfset algorithm = "AES">

<!--- Hex 인크딩 사용 --->
<cfset encoding = "Hex">

<!--- 임의의 보안키생성 --->
<cfset encryptKey = "#generateSecretKey(algorithm)#">

<cfset strForEncrypt = "안녕하세요?">
<cfset encryptstr = encrypt(strForEncrypt, encryptKey, algorithm, encoding)>
<cfset decryptstr = decrypt(encryptstr, encryptKey, algorithm, encoding)>

<cfoutput>
<strong>보안키 :</strong> #encryptKey#<br />
<strong>문자열 :</strong> #strForEncrypt#<br />
<strong>암호화 :</strong> #encryptstr#<br />
<strong>복호화 :</strong> #decryptstr#<br />
</cfoutput>

Encrypt()와 Decrypt()함수는 개인정보 중 이름, 주소, 연락처, 이메일 등을 암호화하여 저장하고 필요시에 복호화해서 사용합니다. 중요한 것은 암호화시 사용한 보안키를 잘 보관해야 한다는것입니다. 이 키가 쉽게 노출된다면 복호화 역시 쉽게 될 수 있으니까요. 위에서 언급한 KISA에서 배포되는 자료에서도 해시함수나 블록암호알고리즘시 사용하는 SALT 또는 비밀키(보안키)를 안전한 곳에 잘 보관해야 하며 필요에 따라서는 외부에서 가져오길 권장합니다. DB암호화 솔루션 업체들의 개념을 보면 이 비밀키(보안키)와 같은 인증요소를 정책으로 지정하고 필요시에 인증을 거친 후 요청하도록 구성되어 있는 제품도 있었습니다.

자, ColdFusion에서도 Hash()와 Encrypt(), Decrypt()함수로 암호화 및 복호화를 할 수 있습니다. 국제적으로 공인받은 알고리즘을 사용하므로 시스템자체가 해킹되거나 취약점으로 인해 보안키가 노출되지 않도록만 한다면 간단하게 데이터를 암호화 할 수 있습니다. 하나만 더 붙히면 이와같이 평문의 문자열을 암호화할때 함수실행 전 단계에서 유출될 수 있으므로 SSL과 같은 보안서버의 구축 역시 필수겠죠?

EncryptBinary() DecryptBinary()

그렇다면 이렇게 문자열은 암호화해서 DB에 넣어두고 열심히 나름 보안을 챙겼다고 합시다. 그럼 사용자가 업로드한 파일은? 가령 개인정보가 적혀있는 이력서.doc파일이 업로드되었다고 해 봅시다. 대부분은 웹루트 하위 디렉토리에 파일이 저장되는 구조로 웹어플리케이션을 구성합니다. 이런 구조는 인증절차(로그인과 같은)을 거쳐 다운로드하도록 구성했어도 구글과 같은 검색엔진에 의해 충분히 해당 디렉토리와 파일이 그대로 노출됩니다. 업로드시 파일명을 변경한다 해도 파일자체를 숨기지는 못합니다. 

따라서 파일 업로드와 같은 경우에는 웹루트가 아닌 다른 곳에 파일을 저장하고, 다운로드시 해당 파일을 불러와 다운로드시켜주는 로직으로 구성해야 합니다. ColdFusion에서의 이와 관련된 이전의 제 글이 있으니 참조바랍니다. (http://archives.nooree.com/blog/post.cfm/coldfusion-dilemma-web-browser)

그런데 어떤 경우로 웹루트에 파일을 저장해야 한다고 가정해 봅시다. 그런 경우에는 파일 자체를 암호화 해줘야 합니다. 함부러 열어볼 수 없도록 말이죠. 이를 위해 ColdFusion에서는 EncryptBinary()와 DecryptBinary() 두 함수를 지원합니다. 사용법은 Encrypt()와 Decrypt()함수와 거의 동일 합니다. 문자열 대신 바이너리파일을 대입하는 것이죠.

EncryptBinary 함수참조 : http://help.adobe.com/en_US/ColdFusion/10.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-6e75.html

DecryptBinary 함수참조 : http://help.adobe.com/en_US/ColdFusion/10.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-6e77.html

가령 업로드된 파일이 JPG이미지 파일일 경우 EncryptBinary()로 암호화 해버리면 해당 파일을 다운로드 해가더라도 이미지파일로 인식할 수 없어 열어 볼 수 없습니다. 역시 예제하나 살펴보죠. 

<!--- AES 알고리즘 사용 --->
<cfset algorithm = "AES">

<!--- Hex 인크딩 사용 --->
<cfset encoding = "Hex">

<!--- 임의의 보안키생성 --->
<cfset encryptKey = "#generateSecretKey(algorithm)#">

<!--- 암호화할 파일 로드 --->
<cffile file="#ExpandPath('./sampleppt.pptx')#" action="readBinary" variable="sampleFile"> 

<!--- 파일암호화 --->
<cfset fileEncrypt = encryptBinary(#sampleFile#, encryptKey, algorithm)>
<!--- 암호화된 파일을 저장 --->
<cffile file="#ExpandPath('./sampleppt_enc.pptx')#" action="write" output="#fileEncrypt#"> 

<!--- 파일복호화 --->
<cfset fileDecrypt = DecryptBinary(#fileEncrypt#, encryptKey, algorithm)>
<!--- 복호화된 파일을 저장 --->
<cffile file="#ExpandPath('./sampleppt_dec.pptx')#" action="write" output="#fileDecrypt#"> 

위 코드에서 쓰인 PPT샘플외에 다양한 이미지, 텍스트파일을 직접 다운로드하여 열어 보시길 바랍니다. (마우스 오른쪽 다른 이름으로 저장하시길 바랍니다.) 

원본 이미지 : sampleimage.png
암호화된 이미지 : sampleimage_enc.png (이미지 파일이 볼 수 있나요?)
​복호화된 이미지 : sampleimage_dec.png (복호화된 원본과 같은 이미지)

원본 텍스트파일 : samplefile.txt
암호화된 텍스트파일 : samplefile_enc.txt (열리나요?)
복호화된 텍스트파일 : samplefile_dec.txt

원본 PPT파일 : sampleppt.pptx
암호화된 PPT파일 : sampleppt_enc.pptx (열리나요?)
복호화된 PPT파일 : sampleppt_dec.pptx

별거 아닌걸 디게 거창하게 이야기했습니다만 웹의 특성상 오픈된 시스템이므로 구현시 꼼꼼한 자세가 필요해 보닙니다. 문자열에 대한 암호화 뿐만 아니라 보안키에 대한 보관방법, 업로드되는 파일의 암호화 등 웹개발자는 신경쓸 것이 참 많습니다. ^^

Powered by

© 2010-2018 NOOREE.COM