웹쉘 스캔 2 - 현승군




아래 현승군이 긴 댓글을 썼길래, 답글을 쓰다보니 저도 길어져서 ;;
새 글로 씁니다.

원문,

흠.. 가장 간단한 방법중의 하나라고도 볼 수 있겠지만..^^;;
효율성을 감안한다면.. 텍스트 기반의 타겟에 대한 스트링 매칭은..
그다지 좋은 방법은 아니죠..^^;;;;
위에서 "XpCmdShell"로 잡았는데~
"XPCmdShell" 이나.. "xpCMDShell"로 바뀌면 못잡을 뿐더러..
극단적인 가정으로 위해가 없는 쉘이 우연찮게 "XpCmdShell"을 갖고있다;;
이러면 또 문제가 될 수 있죠..^^;;;
스크립트 형식(텍스트기반)의 경우에는.. 특정 문자열보다는
구문 형식(?)을 잡는게 좀 더 어렵지만.. 더 효과적인듯..;;
위의 소스중에서 예를 들자면..
"todo = Trim(Request.Form("todo" ));" 이걸 패턴에 추가한다 쳤을때;;
todo 란거는 얼마든지 변경이 가능한 이름이죠~
이런 경우를 감안해서~~
"이름 = Trim(Request.Form("이름" ));" 이런 식으로..;
구문자체를..ㅋ;
=0=;;; 사실 이것도 말처럼 만만한 구현은 아닌..;;;
텍스트라는 것의 특성상... 코드의 위치등.. 유동성도 감안해야하기에;;
.
.
ㅋㅋ.. 저런 웹셸을 전문적으로 찾아내는 엔진을 만드는게 아닌 이상..;;
스트링 매칭도 뭐;;..


화면에 보이는 캡쳐는 페이지의 한 부분일 뿐이고
물론 구문이나 코드 같은 것도 넣어두었지.
예를 들어 다음과 같은 부분도 패턴으로 들어 있지.

 If LCase(cmdPath)="wscriptshell" Then    
  cmdResult=doWsCmdRun(cmdStr)

하지만 어차피 텍스트기반의 스크립트는 문자열이나 구문이나 똑같이 취급되기 때문에
XpCmdShell을 xpCMDShell로 바꿀 수 있다면
todo = Trim(Request.Form("todo")); 이거를
todo=Trim(...) 으로 공백을 없애서 우회하는것도 가능하겠지 ㅋㅋㅋ

그리고 니 말대로 이름 부분을 don't care 처리하는 것도 어렵지 않지.
그러면 이름 부분에는 어떤 문자열이 들어가도 디텍팅이 될테니까
우리가 잘 아는 솔루션 처럼 ^^
하지만 굳이 그럴 필요도 없고,
왜냐면 돈트케어를 필요로 할 만큼 지능적인 코드를 패턴으로 뽑는 귀찮은 짓도 하기 싫고
또 구문 자체를 넣으면 그만큼 비교하는 바이트 수가 늘어나니 속도도 저하되고

그리고 최종 디텍팅 된 결과물은 사용자가 리스트를 확인후 직접 대조할테니
오탐에 대한 염려도 별루 없지
그리고 웹 소스 파일에 xpcmdshell이라는 문자열을 쓰는 넘이 정상 넘일까 -.-?

난 백신 개발자가 아니거든 ^^
다만 비슷하게는 만들 수 있고, 또 보안 솔루션 개발을 했다면 이정도 구현은
아무나 다 할 수 있다고 봐. 못하면 그사람이 이상한거지 -.-
하지만 그게 백신들에게 좀 덜 되어 있으니까 간단하게나마 구현을 해본거고
백신들이 잘 되어 있다면 당연히 그걸 쓰겠지 ^^

하지만 실제로 웹쉘의 디텍팅을 휴리스틱하게 구현하기는 쉽지 않은 거 같아.
일단 희안한 기능 만들기로 유명한 카스퍼스키가 저렇게 패턴 매칭으로 진단하는 것 자체부터
갸들도 뚜렷한 대책은 없다는 거겟지..

앞으로 어떤식으로 백신 엔진을 개량해줄지는
백신 개발자들이 잘 알겠지 :)

Posted by window31


트랙백 보낼 주소 : http://window31.com/trackback/70 관련글 쓰기

댓글을 달아주세요

  1. 2007/10/22 10:52
    댓글 주소 수정/삭제 댓글
    웹쉘 = 짱게 :)
    나는 왜 이런 공식이 성립될까?

    웹쉘도 우짜피 스크립트이기 때문에 파싱을 하던지... 병탁군이 하듯이 바이너리 비교하는 방법도 좋은 방법이지. 가끔씩은 단순한 방법이 최고의 알고리즘인듯... 단, 모두 소문자로 변경해서 검색해 주는 센스! 보통의 텍스트는 대문자가 수가 더 많기 때문에 소문자로 모두 변경하는 시간이 짧거덩..

    결론, 짱게 시려..
    • 2007/10/23 09:34
      댓글 주소 수정/삭제
      오타쟁이...ㅠㅠ
      내가 쓴글을 읽어 보니깐 오타가 있네.. 흠..
      대문자가 수가 더 적은건데.. 즐무~
    • 2007/10/24 09:54
      댓글 주소 수정/삭제
      스캔엔진 공부할때 자네가 만든 엔진이 많은 도움이 되었네 ^^
      물론 바이너리로 본거라 감으로 느낀게 반 이상이지만 ㅠ ㅠ
  2. 2007/10/22 11:13
    댓글 주소 수정/삭제 댓글
    ㅋ.. 이런식으로 댓글에 대한 포스팅이 하나 올라오는건 재밌네요..
    저번 댓글에서 언급을 안한부분이 있는데..
    ^^;; 구문형식을 검사한다는게.. 단순히 문자열을 비교한다는건 아니었어요;
    음.. 뭐랄까.. 위에서 상완이형이 언급한 파싱의 개념이 들어간다고 해야되나..
    todo = Trim(Request.Form("todo" ));
    이거 같은 경우는..
    "변수이름", '=', 'Trim', '(', 'Request.Form', '(',
    '"변수이름"', ')', ')', ';'
    이런 식으로.. 분해해서 그 조합을 체크한다는거죠..^^;;;
    그렇게 체크를 하면.. todo=Trim(...); 이런 식으로 바꾸는건..
    의미가 없잖아요~^^;;
    ㅋ.. 실제 백신들에서 어떻게 처리를 하는지는 본적도 없고.. 모르니까..;
    살짝 재껴두고.. 걍..^^;; 생각나는 방법에 대해서 얘기해 본거였음..ㅋㅋ;
    웹셸을 감지하는 쪽에서 효율성을 따진다면.. 파싱쪽으로 가야겠지만..
    사실..-0- 그런 엔진을 구현하는게 만만치는 않다는거고;;ㅋ
    빨리 빨리.. 대응을 하는 쪽으로 효율성을 생각한다면~
    스트링 매칭도 괜찮다고 생각해요~ㅋㅋ
  3. 2007/10/23 11:20
    댓글 주소 수정/삭제 댓글
    비밀댓글입니다
    • 2007/10/24 10:02
      댓글 주소 수정/삭제
      실제로 카스퍼스키도 니가 말한 파싱을 이용하는 거 같아.
      그래서 카스퍼스키가 잡아대는 패턴만 뽑아서 따로 파일에 저장했을때
      그건 진단하지 않는다는 것이 좋은 증거지.

      실제로 정확한 진단을 위해서는 파싱이 가장 좋긴 하지만
      일단 속도 문제가 있지
      머 프로세스만 스캔한다 치면 DLL도 합쳐봤자 몇개안되니까
      별의별 방법을 다 쓸 수 있지만
      웹쉘은 일단 프로세스 형태가 아니잖아 :)

      그리고 바이너리의 조합도 바이패스적인 측면을 생각한다면
      쉽게 우회할 수 있는건 마찬가지야 ㅋㅋ
      어차피 스크립트니까 어디 진단하는지는 삭제하면서 확인해도 금방 알아낼 수 있고
      그냥 난 단순한 방법으로 가장 빨리 걸러낼 수 있는 구현을 한거지
      또 아무나 다 할 수 있는 방법이고 :)
      빨리 많은 패턴도 넣을 수 있고
      파싱으로 구현해놓으면 패턴 뽑기도 시간 오래 걸리고
      떨거지 웹쉘을 최대한 빨리 진단하려는 것이 목적이지

      물론 돈 받고 파는 상용솔루션을 만든다면 얘기는 달라졌겠지만 ^^
  4. dkwkwkr
    2008/10/29 17:43
    댓글 주소 수정/삭제 댓글
    어차피 원론적인 접근이겠지만 오탐이 아주 심한게 아니라면
    일단 적용해서 파싱까지는 확인하지 않더라도 단순 키워드로 잡는 것도
    괜찮은 방법이라 생각합니다. ^^

BLOG main image
by window31

카테고리

분류 전체보기 (281)
Reverse Engineering (21)
C, C++ (20)
Kernel (8)
Guitar (19)
잡담 (77)
etc (8)
who am i (8)
보안 이야기 (88)
Tools (3)
월간 마이크로소프트웨어/그.. (28)

글 보관함