libipq에서 패턴 DROP시 계속적인 네트워크 패킷 차단 문제
안녕하세요 저번에도 질문을 올렸는데 마땅한 해결책을 찾지못하여
다시한번 구체화 시켜 질문드립니다.
저는 http패킷을 검사하여 간단한 sql-injection 탐지및 차단 프로그램을 만들고 있습니다.
실제 탐지/차단프로그램은 이런식으로 사용하지 않지만 간단한 테스팅을 위하여 아래의 프로그램을 실행시키고
웹브라우저를 통하여 공격문장을 넣어놓은(패턴과 일치하는) 웹페이지에 접속하여 공격 탐지/차단 유무를 테스팅했습니다.
패턴과 일치하지 않을때에는(일반 웹페이지) 정상적으로 작동을 하며 웹브라우징을 할 수 있습니다.
문제는 고의로 공격패턴이 있는 웹페이지를 접속할때입니다.
정상적으로 패킷이 차단이 되고 웹페이지에서 그 문서를 볼 수 없지만 문제는 한번 패킷을 차단하면 계속적으로 차단이 된다는 점입니다.
(웹브라우저를 닫고 혹시나 몰라서 임시파일및 쿠키파일을 모두 삭제해도 말이죠)
그리하여 한번 공격을 탐지하여 차단하면 더이상 어떤 패킷도 통과되지 않습니다.
아래의 소스를 참고해보시면 아시겠지만 패킷의 내용을 담는 3개의 data부분은 분명히 loop을 돌때마다
초기화 되는 구조를 가지고 있습니다.
이런 현상을 겪다보니 한번 drop된 패킷이 커널에 남아있다가 다시 읽혀온다는 생각밖에 안드네요...
분명히 NF_DROP을 하면 커널에서 사라지게 되어있다고 man 페이지에 되어있는데말이죠....
이쪽 분야에 조애가 깊으신 고수님들 문제를 꼭 해결해 주실분이 있다고 믿고 있습니다.
부탁드리겠습니다
아래에 코드를 넣었습니다.
아주 대략적인 구조는 다음과 같습니다.
detect() { 정규화 매칭을 통하여 공격패턴과 일치하면 1 return 일치하지 않으면 0 return } main() { unsigned char buffer[BUFSIZE]={0,}; [생략] h=ipq_create_handle(0,PF_INET); [생략] status=ipq_set_mode(h,IPQ_COPY_PACKET,BUFSIZE); while(1) { case IPQM_PACKET: { ipq_packet_msg_t *m=ipq_get_packet(buffer); struct iphdr *iph=(struct iphdr *) m->payload; struct tcphdr *tcph=(struct tcphdr *) (m->payload)+(iph->ihl<<2); //tcp+ip 헤더의 길이 tcpip_len=(iph->ihl<<2)+(tcph->doff<<2); http_len=(unsigned int) ntohs(iph->tot_len)-((iph->ihl<<2)+(tcph->doff<<2)); //http_data와 printable_http 동적 메모리 할당 http_data=(unsigned char*)malloc(sizeof(unsigned char)*BUFSIZE); printable_http=(unsigned char*)malloc(sizeof(unsigned char)*BUFSIZE); //payload 메모리 복사 memcpy(http_data,(m->payload)+tcpip_len,http_len); for(i=0 ; i< http_len ; i++) { //프린트 불가능 if(isprint(http_data[i])==0) { printable_http[i]='.'; } else //프린트 가능 범위 { printable_http[i]=http_data[i]; } } if(detect()가 1이면) { status=ipq_set_verdict(h,m->packet_id,NF_DROP,0,NULL); } else { //이 프로그램이 packet 통과 유무를 판단한다! status=ipq_set_verdict(h,m->packet_id,NF_ACCEPT,m->data_len,m->payload); } }//switch case 끝 [다른 switch case문 생략] memset(buffer,(int)NULL,sizeof(buffer)); free(http_data); free(printable_http); }//while문 끝 ipq_destroy_handle(h); }//main끝
반환값 검사 반드시
반환값 검사 반드시 하시고요.
OTL
예
네.. bushi님 실제 소스에서는 반환값 검사를 했습니다.
반환값에서는 아무 이상없구요...
왜 이런일이 일어나는지 모르겠습니다.
관심가지고 답변 달아주셔서 너무 감사합니다.
답변을 기다리고 있었습니다.ㅠㅠ
올려주신 부분만으론
올려주신 부분만으론 모르겠습니다.
시험삼아 예전의 소스를 조금 고쳐서 해봤는데 말씀하신 증상 비슷한 것도 나타나지 않습니다.
DROP 이후에도 다른 패킷들 정상적으로 날아옵니다.
OTL
bushi님
그렇다면 제가 소스를 보내드려도 될까요??
이메일을 가르쳐주시면 보내드리겠습니다.
정말 발로 만든(?) 부끄러운 소스이지만 너무 답이 안나오네요...
허락해주신다면 보내드리겠습니다.
참 이상한 일입니다.
테스트 과정입니다.
테스트 과정입니다. 80 포트에 대해 hohohohahaha 라는 문자열을 검사하도록 했습니다.
아래 로그에서...
PASSed 는 tcp 가 아니거나 80 포트가 아니거나 데이타가 없는 패킷에 대해 accept 한 것.
ACCEPTed 는 금칙어가 포함되지 않은 패킷에 대해 accept 한 것.
DROPed 는 금칙어가 포함된 패킷에 대해 drop 한 것.
을 뜻합니다.
DROP 처리한 패킷들은 dopped_packets.txt 에 기록됩니다.
첫번째 시도는 금칙어 없는 정상적인 요청을 했습니다.
이은 두번째 시도는 금칙어가 포함된 공격성 요청을 했습니다.
패킷 몇 번 걸려나온 후 브라우저에서 ESC 를 눌러 강제로 탐색 중지를 했습니다.
이은 세번째 시도는 다시 금칙어가 없는 정상적인 요청을 했습니다.
세번째 시도의 로그를 보면 아시겠지만,
중간에 ACCEPT 된 패킷 외에 마지막에 DROP 된 패킷도 있습니다.
브라우저에 페이지가 이상없이 표시된 걸로 봐서,
이 DROP 된 패킷은 이전의 시도가 계속되고 있는 것으로 생각됩니다.
ESC 를 눌렀음에도 브라우저의 어디에선가 retry 를 계속하고 있거나,
클라이언트측의 네트웍에 남아있던 것이 뒤늦게 날아오는 것이 아닐까 싶습니다.
마지막 두 개의 패킷을 dropped_packets.txt 에서 보면
와
입니다. 확실히 금칙어로 정한 hohohohahaha 가 request 에 포함되어 있습니다.
다른 사람 소스 보는 것은 이미 지치도록 하고 있는 일이라 사양하고 싶고요,
자신의 소스를 보면서 처음부터 다시 하나씩 하나씩 짚어보세요.
제대로 동작할 때 까지.
OTL
요새 시간이 좀
요새 시간이 좀 나서..
전에 질문하셨던 regex 집어넣고 url unescape 는 어디서 줏어와서 집어넣고..
list.h 는 전에 올리신 질문 글에 달린 댓글에 첨부되어 있습니다.
OTL
일단, 그 이후에 계속
일단, 그 이후에 계속 차단된다는 것은 좀 이해하기 어렵네요. 일단, 한가지 예상되는 문제점은 NF_DROP만 처리 하신다면, 웹 브라우저는 해당 패킷에 대해서 ACK가 오지 않기 때문에, 계속적으로(무한은 아니겠지만요) retransmission을 보내게 되겠지요. 해당 세션에 대해서 일단 확실하게 처리를 해보시는 것도 하나의 방법일 거 같습니다. 즉, rst or fin 패킷을 생성해서 server, clinet 모두에게 전송해서 해당 세션을 종료시키도록 해보시면 될 거 같습니다.
------------------------------------------------------
아직은 젊다. 모든 것을 할 수 있는 나이란 말이지.
------------------------------------------------------
아직은 젊다. 모든 것을 할 수 있는 나이란 말이지.
댓글 달기