2010년 11월 25일 목요일

리눅스에서 실제 사용가능한 메모리가 적게 보이는 경우는...메모리 확보하기

리눅스 시스템을 사용하다 보면, 분명 물리적 메모리는 많은데 실제 사용 가능한 메모리가 적게 나와
보이는 경우가 있다. 아래의 경우를 보자:

# free
             total       used       free     shared    buffers     cached
Mem:       8301476    7941864     359612          0     112468    7295056
-/+ buffers/cache:     534340    7767136
Swap:      2650684        676    2650008

전체 메모리는 8,301,476 에서 7,941,864 가 사용되고 있다. 그런데 실제 동작하고 있는 프로세스는
이 정도 만큼을 사용하지 않고 있다. free 에서 보이는 필드 중 cached 가 있다. 캐쉬가 되어 있는 것이
7,295,056 이다. 리눅스 커널은 성능향상을 위해 캐쉬를 하게되는데, 바로 이 수치이다. 이것은 일반적인
상황이며, 많이 사용되고 있다고 걱정할 부분은 아니다. 캐쉬는 실제 프로그램이 동작하기 위해서 사용되는
엑티브된 메모리 페이지 보다 우선순위가 낮게 주어진다.

예를 들어, 1기가의 메모리를 가지고 있는데, 프로그램에 의해 700 메가가 사용되고 있다고 하자. 200메가
정도도 캐쉬되어 있고 50메가 정도가 프리로 남아있는 상태에서 프로그램 동작하는데 150 메가 필요하다면,
캐쉬가 사용되는 부분을 실제 엑티브 되어 돌아가야 하는 프로세스에 할당이 되게 된다.

즉, 캐쉬는 시스템상에서 프로그램이 좀더 빠르게 응답/동작할 수 있도록 하는 것이다.

이런 캐쉬를 사용자에 의해 초기화 시킬 수도 잇는데, /proc/sys/vm/drop_caches 이용하면 된다.

# cat /proc/sys/vm/drop_caches
0
# echo 3 > /proc/sys/vm/drop_caches
# cat /proc/sys/vm/drop_caches
3

위와 같이 값이 3으로 변경된걸 볼 수 있고, 다시 free 를 해 보면 사용가능한 메모리가 크게 늘어나 있는 것을
확인할 수 있다. 대신 캐쉬되어 있는것은 크게 줄어 있다.

# free
             total       used       free     shared    buffers     cached
Mem:       8301476     436616    7864860          0        464      10568
-/+ buffers/cache:     425584    7875892
Swap:      2650684        676    2650008
# cat /proc/meminfo
MemTotal:      8301476 kB
MemFree:       7863868 kB
Buffers:          1492 kB
Cached:          13448 kB
SwapCached:          0 kB
Active:         394288 kB
Inactive:         3456 kB
HighTotal:     7461476 kB
HighFree:      7062172 kB
LowTotal:       840000 kB
LowFree:        801696 kB
SwapTotal:     2650684 kB
SwapFree:      2650008 kB
Dirty:             100 kB
Writeback:           0 kB
AnonPages:      382952 kB
Mapped:          10456 kB
Slab:            13140 kB
SReclaimable:     2968 kB
SUnreclaim:      10172 kB
PageTables:       1300 kB
NFS_Unstable:        0 kB
Bounce:              0 kB
WritebackTmp:        0 kB
CommitLimit:   6801420 kB
Committed_AS:  1179472 kB
VmallocTotal:   116728 kB
VmallocUsed:      4236 kB
VmallocChunk:   111888 kB
HugePages_Total:     0
HugePages_Free:      0
HugePages_Rsvd:      0
HugePages_Surp:      0
Hugepagesize:     2048 kB

이 작업은 커널상에서 캐쉬를 클리어하게 만드는 것으로, 값은 1,2,3 중에 하나를 가질 수 있다. 1은 PageCache 를 2는 트리와 아이노드를 클리어하며 3은 1과2를 두개다 하는 것과 같다. 캐쉬를 클리어하기 전에는 sync 를 수행하고 하는 것이 좋으며, 이 drop_caches 기능은 커널 2.6.16 에 추가되었다.

일부 사용자는 캐쉬 클리어를 한 후 시스템이 Hang 이 되었다는 얘기도 있으므로 참고하길 바란다.

[참고]
1. http://encyclopedia.thefreedictionary.com/cache+memory
2. http://www.faqs.org/docs/linux_admin/buffer-cache.html

2010년 11월 23일 화요일

당신의 패스워드는 안전한가? 클라우드 기반 패스워드 크랙킹

패스워드 크랙킹을 하는데는 많은 컴퓨팅 자원이 필요하다. 많은 연산이 필요해지는데,
CPU 보다는 GPU 가 연산하는데 있어 훨씬 파워풀한 성능을 제공한다. 그런데,이런 GPU 도
클라우드 방식으로 이용하면 더욱 빠르게 처리 가능할 것이다. 최근 아마존에서 제공하는
EC2 클라우드 서비스를 이용해 패스워드를 크랙킹한 것이 소개되었다. 사용된 하드웨어
스펙은 아래와 같다:

22기가 메모리
33.5 EC2 컴퓨터 ( 인텔 제온 X5570, 쿼드코어 X 2)
NVIDIA M2050GPU X 2
1690GB 스토리지
64비트 플랫폼

CUDA-Multiforce 를 이용해 sha1 해쉬 파일을 크랙킹 하는데, 단지 49분이 걸렸다고 한다.
테스트로 이용된 해쉬는 총 14개이며, 아마존 EC2 를 이용하는데 비용은 1시간에 $2.10
이라고 한다. 클라우드 기반의 컴퓨팅 파워를 이용해 저렴한 패스워드 크랙킹이 가능해 진것이다.

일반적으로 이용되는 시스템 자원을 이용하면 얼마나 걸릴까? 때마침 잠깐 테스트할 만한
시스템도 있고하여 겸사겸사 테스트 해보았다. GPU 는 장착되어 있지 않고,
시스템 사양은 아래와같다 :

Intel(R) Xeon(R) CPU E5520  @ 2.27GHz 듀얼 쿼드코아 (16개 로지컬 CPU)
SAS 15K RPM 디스크
메모리 32 기가
64bit 플랫폼/리눅스

사용한 소프트웨어는 RainbowCrack 이다. 사전에 미리 테이블을 만드는 작업을
거쳐 최종 검증을 하게 되는데, 이 테이블을 만드는 사전 작업이 많은 시간이 소요된다.

1. 우선 앞서 예제에서 소개되었던 해쉬는 아래와 같다.

# more sha1_hashes.txt
EB45E66E03EE06E74AC824081C7A71352E51DF90
A94B95A7A4D432DE056B0030DA879AF841376069
3B615E3CD3ACA03AC818C7752A109EC7E2168532
8F2005004F8BAA7A1090A9BF3B03C48D38E78157
26BFB52D1809F04EAD2B7F5C002C1EAA7A584696
7110EDA4D09E062AA5E4A390B0A572AC0D2C0220
1902E3D6FC4E78A0BCC50BA12B882769AFBF4A8C
BFE06C47BE2390ACA934AB6A128C141DCEB4072F
CD3724AC40034097A3D27865D710E4F791B6AEDB
A9993E364706816ABA3E25717850C26C9CD0D89D
0D824508182A1AA0EEF9A0B6EE52F8A32AF06F0A
5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8
EF8420D70DD7676E04BEA55F405FA39B022A90C8
DA39A3EE5E6B4B0D3255BFEF95601890AFD80709

2. rtgen 을 이용해 레인보우 테이블을 생성한다.  이때 패스워드의 길이는 최소 1 에서
6 사이의 길이로 한 것이다.

# time ./rtgen sha1 ascii-32-95 1 6 1 3800 33554432 0
rainbow table sha1_ascii-32-95#1-6_1_3800x33554432_0.rt parameters
hash algorithm:         sha1
hash length:            20
charset:                 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
charset in hex:         20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e
charset length:         95
plaintext length range: 1 - 6
reduce offset:          0x00010000
plaintext total:        742912017120

sequential starting point begin from 0 (0x0000000000000000)
generating...
524288 of 33554432 rainbow chains generated (1 m 18.4 s)
1048576 of 33554432 rainbow chains generated (1 m 17.2 s)
1572864 of 33554432 rainbow chains generated (1 m 17.8 s)
2097152 of 33554432 rainbow chains generated (1 m 18.2 s)
2621440 of 33554432 rainbow chains generated (1 m 18.4 s)
3145728 of 33554432 rainbow chains generated (1 m 18.3 s)
3670016 of 33554432 rainbow chains generated (1 m 18.4 s)
4194304 of 33554432 rainbow chains generated (1 m 18.4 s)
4718592 of 33554432 rainbow chains generated (1 m 18.3 s)
5242880 of 33554432 rainbow chains generated (1 m 18.2 s)
5767168 of 33554432 rainbow chains generated (1 m 18.2 s)
(생략...)

real    83m51.179s

시간을 측정해 보았더니 83 분이 걸렸다. 적지 않은 시간이 걸렸는데, 이 작업이
진행되는 동안 CPU 는 100% 풀로 사용된 것이다. (16개의 Logical CPU)

 PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
29166 root      20   0  157m  13m 1012 S 1600  0.0  22:01.80 rtgen

3. 생성된 테이블을 rtsort 로 정렬을 한다.

# ./rtsort  sha1_ascii-32-95#1-6_5_3800x33554432_0.rt
sha1_ascii-32-95#1-6_5_3800x33554432_0.rt:
32361852928 bytes memory available
loading rainbow table...
sorting rainbow table by end point...
writing sorted rainbow table...

4. 만들어진 테이블을 이용해 패스워드 해쉬 파일을 크랙킹 해본다.

# ./rcrack sha1_ascii-32-95#1-6_0_3800x33554432_0.rt -l sha1_hashes.txt
33167699968 bytes memory available
1 x 536870912 bytes memory allocated for table buffer
851200 bytes memory allocated for chain traverse
disk: sha1_ascii-32-95#1-6_0_3800x33554432_0.rt: 536870912 bytes read
searching for 14 hashes...
plaintext of 7110eda4d09e062aa5e4a390b0a572ac0d2c0220 is 1234
plaintext of cd3724ac40034097a3d27865d710e4f791b6aedb is Bwah
plaintext of 8f2005004f8baa7a1090a9bf3b03c48d38e78157 is P4s$
plaintext of a9993e364706816aba3e25717850c26c9cd0d89d is abc
plaintext of 1902e3d6fc4e78a0bcc50ba12b882769afbf4a8c is bad
disk: finished reading all files

statistics
-------------------------------------------------------
plaintext found:                              5 of 14
total time:                                   7.49 s
  time of chain traverse:                     7.19 s
  time of alarm check:                        0.19 s
  time of wait:                               0.00 s
  time of other operation:                    0.11 s
time of disk read:                            0.64 s
hash & reduce calculation of chain traverse:  101026800
hash & reduce calculation of alarm check:     3773101
number of alarm:                              3140
speed of chain traverse:                      14.04 million/s
speed of alarm check:                         19.96 million/s

result
-------------------------------------------------------
eb45e66e03ee06e74ac824081c7a71352e51df90  <not found>  hex:<not found>
a94b95a7a4d432de056b0030da879af841376069  <not found>  hex:<not found>
3b615e3cd3aca03ac818c7752a109ec7e2168532  <not found>  hex:<not found>
8f2005004f8baa7a1090a9bf3b03c48d38e78157  P4s$  hex:50347324
26bfb52d1809f04ead2b7f5c002c1eaa7a584696  <not found>  hex:<not found>
7110eda4d09e062aa5e4a390b0a572ac0d2c0220  1234  hex:31323334
1902e3d6fc4e78a0bcc50ba12b882769afbf4a8c  bad  hex:626164
bfe06c47be2390aca934ab6a128c141dceb4072f  <not found>  hex:<not found>
cd3724ac40034097a3d27865d710e4f791b6aedb  Bwah  hex:42776168
a9993e364706816aba3e25717850c26c9cd0d89d  abc  hex:616263
0d824508182a1aa0eef9a0b6ee52f8a32af06f0a  <not found>  hex:<not found>
5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8  <not found>  hex:<not found>
ef8420d70dd7676e04bea55f405fa39b022a90c8  <not found>  hex:<not found>
da39a3ee5e6b4b0d3255bfef95601890afd80709  <not found>  hex:<not found>

위 결과와 같이 14개의 패스워드 중 5개를 발견하였다.  레인보우 테이블을 2개로
이용한 후에는 6개로 1개의 테이블을 이용했을 때보다 1개를 더 찾아내었다.
테이블을 더 만들어 해 보았더니 6개에서는 9개를 찾아냈다. (1개 테이블 생성에 80분이라고 하면,
6개 생성에만 8시간이 소요된 것이다)

# ./rcrack *.rt -l sha1_hashes.txt
32374755328 bytes memory available
6 x 536870912 bytes memory allocated for table buffer
851200 bytes memory allocated for chain traverse
disk: sha1_ascii-32-95#1-6_0_3800x33554432_0.rt: 536870912 bytes read
disk: sha1_ascii-32-95#1-6_1_3800x33554432_0.rt: 536870912 bytes read
disk: sha1_ascii-32-95#1-6_2_3800x33554432_0.rt: 536870912 bytes read
disk: sha1_ascii-32-95#1-6_3_3800x33554432_0.rt: 536870912 bytes read
disk: sha1_ascii-32-95#1-6_4_3800x33554432_0.rt: 536870912 bytes read
disk: sha1_ascii-32-95#1-6_5_3800x33554432_0.rt: 536870912 bytes read
searching for 14 hashes...
plaintext of 7110eda4d09e062aa5e4a390b0a572ac0d2c0220 is 1234
plaintext of cd3724ac40034097a3d27865d710e4f791b6aedb is Bwah
plaintext of 8f2005004f8baa7a1090a9bf3b03c48d38e78157 is P4s$
plaintext of a9993e364706816aba3e25717850c26c9cd0d89d is abc
plaintext of 1902e3d6fc4e78a0bcc50ba12b882769afbf4a8c is bad
disk: finished reading all files
searching for 9 hashes...
plaintext of eb45e66e03ee06e74ac824081c7a71352e51df90 is nVidia
searching for 8 hashes...
plaintext of 0d824508182a1aa0eef9a0b6ee52f8a32af06f0a is GoOd!
plaintext of bfe06c47be2390aca934ab6a128c141dceb4072f is G0o|)
searching for 6 hashes...
plaintext of 3b615e3cd3aca03ac818c7752a109ec7e2168532 is W3a$eL
searching for 5 hashes...
searching for 5 hashes...

statistics
-------------------------------------------------------
plaintext found:                              9 of 14
total time:                                   18.14 s
  time of chain traverse:                     17.06 s
  time of alarm check:                        0.76 s
  time of wait:                               0.00 s
  time of other operation:                    0.32 s
time of disk read:                            2.87 s
hash & reduce calculation of chain traverse:  339161400
hash & reduce calculation of alarm check:     17185485
number of alarm:                              13776
speed of chain traverse:                      19.88 million/s
speed of alarm check:                         22.52 million/s

테이블을 생성하기 까지는 많은 시간이 걸리나, 테이블을 이용해서 찾는 경우는
금방 찾아진다. 그렇다면, 위와 같은 경우를 접목해 보면
클라우드 기반의 시스템 파워를 이용해 테이블을 크게 생성해 놓는다면
추후에 패스워드를 찾는데 오랜 시간이 걸리지 않는것이다. 패스워드 길이가 왜
짧으면 위험한지에 대한 이유를 알 수 있을 것이다. 다음 글은 왜 12자리의 패스워드를 사용해야 하는 가에
대한 포스팅이다.


각 개별 컴퓨팅 파워는 높아지고, 클라우드 방식의 활용은 점차 확대되고 있다. 여기서 필자가 이것을
소개한 이유는 크랙킹을 소개하고자 하는 것은 아니다. 이런 자원이 좋은 쪽으로 이용되면
다양한 과학발전등 큰 도움이 되지만, 악의적 형태로 이용되면 말 하지 않아도 알 것이다.

현재의 수준이 이렇다는 것을 함께 공유하고 싶다. 왜 자꾸 '보안' 이라는 것에 대해서 관심을
가져야 하는 것인지를 말이다...

[참고]
1. 아마존 EC2 를 이용한 클라우트 크랙킹
2. RainbowCrack Project

2010년 11월 22일 월요일

리눅스에서 강제 리부팅이 필요한 경우에는...

리눅스 시스템에서 부팅이나 기타 명령어를 수행하고자 할때 응답이 없는
경우가 있다. 프로세스를 kill 하려고 해도 죽지 않거나 sync or reboot 를
해도 그냥 멈춰 있는 경우를 가끔 경험하는 때가 있다.

# reboot

Broadcast message from root@xxxx (pts/4) (Mon Nov  8 16:45:00 2010):

The system is going down for reboot NOW!


이럴때 강제적으로 리부팅하는 하는 방법이 있다. 다음과 같이 설정하여
강제적으로 리부팅이 가능하다.

echo 1 > /proc/sys/kernel/sysrq
echo b > /proc/sysrq-trigger

sysrq 에 값을 셋팅하는데 sysrq 는 무엇일까? sysrq.c 에 기술된 내용을 보면
다음과 같다:

*  What is the magic SysRq key?

Fix Unresponsive or Frozen Linux Computers using Shortcuts

이미지출처 : www.makeuseof.com


It is a 'magical' key combo you can hit which the kernel will respond to regardless of whatever else it is doing, unless it is completely locked up.

즉, 매직키와 같은 것으로 솔라리스 계열의 스팍 시스템 키보드를 보면
Stop 키가 있다. Alt-Stop-<command key> 를 누르면 특정 명령이 수행되는
형태와 같은 것이다.  이 command key 는 사전에 정의된 것으로
'b' 는 syncing 또는 언마운트 없이 즉시 리부팅을 수행하고, 'e' 는
init 를 제외한 모든 프로세스에 SIGTERM 을 보낸다.

위 예와 같이 sysrq 에 1을 설정하여 enable 상태를 만들고 sysrq-trigger에
b 명령어를 보내 즉시 리부팅을 수행하도록 한다.

[참고]
1. Magic SysRq key
http://en.wikipedia.org/wiki/Magic_SysRq_key

2010년 11월 17일 수요일

올해 4월, 전세계 인터넷의 15%가 중국으로 흘렀다고?

이미지출처 : NDIA


흥미로운 기사 하나를 접했다. 올 초, 정확히는 4월 18일 인터넷 트래픽 양의 15% 가까이가 18 분동안 중국으로 우회 되었다는 것이다. 이 사실은
11월17일 미 국회에서 미국-중국의 양국관계에 관한 경제, 보안을 검토 하는 연례보고서에서 그 내용이 알려졌다.

18분동안 중국으로 리다이렉션된 트래픽은 미국 정부, 국방부 및 군사 관련 사이트 및 델, 야후, 마이크로소프트, IBM 과 같은 상업 사이트까지 많은 수를 포함하고 있다.

인터넷에서는 해당 사이트를 찾아갈때 라우팅이라는 경로를 통해 최적의 경로를 따라 사이트를 찾아 들어간다. 정상적인 경우라면 중국을 거치지 않고 들어가야 하는데, 어떤 이유에서 해당 사이트를 찾아 들어가기 까지 중국의 차이나 텔레콤을 거쳐서 정보가 흘러갔다는 것이다.

그렇다면 중국에서는 트래픽을 충분히 감시할 수 있는 상황이 되었을 것이다. 암호화 되지 않은
트래픽 이라면 이메일, 메신저와 같은 내용들이 감청당했을 수 있다. 이렇게 중국을 거쳐서 트래픽이 흘렀어도, 사용자가 느끼기에는 큰 차이가 없었기 때문에 인지도 늦었던 것 같다.

현재 이와 같은 상황이 발생된 이유에 대해 세부적인 사항은 많이 알려져 있지 않다.

정확한 사실 한가지는 2010년4월18일 인터넷 트래픽의 15%가 18분동안 중국의 차이나 텔레콤으로
흘렀다는 사실이다. 무슨일이 일어났을지는 모르지만, 정보 수집형태로 이용된다면 아주 무서운 일이 아닐 수 없다.

물론, 국내에서도 이와 같은 일이 충분히 일어날 수 있다. 만약 악성코드가 감염되어 특정한 곳을 거쳐서 트래픽이 흐르도록 조정된다면, 정보는 중간에서 감청될 수 있다. 사이버전에 효과적으로 이용될 수 있는 방법중의 하나가 될 것이다.

