Menu

[r13]: / NomNomAgent.py  Maximize  Restore  History

Download this file

335 lines (294 with data), 10.3 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
#!/usr/bin/env python2
#
# NomNom Agent v0.1 PreAlpha
#
# Author(s): Pasv (pasvninja [at] gmail[dot]com)
# Licensed under: GPLv3
#
# TODO: import ConfigParser ? or will this project not need
#
from scapy import *
import sys
import os
import string
import socket
import select
import threading
import sqlite3
import re
import time
import getopt
DEBUG=True
DEBUGFILE=False
DEBUGFH=False
SQL_INJECTION_TEST=False
LOGDIR="/tmp/nomnom.log"
SQLDB="/tmp/nomnom.db"
id=0
# Constants:
T_IDCLIENT, T_IDSERVER, T_GET, T_POST, T_TITLE, T_COOKIE, T_SETCOOKIE, T_CSERVER, T_CCLIENT, T_SSERVER, T_SCLIENT, T_COMMAND = range(12)
def debug(msg):
msg = time.ctime() + ":*:" + msg
if DEBUG:
print msg
if DEBUGFILE:
os.write(DEBUGFH.fileno(), msg+"\n")
return
# end of debug()
class loggingThread(threading.Thread):
def __init__(self,readpipe):
self.readpipe=readpipe
threading.Thread.__init__(self)
def run(self):
debug("[+] started logging...")
# this might be CPU expensive, switch to select method later
fileexists=os.path.exists(SQLDB)
self.sqlfh=sqlite3.connect(SQLDB)
self.cur=self.sqlfh # self.sqlfh.cursor()
if(not fileexists):
self.init_sql()
while True: # cant be blocking, thus select
(r,w,x)=select.select([self.readpipe],[],[])
if(r):
try:
sqlquery=os.read(self.readpipe, 8000)
debug("READ THIS FROM PIPE:" + sqlquery)
(id,datatype,tolog) = re.split(":", sqlquery, 2)
#debug("sending: %d; type: %d; data: %s" % (id,datatype,tolog))
if(self.log(id,tolog,datatype)):
debug("[+] SQL query successful: " + sqlquery)
except:
#debug("[-] found an exception in reading from pipe, aborting")
continue
def check_for_injection(self, sqlquery):
# TODO, but for now..
return False
def log(self, id, query, infotype):
debug ("logging query:" + query)
# TODO: check these queries against the sqlite3 cli client
if(check_for_injection(query,id,infotype)):
debug("[*!*] SQL injection detected, aborting: " + query)
# return False
elif(infotype == T_IDCLIENT):
debug("Doing an T_IDCLIENT")
self.cur.execute("INSERT INTO PacketsFromClient VALUES(?,null,null,null,null,null);", (query,id))
elif(infotype == T_IDSERVER): # creates the initial entry
self.cur.execute("INSERT INTO PacketsFromServer VALUES(?,null,null,null,null);", (query,id))
elif(infotype == T_TITLE):
self.cur.execute("UPDATE PacketsFromServer SET Title=? WHERE id=?", (query,id))
elif(infotype == T_COOKIE):
self.cur.execute("UPDATE PacketsFromClient SET Cookie=? WHERE id=?", (query,id))
elif(infotype == T_CSERVER): # CCLIENT stands for Client's CLIENT (hackish: clean!)
self.cur.execute("UPDATE PacketsFromClient SET Server=? WHERE id=?", (query,id))
elif(infotype == T_CCLIENT):
self.cur.execute("UPDATE PacketsFromClient SET Client=? WHERE id=?", (query,id))
# ushiro no do: (strings are not escaped)
elif(infotype == T_COMMAND and SQL_INJECTION_TEST == True):
self.cur.execute("UPDATE PacketsFromClient SET Cmd=%s WHERE id=%s" % (query,id))
else:
debug("[-] unrecognized infotype")
return False
self.sqlfh.commit()
return True
def log2server(self, query):
pass
def init_sql(self):
debug("[+] Initializing database")
self.cur.execute("""CREATE TABLE PacketsFromServer (id INTEGER PRIMARY KEY, Server VARCHAR(50), Client VARCHAR(50), SetCookie VARCHAR(200), Title VARCHAR(100));""")
self.cur.execute("""CREATE TABLE PacketsFromClient (id INTEGER PRIMARY KEY, Server VARCHAR(50), Client VARCHAR(50), Cookie VARCHAR(200), PostQuery VARCHAR(200), GetQuery VARCHAR(200));""")
self.sqlfh.commit()
# End loggingthread() class
# This thread will communicate with the proxy and accept commands
# is this method acceptable????
# TODO: add error/exception checking to the socket stuff
class proxycontrolThread(threading.Thread):
def __init__(self,host,port):
self.host=host
self.port=port
self.soc=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.to_write = False
threading.Thread.__init__(self)
def run(self):
if(not self.host):
pass
else:
self.host=self.host
self.soc.connect((self.host, self.port))
# If cant connect go sleep() and then come back try it again
self.soc.setblocking(0) # is this a good idea? hmmm
while True:
(r,w,x) = select.select([self.soc],[self.soc],[self.soc])
if(r):
self.read_from_proxy(self.soc)
if(w and self.to_write):
self.write_to_proxy(self.soc)
#if(x): ???
# check if socket closed here, do some cleanups
def write_to_proxy(soc):
pass
def read_from_proxy(soc):
# data= read(.... yadda yadda
# parsing it out: (make a better splitter too later..?)
sqlquery=re.split(":*:", data, 3) # maybe not 3 tho....
def sql_query(Want, From, Variable, Value):
return "SELECT %s FROM %s WHERE %s=%s" % (Want, From , Variable, Value)
# End proxycontrolThread() class
# TODO:
# -check and make sure all the ID shit is set well init functions and finish up logging
# - move on to making the connection for the NomNom Proxy (pipe commands to log/and insert auditing
# - maybe even authentication later between Agent-Proxy : PSK? encryption(AES?)?
class sniffer():
def __init__(self,device):
self.device=device
self.id_base = 0
def run(self):
if(not self.device):
sniff(prn=self.handle_packet,filter="tcp port 80",store=0);
else:
sniff(iface=self.device, prn=self.handle_packet,filter="tcp port 80",store=0);
def make_id(self,pkt):
#todo int() these
ip_id=pkt.sprintf("%IP.id%")
tcp_seq=pkt.sprintf("%TCP.seq%")
tcp_ack=pkt.sprintf("%TCP.ack%")
# think of a better one soon...
# return((tcp_seq & tcp_id) - %TCP.ack%)
# or even incremental mode would just work...
self.id_base += 1
return(self.id_base)
def handle_title(self,id,pkt,offset):
debug("[] handling a <title> tag at " + str(offset))
pktcopy=str(pkt)[offset:]
end=pktcopy.find("</title>")
title=pktcopy[7:end]
self.pipe2log(id, T_TITLE, title)
def handle_setcookie(self,id,pkt,offset):
debug("[] handling a Set-Cookie: header at " + str(offset))
pktcopy=str(pkt)[offset:]
cookie=""
while pktcopy.find("Set-Cookie:") >= 0:
end=pktcopy.find("\r\n")
cookie+=pktcopy[12:end]
debug("[] set-cookie len: " + str(len(cookie)))
debug("[] set-cookie:" + cookie)
pktcopy=pktcopy[end:]
self.pipe2log(id,T_SETCOOKIE,cookie)
def handle_get(self,id,pkt,offset):
debug("[] handling a GET request at " + str(offset))
end=str(pkt)[offset:].find("\r\n")
getquery=str(pkt)[offset+4:offset+end]
self.pipe2log(id, T_GET, getquery)
def handle_post(self,id,pkt,offset):
debug ("[] handling a POST request at " + str(offset))
end=str(pkt)[offset:].find("\r\n")
postquery=str(pkt)[offset+5:offset+end]
self.pipe2log(id, T_POST, postquery)
def handle_cookie(self,id,pkt,offset):
debug("[] handling a Cookie: header at " + str(offset))
pktcopy=str(pkt)[offset:]
cookie=""
while pktcopy.find("Cookie:") >= 0:
end=pktcopy.find("\r\n")
cookie+=pktcopy[8:end]
debug("[] cookie len: " + str(len(cookie)))
debug("[] cookie:" + cookie)
pktcopy=pktcopy[end:]
self.pipe2log(id, T_COOKIE, cookie)
# This is from the server
def handle_from_http(self,id,pkt):
#debug("[] handling packet from HTTP server..")
self.pipe2log(id,T_IDSERVER,id)
offset=str(pkt).find("<title>")
if (offset >= 0): # found title
self.handle_title(id,pkt,offset)
offset=str(pkt).find("Set-Cookie:")
if (offset >= 0):
self.handle_setcookie(id,pkt,offset)
# This is from the browser
def handle_to_http(self,id,pkt):
#debug("[] handling packet from HTTP client..")
self.pipe2log(id,T_IDCLIENT,id)
self.pipe2log(id,T_CCLIENT,pkt.sprintf("%IP.src%"))
self.pipe2log(id,T_CSERVER,pkt.sprintf("%IP.dst%"))
offset=-1
offset=str(pkt).find("GET ")
#if(offset != -1):
# self.handle_get(id,pkt,offset)
offset=-1
offset=str(pkt).find("POST ")
if(offset != -1):
self.handle_post(id,pkt,offset)
offset=str(pkt).find("Cookie: ")
if(offset != -1):
self.handle_cookie(id,pkt,offset)
# might be diff for win32
def pipe2log(self,packetid, datatype, query):
(r,w,x)=select.select([],[writepipe],[])
if(w):
try:
os.write(writepipe, "%d:%d:%s" % (packetid,datatype,query))
except:
debug("couldnt write to pipe!")
else: # wtf
pass
def handle_packet(self,pkt):
id=self.make_id(pkt)
if(SQL_INJECTION_TEST == True):
if(str(pkt).find("SQL_INJECTION_TEST") >= 0):
self.pipe2log(id, pkt.payload(), T_SQL) #change
if(pkt.sprintf("%TCP.dport%") == "www"):
self.handle_to_http(id,pkt)
elif(pkt.sprintf("%TCP.sport%") == "www"):
self.handle_from_http(id,pkt)
else:
debug("neither protocol: source: %s dest: %s " % (pkt.sprintf("%TCP.sport%"),pkt.sprintf("%TCP.dport%") ))
# end sniffer class
def usage():
print " NomNomAgent.py Usage:\n"
print "./NomNomAgent.py [-p port] [-t host] [-h] [-d] [-l log]"
print "-p port : NomNom proxy control port"
print "-t host : NomNom proxy host"
print "-l log : debug to file log"
print "-i device: device to sniff on"
print "-d debug : turn on debug output"
print "-h help (this output)"
if __name__ == "__main__":
proxyhost=""
debug("[+] Initiating..")
device=False
try: opts, args = getopt.getopt(sys.argv[1:], "l:t:hdp:", [])
except getopt.GetoptError, e:
usage()
exit(-1)
for opt, value in opts:
if(opt == "-d"):
DEBUG=True
if(opt == "-p"):
port=int(value)
if(opt == "-h"):
usage()
exit(1)
if(opt == "-t"):
proxyhost=str(value)
if(opt == "-l"):
DEBUGFILE=str(value)
if(opt == "-i"):
device=str(value)
if DEBUGFILE:
try:
DEBUGFH = open(DEBUGFILE, "w")
except IOError:
DEBUGFILE=0
if(not proxyhost):
usage()
exit(1)
(readpipe,writepipe) = os.pipe();
#instantiate the main classes:
logthread=loggingThread(readpipe)
logthread.start()
proxythread=proxycontrolThread(proxyhost,port)
proxythread.start()
#debating whether or not to actually thread sniffer, or just leave it as main thread... hrm
snifferthread=sniffer(device)
snifferthread.run()
#end main
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.