forked from angeloxx/modsec-replay
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmodsec-replay-client.py
More file actions
108 lines (97 loc) · 5.14 KB
/
modsec-replay-client.py
File metadata and controls
108 lines (97 loc) · 5.14 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
#!/usr/bin/python
#
#
# serial format support by spartantri
import os, traceback, auditparser, socket
from optparse import OptionParser
# Send the single request
def sendRequest(filename,host,port,usessl,offset,remotehostname):
if auditparser.isValidFile(filename):
print "I: Valid audit file found %s" % (filename)
max_offset = 0
if offset>0:
max_offset=auditparser.isValidOffset(filename,offset)
if max_offset == 0:
offset=0
for pointer in xrange(offset,max_offset):
try:
# Get headers, remove X-REPLAY-ID if found and add it again
headers = filter( lambda x: not (x.startswith("X-Replay-Id:") or x.startswith("X-Forwarded") or x.startswith("Connection: Keep-Alive")), auditparser.getAuditPart(filename,"REQUEST-HEADER",pointer).split("\n"))
headers.insert(2,"X-Replay-Id: %s" % auditparser.requestHash(filename))
headers.insert(3,"X-Original-Id: %s" % auditparser.getAuditPart(filename,"UNIQUE-ID",pointer))
headers.insert(4,"Connection: Close")
body = auditparser.getAuditPart(filename,"REQUEST-BODY",pointer)
# TODO: send additional header that contains request-id needed by the loop
if usessl:
import ssl
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(10)
if remotehostname != "":
s = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLSv1_2)
else:
s = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLSv1_2)
else:
s = socket.socket(socket.AF_INET)
s.connect((str(host),int(port)))
s.send(auditparser.getAuditPart(filename,"LOG",pointer) + "\r\n")
for header in headers:
s.send(header.decode('string_escape') + "\r\n")
if body != "":
s.send(body)
if options.verbose >= 2:
print "D: SENT =============================="
for li in headers:
print " %s" % li
for li in body.split("\n"):
print " %s" % li
print " ==================================="
s.settimeout(5)
response = ""
answer = True
while answer:
try:
newdata = s.recv(2048)
if newdata == "":
answer = False
else:
response = response + newdata
except:
answer = False
if options.verbose >= 2:
print "D: RECEIVED =========================="
for li in response.split("\n"):
print " %s" % li
print " ==================================="
try:
s.close()
except:
pass
except Exception, e:
print "E: unable to send %s to %s:%s" % (filename,host,port)
traceback.print_exc()
else:
print "E: Invalid audit file %s" % (filename)
parser = OptionParser()
parser.add_option("--source", dest="source", help="use recursively the specified audit directory as source", default="/var/log/apache/audit/")
parser.add_option("--only-url", dest="url", help="consider only the request to the specified URL (startswith is in use)", default="")
parser.add_option("--host", dest="remotehost", help="send request to the specified host", default="localhost")
parser.add_option("--port", dest="remoteport", help="send request to the specified port", type="int", default=80)
parser.add_option("--usessl", dest="usessl", help="send request to the specified host:port (TBD)", default=False)
parser.add_option("--timeout", dest="timeout", help="send timeout", type="int", default=10)
parser.add_option("-v", "--verbose", dest="verbose", help="increase verbosity level (0..9)", action="count", default=0)
parser.add_option("--delay", dest="delay", help="delay between two requests in ms", type="int", default=100)
parser.add_option("--offset", dest="offset", help="jump to offset in the logfile", type="int", default=0)
parser.add_option("--hostname", dest="remotehostname", help="send request to the specified hostname SNI", default="")
(options, args) = parser.parse_args()
if options.verbose > 0:
print "I: Verbose %d" % options.verbose
if os.path.isfile(options.source):
sendRequest(options.source,options.remotehost,options.remoteport,options.usessl,options.offset,options.remotehostname)
elif os.path.isdir(options.source):
for filename in auditparser.findFiles(options.source, '*'):
sendRequest(filename,options.remotehost,options.remoteport,options.usessl,options.offset,options.remotehostname)
else:
print "E: File or dir does not exist: %s" % (options.source)
#
#...but I don't support globs at the moment
#