본문 바로가기

[PROGRAMMING]/▶Python

Python기반 웹크롤러 및 스캐너 개발

※ 주의사항

아래 공격 코드는 연구 목적으로 작성된 것이며, 허가 받지 않은 공간에서는 테스트를 절대 금지합니다.

악의 적인 목적으로 이용할 시 발생할 수 있는 법적 책임은 자신한테 있습니다. 이는 해당 글을 열람할 때 동의하였다는 것을 의미합니다.

해당 문서의 저작권은 해당 프로젝트 참여 저자들에게 모두 있습니다. 외부에 공개시 법적 조치가 가해질 수 있습니다.

 

소스하이라이팅

http://cafe.naver.com/boanproject/book3608946/6573

개요

파이썬 기반으로 제작한 웹사이트 크롤링입니다.

개발한 목적은 웹사이트 점검시 수동점검과 자동점검을 진행하게되는데 스캐너같은경우는 스레드갯수만 조절이 가능하고 초당 리퀘스트 갯수를 조절 할 수가 없습니다.

또한 파로스나 burpsuite같은경우 크롤링기능을 사용할 수 있는데 크롤링할때 내가 원하는 페이지만 크롤링이 불가능합니다.

ex)www.test.com 이면 test.com만 크롤링하면되는데 http://www.test.com내의 www.pentest.com 의 링크가있을경우www.pentest.com url까지 모두 크롤링을 합니다.

그리고 마찬가지로 초당 리퀘스트설정이 없기때문에 과부하에 민감한 운영사이트에는 사용을 할 수가 없습니다.

그래서 python기반으로 초당 리퀘스트 세팅을 설정하고 점검사이트만 크롤링이 가능하도록 개발하였습니다.

그리고 원래 목적은 크롤링으로 개발하는 거였으나 크롤링을 완료하고 난 후에 주민등록을 검출할 수 있는 기능을 추가하였습니다.

이뿐만아니라 추후에 xss,sql injection 등등의 추가 모듈을 개발하여 적용하여 사용이 가능합니다.

 

 

 

 

 


테스트 환경 (해당 될시에만)

 운영 체제 (OS) : windows7, 가상 웹사이트


 

동영상 시연

본문 테스트 크기 10pt , 글꼴 (Verdana)

 

상세 분석

 

 

[그림.1]

 

알고리즘의 상단은 로그인하는 부분이고 하단은 크롤링기능을 하는 부분입니다.

 [그림.2]

 

그림2의 1,2,3의 URL을 수집합니다.

1번URL은 로그인 하기전의 Main page URL이고 2번은 로그인을 할때 Request보내는 URL입니다.

그리고 마지막으로 3번은 로그인을 완료하고 나온 다음페이지의 URL입니다.

총3가지의 URL을 수집합니다.

 

 [그림.3]

 

수집한 URL을 1.login 메뉴를 통해 입력합니다.

여기에서 가운데 URL을 보면 ID와 PASS 파라미터가 있습니다.

저렇게 입력을하게되면 저부분을 통해서 통으로 Request보내는 방식이 아닙니다.

저부분은 나중에 Mechanize 모듈을 이용하여 로그인 페이지의 Form을 찾고 Form 안의 태그에서 type='text'와 type='password'부분을 찾게됩니다.

자세한 과정은 이후에 설명하겠습니다.

 

 [그림.4]

 

그림.3번 과정을 거치고나면 2번메뉴를 세팅해야합니다.

2번메뉴는 프록시를 세팅하는 부분인데 이부분을 만들어 놓은 이유는 내부망에서 외부망으로 접속을할때 프록시서버를 경유하도록 하는 곳에서는 프록시를 설정 해야만 접속이 가능합니다. 프록시 세팅을 하지 않는다면 인터넷을 사용할 수 없습니다.

이러한 문제점을 해결 하기위해 프록시를 세팅할 수 있도록 기능을 만들었습니다.

프록시 세팅은 적용/미적용 으로 설정하여 사용이 가능합니다. 

 

 

 

 [그림.5]

 

프록시 세팅을한 후 3번메뉴 crawl start메뉴로 이동하면 ID와 PW를 입력할 수 있도록 나오게 되는데 이부분은 그림.5의 중간부분의 빨간 박스를 보면 각각 id, pass,, 0을 확인 할 수 있습니다. 

 

[그림.6]

 

우선 form 형식을 모두 리스트 형식으로 가저오고 가저온 폼안에 type='password'가 있는 리스트 데이터를 찾습니다.

그리고 해당폼에서 폼네임 Name='login_chk.asp' 값을 가저옵니다.

그리고 가저온 폼값에서 type='passwrod'를 찾고 이 위치를 중심으로 이값을 center라고 세팅한다고 가정합니다.

그리고 form 값 내의 center 에서 제일 가까운 type='text'를 찾습니다.

이렇게 하는 이유는 폼값내의 type='text'가 여러개 존재할 가능성도 있기 때문에 type='passwrod'에서 가장 가까운 type='text'는 99% 아이디를 입력받는 input 태그입니다. 

그렇기 때문에  center위치보다 작은 type='text'를 갖고있는 input 태그중에 type='password'와 가장 가까운 input 태그인것을 id를입력받는 폼으로써

해당태그의 name='' 값을 얻게됩니다.

그래서 얻게되는 값이 id, pass, login_chk.asp 가 되는것입니다.

이렇게 FORM/ID/PW 를 가저오는 이유는 Mechanize라는 python에서 사용되는 모듈을 사용하여 로그인 시스템을 구축하기 위해서입니다.

Mechanize를 사용해서 로그인을 할때는 반듯이 로그인 페이지의 Form값을 얻어와야합니다.

만약에 Mechanize에서 Form값을 인식을 하지 못할 경우에는 nr=0 또는 nr=1 와 같은식으로 0번째Form 첫번째Form을 지정하여 사용할 수 있습니다.

하지만 이렇게 간단히 되면 좋은데 그렇지 않습니다.

간혹 Form Name이 있는데도 불구하고 해당 html페이지의 폼값을 인식하지 못하는 경우가 있습니다.

이럴때를 대비해서 Urllib2 모듈을 사용하여 예외처리를 하는방식으로 결정했습니다.

하지만 Urllib2를 이용해서 로그인하는 방식은 로그인처리만 해놓고 크롤기능까지 가능하도록 구현은 하지않은 상태입니다.

언제든지 필요하면 구현가능 하지만 다른도구를 만들어 보고싶은게 있어서 아쉽지만 로그인 예외처리 방식은 잠시 보류합니다. 

 

 [그림.7]


이제 ID/PW를 입력하고 정상적으로 로그인이 되었는지 확인합니다.

그림.7번의 기능은 그냥 디버깅 확인용으로 구현한것입니다.

정상적으로 로그인 된 것을 확인 할 수 있습니다.


  [그림.8]

 

로그인을 성공하게 되면 크롤링이 몇초에 한번씩 request를 할것인지에 대한 설정을 할 수 있습니다. 

제가 점검용으로 사용할 크롤러를 만들기 위한 이유중에 한부분입니다.

보통 크롤러나 스캐너같은 경우 타켓사이트에대한 타임세팅을 할 수 없습니다.

스캐너같은경우는 스레드 설정은 가능하지만 역시 초당 리퀘스트 세팅을 할 수 없습니다.

그렇기 때문에 간혹 점검 하다보면 서버 과부하 문제로 자동툴사용을 금지요청을 하는경우도 있습니다.

하지만 리퀘스트당 초단위로 세팅하여 크롤링속도를 조절한다면 이러한 문제를 해결할 수 있을거라 생각했습니다.

시간이 조금 걸리겠지만 2초에 한번씩 리퀘스트를 해서 그 결과를 얻을 수 있다면 수동작업과 점검시간을 줄일 수 있을것입니다.

 

  [그림.9]


time setting을 마치고나면 본격적으로 크롤링을 시작하게됩니다.

그림.9을 보면 Request했을때의 에러가 발생하면 해당되는 URL에대한 HTTP ErrorCode를 추가했습니다.

그리고 정상적으로 존재하는 URL즉 Request에 성공한 URL은 Connect Success라는 명령어로 표시했습니다.

그리고 Request하고 Response하여 얻은 html페이지중에 하이퍼링크나 히든속성의 파라미터가 없을경우 None html page link이고

URL overrab은 html페이지에서 가저온 URL들중 중복된 URL입니다.

 

[그림.10]

크롤링의 간단한 원리는  그림.2번의 3번URL(Main) 부터 시작을 합니다.

메인 URL의 모든 하이퍼링크를 가저와 리스트형태로 저장합니다.

그리고 Hidden속성의 파라미터값과 value값을 결합합니다.

결합 후 현재 html을 불러온 url과 결합한 히든값을 재결합 합니다. 

즉 www.test.com + a=1&b=2 와 같이 결합니다.

하지만 이렇게 처리하려면 예외처리를 많이해야합니다. 물론 예외처리까지 어느정도 해놓은 상태이구요

예로들자면 www.test.com 의 url인경우와 www.test.com/ba/,www.test.com/ba 인경우 www.test.com/ba/login.asp? 등등의 경우라면 예외처리를 해야합니다.

www.test.com/ba + a=1&b=2 인경우 결합하게 되면 www.test.com/baa=1&b=2 와같은 url이완성이되며 이처럼 없는 url을 만들어냅니다.

그렇기 때문에 정상적인 url이 되도록 예외처리가 진행이 되어야합니다.

 


 

  [그림.11]

 

 크롤링의 동작순서는 첫번째 모든 하이퍼링크를 수집합니다. 그리고 수집하면서 히든속성의 값들을 URL로 구성하여 보관합니다.

이처럼 URL 을 수집합니다.

수집되는 URL중 중복되는 URL은 제외하고 하고 하이퍼링크URL을 Request 합니다.

그리고 종료되면 히든속성을 결합한 URL을 Request합니다.

이 두 과정이 진행될때 Request한적이 없는 URL만 추가로 수집하고 다시 Request하는 방식입니다.


  [그림.12]


히든속성으로 재결합된 URL이 크롤링을 마치면 각각의 결과들을 HTML페이지로 저장합니다.

그리고 제가 추가로 구현한 기능입니다.

보통 스캐너들에서 검출되는 주민등록번호라고 확인을해보면 죄다 가짜입니다.

그냥 숫자형태와 주민번호형태로 13자리이면 무조건 가저오는것 같습니다.

결론은 xss나 injection취약점에 대해는 잘 찾는 편이지만 그 외의 기능은 성실히 구현한것 같지않은 느낌이 듭니다.  

이것은 어디까지나 제가 사용해본 스캐너 경험담입니다. ㅋ 뭐 제각각입니다. xss/injection등도 오탐이 무지많은 멍청한 스캐너들도 많구요 ㅋ

각설하고 아무튼 수집된 URL을 대상으로 해당되는 페이지에 주민등록번호 유형의 숫자가 있을경우 수집을 합니다.

수집을 한 후 주민등록 검증방식으로 실제 사용되는 주민등록번호인지 가짜 주민번호인지 검증을 하게됩니다.

검증 결과는 실제 주민등록번호일경우 Original ok로 나오며, 가짜 주민번호일경우 Imitation false 로 표시했습니다.

 

  [그림.13]

로그형태로 한번보여주고...

 

  [그림.14]

 역시 스캔결과를 HTML페이지로 저장해줍니다.

scanresult.html을 오픈하면....

 

 [그림.15]

 

해당 결과에 대한 페이지를 그림과같이 보여줍니다.

실제 해당 페이지에 대한 링크를 클릭하면 어느위치에서 발생된 정보인지 쉽게 확인할 수 있구요
이와같이 추가모듈을 시험삼아 적용해 보았습니다.

물론 이외에 XSS/INJECTION 과같은 패턴을 모듈로 개발해서 붙이면 그럴듯한 스캐너가 될것같습니다.