현재 나의 트래픽이 어느 경로로 흘러가고 있는가가 궁금하다면 traceroute 로 쉽게 확인할 수 있다. 윈도우 사용자라면 tracert 명령어를 이용하면 된다.

<윈도우에서 경로추적 예>

C:\>tracert google.com

최대 30홉 이상의
google.com [74.125.53.104](으)로 가는 경로 추적:

  1     5 ms    <1 ms    <1 ms  192.168.0.200
  2     7 ms     7 ms     7 ms  218.146.42.254
  3     7 ms     6 ms     7 ms  121.140.24.161
  4     7 ms     7 ms     6 ms  218.146.42.253
  5     8 ms     7 ms     7 ms  112.190.32.93
  6     8 ms     7 ms     7 ms  218.145.32.193
  7     7 ms     7 ms     7 ms  112.174.81.114
  8     7 ms     7 ms     7 ms  112.174.83.34
  9   123 ms   122 ms   123 ms  112.174.87.126
 10   146 ms   140 ms   133 ms  74.125.51.181
 11   154 ms   123 ms   131 ms  209.85.249.32
 12   124 ms   134 ms   124 ms  66.249.94.199
 13   130 ms   147 ms   130 ms  216.239.46.200
 14   130 ms   130 ms   129 ms  216.239.48.139
 15   135 ms   142 ms   143 ms  72.14.232.70
 16   130 ms   131 ms   130 ms  pw-in-f104.1e100.net [74.125.53.104]

추적을 완료했습니다.

이와 관련 세부적 내용이 확인되면 다시 공유하도록 하겠다.

From rigel.

[참고]
1. ABC뉴스

커널에서 drop 되는 패킷 수가 많다면...

tcpdump 와 같은 패킷 덤프 프로그램을 사용하면 몇 건의 패킷덤프가 되었는지 확인할 수 있다. 그런데, 캡쳐된 상태를 관심있게 살펴 보았다면, 의외로 drop 된 패킷 건수가 크게 나타나는 경우를 경험해 보았을지도 모른다.
다음의 경우를 보자:

16 packets captured
351742 packets received by filter
351655 packets dropped by kernel

tcpdump 를 이용해 패킷 덤프를 하다 Ctrl+C 를 통해 중지 하였는데, 16개의 패킷이 캡쳐되었다. 그런데 packets dropped by kernel 을 보면 그 카운터가 꽤 높다. 필터에서 받은 패킷 건수가 351,742 건인데 drop된 건수가 351,655 라는 것이다. 이러한 것은 다양한 원인이 있겠지만, 사용하는 패킷덤프 프로그램에 의한 영향이거나, 네트워크적인 영향, 하드웨어, 패킷필터, 운영체제와 관련한 것등이 있을 것이다.

이런 경우 IP 주소등을 이름으로 변경하는 작업등이 이뤄지지 않도록 하는 것 만으로도 큰 효과를 볼 수 있다.
tcpdump 에서는 '-n' 옵션을 사용하면 된다.

# tcpdump -i eth0 -n
51119 packets captured
51612 packets received by filter
493 packets dropped by kernel

같은 조건의 환경인데, -n 만을 사용하는 것만으로도 큰 차이가 나타난다. 패킷덤프시에는 이점을 참고하기 바란다. 이외, 커널 상에서 네트워크 관련 파라미터를 수정하는 것도 도움이 될 것이다. 패킷 덤프만이 아니라, 네트워크 관련된 서비스를 하는 시스템이라면 한번쯤은 검토해 보아야 한다.

sysctl 을 통해 관련 파라미터 정보를 확인할 수 있는데, 예를 들어 backlog 를 확인해 보면 아래와 같다.

# sysctl -a | grep backlog
error: permission denied on key 'net.ipv4.route.flush'
net.ipv4.tcp_max_syn_backlog = 1024
net.core.netdev_max_backlog = 5000

backlog 는 새로운 연결을 맺는데 관련하여 영향을 주는 파라미터중 하나다. 이외 여러가지 값 들이 있는데, 네트워크 연결이 많다면 다음과 같은 설정이 권장된다.

      net.core.wmem_max = 8388608
      net.core.rmem_max = 8388608
      net.ipv4.tcp_wmem = 4096 65536 8388608
      net.ipv4.tcp_rmem = 4096 87380 8388608
      net.ipv4.tcp_default_win_scale = 7
      net.ipv4.tcp_moderate_rcvbuf = 1
각 값의 설정은 sysctl 을 통하거나 /proc 파일 시스템을 직접 엑세스 할 수 있다.  sysctl 을 이용한다면,

# sysctl -w net.core.rmem_max=8388608

와 같다. 참고로 리눅스 2.6.17 이후에는 오토튜닝이라는 기능이 있는데, 이것은 각 연결에 따라 버퍼 사이즈등이 동적으로 업데이트 되는 것이다. 이 값은 /proc/sys/net/ipv4/tcp_moderate_rcvbuf 를 통해 확인해 볼 수 있는데,

# cat /proc/sys/net/ipv4/tcp_moderate_rcvbuf

1 의 값이 셋팅되어 있다면 autotuning 이 설정되어 있는 것이다.  이런, 네트워크 관련 파라미터 설정외에도
현재 네트워크 관련한 상태를 확인해 보는 것도 원인 파악에 도움이 된다. 네트워크 상태를 파악하는데 기본적으로 많이 사용되는 netstat 를 사용하는 것만으로도 많은 정보를 얻을 수 있다.

# netstat -s
Ip:
    2987551774 total packets received
    480 with invalid headers
    4288 with invalid addresses
    139108843 forwarded
    0 incoming packets discarded
    2804683209 incoming packets delivered
    1904276683 requests sent out
    1832 outgoing packets dropped
    1344 dropped because of missing route
    169 fragments dropped after timeout
    1551222 reassemblies required
    38285 packets reassembled ok
    230 packet reassembles failed
    31867 fragments received ok
    5222 fragments failed
    1377531 fragments created
Icmp:
    331800 ICMP messages received
    26 input ICMP message failed.
    ICMP input histogram:
        destination unreachable: 331772
        echo requests: 4
        echo replies: 24
    345417 ICMP messages sent
    0 ICMP messages failed
    ICMP output histogram:
        destination unreachable: 340488
        time exceeded: 451
        redirect: 1831
        echo request: 2647
IcmpMsg:
        InType0: 24
        InType3: 331772
        InType8: 4
        OutType3: 340488
        OutType5: 1831
        OutType8: 2647
        OutType11: 451
Tcp:
    7723898 active connections openings
    13569062 passive connection openings
    1469362 failed connection attempts
    2505823 connection resets received
    64 connections established
    2794594182 segments received
    1750284379 segments send out
    4751200 segments retransmited
    0 bad segments received.
    1074943 resets sent
Udp:
    9438290 packets received
    323420 packets to unknown port received.
    0 packet receive errors
    9784976 packets sent
