Skip to content

Commit

Permalink
Merge 4f8b10d into 0c5f4e1
Browse files Browse the repository at this point in the history
  • Loading branch information
glaslos committed Nov 8, 2020
2 parents 0c5f4e1 + 4f8b10d commit 6ac834c
Show file tree
Hide file tree
Showing 18 changed files with 496 additions and 43 deletions.
9 changes: 8 additions & 1 deletion conpot/core/attack_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,16 @@
logger = logging.getLogger(__name__)


# one instance per connection
NEW_CONNECTION = "NEW_CONNECTION"
CONNECTION_LOST = "CONNECTION_LOST"
CONNECTION_CLOSED = "CONNECTION_CLOSED"
CONNECTION_FAILED = "CONNECTION_FAILED"
CONNECTION_TERMINATED = "CONNECTION_TERMINATED"
CONNECTION_QUIT = "CONNECTION_QUIT"
CONNECTION_TIMEOUT = "CONNECTION_TIMEOUT"


# one instance per connection
class AttackSession(object):
def __init__(
self,
Expand Down
11 changes: 6 additions & 5 deletions conpot/protocols/IEC104/IEC104_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from .frames import struct, TESTFR_act, socket, errno
import logging
import conpot.core as conpot_core
from conpot.core import attack_session
from gevent.server import StreamServer
import gevent
from .errors import Timeout_t3
Expand Down Expand Up @@ -52,7 +53,7 @@ def handle(self, sock, address):
address[1],
session.id,
)
session.add_event({"type": "NEW_CONNECTION"})
session.add_event({"type": attack_session.NEW_CONNECTION})
iec104_handler = IEC104(self.device_data_controller, sock, address, session.id)
try:
while True:
Expand All @@ -65,7 +66,7 @@ def handle(self, sock, address):
request = sock.recv(6)
if not request:
logger.info("IEC104 Station disconnected. (%s)", session.id)
session.add_event({"type": "CONNECTION_LOST"})
session.add_event({"type": attack.session.CONNECTION_LOST})
iec104_handler.disconnect()
break
while request and len(request) < 2:
Expand Down Expand Up @@ -124,18 +125,18 @@ def handle(self, sock, address):
except gevent.Timeout:
logger.warning("T1 timed out. (%s)", session.id)
logger.info("IEC104 Station disconnected. (%s)", session.id)
session.add_event({"type": "CONNECTION_LOST"})
session.add_event({"type": attack_session.CONNECTION_LOST})
iec104_handler.disconnect()
break
except socket.timeout:
logger.debug("Socket timeout, remote: %s. (%s)", address[0], session.id)
session.add_event({"type": "CONNECTION_LOST"})
session.add_event({"type": attack_session.CONNECTION_LOST})
except socket.error as err:
if isinstance(err.args, tuple):
if err.errno == errno.EPIPE:
# remote peer disconnected
logger.info("IEC104 Station disconnected. (%s)", session.id)
session.add_event({"type": "CONNECTION_LOST"})
session.add_event({"type": attack_session.CONNECTION_LOST})
else:
# determine and handle different error
pass
Expand Down
3 changes: 2 additions & 1 deletion conpot/protocols/bacnet/bacnet_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import conpot.core as conpot_core
from conpot.protocols.bacnet.bacnet_app import BACnetApp
from conpot.core.protocol_wrapper import conpot_protocol
from conpot.core import attack_session
import logging

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -69,7 +70,7 @@ def handle(self, data, address):
logger.info(
"New Bacnet connection from %s:%d. (%s)", address[0], address[1], session.id
)
session.add_event({"type": "NEW_CONNECTION"})
session.add_event({"type": attack_session.NEW_CONNECTION})
# I'm not sure if gevent DatagramServer handles issues where the
# received data is over the MTU -> fragmentation
if data:
Expand Down
9 changes: 5 additions & 4 deletions conpot/protocols/enip/enip_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from cpppo.server.enip import parser
from cpppo.server.enip import device
from conpot.core.protocol_wrapper import conpot_protocol
from conpot.core import attack_session
import conpot.core as conpot_core

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -133,7 +134,7 @@ def handle(self, conn, address, enip_process=None, delay=None, **kwds):
"enip", host, port, conn.getsockname()[0], conn.getsockname()[1]
)
logger.debug("ENIP server %s begins serving client %s", name, address)
session.add_event({"type": "NEW_CONNECTION"})
session.add_event({"type": attack_session.NEW_CONNECTION})

tcp = conn.family == socket.AF_INET and conn.type == socket.SOCK_STREAM
udp = conn.family == socket.AF_INET and conn.type == socket.SOCK_DGRAM
Expand Down Expand Up @@ -332,7 +333,7 @@ def handle_tcp(
cpppo.timer() - begun,
delayseconds,
)
session.add_event({"type": "CONNECTION_CLOSED"})
session.add_event({"type": attack_session.CONNECTION_CLOSED})
except:
logger.error("Failed request: %s", parser.enip_format(data))
enip_process(address, data=cpppo.dotdict()) # Terminate.
Expand Down Expand Up @@ -491,7 +492,7 @@ def handle_udp(self, conn, name, enip_process, session, **kwds):
logger.debug(
"Transaction complete after %7.3fs", cpppo.timer() - begun
)
session.add_event({"type": "CONNECTION_CLOSED"})
session.add_event({"type": attack_session.CONNECTION_CLOSED})
stats["processed"] = source.sent
except:
# Parsing failure. Suck out some remaining input to give us some context, but don't re-raise
Expand All @@ -512,7 +513,7 @@ def handle_udp(self, conn, name, enip_process, session, **kwds):
where,
"".join(traceback.format_exception(*sys.exc_info())),
)
session.add_event({"type": "CONNECTION_FAILED"})
session.add_event({"type": attack_session.CONNECTION_FAILED})

def set_tags(self):
typenames = {
Expand Down
7 changes: 4 additions & 3 deletions conpot/protocols/ftp/ftp_base_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from gevent import select
import conpot.core as conpot_core
from conpot.core.filesystem import FilesystemError
from conpot.core import attack_session
import logging
import errno
import time
Expand Down Expand Up @@ -241,7 +242,7 @@ def setup(self):
self.client_address[0], self.client_address[1], self.session.id
)
)
self.session.add_event({"type": "NEW_CONNECTION"})
self.session.add_event({"type": attack_session.NEW_CONNECTION})
# send 200 + banner -- new client has connected!
self.respond(b"200 " + self.config.banner.encode())
# Is there a delay in command response? < gevent.sleep(0.5) ?
Expand Down Expand Up @@ -297,7 +298,7 @@ def handle_cmd_channel(self):
self.client_address, self.session.id
)
)
self.session.add_event({"type": "CONNECTION_LOST"})
self.session.add_event({"type": attack_session.CONNECTION_LOST})
self.finish()
return
socket_read, socket_write, _ = gevent.select.select(
Expand Down Expand Up @@ -354,7 +355,7 @@ def handle_cmd_channel(self):
self.client_address, self.session.id, se
)
)
self.session.add_event({"type": "CONNECTION_LOST"})
self.session.add_event({"type": attack_session.CONNECTION_LOST})
self.finish()

def respond(self, response):
Expand Down
9 changes: 5 additions & 4 deletions conpot/protocols/ftp/ftp_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from gevent import socket
from fs import errors
from conpot.core.filesystem import FilesystemError, FSOperationNotPermitted
from conpot.core import attack_session
from conpot.protocols.ftp.ftp_utils import FTPPrivilegeException, get_data_from_iter

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -114,7 +115,7 @@ def do_SYST(self, arg):

def do_QUIT(self, arg):
self.respond(b"221 Bye.")
self.session.add_event({"type": "CONNECTION_TERMINATED"})
self.session.add_event({"type": attack_session.CONNECTION_TERMINATED})
self.disconnect_client = True

def do_SITE_HELP(self, line):
Expand Down Expand Up @@ -879,7 +880,7 @@ def _process_command(self, cmd, *args, **kwargs):
if self.invalid_login_attempt >= self.max_login_attempts:
self.respond(b"421 Too many connections. Service temporarily unavailable.")
self.disconnect_client = True
self.session.add_event({"type": "CONNECTION_TERMINATED"})
self.session.add_event({"type": attack_session.CONNECTION_TERMINATED})
else:
try:
method = getattr(self, "do_" + cmd.replace(" ", "_"))
Expand Down Expand Up @@ -937,7 +938,7 @@ def process_ftp_command(self):
)
# TODO: what to respond here? For now just terminate the session
self.disconnect_client = True
self.session.add_event({"type": "CONNECTION_TERMINATED"})
self.session.add_event({"type": attack_session.CONNECTION_TERMINATED})
elif not (self.metrics.timeout() < self.config.timeout) and (
not self._data_channel
):
Expand All @@ -946,7 +947,7 @@ def process_ftp_command(self):
self.client_address, self.session.id
)
)
self.session.add_event({"type": "CONNECTION_TIMEOUT"})
self.session.add_event({"type": attack_session.CONNECTION_TIMEOUT})
self.respond(b"421 Timeout.")
self.disconnect_client = True
else:
Expand Down
5 changes: 3 additions & 2 deletions conpot/protocols/guardian_ast/guardian_ast_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import logging
import random
import conpot.core as conpot_core
from conpot.core import attack_session
from conpot.core.protocol_wrapper import conpot_protocol
from conpot.helpers import str_to_bytes

Expand Down Expand Up @@ -55,7 +56,7 @@ def handle(self, sock, addr):
logger.info(
"New GuardianAST connection from %s:%d. (%s)", addr[0], addr[1], session.id
)
session.add_event({"type": "NEW_CONNECTION"})
session.add_event({"type": attack_session.NEW_CONNECTION})
current_time = datetime.datetime.utcnow()
fill_start = self.fill_offset_time - datetime.timedelta(minutes=313)
fill_stop = self.fill_offset_time - datetime.timedelta(minutes=303)
Expand Down Expand Up @@ -507,7 +508,7 @@ def I20500():
logger.info(
"GuardianAST client disconnected %s:%d. (%s)", addr[0], addr[1], session.id
)
session.add_event({"type": "CONNECTION_LOST"})
session.add_event({"type": attack_session.CONNECTION_LOST})

def start(self, host, port):
connection = (host, port)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import gevent
from gevent.server import StreamServer
import conpot.core as conpot_core
from conpot.core import attack_session
from conpot.protocols.kamstrup.management_protocol.command_responder import (
CommandResponder,
)
Expand Down Expand Up @@ -52,7 +53,7 @@ def handle(self, sock, address):
address[1],
session.id,
)
session.add_event({"type": "NEW_CONNECTION"})
session.add_event({"type": attack_session.NEW_CONNECTION})

try:
sock.send(
Expand All @@ -67,7 +68,7 @@ def handle(self, sock, address):
data = sock.recv(1024)
if not data:
logger.info("Kamstrup client disconnected. (%s)", session.id)
session.add_event({"type": "CONNECTION_LOST"})
session.add_event({"type": attack_session.CONNECTION_LOST})
break
request = data.decode()
logdata = {"request": request}
Expand All @@ -83,15 +84,15 @@ def handle(self, sock, address):
gevent.sleep(0.25) # TODO measure delay and/or RTT

if response is None:
session.add_event({"type": "CONNECTION_LOST"})
session.add_event({"type": attack_session.CONNECTION_LOST})
break
# encode data before sending
reply = str_to_bytes(response)
sock.send(reply)

except socket.timeout:
logger.debug("Socket timeout, remote: %s. (%s)", address[0], session.id)
session.add_event({"type": "CONNECTION_LOST"})
session.add_event({"type": attack_session.CONNECTION_LOST})

sock.close()

Expand Down
9 changes: 5 additions & 4 deletions conpot/protocols/kamstrup/meter_protocol/kamstrup_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import gevent
from conpot.helpers import chr_py3
import conpot.core as conpot_core
from conpot.core import attack_session
from conpot.protocols.kamstrup.meter_protocol import request_parser
from conpot.protocols.kamstrup.meter_protocol.command_responder import CommandResponder
from conpot.core.protocol_wrapper import conpot_protocol
Expand Down Expand Up @@ -65,7 +66,7 @@ def handle(self, sock, address):
address[1],
session.id,
)
session.add_event({"type": "NEW_CONNECTION"})
session.add_event({"type": attack_session.NEW_CONNECTION})

