Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
W
Warden Connectors
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
713
Warden
Warden Connectors
Commits
4273857c
Commit
4273857c
authored
6 years ago
by
Daniel Studený
Browse files
Options
Downloads
Patches
Plain Diff
Copied Pavel Eis version of connector from separate branch.
parent
30030682
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
tippingpoint/tpToIdea.py
+452
-0
452 additions, 0 deletions
tippingpoint/tpToIdea.py
with
452 additions
and
0 deletions
tippingpoint/tpToIdea.py
0 → 100644
+
452
−
0
View file @
4273857c
# python ./tpToIdea.py --origdata --oneshot -d /root/Dokumenty/PycharmProjects/TippingPoint/IdeaLogTest -n cz.cesnet.server.tippingpoint /root/Dokumenty/PycharmProjects/TippingPoint/tp-test-log.txt /root/Dokumenty/PycharmProjects/TippingPoint/tp-log2.txt --test
import
json
from
uuid
import
uuid4
import
re
import
socket
import
optparse
import
sys
import
os
import
signal
import
resource
import
os.path
as
pth
import
atexit
import
time
import
logging
class
FileWatcher
(
object
):
def
__init__
(
self
,
filename
,
tail
=
True
):
self
.
filename
=
filename
self
.
open
()
self
.
line_buffer
=
""
if
tail
and
self
.
f
:
self
.
f
.
seek
(
0
,
os
.
SEEK_END
)
def
open
(
self
):
try
:
self
.
f
=
open
(
self
.
filename
,
"
r
"
)
st
=
os
.
fstat
(
self
.
f
.
fileno
())
self
.
inode
,
self
.
size
=
st
.
st_ino
,
st
.
st_size
except
IOError
:
self
.
f
=
None
self
.
inode
=
-
1
self
.
size
=
-
1
def
_check_reopen
(
self
):
try
:
st
=
os
.
stat
(
self
.
filename
)
cur_inode
,
cur_size
=
st
.
st_ino
,
st
.
st_size
except
OSError
as
e
:
cur_inode
=
-
1
cur_size
=
-
1
if
cur_inode
!=
self
.
inode
or
cur_size
<
self
.
size
:
self
.
close
()
self
.
open
()
def
readline
(
self
):
if
not
self
.
f
:
self
.
open
()
if
not
self
.
f
:
return
self
.
line_buffer
res
=
self
.
f
.
readline
()
if
not
res
:
self
.
_check_reopen
()
if
not
self
.
f
:
return
self
.
line_buffer
res
=
self
.
f
.
readline
()
if
not
res
.
endswith
(
"
\n
"
):
self
.
line_buffer
+=
res
else
:
res
=
self
.
line_buffer
+
res
self
.
line_buffer
=
""
return
res
def
close
(
self
):
try
:
if
self
.
f
:
self
.
f
.
close
()
except
IOError
:
pass
self
.
inode
=
-
1
self
.
size
=
-
1
def
__repr__
(
self
):
return
'
%s(
"
%s
"
)
'
%
(
type
(
self
).
__name__
,
self
.
filename
)
def
__enter__
(
self
):
return
self
def
__exit__
(
self
,
exc_type
,
exc_val
,
exc_tb
):
self
.
close
()
return
False
def
__iter__
(
self
):
return
self
def
next
(
self
):
return
self
.
readline
()
class
Filer
(
object
):
def
__init__
(
self
,
directory
):
self
.
basedir
=
self
.
_ensure_path
(
directory
)
self
.
tmp
=
self
.
_ensure_path
(
pth
.
join
(
self
.
basedir
,
"
tmp
"
))
self
.
incoming
=
self
.
_ensure_path
(
pth
.
join
(
self
.
basedir
,
"
incoming
"
))
self
.
hostname
=
socket
.
gethostname
()
self
.
pid
=
os
.
getpid
()
def
_ensure_path
(
self
,
p
):
try
:
os
.
mkdir
(
p
)
except
OSError
:
if
not
pth
.
isdir
(
p
):
raise
return
p
def
_get_new_name
(
self
,
fd
=
None
):
(
inode
,
device
)
=
os
.
fstat
(
fd
)[
1
:
3
]
if
fd
else
(
0
,
0
)
return
"
%s.%d.%f.%d.%d
"
%
(
self
.
hostname
,
self
.
pid
,
time
.
time
(),
device
,
inode
)
def
create_unique_file
(
self
):
# First find and open name unique within tmp
tmpname
=
None
while
not
tmpname
:
tmpname
=
self
.
_get_new_name
()
try
:
fd
=
os
.
open
(
pth
.
join
(
self
.
tmp
,
tmpname
),
os
.
O_CREAT
|
os
.
O_RDWR
|
os
.
O_EXCL
)
except
OSError
as
e
:
if
e
.
errno
!=
errno
.
EEXIST
:
raise
# other errors than duplicates should get noticed
tmpname
=
None
# Now we know the device/inode, rename to make unique within system
newname
=
self
.
_get_new_name
(
fd
)
os
.
rename
(
pth
.
join
(
self
.
tmp
,
tmpname
),
pth
.
join
(
self
.
tmp
,
newname
))
nf
=
os
.
fdopen
(
fd
,
"
w
"
)
return
nf
,
newname
def
publish_file
(
self
,
short_name
):
os
.
rename
(
pth
.
join
(
self
.
tmp
,
short_name
),
pth
.
join
(
self
.
incoming
,
short_name
))
class
IdeaGen
(
object
):
idea_categories
=
{
'
Malware.Worm
'
:
re
.
compile
(
"
^Exploits: .*?Worm
"
),
'
Attempt.Login
'
:
re
.
compile
(
"
SipVicious Brute Force
"
),
'
Attempt.Exploit
'
:
re
.
compile
(
"
^Exploits: .*?Attempt
"
),
'
Other
'
:
re
.
compile
(
"
P2P
"
),
'
Recon.Scanning
'
:
re
.
compile
(
"
^Reconnaissance
"
),
'
Vulnerable.Open
'
:
re
.
compile
(
"
(^Vulnerabilities: [0-9]{5}|^Network Equipment: [0-9]{4} SNMP)
"
),
'
Vulnerable.Config
'
:
re
.
compile
(
"
^Vulnerabilities: [0-9]{4} ICMP
"
)}
anomaly_re
=
re
.
compile
(
"
(^Network Equipment: [0-9]{4} IP|^Traffic Normalization: [0-9]{4} (?!Tunneling))
"
)
availability_ddos_re
=
re
.
compile
(
"
^Traffic Normalization:
"
)
def
__init__
(
self
,
name
,
test
=
False
):
self
.
name
=
name
self
.
test
=
test
def
convert_category
(
self
,
category
,
incident
,
examples_of_incident
):
'''
converts category from record to IDEA category
:param category: TippingPoint category description
:param incident: TippingPoint incident description
:param examples_of_incident: some TippingPoing incident descriptions has examples
:return: if category or incident is empty or is not important for saving it return None, otherwise return
converted category
'''
if
not
(
category
and
incident
):
return
None
tp_category
=
category
+
"
:
"
+
incident
if
IdeaGen
.
anomaly_re
.
search
(
tp_category
)
and
not
examples_of_incident
:
return
"
Anomaly.Traffic
"
if
IdeaGen
.
availability_ddos_re
.
search
(
tp_category
)
and
examples_of_incident
:
return
"
Availability.DoS
"
for
category
,
pattern
in
IdeaGen
.
idea_categories
.
items
():
if
pattern
.
search
(
tp_category
):
return
category
return
None
def
gen_event_idea
(
self
,
timestamp
,
category
,
id_taxonomy
,
cve
,
examples_of_incident
,
proto
,
src_ip
,
src_port
,
dest_ip
,
dest_port
,
conn_count
,
url
,
orig_data
,
incident_desription
):
'''
put every piece of record together into IDEA message
:return: new IDEA message
'''
event
=
{
'
Format
'
:
"
IDEA0
"
,
'
ID
'
:
str
(
uuid4
()),
'
DetectTime
'
:
time
.
strftime
(
"
%y-%m-%dT%H:%M:%S
"
,
time
.
localtime
(
timestamp
)),
'
Category
'
:
[
category
]
+
([
"
Test
"
]
if
self
.
test
else
[]),
'
Note
'
:
incident_desription
,
'
Ref
'
:
[]
}
if
cve
:
event
[
'
Ref
'
].
append
(
"
cve:
"
+
cve
)
if
id_taxonomy
:
event
[
'
Ref
'
].
append
(
"
tipping_point_taxonomy:%d
"
%
int
(
id_taxonomy
))
if
conn_count
:
event
[
'
ConnCount
'
]
=
conn_count
source
=
{}
target
=
{}
if
src_ip
:
af
=
"
IP4
"
if
not
'
:
'
in
src_ip
else
"
IP6
"
source
[
af
]
=
[
src_ip
]
if
src_port
:
source
[
'
Port
'
]
=
[
src_port
]
if
proto
:
source
[
'
Proto
'
]
=
[
proto
]
if
url
:
source
[
'
url
'
]
=
url
if
dest_ip
:
af
=
"
IP4
"
if
not
'
:
'
in
dest_ip
else
"
IP6
"
target
[
af
]
=
[
dest_ip
]
if
dest_port
:
target
[
'
Port
'
]
=
[
dest_port
]
if
source
:
event
[
'
Source
'
]
=
[
source
]
if
target
:
event
[
'
Target
'
]
=
[
target
]
if
examples_of_incident
:
event
[
'
Note
'
]
+=
"
, examples of event:
"
+
examples_of_incident
[
6
:]
if
orig_data
:
event
[
'
Attach
'
]
=
{
'
Handle
'
:
"
att1
"
,
'
Note
'
:
"
original data
"
,
'
Content
'
:
orig_data
}
event
[
'
Node
'
]
=
[{
'
Name
'
:
self
.
name
,
'
Type
'
:
[
"
Connection
"
,
"
Honeypot
"
,
"
Recon
"
],
'
SW
'
:
[
"
HP Tipping Point
"
],
}]
return
event
def
daemonize
(
work_dir
=
None
,
chroot_dir
=
None
,
umask
=
None
,
uid
=
None
,
gid
=
None
,
pidfile
=
None
,
files_preserve
=
[],
signals
=
{}):
# Dirs, limits, users
if
chroot_dir
is
not
None
:
os
.
chdir
(
chroot_dir
)
os
.
chroot
(
chroot_dir
)
if
umask
is
not
None
:
os
.
umask
(
umask
)
if
work_dir
is
not
None
:
os
.
chdir
(
work_dir
)
if
gid
is
not
None
:
os
.
setgid
(
gid
)
if
uid
is
not
None
:
os
.
setuid
(
uid
)
# Doublefork, split session
if
os
.
fork
()
>
0
:
os
.
_exit
(
0
)
try
:
os
.
setsid
()
except
OSError
:
pass
if
os
.
fork
()
>
0
:
os
.
_exit
(
0
)
# Setup signal handlers
for
(
signum
,
handler
)
in
signals
.
items
():
signal
.
signal
(
signum
,
handler
)
# Close descriptors
descr_preserve
=
set
(
f
.
fileno
()
for
f
in
files_preserve
)
maxfd
=
resource
.
getrlimit
(
resource
.
RLIMIT_NOFILE
)[
1
]
if
maxfd
==
resource
.
RLIM_INFINITY
:
maxfd
=
65535
for
fd
in
range
(
maxfd
,
3
,
-
1
):
# 3 means omit stdin, stdout, stderr
if
fd
not
in
descr_preserve
:
try
:
os
.
close
(
fd
)
except
Exception
:
pass
# Redirect stdin, stdout, stderr to /dev/null
devnull
=
os
.
open
(
os
.
devnull
,
os
.
O_RDWR
)
for
fd
in
range
(
3
):
os
.
dup2
(
devnull
,
fd
)
# PID file
if
pidfile
is
not
None
:
pidd
=
os
.
open
(
pidfile
,
os
.
O_RDWR
|
os
.
O_CREAT
|
os
.
O_EXCL
|
os
.
O_TRUNC
)
os
.
write
(
pidd
,
str
(
os
.
getpid
())
+
"
\n
"
)
os
.
close
(
pidd
)
# Define and setup atexit closure
@atexit.register
def
unlink_pid
():
try
:
os
.
unlink
(
pidfile
)
except
Exception
:
pass
def
get_args
():
optp
=
optparse
.
OptionParser
(
usage
=
"
usage: %prog [options] logfile ...
"
,
description
=
"
Watch HP-Tipping_Point logfiles and generate Idea events into directory
"
)
optp
.
add_option
(
"
-n
"
,
"
--name
"
,
default
=
None
,
dest
=
"
name
"
,
type
=
"
string
"
,
action
=
"
store
"
,
help
=
"
Warden client name
"
)
optp
.
add_option
(
"
--test
"
,
default
=
False
,
dest
=
"
test
"
,
action
=
"
store_true
"
,
help
=
"
Add Test category
"
)
optp
.
add_option
(
"
-o
"
,
"
--oneshot
"
,
default
=
False
,
dest
=
"
oneshot
"
,
action
=
"
store_true
"
,
help
=
"
process files and quit (do not daemonize)
"
)
optp
.
add_option
(
"
--poll
"
,
default
=
1
,
dest
=
"
poll
"
,
type
=
"
int
"
,
action
=
"
store
"
,
help
=
"
log file polling interval
"
)
optp
.
add_option
(
"
-d
"
,
"
--dir
"
,
default
=
None
,
dest
=
"
dir
"
,
type
=
"
string
"
,
action
=
"
store
"
,
help
=
"
Target directory (mandatory)
"
)
optp
.
add_option
(
"
-p
"
,
"
--pid
"
,
default
=
pth
.
join
(
"
/var/run
"
,
pth
.
splitext
(
pth
.
basename
(
sys
.
argv
[
0
]))[
0
]
+
"
.pid
"
),
dest
=
"
pid
"
,
type
=
"
string
"
,
action
=
"
store
"
,
help
=
"
create PID file with this name (default: %default)
"
)
optp
.
add_option
(
"
-u
"
,
"
--uid
"
,
default
=
None
,
dest
=
"
uid
"
,
type
=
"
int
"
,
action
=
"
store
"
,
help
=
"
user id to run under
"
)
optp
.
add_option
(
"
-g
"
,
"
--gid
"
,
default
=
None
,
dest
=
"
gid
"
,
type
=
"
int
"
,
action
=
"
store
"
,
help
=
"
group id to run under
"
)
optp
.
add_option
(
"
--origdata
"
,
default
=
False
,
dest
=
"
origdata
"
,
action
=
"
store_true
"
,
help
=
"
Store original report to IDEA message
"
)
return
optp
def
not_empty
(
test_string
):
# tests if string is not empty
return
None
if
test_string
.
strip
()
in
[
""
,
"
null
"
]
else
test_string
def
save_events
(
event
,
filer
):
f
,
name
=
filer
.
create_unique_file
()
with
f
:
f
.
write
(
json
.
dumps
(
event
,
ensure_ascii
=
True
))
filer
.
publish_file
(
name
)
def
process_data
(
line
,
filer
,
origdata
,
idea_gen
):
'''
takes one record, parse it to parameters, give it to Ideagen and writes to file
:param line: one record
:param idea_file: where output goes
:param origdata: if true, write original record to IDEA message
'''
row
=
line
.
split
(
"
,
"
)
while
re
.
search
(
"
^CVE-.*$
"
,
row
[
4
]):
row
[
3
]
+=
"
,
"
+
row
[
4
]
del
row
[
4
]
examples_of_incident
=
[]
while
not
re
.
search
(
"
(UDP|IP|ICMP|DNS|IP6)
"
,
row
[
5
]):
examples_of_incident
.
append
(
row
[
5
])
del
row
[
5
]
examples_of_incident
=
"
"
.
join
(
examples_of_incident
)
category
=
idea_gen
.
convert_category
(
category
=
row
[
1
],
incident
=
row
[
4
],
examples_of_incident
=
examples_of_incident
)
if
category
and
not_empty
(
row
[
0
][
-
14
:
-
3
]):
idea_event
=
idea_gen
.
gen_event_idea
(
timestamp
=
int
(
row
[
0
][
-
14
:
-
3
]),
category
=
category
,
id_taxonomy
=
not_empty
(
row
[
2
]),
cve
=
not_empty
(
row
[
3
]),
examples_of_incident
=
not_empty
(
examples_of_incident
),
proto
=
not_empty
(
row
[
5
]),
src_ip
=
not_empty
(
row
[
6
]),
src_port
=
not_empty
(
row
[
7
]),
dest_ip
=
not_empty
(
row
[
8
]),
dest_port
=
not_empty
(
row
[
9
]),
conn_count
=
not_empty
(
row
[
10
]),
url
=
not_empty
(
row
[
12
]),
orig_data
=
str
(
line
)
if
origdata
else
False
,
incident_desription
=
row
[
4
])
save_events
(
idea_event
,
filer
)
running_flag
=
True
reload_flag
=
False
def
terminate_me
(
signum
,
frame
):
global
running_flag
running_flag
=
False
def
reload_me
(
signum
,
frame
):
global
reload_flag
reload_flag
=
True
def
main
():
global
running_flag
global
reload_flag
logging
.
basicConfig
(
format
=
'
%(levelname)s:%(message)s
'
,
level
=
logging
.
DEBUG
,
filename
=
'
tipping_point_log.log
'
,
filemode
=
'
w
'
)
optp
=
get_args
()
opts
,
args
=
optp
.
parse_args
()
if
not
args
or
opts
.
name
is
None
or
opts
.
dir
is
None
:
optp
.
print_help
()
sys
.
exit
()
if
opts
.
oneshot
:
signal
.
signal
(
signal
.
SIGINT
,
terminate_me
)
signal
.
signal
(
signal
.
SIGTERM
,
terminate_me
)
files
=
[
open
(
arg
)
for
arg
in
args
]
else
:
daemonize
(
pidfile
=
opts
.
pid
,
uid
=
opts
.
uid
,
gid
=
opts
.
gid
,
signals
=
{
signal
.
SIGINT
:
terminate_me
,
signal
.
SIGTERM
:
terminate_me
,
signal
.
SIGHUP
:
reload_me
})
files
=
[
FileWatcher
(
arg
)
for
arg
in
args
]
filer
=
Filer
(
opts
.
dir
)
idea_gen
=
IdeaGen
(
opts
.
name
,
opts
.
test
)
while
running_flag
:
for
log_file
in
files
:
while
True
:
line
=
log_file
.
readline
()
if
line
is
None
or
not
line
.
strip
():
logging
.
info
(
"
no line
"
)
break
logging
.
info
(
"
readline
"
)
process_data
(
line
,
filer
,
opts
.
origdata
,
idea_gen
)
if
not
running_flag
:
break
if
reload_flag
:
for
f
in
files
:
f
.
close
()
f
.
open
()
reload_flag
=
False
if
opts
.
oneshot
:
break
else
:
time
.
sleep
(
opts
.
poll
)
if
__name__
==
"
__main__
"
:
main
()
\ No newline at end of file
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment