Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/dependencies_table.rst
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@
+-------------------------------+-------------------+--------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+
| pyinstaller-hooks-contrib | 2026.0 | Apache Software License; GNU General Public License v2 (GPLv2) | Community maintained hooks for PyInstaller |
+-------------------------------+-------------------+--------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+
| PyMySQL | >=1.1.0 | MIT License | Pure-Python MySQL client library |
+-------------------------------+-------------------+--------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+
| pylint | 4.0.4 | GPL-2.0-or-later | python code static checker |
+-------------------------------+-------------------+--------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+
| pyproject_hooks | 1.2.0 | MIT License | Wrappers to call pyproject.toml-based build backend hooks. |
Expand Down
1 change: 1 addition & 0 deletions docs/developer_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Documentation of PEAT's Python codebase and APIs.
device_api
device_modules
general_apis
mysql
heat_api
python_examples
elastic_implementation
Expand Down
6 changes: 6 additions & 0 deletions docs/general_apis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ HTTP
:members:
:private-members:

MySQL
^^^^^
.. automodule:: peat.protocols.mysql
:members:
:private-members:

SNMP
^^^^
.. automodule:: peat.protocols.snmp
Expand Down
62 changes: 62 additions & 0 deletions docs/mysql.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
*****
MySQL
*****

MySQL and MariaDB are widely deployed relational database servers. In OT environments, MySQL/MariaDB instances are commonly found on historian servers, HMI backends, and engineering workstations.

PEAT supports both unauthenticated fingerprinting (via the TCP greeting packet) and authenticated enumeration (via SQL queries) using the :class:`~peat.protocols.mysql.MySQL` protocol class.

.. seealso::

:class:`~peat.protocols.mysql.MySQL`
PEAT protocol class for MySQL/MariaDB connections

`MySQL Documentation <https://dev.mysql.com/doc/>`__

`MariaDB Documentation <https://mariadb.com/kb/en/documentation/>`__

`PyMySQL <https://pymysql.readthedocs.io/en/latest/>`__
The underlying Python library used for authenticated connections

Fingerprinting without credentials
-----------------------------------

MySQL sends an initial handshake packet immediately after a TCP connection is established, before any authentication takes place. This packet includes the server version string (e.g. ``8.0.32`` or ``10.6.12-MariaDB``).

:meth:`~peat.protocols.mysql.MySQL.read_greeting` reads this packet over a raw TCP socket, allowing PEAT to identify a MySQL/MariaDB server and extract its version without credentials.

Data collected
--------------

When credentials are available, PEAT can enumerate the following via SQL queries:

- Server version string and parsed version tuple
- Database names visible to the authenticated user
- Table names per database
- Approximate row counts per table (from ``information_schema``)
- User accounts and their allowed hosts (from ``mysql.user``)
- Grants for each user (``SHOW GRANTS``)
- Global system variables (``SHOW GLOBAL VARIABLES``)
- Active connections and queries (``SHOW FULL PROCESSLIST``)

Configuration
-------------

Credentials and connection options are specified in the PEAT config file under the ``mysql`` key in ``device_options``:

.. code-block:: yaml

device_options:
mysql:
credentials:
user: root
pass: secret
port: 3306
timeout: 10

Developer notes
---------------

The :class:`~peat.protocols.mysql.MySQL` class uses a lazy connection pattern: the underlying PyMySQL connection is not established when the object is created, but on the first call to any query method. This avoids opening TCP connections to hosts that are later filtered or skipped before enumeration begins.

The class is designed as a base class. The :meth:`~peat.protocols.mysql.MySQL.on_connected` and :meth:`~peat.protocols.mysql.MySQL.enumerate` hooks are intended to be overridden in device-specific subclasses. ``on_connected`` runs immediately after authentication and can be used to run setup queries or populate instance attributes. ``enumerate`` should return a dict of any device-specific table data — for example, a subclass targeting a historian might query proprietary tables that have no meaning in a generic MySQL context. The base class implementations are no-ops that return nothing and an empty dict respectively.
1 change: 1 addition & 0 deletions docs/tcp_ip_protocols_used_by_peat.csv
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"Modbus/TCP", "502", "TCP", ":class:`~peat.modules.schneider.m340.m340.M340`", ""
"UMAS", "502", "TCP", ":class:`~peat.modules.schneider.m340.m340.M340`", ":term:`UMAS` is a proprietary protocol built on top of Modbus/TCP. Used by Schneider Electric Modicon devices."
"ServLink/TCP", "666, 667", "TCP", ":class:`~peat.modules.woodward.easygen_3500xt.Easygen3500XT`", "ServLink is a Woodward-proprietary protocol for communicating with various devices over either TCP or Serial, including the easYgen 3500XT, 2301E, and potentially other devices. ServLink typically uses port 666, but it may use port 667."
"MySQL", "3306", "TCP", ":class:`~peat.protocols.mysql.MySQL`", "MySQL/MariaDB initial handshake and query protocol. Used for unauthenticated server fingerprinting via the TCP greeting packet and authenticated enumeration of database server version, schemas, users, and configuration."
"postgres", "5432", "TCP", ":class:`~peat.modules.sel.sel_rtac.SELRTAC`", "PostgreSQL database communication. Commonly known as the 'wire protocol'."
"ION", "7700, 7701, 7702", "TCP", ":class:`~peat.modules.schneider.ion.ion.ION`", "Proprietary protocol for Schneider Electric PowerLogic ION power meters. Used for reading and updating device configuration, firmware updates, and general communications between ION Setup software and a ION meter. ION uses port 7700 by default, but can also use ports 7701 or 7702."
"CIP", "44818", "TCP, UDP", ":class:`~peat.modules.rockwell.controllogix.ControlLogix`", ":term:`CIP` (Common Industrial Protocol) is a Rockwell/Allen-Bradley-developed protocol used by Rockwell devices and others."
3 changes: 3 additions & 0 deletions examples/peat-config-simple.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,9 @@ device_options:
timeout: 5.0
servlink_serial:
timeout: 5.0
mysql:
port: 3306
timeout: 5.0
postgres:
port: 5432
timeout: 5.0
Expand Down
7 changes: 7 additions & 0 deletions examples/peat-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,13 @@ device_options:
servlink_serial:
timeout: 5.0

# MySQL/MariaDB protocol
#
# "mysql" is not currently used by anyone, but is left here for future compatibility and documentation/reference.
mysql:
port: 3306
timeout: 5.0

# PostgreSQL protocol (used for communicating with PostgreSQL databases)
#
# "postgres" is used by the following modules: SELRTAC
Expand Down
1 change: 1 addition & 0 deletions newsfragments/59.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add MySQL/MariaDB protocol class (``peat/protocols/mysql.py``) with unauthenticated server fingerprinting via TCP greeting packet, PyMySQL-backed query helpers, and ``on_connected``/``enumerate`` subclass hooks for device-specific extensions.
42 changes: 11 additions & 31 deletions pdm.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions peat/data/default_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"modbus_tcp": {"port": 502, "timeout": config.DEFAULT_TIMEOUT},
"servlink_tcp": {"port": 666, "timeout": config.DEFAULT_TIMEOUT},
"servlink_serial": {"timeout": config.DEFAULT_TIMEOUT},
"mysql": {"port": 3306, "timeout": config.DEFAULT_TIMEOUT},
"postgres": {"port": 5432, "timeout": config.DEFAULT_TIMEOUT},
"ion_protocol": {
"port": 7700,
Expand Down
1 change: 1 addition & 0 deletions peat/protocols/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from .http import HTTP
from .interfaces import *
from .ip import *
from .mysql import MySQL
from .serial import *
from .snmp import *
from .ssh import SSH
Expand Down
Loading
Loading