UdpLite:
TcpExt:
    879602 resets received for embryonic SYN_RECV sockets
    552 packets pruned from receive queue because of socket buffer overrun
    21 ICMP packets dropped because they were out-of-window
...(생략)

그리고 다음 도표는 IBM 에서 정리된 파라미터 정보인데, 각 파라미터를 이해하는데 도움이 될거 같아 첨부하였다.

Tunable parameterDefault valueOption description
/proc/sys/net/core/rmem_default"110592"Defines the default receive window size; for a large BDP, the size should be larger.
/proc/sys/net/core/rmem_max"110592"Defines the maximum receive window size; for a large BDP, the size should be larger.
/proc/sys/net/core/wmem_default"110592"Defines the default send window size; for a large BDP, the size should be larger.
/proc/sys/net/core/wmem_max"110592"Defines the maximum send window size; for a large BDP, the size should be larger.
/proc/sys/net/ipv4/tcp_window_scaling"1"Enables window scaling as defined by RFC 1323; must be enabled to support windows larger than 64KB.
/proc/sys/net/ipv4/tcp_sack"1"Enables selective acknowledgment, which improves performance by selectively acknowledging packets received out of order (causing the sender to retransmit only the missing segments); should be enabled (for wide area network communication), but it can increase CPU utilization.
/proc/sys/net/ipv4/tcp_fack"1"Enables Forward Acknowledgment, which operates with Selective Acknowledgment (SACK) to reduce congestion; should be enabled.
/proc/sys/net/ipv4/tcp_timestamps"1"Enables calculation of RTT in a more accurate way (see RFC 1323) than the retransmission timeout; should be enabled for performance.
/proc/sys/net/ipv4/tcp_mem"24576 32768 49152"Determines how the TCP stack should behave for memory usage; each count is in memory pages (typically 4KB). The first value is the low threshold for memory usage. The second value is the threshold for a memory pressure mode to begin to apply pressure to buffer usage. The third value is the maximum threshold. At this level, packets can be dropped to reduce memory usage. Increase the count for large BDP (but remember, it's memory pages, not bytes).
/proc/sys/net/ipv4/tcp_wmem"4096 16384 131072"Defines per-socket memory usage for auto-tuning. The first value is the minimum number of bytes allocated for the socket's send buffer. The second value is the default (overridden by wmem_default) to which the buffer can grow under non-heavy system loads. The third value is the maximum send buffer space (overridden by wmem_max).
/proc/sys/net/ipv4/tcp_rmem"4096 87380 174760"Same as tcp_wmem except that it refers to receive buffers for auto-tuning.
/proc/sys/net/ipv4/tcp_low_latency"0"Allows the TCP/IP stack to give deference to low latency over higher throughput; should be disabled.
/proc/sys/net/ipv4/tcp_westwood"0"Enables a sender-side congestion control algorithm that maintains estimates of throughput and tries to optimize the overall utilization of bandwidth; should be enabled for WAN communication. This option is also useful for wireless interfaces, as packet loss may not be caused by congestion.
/proc/sys/net/ipv4/tcp_bic"1"Enables Binary Increase Congestion for fast long-distance networks; permits better utilization of links operating at gigabit speeds; should be enabled for WAN communication.


2010년 11월 15일 월요일

Scapy 로 패킷 핸들링하는 프로그램 만들기 - 세번째

Scapy 의 마지막으로 세번째 이야기를 소개해본다. 이번에는 Scapy 를 이용해 나만의 프로그램을
만드는 방법이다. 앞서 소개한 것과 같이 Scapy 는 파이썬기반이어서, 파이썬에서도 Scapy 모듈을 로드하여
내가 원하는 형태로 패킷을 쉽게 다룰 수가 있다.

모든 패킷 도구들이 내가 원하는 입맛에 맞게 맞춰져 있지는 않다. 이럴때 Scapy 는 간단하게 패킷을 쉽게
다룰 수 있는 방법을 제공해 준다. 이에 몇 가지 사용 예제를 소개해 본다. 예제를 보는 것 만으로도
쉽게 이해가 될 것이며, 이 예제를 기반으로 원하는 프로그램으로 확장하는 것은 그리 어렵지 않을 것이다.
여기 외에, 인터넷을 찾아보면 많은 예제파일들이 있으므로 여기서는 '아 ~ 이현형태로 이용가능하구나' 하는 것만을 인지해 두면 될것 같다.

1. 간단한 ICMP 패킷 보내보기

첫 시작으로 간단하게 ICMP 패킷 보내는 것을 해 보자. 우선, Scapy 모듈을 사용하기 위해서는
모듈을 불러들여야 한다.

from scapy.all import sr1, IP, ICMP

위와 같이 하여 sr1, IP, ICMP 만을 로드하였다. 물론 import * 로 하여 전체 관련된 것을 모두 로드할 수 도 있다. import sys 는 실행할때 인자로 받아들일 값을 사용하기 위해 sys 모듈을 로드하였고,
packet 변수에 IP()/ICMP() 와 같이 하여 IP 와 ICMP 헤더를 넣어주었다. 이때 IP 헤더에는 인자로 받은 값을 넘겨주어 목적지 주소를 지정한 것이다. show() 는 각 구성 형태를 세부적으로 보여주며, sr1 은 패킷 한개를 발송하도록 정의한 것이다.

#!/usr/local/bin/python
# PacketInside.com - Scapy Example
import sys
from scapy.all import sr1,IP,ICMP

packet=IP(dst=sys.argv[1])/ICMP()
print "+-------- Sending Packet INFO"
packet.show()
result = sr1(packet)
if result:
    print "+-------- Receiving Packet INFO"
    result.show()

발송하기 전에 패킷 구성 형태를 packet.show() 를 통해 한번 보여주고, 패킷 발송후에 성공했으면
전달 받은 패킷 데이터를 또 보여주는 간단한 구조다. 다음과 같이 실행해 본다.

# ./icmp.py google.com
WARNING: No route found for IPv6 destination :: (no default route?)
+-------- Sending Packet INFO
###[ IP ]###
  version   = 4
  ihl       = None
  tos       = 0x0
  len       = None
  id        = 1
  flags     =
  frag      = 0
  ttl       = 64
  proto     = icmp
  chksum    = None
  src       = 192.168.0.240
  dst       = Net('google.com')
  \options   \
###[ ICMP ]###
     type      = echo-request
     code      = 0
     chksum    = None
     id        = 0x0
     seq       = 0x0
Begin emission:
.Finished to send 1 packets.
*
Received 2 packets, got 1 answers, remaining 0 packets
+-------- Receiving Packet INFO
###[ IP ]###
  version   = 4L
  ihl       = 5L
  tos       = 0x0
  len       = 46
  id        = 56007
  flags     =
  frag      = 0L
  ttl       = 49
  proto     = icmp
  chksum    = 0x6d5f
  src       = 74.125.53.147
  dst       = 192.168.0.240
  \options   \
###[ ICMP ]###
     type      = echo-reply
     code      = 0
     chksum    = 0x0
     id        = 0x0
     seq       = 0x0
###[ Raw ]###
        load      = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
 
google.com 으로 ICMP 패킷을 보내고 전달받은 결과를 보여준다. 와이어샤크로 해당 패킷을 덤프해 보면
아래와 같이 제대로 패킷이 전송된 것을 알 수 있다.


만약 위 packet 변수에 아래와 같은 값을 입력하면 어떨까?

packet=IP(dst=sys.argv[1])/TCP(sport=4321,dport=80)/Raw(load="GET /index.html HTTP/1.0 \n\n")

의미는 간단해 보인다. TCP 출발지 포트를 4321, 목적지 포트를 80 으로 하고 페이로드에는 /index.html 을 요청하는 것을 집어 넣은 것이다. 하지만 이렇게 바꾸고 실행하면 오류가 발생한다. Scapy 모듈을 로드시에 IP,ICMP 만 했기 때문이다. 모듈 로드를 아래와 같이 해 주어야 한다.

from scapy.all import sr1,IP,TCP,Raw

2. ARP 패킷 모니터링

네트워크 인터페이스에서 ARP 트래픽만을 모니터링 하는 코드를 보자. 앞서 소개한 Scapy 에서 패킷 덤프를 할때 sniff 를 사용 한다고 했다. sniff() 를 통해 패킷 덤프를 하되, filter 를 통해 arp 프로토콜로만 한정을 한다.
#!/usr/local/bin/python
from scapy.all import *

def arp_monitor_callback(pkt):
    if ARP in pkt and pkt[ARP].op in (1,2):
        return pkt.sprintf("%ARP.hwsrc% %ARP.psrc%")

sniff(prn=arp_monitor_callback, filter="arp", store=0)

arp_monitor_callback 이라는 함수를 정의하고 넘어온 pkt 에서 ARP 가 있으면 하드웨어 맥 주소와 출발지 주소를 sprintf 로 리턴해 주어 출력하도록 한 것이다. ARP 이외도 ICMP, TCP 등 여러분들이 원하는 형태로 지정만 하면 출력이 가능해 지는 것이다. 위 코드의 실행결과는 아래와 같다:

# ./arp.py
WARNING: No route found for IPv6 destination :: (no default route?)
00:e0:4d:41:fc:XX 192.168.0.221
00:01:36:2e:0b:XX 192.168.0.200
00:01:36:2e:0b:XX 192.168.0.200
00:e0:4d:41:fc:XX 192.168.0.221

3. 패킷 추출정보 파일로 저장하기
 
지정한 파일을 읽어들이고 Payload 부분만 저장해 보자. 이때 출발지 주소가 192.168.0.240 인 IP 로만 한정을 한다. 각 세부 동작내용은 아래 주석을 참고하자

#!/usr/local/bin/python
from scapy.all import *

src="192.168.0.240" # 출발지 IP 정의
pcap_file = "test3.pcap" # 읽어들일 PCAP 파일 정의
pcap = rdpcap(pcap_file) # rdpcap() 을 통해 pcap_file 을 읽어들임

data = "" # data 변수 초기화
for packet in pcap: # 읽어들인 pcap 파일을 루프돌면서 처리
  ilayer = packet.getlayer("IP") # getlayer 를 통해 IP 레이어를 ilayer 에 저장
  if ilayer.src != src: # 출발지가 192.168.0.240 이 아닌 경우 Skip
    continue
  tlayer = packet.getlayer("TCP") # TCP 레이어를 tlayer 에 저장
  if packet.getlayer("Raw"): # Raw 영역이 존재하면, payload 를 data 에 추가
  data += str(tlayer.payload)
f = open("raw_data.dat", 'w') # raw_data.dat 를 오픈하고 기록한다.
f.write(data)
f.close()

실행을 해 보면 raw_data.dat 가 만들어지고, 이 파일에는 Payload 만 저장된 것을 확인할 수 있다.

# hexdump -C raw_data.dat | more
00000000  47 45 54 20 2f 20 48 54  54 50 2f 31 2e 31 0d 0a  |GET / HTTP/1.1..|
00000010  48 6f 73 74 3a 20 67 6f  6f 67 6c 65 2e 63 6f 6d  |Host: google.com|
00000020  0d 0a 55 73 65 72 2d 41  67 65 6e 74 3a 20 4d 6f  |..User-Agent: Mo|
00000030  7a 69 6c 6c 61 2f 35 2e  30 20 28 58 31 31 3b 20  |zilla/5.0 (X11; |
00000040  55 3b 20 4c 69 6e 75 78  20 69 36 38 36 3b 20 65  |U; Linux i686; e|
00000050  6e 3b 20 72 76 3a 31 2e  39 2e 30 2e 31 39 29 20  |n; rv:1.9.0.19) |
00000060  47 65 63 6b 6f 2f 32 30  30 38 30 35 32 38 20 45  |Gecko/20080528 E|
00000070  70 69 70 68 61 6e 79 2f  32 2e 32 32 0d 0a 41 63  |piphany/2.22..Ac|
00000080  63 65 70 74 3a 20 74 65  78 74 2f 68 74 6d 6c 2c  |cept: text/html,|
00000090  61 70 70 6c 69 63 61 74  69 6f 6e 2f 78 68 74 6d  |application/xhtm|
000000a0  6c 2b 78 6d 6c 2c 61 70  70 6c 69 63 61 74 69 6f  |l+xml,applicatio|
000000b0  6e 2f 78 6d 6c 3b 71 3d  30 2e 39 2c 2a 2f 2a 3b  |n/xml;q=0.9,*/*;|
000000c0  71 3d 30 2e 38 0d 0a 41  63 63 65 70 74 2d 4c 61  |q=0.8..Accept-La|
...(생략)

즉, 필요한 부분만 얻어내서 파일로 만들 수도 있다. 패킷파일의 모든 부분을 출력시키거나 쉽게 저장할 수도 있으며, getlayer() 를 통해 원하는 레이어 영역으로 쉽게 접근할 수 있다.

4. HTTP 패킷을 처리하는 프로그램 형태를 만들어 보자.

조금 더 프로그램 형태를 갖춰서 HTTP 정보를 얻어내는 코드를 살펴보도록 하겠다. 여기 예에서는 기본적인 부분에 대해서 설명하고 있는 것이므로, 응용만 하면 원하는 형태로 쉽게 핸들링이 가능해진다. 이런식으로 사용할 수 있다는 것을 보여주기 위해 작성된 것이므로, 여러분들이 다양하게 응용해 보기 바란다.

#!/usr/local/bin/python
# PacketInside.com - Examples
import sys
from scapy.all import *

CNT = 10 # CNT 에 10 을 지정

def run(target):

    try:
        pkt = rdpcap(target, count=CNT) # 패킷파일을 오픈할때 10 개 까지만 읽어들인다.
    except MemoryError: # 패킷파일을 오픈하다 메모리 에러가 발생하는 경우 Exception 처리
        print "Sorry - Memory Error"
        sys.exit() # 메모리 에러를 출력하고 프로그램 종료
    numPkt = len(pkt) # pkt 의 길이를 numPkt 에 저장

    print "Analyzing : " + target
    print "Total Packets: %d\n" % numPkt # 전체 패킷의 Count 를 출력, rdpcap() 에서 count 를 사용하지 않을시는 전체 패킷 건수를 표시하나 카운트를 10으로 제한했으므로 항상 10이 됨

    for packet in pkt:
        layer = packet.payload
        while layer: # 각 레이어 별로 루프 돌면서 처리
            layerName = layer.name # 레이어 이름을 layerName 에 저장
            if layerName == "IP": # 만약 레이어 이름이 IP 인 경우 다음 내용 수행
                print "[IP Layer]\nSRC: %s, DST: %s" % (layer.src, layer.dst)
# 출발지 와 목적지 주소를 출력 함

            if layerName == "TCP": # 레이어가 TCP 인 경우
                print "[TCP Layer]\nSPORT: %s, DPORT: %s" % (layer.sport, layer.dport)
            if layerName == "Raw": # 레이어가 Raw 인 경우 ( Payload 가 됨)
                result = processHTTP(layer.load) # Raw 가 있는 경우 processHTTP 를 호출함
                if result != "Error": # 넘어온 결과가 Error 인 경우 에러 결과를 출력
                    print result[0] + " " + result[1]

            layer = layer.payload

def processHTTP(data):

    str_method = ""
    str_uri = ""

    # 정규표현식을 통해 넘어온 데이터에서 METHOD, URI, HTTP 버전 정보등으로 구분함
    h = re.search("(?P<method>(^GET|^POST|^PUT|^DELETE)) (?P<uri>.+) (?P<version>.+)", data)
    if not h: return "Error" # 정규표현식에 해당하는 데이터가 없는 경우 Error 를 리턴해줌

    # method 로 정의된 부준은 str_method 에 저장
    if h.group("method"): str_method = h.group("method")
    # URI 데이터는 str_uri 에 저장
    if h.group("uri"): str_uri = h.group("uri")

    return str_method,str_uri # method 와 uri 를 리턴해 줌

# call run
run("tt.pcap") # run 함수를 호출, 이때 읽어들일 pcap 파일을 같이 전달


실행된 결과는 아래 화면과 같다 :

패킷을 분석할 데이터가 많은 경우에는 클래스와 함수를 적절히 사용하여 프로그램을 작성하면, 더욱 효과적으로 사용할 수 있을 것이다.

여기서는 소개하는데 한계가 있기 때문에, 이 정도 선에서 마무리 하고자 한다. 기본적인 것들은 다 언급하였기 때문에 파이썬에 익숙한 분들이라면 어렵지 않게 패킷분석 프로그램을 만들 수가 있다. 물론, 분석 대상의 범위에 따라서 달라지겠지만 Scapy 모듈만을 이용해서 뚝딱 원하는 형태로 패킷을 다룰 수 있으므로, 유용한 도구임에는 틀림없다.  

세번째 소개 글은 프로그램 예제를 만들고 검증하다 보니, 여러분들한테 소개하기까지 늦어졌다. 요 근래, 필자를 괴롭히는 귀차니즘이 한 몫하기도 했다. :-)

Scapy 를 이용하려는 분들에게 조금이라도 도움이 되길 바라며 Scapy 소개를 끝마친다.

From Rigel.

2010년 11월 9일 화요일

안드로이드폰 취약점 테스트 결과 - 권한획득 OK !

몇일전 안드로이드 취약점에 대해서 포스팅을 하였다. 이제서야 테스팅을 해 보았는데, 제대로 동작을 잘 한다.
WebKit 의 취약점을 이용하는 것인 만큼, 사용자는 공격자가 만들어 놓은 웹 페이지에 접속하는 것만으로도
권한을 얻을 수 있는 가능성을 제공해 준다.

공격코드에 포함된 쉘 코드는 리버스쉘 코드로 원격에서 명령어 수행이 가능해진다. 일전에 안드로이드 폰의
IP 에 대해서 알아보았는데, 필자가 사용하는 것은 내부에서는 Private 주소를 사용하게 된다. 이 뜻은, NAT 개념과 같아서 외부에서는 내부 안드로이드 폰으로 접근이 현실적으로 쉽지 않다. 하지만, 리버스 쉘은 안드로이드 폰 자체에서 외부로 접속하는 것이므로 쉽게 우회가 가능해진다.

다음과 같은 형태로 테스트를 진행했다.

192.168.0.223 (안드로이드 폰) -> 192.168.0.240: 7777 (웹 서버)  로 접근하여 취약점 코드 페이지가 실행되고, 리버스 쉘 코드가 수행되어 다시 192.168.0.240 의 7777 번 포트로 연결이 되는 것이다. 접속되면 아래와 같이 연결이 된 것을 확인할 수 있다.

$ netstat -na | grep 7777
tcp        0      0 192.168.0.240:7777      192.168.0.223:54960     ESTABLISHED

다음은 접속화면의 예로, ls 명령어 수행과 df 를 한 결과이다.


ps 를 통해 프로세스의 결과 일부는 아래와 같고, 뒤에 id 를 통해 권한을 확인한 것이다.

app_40    3095  1201  668    324   c006e1b8 afe0d62c S ///system/bin/sh
app_40    3139  3095  668    324   c006e1b8 afe0d62c S /system/bin/sh
app_40    3147  3139  668    316   c006e1b8 afe0d62c S /system/bin/sh
app_40    3149  3147  2128   420   c006e1b8 0010d508 S /system/bin/busybox
app_40    3173  3149  816    336   00000000 afe0c75c R ps
id
uid=10040(app_40) gid=10040(app_40) groups=1015(sdcard_rw),3003(inet)

접속된 권한이 app_40 이므로, 실행된 각 프로세스는 app_40 을 갖고 있다.

이렇게 쉘 권한을 얻었다는 뜻은 무엇일까? 원하는대로 조작이 충분히 가능해 지는 것이다. 물론 권한 제약이 있지만, 이전에 공개된 root 권한을 획득하는 공격코드와 같은 것만 제대로 준비되면 이것또한 가능해 진다.

무엇보다도 이번에 공개된 취약점의 장점은, 현재 인터넷 상에서 많이 발생하는 웹을 이용한 형태의 취약점과
같이 안드로이드폰의 브라우저를 통해 특정 사이트를 방문하는 것 만으로 권한획득이 가능해 진다는 점에서
앞으로 안드로이드를 이용한 위험성에 대해서 더욱 깊게 고민해 봐야 될 문제이다.
사용자가 조작된 페이지에 방문하게 하는 것은 사회공학적 기법만을 사용해서도 어렵지 않게 끌어들일 수 있다.

참고로, 브라우저를 통해 접속된 후에는 브라우저가 Crash 되어 종료버린다.

이 글의 목적은 현재 공개된 안드로이드  취약점코드에 대해 위험성을 알리고자 하는 것이다. 악의적으로
이용되지 않기를 바라며, 앞으로 브라우저를 통한 웹 사이트 방문시에는 주의가 요구된다.
(* 안드로이드 2.2 에서는 패치가 된 상태이다.)

[관련 글]

2010년 11월 6일 토요일

웹 기반의 안드로이드 공격 코드 공개...주의!

웹 기반의 안드로이드 공격이 가능한 취약점이 공개되었다. 웹 환경에서 많이 발생하는 형태의
요즈음 공격방식과 같이 말이다. 몇일전에도 IE 취약점과 관련하여 0-day 취약점이 공개되어
주의가 요구 되고 있다.

최근 알려진 안드로이드 취약점은 WebKit 의 취약점을 이용한 것으로, 안드로이드 단말기에서
악의적 코드가 삽입되어 있는 사이트에 방문하였을 경우 임의의 코드가 실행될 수 있는 것이다.
이번 취약점은 CVE-2010-1807 로 사파리에서 발견된 버그인데, 그대로 안드로이드에서도 재현이 된다는 것이다. floating-point 데이터를 제대로 검증하지 않아 발생되는 것으로, 조작된 웹 페이지를 통해
임의의 코드 실행또는 애플리케이션 Crash 로 DoS 상태를 만들 수 있다.

<공격코드의 일부>  
for (i = 0; i <= 1000; i++)
        {
                if (i>999)
        {
        sploit(-parseFloat("NAN(ffffe00572c60)"));
        }
        document.write("The targets!! " + target[i]);
        document.write("<br />");
....(생략)

관련 취약점을 이용한 공격코드도 이미 Public 하게 공개되어 있어 주의가 요구된다.
안드로이드 2.2 버전 이상에서는 영향을 받지 않는다. 구글에 따르면 안드로이드폰 36.2%는 2.2 로 운영된다고 한다.

시간이 되는 대로 나의 안드로이드 단말기에서도 테스트 해 볼 예정이다.

어찌되었든 중요한 것은 모바일 단말기들에 대한 보안 위협이 점차 커지고 있다는 것이다. 특히나 이와 같이
조작된 웹 페이지를 방문하는 것만으로도 영향을 받을 수 있다는 것은 지금 현재의 컴퓨터에서 일어나는
보안 위협이 많은 부분 모바일에서도 나타날 수 있다는 뜻이 된다. 물론, 제한된 권한으로 완벽한 접근에는 한계가 있지만.. 루팅이 된 단말기라면 얘기는 달라진다. 또한 루트를 얻을 수 있는 취약점등을 이용해 원격에서도
가능해진다면 이것은 말 하지 않아도 추측이 가능할 것이다.


2010년 11월 1일 월요일

EMET(Enhanced Mitigation Experience Toolkit) 보안 설정도구 소개

인터넷을 사용하는 한, '보안' 이라는 부분에서는 안전해지기 어려운 것이 현실이다. 소프트웨어는 취약점에 계속 노출되어 있고, 인터넷이라는 연결을 통해 외부에서 누군가가 접근할 수도 있다.
대중적으로 많이 이용되는 인터넷 익스플로러와 같은 브라우저, 플래쉬, PDF 의 취약점이 계속 보고되고 있는 것도 이런 이유이다. 대중적인 것이기 때문에 위험에 더욱 많이 노출되어 있다.

사용하는 내 컴퓨터 시스템을 더욱 안전하게 사용할 수 있는 도구를 하나 소개해 보고자 한다. 마이크로소프트사에서 배포하는 Enhanced Mitigation Experience Toolkit 이 바로 그것이다. 현재 2.0 버전이며, 다운로드는 아래 '참고' 의 링크를 이용하면 된다.

다운받아 설치 한 후, 실행하면 아래와 같은 간단한 화면을 볼 수 있다.


DEP(Data Execution Prevention), SEHOP(Structured Exception Handler Overwrite Protection), ASLR(Address Space Layout Randomization) 상태를 볼 수 있고, 그 아래 화면은 프로세스별 적용 상태를 나타낸다.  이 DEP, SEHOP, ASLR 은 공격에 이용되는 주요 기술들을 차단해 주는 방법중에 하나이다. 여기서는 이 기법에 대해서 자세히 설명하지는 않겠다.

일단 EMET 를 한마디로 요약하자면 취약점으로 부터 시스템을 보호해 줄 수 있는 기능을 제공해 주는 것이다. 가장 좋은 방법은 프로그램 자체가 안전하게 코딩되면 좋지만, 우리가 사용하는 프로그램마다 안전한 방식을 기대하기란 어렵다. EMET 는 소스코드 같은 것이 없어도 프로세스단위로도 취약한 상태를 완화 시킬 수 있는 기능을 제공해 주므로 보다 안전한 환경을 원한다면 유용한 도구가 될 것이다.

예를 들어, 최근에 공개된 어도비사의 아크로뱃 리더를 이용한 취약점은 데이터 실행 방지 기술인 DEP를 우회하기 위해 ROP(Return Oriented Programming) 기법을 사용하고 있다. 일반적으로 이런 경우는 ASLR 기술이 적용되어 방지할 수 있지만, 해당 제품에서는 ASLR 을 사용하지 않고 있다. 그러므로 공격에 이용될 주소가 예측이 가능해진다. 하지만 ASLR 을 이용하면 취약점으로부터 안전해 질 수 있는 것이다.

어찌되었던 이 툴킷을 이용해 100% 완벽하게 지킬 수는 없지만, 각 기능을 사용하지 않는 것 보다는 충분히 안전한 환경을 제공해주는 것은 맞다. 사용하는 것도 간단하므로, 관심있는 사용자라면 한번 시도해 보는 것이 좋을것 같다.

Configure System 을 클릭하면 사전에 설정된 프로파일이 있으므로 생소한 분들은 다음 2가지중 하나를 선택하면 된다.

- Maximum Security Settings : 보안 설정을 최고로 원하는경우
- Recommended Security Settings : 보안 설정이 최고는 아니지만 권장하는 형태로 원하는 경우
(설정을 적용한 후에는 시스템 재 부팅이 필요하다)

설정을 다 적용한 경우에, 상황에 따라 시스템에서 동작하던 응용프로그램이 예외현상이 발생할 수 도 있다. 이런 경우는 정책을 제거하고 EMET 설정에 의해 발생한 것인지 확인해 보아야 한다.

참고로, 사용가능한 환경은 아래와 같다:

Client Operating Systems
• Windows XP service pack 3 and above
• Windows Vista service pack 1 and above
• Windows 7 all service packs

Server Operation Systems
• Windows Server 2003 service pack 1 and above
• Windows Server 2008 all service packs
• Windows Server 2008 R2 all service packs

[참고]
1. EMET 다운로드
2. EMET 2.0 소개
3. EMET 소개 동영상