self.server_active = True

Expand All @@ -76,7 +77,7 @@ def handle(self, sock, address):

if not raw_request:
logger.info("Kamstrup client disconnected. (%s)", session.id)
session.add_event({"type": "CONNECTION_LOST"})
session.add_event({"type": attack_session.CONNECTION_LOST})
break

for x in raw_request:
Expand All @@ -85,7 +86,7 @@ def handle(self, sock, address):
while True:
request = parser.get_request()
if not request:
session.add_event({"type": "CONNECTION_LOST"})
session.add_event({"type": attack_session.CONNECTION_LOST})
break
else:
logdata = {
Expand Down Expand Up @@ -113,7 +114,7 @@ def handle(self, sock, address):

except socket.timeout:
logger.debug("Socket timeout, remote: %s. (%s)", address[0], session.id)
session.add_event({"type": "CONNECTION_LOST"})
session.add_event({"type": attack_session.CONNECTION_LOST})

sock.close()

Expand Down
15 changes: 8 additions & 7 deletions conpot/protocols/modbus/modbus_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from conpot.core.protocol_wrapper import conpot_protocol
from conpot.protocols.modbus import slave_db
import conpot.core as conpot_core
from conpot.core import attack_session

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -105,7 +106,7 @@ def handle(self, sock, address):
logger.info(
"New Modbus connection from %s:%s. (%s)", address[0], address[1], session.id
)
session.add_event({"type": "NEW_CONNECTION"})
session.add_event({"type": attack_session.NEW_CONNECTION})

try:
while True:
Expand All @@ -121,17 +122,17 @@ def handle(self, sock, address):

if not request:
logger.info("Modbus client disconnected. (%s)", session.id)
session.add_event({"type": "CONNECTION_LOST"})
session.add_event({"type": attack_session.CONNECTION_LOST})
break
if request.strip().lower() == "quit.":
logger.info("Modbus client quit. (%s)", session.id)
session.add_event({"type": "CONNECTION_QUIT"})
session.add_event({"type": attack_session.CONNECTION_QUIT})
break
if len(request) < 7:
logger.info(
"Modbus client provided data {} but invalid.".format(session.id)
)
session.add_event({"type": "CONNECTION_TERMINATED"})
session.add_event({"type": attack_session.CONNECTION_TERMINATED})
break
_, _, length = struct.unpack(">HHH", request[:6])
while len(request) < (length + 6):
Expand Down Expand Up @@ -169,7 +170,7 @@ def handle(self, sock, address):
logger.info(
"Modbus connection terminated with client %s.", address[0]
)
session.add_event({"type": "CONNECTION_TERMINATED"})
session.add_event({"type": attack_session.CONNECTION_TERMINATED})
sock.shutdown(socket.SHUT_RDWR)
sock.close()
break
Expand All @@ -179,13 +180,13 @@ def handle(self, sock, address):
"Modbus client ignored due to invalid addressing." " (%s)",
session.id,
)
session.add_event({"type": "CONNECTION_TERMINATED"})
session.add_event({"type": attack_session.CONNECTION_TERMINATED})
sock.shutdown(socket.SHUT_RDWR)
sock.close()
break
except socket.timeout:
logger.debug("Socket timeout, remote: %s. (%s)", address[0], session.id)
session.add_event({"type": "CONNECTION_LOST"})
session.add_event({"type": attack_session.CONNECTION_LOST})

def start(self, host, port):
self.host = host
Expand Down

0 comments on commit 6ac834c

Please sign in to comment.