update schemas, use relative imports

This commit is contained in:
Justin Bastress 2018-04-23 10:30:55 -04:00
parent edcae52fec
commit 0fb044b15e
67 changed files with 893 additions and 117 deletions

@ -1,19 +1,19 @@
# Ensure that all of the modules get executed so that they are registered
import schemas.bacnet
import schemas.dnp3
import schemas.fox
import schemas.ftp
import schemas.http
import schemas.modbus
import schemas.mssql
import schemas.mysql
import schemas.ntp
import schemas.oracle
import schemas.pop3
import schemas.postgres
import schemas.redis
import schemas.siemens
import schemas.smb
import schemas.smtp
import schemas.ssh
import schemas.telnet
import bacnet
import dnp3
import fox
import ftp
import http
import modbus
import mssql
import mysql
import ntp
import oracle
import pop3
import postgres
import redis
import siemens
import smb
import smtp
import ssh
import telnet

591
schemas/a.diff Normal file

@ -0,0 +1,591 @@
diff --git a/schemas/__init__.py b/schemas/__init__.py
index dbc1813..a026bb0 100644
--- a/schemas/__init__.py
+++ b/schemas/__init__.py
@@ -1,19 +1,19 @@
# Ensure that all of the modules get executed so that they are registered
-import schemas.bacnet
-import schemas.dnp3
-import schemas.fox
-import schemas.ftp
-import schemas.http
-import schemas.modbus
-import schemas.mssql
-import schemas.mysql
-import schemas.ntp
-import schemas.oracle
-import schemas.pop3
-import schemas.postgres
-import schemas.redis
-import schemas.siemens
-import schemas.smb
-import schemas.smtp
-import schemas.ssh
-import schemas.telnet
+import bacnet
+import dnp3
+import fox
+import ftp
+import http
+import modbus
+import mssql
+import mysql
+import ntp
+import oracle
+import pop3
+import postgres
+import redis
+import siemens
+import smb
+import smtp
+import ssh
+import telnet
diff --git a/schemas/bacnet.py b/schemas/bacnet.py
index e7326be..5975a2a 100644
--- a/schemas/bacnet.py
+++ b/schemas/bacnet.py
@@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
bacnet_scan_response = SubRecord({
"result": SubRecord({
diff --git a/schemas/dnp3.py b/schemas/dnp3.py
index 4b0b12b..5970dab 100644
--- a/schemas/dnp3.py
+++ b/schemas/dnp3.py
@@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
dnp3_scan_response = SubRecord({
"result": SubRecord({
diff --git a/schemas/fox.py b/schemas/fox.py
index 12821d2..7e5cd10 100644
--- a/schemas/fox.py
+++ b/schemas/fox.py
@@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
fox_scan_response = SubRecord({
'result': SubRecord({
diff --git a/schemas/ftp.py b/schemas/ftp.py
index 08a2278..aca3c8c 100644
--- a/schemas/ftp.py
+++ b/schemas/ftp.py
@@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
# modules/ftp.go - FTPScanResults
ftp_scan_response = SubRecord({
diff --git a/schemas/http.py b/schemas/http.py
index bcbdf29..fcd812d 100644
--- a/schemas/http.py
+++ b/schemas/http.py
@@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
# lib/http/header.go: knownHeaders
http_known_headers = [
diff --git a/schemas/imap.py b/schemas/imap.py
index 7f7c86b..bf0c30a 100644
--- a/schemas/imap.py
+++ b/schemas/imap.py
@@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
imap_scan_response = SubRecord({
"result": SubRecord({
diff --git a/schemas/modbus.py b/schemas/modbus.py
index 6c61263..30e8c36 100644
--- a/schemas/modbus.py
+++ b/schemas/modbus.py
@@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
mei_object_names = [
'vendor',
diff --git a/schemas/mssql.py b/schemas/mssql.py
index 28d61f7..b854890 100644
--- a/schemas/mssql.py
+++ b/schemas/mssql.py
@@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
ENCRYPT_MODES = [
"ENCRYPT_OFF",
diff --git a/schemas/mysql.py b/schemas/mysql.py
index b1150eb..84fb9c7 100644
--- a/schemas/mysql.py
+++ b/schemas/mysql.py
@@ -5,9 +5,9 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
-from schemas.zgrab2 import DebugOnly
+from zgrab2 import DebugOnly
# zgrab2/lib/mysql/mysql.go: GetServerStatusFlags()
mysql_server_status_flags = zgrab2.FlagsSet([
diff --git a/schemas/ntp.py b/schemas/ntp.py
index 482ed91..7412e17 100644
--- a/schemas/ntp.py
+++ b/schemas/ntp.py
@@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
ntp_short = SubRecord({
"seconds": Unsigned16BitInteger(),
diff --git a/schemas/oracle.py b/schemas/oracle.py
index 1560560..6119a60 100644
--- a/schemas/oracle.py
+++ b/schemas/oracle.py
@@ -6,7 +6,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
FlagsSet = zgrab2.FlagsSet
diff --git a/schemas/pop3.py b/schemas/pop3.py
index b01ccef..6de93f0 100644
--- a/schemas/pop3.py
+++ b/schemas/pop3.py
@@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
pop3_scan_response = SubRecord({
"result": SubRecord({
diff --git a/schemas/postgres.py b/schemas/postgres.py
index 0a8c37a..db8bb91 100644
--- a/schemas/postgres.py
+++ b/schemas/postgres.py
@@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
# modules/postgres/scanner.go - decodeError() (TODO: Currently an unconstrained
# map[string]string; it is possible to get "unknown (0x%x)" fields, but it
diff --git a/schemas/redis.py b/schemas/redis.py
index 01a630b..c68c6b9 100644
--- a/schemas/redis.py
+++ b/schemas/redis.py
@@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
redis_scan_response = SubRecord({
"result": SubRecord({
diff --git a/schemas/siemens.py b/schemas/siemens.py
index ba0ee26..a986401 100644
--- a/schemas/siemens.py
+++ b/schemas/siemens.py
@@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
siemens_scan_response = SubRecord({
'result': SubRecord({
diff --git a/schemas/smb.py b/schemas/smb.py
index 19d9e23..37dc133 100644
--- a/schemas/smb.py
+++ b/schemas/smb.py
@@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
header_log = {
'protocol_id': Binary(),
diff --git a/schemas/smtp.py b/schemas/smtp.py
index f87514f..003be12 100644
--- a/schemas/smtp.py
+++ b/schemas/smtp.py
@@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
smtp_scan_response = SubRecord({
"result": SubRecord({
diff --git a/schemas/ssh.py b/schemas/ssh.py
index b0537c8..a59b0ad 100644
--- a/schemas/ssh.py
+++ b/schemas/ssh.py
@@ -5,36 +5,117 @@ from zschema.leaves import *
from zschema.compounds import *
import zschema.registry
-from schemas.zcrypto import *
-import schemas.zgrab2 as zgrab2
+import schemas.zcrypto as zcrypto
+import zgrab2 as zgrab2
+
+# NOTE: Despite the fact that we have e.g. "supportedHostKeyAlgos",
+# "allSupportedCiphers", etc, including a different value is not syntactically
+# incorrect...so all of the following algorithm identifiers are Strings with
+# examples=[...], rather tha Enums with values=[...].
+
+# lib/ssh/common.go -- allSupportedKexAlgos
+KexAlgorithm = String.with_args(
+ doc="An ssh key exchange algorithm identifier, named according to section 6 of https://www.ietf.org/rfc/rfc4251.txt; see https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-15 for standard values.",
+ examples=[
+ "diffie-hellman-group1-sha1",
+ "diffie-hellman-group14-sha1",
+ "ecdh-sha2-nistp256",
+ "ecdh-sha2-nistp384",
+ "ecdh-sha2-nistp521",
+ "curve25519-sha256@libssh.org",
+ "diffie-hellman-group-exchange-sha1",
+ "diffie-hellman-group-exchange-sha256",
+ ]
+)
+
+KexAlgorithms = ListOf.with_args(KexAlgorithm())
+
+# Defined in lib/ssh/common.go -- supportedHostKeyAlgos, though they are
+# generated via PublicKey.Type()
+KeyAlgorithm = String.with_args(
+ doc="An ssh public key algorithm identifier, named according to section 6 of https://www.ietf.org/rfc/rfc4251.txt; see https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-19 for standard values.",
+ examples=[
+ "ssh-rsa-cert-v01@openssh.com",
+ "ssh-dss-cert-v01@openssh.com",
+ "ecdsa-sha2-nistp256-cert-v01@openssh.com",
+ "ecdsa-sha2-nistp384-cert-v01@openssh.com",
+ "ecdsa-sha2-nistp521-cert-v01@openssh.com",
+ "ssh-ed25519-cert-v01@openssh.com",
+ "ssh-rsa",
+ "ssh-dss",
+ "ecdsa-sha2-nistp256",
+ "ecdsa-sha2-nistp384",
+ "ecdsa-sha2-nistp521",
+ "ssh-ed25519",
+ ]
+)
+
+KeyAlgorithms = ListOf.with_args(KeyAlgorithm())
+
+# From lib/ssh/common.go -- allSupportedCiphers
+CipherAlgorithm = String.with_args(
+ doc="An ssh cipher algorithm identifier, named according to section 6 of https://www.ietf.org/rfc/rfc4251.txt; see https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-16 for standard values.",
+ examples=[
+ "aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com",
+ "aes128-cbc", "3des-cbc", "arcfour256", "arcfour128", "arcfour",
+ ]
+)
+
+CipherAlgorithms = ListOf.with_args(CipherAlgorithm())
+
+# From lib/ssh/common.go -- supportedMACs.
+MACAlgorithm = String.with_args(
+ doc="An ssh MAC algorithm identifier, named according to section 6 of https://www.ietf.org/rfc/rfc4251.txt; see https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-18 for standard values.",
+ examples=["hmac-sha2-256", "hmac-sha1", "hmac-sha1-96"]
+)
+MACAlgorithms = ListOf.with_args(MACAlgorithm())
+
+# From lib/ssh/common.go -- supportedCompressions
+CompressionAlgorithm = String.with_args(
+ doc="An ssh compression algorithm identifier, named according to section 6 of https://www.ietf.org/rfc/rfc4251.txt; see https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-20 for standard values.",
+ examples=["none", "zlib"]
+)
+CompressionAlgorithms = ListOf.with_args(CompressionAlgorithm())
+
+LanguageTag = String.with_args(doc="A language tag, as defined in https://www.ietf.org/rfc/rfc3066.txt.")
+LanguageTags = ListOf.with_args(LanguageTag(), doc="A name-list of language tags in order of preference.")
# zgrab2/lib/ssh/messages.go: (Json)kexInitMsg
-zgrab2_ssh_kex_init_message = SubRecord({
+KexInitMessage = SubRecordType({
"cookie": Binary(),
- "kex_algorithms": ListOf(String()),
- "host_key_algorithms": ListOf(String()),
- "client_to_server_ciphers": ListOf(String()),
- "server_to_client_ciphers": ListOf(String()),
- "client_to_server_macs": ListOf(String()),
- "server_to_client_macs": ListOf(String()),
- "client_to_server_compression": ListOf(String()),
- "server_to_client_compression": ListOf(String()),
- "client_to_server_languages": ListOf(String()),
- "server_to_client_languages": ListOf(String()),
+ "kex_algorithms": KexAlgorithms(doc="Key exchange algorithms used in the handshake."),
+ "host_key_algorithms": KeyAlgorithms(doc="Asymmetric key algorithms for the host key supported by the client."),
+ "client_to_server_ciphers": CipherAlgorithms(),
+ "server_to_client_ciphers": CipherAlgorithms(),
+ "client_to_server_macs": MACAlgorithms(),
+ "server_to_client_macs": MACAlgorithms(),
+ "client_to_server_compression": CompressionAlgorithms(),
+ "server_to_client_compression": CompressionAlgorithms(),
+ "client_to_server_languages": LanguageTags(),
+ "server_to_client_languages": LanguageTags(),
"first_kex_follows": Boolean(),
"reserved": Unsigned32BitInteger(),
})
# zgrab2/lib/ssh/log.go: EndpointId
-zgrab2_ssh_endpoint_id = SubRecord({
+EndpointID = SubRecordType({
"raw": String(),
"version": String(),
"software": String(),
- "comment": String()
+ "comment": String(),
+})
+
+# This could be merged into a single class with e.g. an analyzed param,
+# but it's probably clearer to just duplicate it.
+AnalyzedEndpointID = SubRecordType({
+ "raw": AnalyzedString(),
+ "version": String(),
+ "software": AnalyzedString(),
+ "comment": AnalyzedString(),
})
# zgrab2/lib/ssh/kex.go: kexResult
-zgrab2_ssh_kex_result = SubRecord({
+KexResult = SubRecordType({
"H": Binary(),
"K": Binary(),
"session_id": Binary()
@@ -45,47 +126,53 @@ ED25519PublicKey = SubRecordType({
"public_bytes": Binary(),
})
+# zgrab2/lib/ssh/kex.go: curve25519sha256JsonLogParameters (via curve25519sha256)
+Curve25519SHA256Params = SubRecordType({
+ "client_public": Binary(required=False),
+ "client_private": Binary(required=False),
+ "server_public": Binary(required=False),
+})
+
# zgrab2/lib/ssh/certs.go: JsonSignature
-xssh_signature = SubRecord({
+Signature = SubRecordType({
"parsed": SubRecord({
- "algorithm": String(),
+ "algorithm": KeyAlgorithm(),
"value": Binary(),
}),
"raw": Binary(),
"h": Binary(),
})
-# zgrab/ztools/keys/ecdhe.go: ECDHPrivateParams
-golang_crypto_param = SubRecord({
- "value":Binary(),
- "length":Unsigned32BitInteger()
-})
-
# lib/ssh/kex.go: PublicKeyJsonLog, sans the certkey_public_key (since that would create a loop)
SSHPublicKey = SubRecordType({
"raw": Binary(),
"fingerprint_sha256": String(),
+ # TODO: Enum? Obviously must serialize to one of rsa/dsa/ecdsa/ed25519_public_key...
"algorithm": String(),
- "rsa_public_key": RSAPublicKey(),
- "dsa_public_key": DSAPublicKey(),
- "ecdsa_public_key": ECDSAPublicKey(),
+ # For compatiblity with ztag
+ "key_algorithm":String(),
+ "rsa_public_key": zcrypto.RSAPublicKey(),
+ "dsa_public_key": zcrypto.DSAPublicKey(),
+ "ecdsa_public_key": zcrypto.ECDSAPublicKey(),
"ed25519_public_key": ED25519PublicKey(),
})
+CertType = SubRecordType({
+ "id": Enum(values=[1, 2], doc="The numerical certificate type value. 1 identifies user certificates, 2 identifies host certificates."),
+ "name": Enum(values=["USER", "HOST", "unknown"], doc="The human-readable name for the certificate type."),
+})
+
# lib/ssh/certs.go: JsonCertificate
-SSHPublicKeyCert = SubRecordType({
+SSHPublicKeyCert = SubRecord.with_args({
# TODO: Use / include our cert type here, or maybe somewhere else in the response?
"certkey_public_key": SubRecord({
- "nonce":Binary(),
- # This works, since SSHPublicKey() does not include certkey_public_key.
+ "nonce": Binary(),
+ # Note that this is not recursive, since SSHPublicKey() does not include certkey_public_key.
"key": SSHPublicKey(),
- "serial": String(),
- "cert_type": SubRecord({
- "id": Unsigned32BitInteger(),
- "name": String(),
- }),
- "key_id": String(),
- "valid_principals": ListOf(String()),
+ "serial": String(doc="The certificate serial number, encoded as a base-10 string."),
+ "cert_type": CertType(),
+ "key_id": String(doc="A free-form text field filled in by the CA at the time of signing, intended to identify the principal in log messages."),
+ "valid_principals": ListOf(String(), doc="Names for which this certificate is valid; hostnames for cert_type=HOST certificates and usernames for cert_type=USER certificates."),
"validity": SubRecord({
"valid_after": DateTime(doc="Timestamp of when certificate is first valid. Timezone is UTC."),
"valid_before": DateTime(doc="Timestamp of when certificate expires. Timezone is UTC."),
@@ -93,7 +180,7 @@ SSHPublicKeyCert = SubRecordType({
}),
"reserved": Binary(),
"signature_key": SSHPublicKey(),
- "signature": xssh_signature,
+ "signature": Signature(),
"parse_error": String(),
"extensions": SubRecord({
"known": SubRecord({
@@ -116,53 +203,47 @@ SSHPublicKeyCert = SubRecordType({
}, extends=SSHPublicKey())
+# zgrab2/lib/ssh/common.go: directionAlgorithms
+DirectionAlgorithms = SubRecordType({
+ "cipher": CipherAlgorithm(),
+ "mac": MACAlgorithm(),
+ "compression": CompressionAlgorithm(),
+})
+
+# zgrab2/lib/ssh/kex.go: interface kexAlgorithm
+# Searching usages of kexAlgorithm turns up:
+# - dhGroup: dh_params, server_signature, server_host_key
+# - ecdh: ecdh_params, server_signature, server_host_key
+# - curve25519sha256: curve25519_sha256_params, server_signature, server_host_key
+# - dhGEXSHA: dh_params, server_signature, server_host_key
+KeyExchange = SubRecordType({
+ "curve25519_sha256_params": Curve25519SHA256Params(),
+ "ecdh_params": zcrypto.ECDHParams(),
+ "dh_params": zcrypto.DHParams(),
+ "server_signature": Signature(),
+ "server_host_key": SSHPublicKeyCert(),
+})
+
+# zgrab2/lib/ssh/common.go: algorithms (aux in MarshalJSON)
+AlgorithmSelection = SubRecordType({
+ "dh_kex_algorithm": KexAlgorithm(),
+ "host_key_algorithm": KeyAlgorithm(),
+ "client_to_server_alg_group": DirectionAlgorithms(),
+ "server_to_client_alg_group": DirectionAlgorithms(),
+})
+
# zgrab2/lib/ssh/log.go: HandshakeLog
# TODO: Can ssh re-use any of the generic TLS model?
ssh_scan_response = SubRecord({
"result": SubRecord({
- "server_id": SubRecord({
- "raw": AnalyzedString(),
- "version": String(),
- "software": AnalyzedString(),
- "comment": AnalyzedString(),
- }),
- "client_id": zgrab2_ssh_endpoint_id,
- "server_key_exchange": zgrab2_ssh_kex_init_message,
- "client_key_exchange": zgrab2_ssh_kex_init_message,
- "algorithm_selection": SubRecord({
- "dh_kex_algorithm": String(),
- "host_key_algorithm": String(),
- "client_to_server_alg_group": SubRecord({
- "cipher": String(),
- "mac": String(),
- "compression": String(),
- }),
- "server_to_client_alg_group": SubRecord({
- "cipher": String(),
- "mac": String(),
- "compression": String(),
- }),
- }),
- "key_exchange": SubRecord({
- "curve25519_sha256_params": SubRecord({
- "server_public": Binary(),
- }),
- "ecdh_params": SubRecord({
- "server_public": SubRecord({
- "x": golang_crypto_param,
- "y": golang_crypto_param,
- }),
- }),
- "dh_params": SubRecord({
- "prime": golang_crypto_param,
- "generator": golang_crypto_param,
- "server_public": golang_crypto_param,
- }),
- "server_signature": xssh_signature,
- "server_host_key": SSHPublicKeyCert(),
- }),
+ "server_id": AnalyzedEndpointID(),
+ "client_id": EndpointID(),
+ "server_key_exchange": KexInitMessage(),
+ "client_key_exchange": KexInitMessage(),
+ "algorithm_selection": AlgorithmSelection(),
+ "key_exchange": KeyExchange(),
"userauth": ListOf(String()),
- "crypto": zgrab2_ssh_kex_result
+ "crypto": KexResult(),
})
}, extends=zgrab2.base_scan_response)
diff --git a/schemas/telnet.py b/schemas/telnet.py
index 2a28ae4..a06afe8 100644
--- a/schemas/telnet.py
+++ b/schemas/telnet.py
@@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
-import schemas.zgrab2 as zgrab2
+import zgrab2 as zgrab2
telnet_option = SubRecord({
"name": String(),

@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
bacnet_scan_response = SubRecord({
"result": SubRecord({

@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
dnp3_scan_response = SubRecord({
"result": SubRecord({

@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
fox_scan_response = SubRecord({
'result': SubRecord({

@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
# modules/ftp.go - FTPScanResults
ftp_scan_response = SubRecord({

@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
# lib/http/header.go: knownHeaders
http_known_headers = [

@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
imap_scan_response = SubRecord({
"result": SubRecord({

@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
mei_object_names = [
'vendor',

@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
ENCRYPT_MODES = [
"ENCRYPT_OFF",

@ -5,9 +5,9 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
from schemas.zgrab2 import DebugOnly
from zgrab2 import DebugOnly
# zgrab2/lib/mysql/mysql.go: GetServerStatusFlags()
mysql_server_status_flags = zgrab2.FlagsSet([

@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
ntp_short = SubRecord({
"seconds": Unsigned16BitInteger(),

@ -6,7 +6,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
FlagsSet = zgrab2.FlagsSet

@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
pop3_scan_response = SubRecord({
"result": SubRecord({

@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
# modules/postgres/scanner.go - decodeError() (TODO: Currently an unconstrained
# map[string]string; it is possible to get "unknown (0x%x)" fields, but it

@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
redis_scan_response = SubRecord({
"result": SubRecord({

@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
siemens_scan_response = SubRecord({
'result': SubRecord({

@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
header_log = {
'protocol_id': Binary(),

@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
smtp_scan_response = SubRecord({
"result": SubRecord({

@ -5,36 +5,117 @@ from zschema.leaves import *
from zschema.compounds import *
import zschema.registry
from schemas.zcrypto import *
import schemas.zgrab2 as zgrab2
import schemas.zcrypto as zcrypto
import zgrab2 as zgrab2
# NOTE: Despite the fact that we have e.g. "supportedHostKeyAlgos",
# "allSupportedCiphers", etc, including a different value is not syntactically
# incorrect...so all of the following algorithm identifiers are Strings with
# examples=[...], rather tha Enums with values=[...].
# lib/ssh/common.go -- allSupportedKexAlgos
KexAlgorithm = String.with_args(
doc="An ssh key exchange algorithm identifier, named according to section 6 of https://www.ietf.org/rfc/rfc4251.txt; see https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-15 for standard values.",
examples=[
"diffie-hellman-group1-sha1",
"diffie-hellman-group14-sha1",
"ecdh-sha2-nistp256",
"ecdh-sha2-nistp384",
"ecdh-sha2-nistp521",
"curve25519-sha256@libssh.org",
"diffie-hellman-group-exchange-sha1",
"diffie-hellman-group-exchange-sha256",
]
)
KexAlgorithms = ListOf.with_args(KexAlgorithm())
# Defined in lib/ssh/common.go -- supportedHostKeyAlgos, though they are
# generated via PublicKey.Type()
KeyAlgorithm = String.with_args(
doc="An ssh public key algorithm identifier, named according to section 6 of https://www.ietf.org/rfc/rfc4251.txt; see https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-19 for standard values.",
examples=[
"ssh-rsa-cert-v01@openssh.com",
"ssh-dss-cert-v01@openssh.com",
"ecdsa-sha2-nistp256-cert-v01@openssh.com",
"ecdsa-sha2-nistp384-cert-v01@openssh.com",
"ecdsa-sha2-nistp521-cert-v01@openssh.com",
"ssh-ed25519-cert-v01@openssh.com",
"ssh-rsa",
"ssh-dss",
"ecdsa-sha2-nistp256",
"ecdsa-sha2-nistp384",
"ecdsa-sha2-nistp521",
"ssh-ed25519",
]
)
KeyAlgorithms = ListOf.with_args(KeyAlgorithm())
# From lib/ssh/common.go -- allSupportedCiphers
CipherAlgorithm = String.with_args(
doc="An ssh cipher algorithm identifier, named according to section 6 of https://www.ietf.org/rfc/rfc4251.txt; see https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-16 for standard values.",
examples=[
"aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com",
"aes128-cbc", "3des-cbc", "arcfour256", "arcfour128", "arcfour",
]
)
CipherAlgorithms = ListOf.with_args(CipherAlgorithm())
# From lib/ssh/common.go -- supportedMACs.
MACAlgorithm = String.with_args(
doc="An ssh MAC algorithm identifier, named according to section 6 of https://www.ietf.org/rfc/rfc4251.txt; see https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-18 for standard values.",
examples=["hmac-sha2-256", "hmac-sha1", "hmac-sha1-96"]
)
MACAlgorithms = ListOf.with_args(MACAlgorithm())
# From lib/ssh/common.go -- supportedCompressions
CompressionAlgorithm = String.with_args(
doc="An ssh compression algorithm identifier, named according to section 6 of https://www.ietf.org/rfc/rfc4251.txt; see https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-20 for standard values.",
examples=["none", "zlib"]
)
CompressionAlgorithms = ListOf.with_args(CompressionAlgorithm())
LanguageTag = String.with_args(doc="A language tag, as defined in https://www.ietf.org/rfc/rfc3066.txt.")
LanguageTags = ListOf.with_args(LanguageTag(), doc="A name-list of language tags in order of preference.")
# zgrab2/lib/ssh/messages.go: (Json)kexInitMsg
zgrab2_ssh_kex_init_message = SubRecord({
KexInitMessage = SubRecordType({
"cookie": Binary(),
"kex_algorithms": ListOf(String()),
"host_key_algorithms": ListOf(String()),
"client_to_server_ciphers": ListOf(String()),
"server_to_client_ciphers": ListOf(String()),
"client_to_server_macs": ListOf(String()),
"server_to_client_macs": ListOf(String()),
"client_to_server_compression": ListOf(String()),
"server_to_client_compression": ListOf(String()),
"client_to_server_languages": ListOf(String()),
"server_to_client_languages": ListOf(String()),
"kex_algorithms": KexAlgorithms(doc="Key exchange algorithms used in the handshake."),
"host_key_algorithms": KeyAlgorithms(doc="Asymmetric key algorithms for the host key supported by the client."),
"client_to_server_ciphers": CipherAlgorithms(),
"server_to_client_ciphers": CipherAlgorithms(),
"client_to_server_macs": MACAlgorithms(),
"server_to_client_macs": MACAlgorithms(),
"client_to_server_compression": CompressionAlgorithms(),
"server_to_client_compression": CompressionAlgorithms(),
"client_to_server_languages": LanguageTags(),
"server_to_client_languages": LanguageTags(),
"first_kex_follows": Boolean(),
"reserved": Unsigned32BitInteger(),
})
# zgrab2/lib/ssh/log.go: EndpointId
zgrab2_ssh_endpoint_id = SubRecord({
EndpointID = SubRecordType({
"raw": String(),
"version": String(),
"software": String(),
"comment": String()
"comment": String(),
})
# This could be merged into a single class with e.g. an analyzed param,
# but it's probably clearer to just duplicate it.
AnalyzedEndpointID = SubRecordType({
"raw": AnalyzedString(),
"version": String(),
"software": AnalyzedString(),
"comment": AnalyzedString(),
})
# zgrab2/lib/ssh/kex.go: kexResult
zgrab2_ssh_kex_result = SubRecord({
KexResult = SubRecordType({
"H": Binary(),
"K": Binary(),
"session_id": Binary()
@ -45,47 +126,53 @@ ED25519PublicKey = SubRecordType({
"public_bytes": Binary(),
})
# zgrab2/lib/ssh/kex.go: curve25519sha256JsonLogParameters (via curve25519sha256)
Curve25519SHA256Params = SubRecordType({
"client_public": Binary(required=False),
"client_private": Binary(required=False),
"server_public": Binary(required=False),
})
# zgrab2/lib/ssh/certs.go: JsonSignature
xssh_signature = SubRecord({
Signature = SubRecordType({
"parsed": SubRecord({
"algorithm": String(),
"algorithm": KeyAlgorithm(),
"value": Binary(),
}),
"raw": Binary(),
"h": Binary(),
})
# zgrab/ztools/keys/ecdhe.go: ECDHPrivateParams
golang_crypto_param = SubRecord({
"value":Binary(),
"length":Unsigned32BitInteger()
})
# lib/ssh/kex.go: PublicKeyJsonLog, sans the certkey_public_key (since that would create a loop)
SSHPublicKey = SubRecordType({
"raw": Binary(),
"fingerprint_sha256": String(),
# TODO: Enum? Obviously must serialize to one of rsa/dsa/ecdsa/ed25519_public_key...
"algorithm": String(),
"rsa_public_key": RSAPublicKey(),
"dsa_public_key": DSAPublicKey(),
"ecdsa_public_key": ECDSAPublicKey(),
# For compatiblity with ztag
"key_algorithm":String(),
"rsa_public_key": zcrypto.RSAPublicKey(),
"dsa_public_key": zcrypto.DSAPublicKey(),
"ecdsa_public_key": zcrypto.ECDSAPublicKey(),
"ed25519_public_key": ED25519PublicKey(),
})
CertType = SubRecordType({
"id": Enum(values=[1, 2], doc="The numerical certificate type value. 1 identifies user certificates, 2 identifies host certificates."),
"name": Enum(values=["USER", "HOST", "unknown"], doc="The human-readable name for the certificate type."),
})
# lib/ssh/certs.go: JsonCertificate
SSHPublicKeyCert = SubRecordType({
SSHPublicKeyCert = SubRecord.with_args({
# TODO: Use / include our cert type here, or maybe somewhere else in the response?
"certkey_public_key": SubRecord({
"nonce":Binary(),
# This works, since SSHPublicKey() does not include certkey_public_key.
"nonce": Binary(),
# Note that this is not recursive, since SSHPublicKey() does not include certkey_public_key.
"key": SSHPublicKey(),
"serial": String(),
"cert_type": SubRecord({
"id": Unsigned32BitInteger(),
"name": String(),
}),
"key_id": String(),
"valid_principals": ListOf(String()),
"serial": String(doc="The certificate serial number, encoded as a base-10 string."),
"cert_type": CertType(),
"key_id": String(doc="A free-form text field filled in by the CA at the time of signing, intended to identify the principal in log messages."),
"valid_principals": ListOf(String(), doc="Names for which this certificate is valid; hostnames for cert_type=HOST certificates and usernames for cert_type=USER certificates."),
"validity": SubRecord({
"valid_after": DateTime(doc="Timestamp of when certificate is first valid. Timezone is UTC."),
"valid_before": DateTime(doc="Timestamp of when certificate expires. Timezone is UTC."),
@ -93,7 +180,7 @@ SSHPublicKeyCert = SubRecordType({
}),
"reserved": Binary(),
"signature_key": SSHPublicKey(),
"signature": xssh_signature,
"signature": Signature(),
"parse_error": String(),
"extensions": SubRecord({
"known": SubRecord({
@ -116,53 +203,47 @@ SSHPublicKeyCert = SubRecordType({
}, extends=SSHPublicKey())
# zgrab2/lib/ssh/common.go: directionAlgorithms
DirectionAlgorithms = SubRecordType({
"cipher": CipherAlgorithm(),
"mac": MACAlgorithm(),
"compression": CompressionAlgorithm(),
})
# zgrab2/lib/ssh/kex.go: interface kexAlgorithm
# Searching usages of kexAlgorithm turns up:
# - dhGroup: dh_params, server_signature, server_host_key
# - ecdh: ecdh_params, server_signature, server_host_key
# - curve25519sha256: curve25519_sha256_params, server_signature, server_host_key
# - dhGEXSHA: dh_params, server_signature, server_host_key
KeyExchange = SubRecordType({
"curve25519_sha256_params": Curve25519SHA256Params(),
"ecdh_params": zcrypto.ECDHParams(),
"dh_params": zcrypto.DHParams(),
"server_signature": Signature(),
"server_host_key": SSHPublicKeyCert(),
})
# zgrab2/lib/ssh/common.go: algorithms (aux in MarshalJSON)
AlgorithmSelection = SubRecordType({
"dh_kex_algorithm": KexAlgorithm(),
"host_key_algorithm": KeyAlgorithm(),
"client_to_server_alg_group": DirectionAlgorithms(),
"server_to_client_alg_group": DirectionAlgorithms(),
})
# zgrab2/lib/ssh/log.go: HandshakeLog
# TODO: Can ssh re-use any of the generic TLS model?
ssh_scan_response = SubRecord({
"result": SubRecord({
"server_id": SubRecord({
"raw": AnalyzedString(),
"version": String(),
"software": AnalyzedString(),
"comment": AnalyzedString(),
}),
"client_id": zgrab2_ssh_endpoint_id,
"server_key_exchange": zgrab2_ssh_kex_init_message,
"client_key_exchange": zgrab2_ssh_kex_init_message,
"algorithm_selection": SubRecord({
"dh_kex_algorithm": String(),
"host_key_algorithm": String(),
"client_to_server_alg_group": SubRecord({
"cipher": String(),
"mac": String(),
"compression": String(),
}),
"server_to_client_alg_group": SubRecord({
"cipher": String(),
"mac": String(),
"compression": String(),
}),
}),
"key_exchange": SubRecord({
"curve25519_sha256_params": SubRecord({
"server_public": Binary(),
}),
"ecdh_params": SubRecord({
"server_public": SubRecord({
"x": golang_crypto_param,
"y": golang_crypto_param,
}),
}),
"dh_params": SubRecord({
"prime": golang_crypto_param,
"generator": golang_crypto_param,
"server_public": golang_crypto_param,
}),
"server_signature": xssh_signature,
"server_host_key": SSHPublicKeyCert(),
}),
"server_id": AnalyzedEndpointID(),
"client_id": EndpointID(),
"server_key_exchange": KexInitMessage(),
"client_key_exchange": KexInitMessage(),
"algorithm_selection": AlgorithmSelection(),
"key_exchange": KeyExchange(),
"userauth": ListOf(String()),
"crypto": zgrab2_ssh_kex_result
"crypto": KexResult(),
})
}, extends=zgrab2.base_scan_response)

@ -5,7 +5,7 @@ from zschema.compounds import *
import zschema.registry
import schemas.zcrypto as zcrypto
import schemas.zgrab2 as zgrab2
import zgrab2 as zgrab2
telnet_option = SubRecord({
"name": String(),

1
schemas/testdata/ftp-authtls.json vendored Normal file

File diff suppressed because one or more lines are too long

1
schemas/testdata/ftp-default.json vendored Normal file

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"ftp":{"status":"success","protocol":"ftp","result":{"banner":"220 (vsFTPd 3.0.3)\r\n"},"timestamp":"2018-04-06T19:37:52Z"}}}

1
schemas/testdata/http-http.json vendored Normal file

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"http":{"status":"success","protocol":"http","result":{"response":{"status_line":"200 OK","status_code":200,"protocol":{"name":"HTTP/1.1","major":1,"minor":1},"headers":{"accept_ranges":["bytes"],"content_length":["36"],"content_type":["text/html"],"last_modified":["Fri, 09 Feb 2018 20:18:50 GMT"],"server":["lighttpd/1.4.35"],"unknown":[{"key":"etag","value":["\"2262550883\""]},{"key":"date","value":["Fri, 06 Apr 2018 19:38:09 GMT"]}]},"body":"\u003chtml\u003e\u003cbody\u003eHTTP INDEX\u003c/body\u003e\u003c/html\u003e","body_sha256":"c11fdc020dbb3150da741f51dcf0423c5ce93a798e91bd5c1957ea7299f4e103","content_length":36,"request":{"url":{"scheme":"http","host":"target","path":"/"},"method":"GET","headers":{"unknown":[{"key":"accept","value":["*/*"]},{"key":"user_agent","value":["Mozilla/5.0 zgrab/0.x"]}]},"host":"target"}}},"timestamp":"2018-04-06T19:38:09Z"}}}

1
schemas/testdata/http-https.json vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
schemas/testdata/mysql-5.5.json vendored Normal file

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"mysql":{"status":"success","protocol":"mysql","result":{"protocol_version":10,"server_version":"5.5.58","connection_id":1,"auth_plugin_data":"aWZFZlJGRm97PVove0FuJ3Q4VzAA","character_set":8,"status_flags":{"SERVER_STATUS_AUTOCOMMIT":true},"capability_flags":{"CLIENT_COMPRESS":true,"CLIENT_CONNECT_WITH_DB":true,"CLIENT_FOUND_ROWS":true,"CLIENT_IGNORE_SIGPIPE":true,"CLIENT_IGNORE_SPACE":true,"CLIENT_INTERACTIVE":true,"CLIENT_LOCAL_FILES":true,"CLIENT_LONG_FLAG":true,"CLIENT_LONG_PASSWORD":true,"CLIENT_MULTI_RESULTS":true,"CLIENT_MULTI_STATEMENTS":true,"CLIENT_NO_SCHEMA":true,"CLIENT_ODBC":true,"CLIENT_PLUGIN_AUTH":true,"CLIENT_PROTOCOL_41":true,"CLIENT_PS_MULTI_RESULTS":true,"CLIENT_RESERVED":true,"CLIENT_SECURE_CONNECTION":true,"CLIENT_TRANSACTIONS":true},"auth_plugin_name":"mysql_native_password","raw_packets":["CjUuNS41OAABAAAAaWZFZlJGRm8A//cIAgAPgBUAAAAAAAAAAAAAez1aL3tBbid0OFcwAG15c3FsX25hdGl2ZV9wYXNzd29yZAA="]},"timestamp":"2018-04-06T19:39:14Z"}}}

1
schemas/testdata/mysql-5.6.json vendored Normal file

@ -0,0 +1 @@
{"ip":"172.17.0.4","domain":"target","data":{"mysql":{"status":"success","protocol":"mysql","result":{"protocol_version":10,"server_version":"5.6.38","connection_id":1,"auth_plugin_data":"MEtmQVJZRzkoWGZ4SkdmSyd6WCYA","character_set":8,"status_flags":{"SERVER_STATUS_AUTOCOMMIT":true},"capability_flags":{"CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS":true,"CLIENT_COMPRESS":true,"CLIENT_CONNECT_ATTRS":true,"CLIENT_CONNECT_WITH_DB":true,"CLIENT_FOUND_ROWS":true,"CLIENT_IGNORE_SIGPIPE":true,"CLIENT_IGNORE_SPACE":true,"CLIENT_INTERACTIVE":true,"CLIENT_LOCAL_FILES":true,"CLIENT_LONG_FLAG":true,"CLIENT_LONG_PASSWORD":true,"CLIENT_MULTI_RESULTS":true,"CLIENT_MULTI_STATEMENTS":true,"CLIENT_NO_SCHEMA":true,"CLIENT_ODBC":true,"CLIENT_PLUGIN_AUTH":true,"CLIENT_PLUGIN_AUTH_LEN_ENC_CLIENT_DATA":true,"CLIENT_PROTOCOL_41":true,"CLIENT_PS_MULTI_RESULTS":true,"CLIENT_RESERVED":true,"CLIENT_SECURE_CONNECTION":true,"CLIENT_TRANSACTIONS":true},"auth_plugin_name":"mysql_native_password","raw_packets":["CjUuNi4zOAABAAAAMEtmQVJZRzkA//cIAgB/gBUAAAAAAAAAAAAAKFhmeEpHZksnelgmAG15c3FsX25hdGl2ZV9wYXNzd29yZAA="]},"timestamp":"2018-04-06T19:39:16Z"}}}

1
schemas/testdata/mysql-5.7.json vendored Normal file

File diff suppressed because one or more lines are too long

1
schemas/testdata/mysql-8.0.json vendored Normal file

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
{"ip":"172.17.0.4","domain":"target","data":{"ntp":{"status":"success","protocol":"ntp","result":{"version":3,"time":"2018-04-06T19:39:54.40363944Z","time_response":{"leap_indicator":3,"version":3,"mode":4,"stratum":0,"poll":3,"precision":-22,"root_delay":{"seconds":0,"fraction":0},"root_dispersion":{"seconds":0,"fraction":16},"reference_id":"SU5JVA==","reference_timestamp":{"seconds":0,"fraction":0},"origin_timestamp":{"seconds":0,"fraction":0},"receive_timestamp":{"seconds":3732032394,"fraction":1733618196},"transmit_timestamp":{"seconds":3732032394,"fraction":1738320156}},"monlist_response":"AAAAAgAAAAAAAAAAAAAABKwRAAWlHQMDAAAAAJTbAwMAAAAAAAAAAAAAAAAAAAAA","monlist_header":{"is_response":true,"has_more":false,"version":3,"mode":7,"is_authenticated":false,"sequence_number":0,"implementation_number":"IMPL_XNTPD","request_code":"REQ_MON_GETLIST","error":"INFO_OKAY","num_items":1,"mbz":0,"item_size":48}},"timestamp":"2018-04-06T19:39:54Z"}}}

@ -0,0 +1 @@
{"ip":"172.17.0.4","domain":"target","data":{"ntp":{"status":"success","protocol":"ntp","result":{"version":3,"time":"2018-04-06T19:39:50.515312746Z","time_response":{"leap_indicator":3,"version":3,"mode":4,"stratum":0,"poll":3,"precision":-22,"root_delay":{"seconds":0,"fraction":0},"root_dispersion":{"seconds":0,"fraction":12},"reference_id":"SU5JVA==","reference_timestamp":{"seconds":0,"fraction":0},"origin_timestamp":{"seconds":0,"fraction":0},"receive_timestamp":{"seconds":3732032390,"fraction":2213251392},"transmit_timestamp":{"seconds":3732032390,"fraction":2214061226}},"monlist_response":"AAAAAQAAAAAAAAAAAAAAA6wRAAWsEQAEAAAAAZTbAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","monlist_header":{"is_response":true,"has_more":false,"version":3,"mode":7,"is_authenticated":false,"sequence_number":0,"implementation_number":"IMPL_XNTPD","request_code":"REQ_MON_GETLIST_1","error":"INFO_OKAY","num_items":1,"mbz":0,"item_size":72}},"timestamp":"2018-04-06T19:39:50Z"}}}

@ -0,0 +1 @@
{"ip":"172.17.0.4","domain":"target","data":{"ntp":{"status":"success","protocol":"ntp","result":{"monlist_response":"AAAAAgAAAAIAAAAAAAAAA6wRAAWsEQAEAAAAAZTbAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","monlist_header":{"is_response":true,"has_more":false,"version":3,"mode":7,"is_authenticated":false,"sequence_number":0,"implementation_number":"IMPL_XNTPD","request_code":"REQ_MON_GETLIST_1","error":"INFO_OKAY","num_items":1,"mbz":0,"item_size":72}},"timestamp":"2018-04-06T19:39:52Z"}}}

@ -0,0 +1 @@
{"ip":"172.17.0.4","domain":"target","data":{"ntp":{"status":"success","protocol":"ntp","result":{"monlist_response":"AAAAAgAAAAIAAAAAAAAABKwRAAWlHQMDAAAAAJTbAwMAAAAAAAAAAAAAAAAAAAAA","monlist_header":{"is_response":true,"has_more":false,"version":3,"mode":7,"is_authenticated":false,"sequence_number":0,"implementation_number":"IMPL_XNTPD","request_code":"REQ_MON_GETLIST","error":"INFO_OKAY","num_items":1,"mbz":0,"item_size":48}},"timestamp":"2018-04-06T19:39:56Z"}}}

@ -0,0 +1 @@
{"ip":"172.17.0.4","domain":"target","data":{"ntp":{"status":"success","protocol":"ntp","result":{"version":3,"time":"2018-04-06T19:39:48.515473906Z","time_response":{"leap_indicator":3,"version":3,"mode":4,"stratum":0,"poll":3,"precision":-22,"root_delay":{"seconds":0,"fraction":0},"root_dispersion":{"seconds":0,"fraction":10},"reference_id":"SU5JVA==","reference_timestamp":{"seconds":0,"fraction":0},"origin_timestamp":{"seconds":0,"fraction":0},"receive_timestamp":{"seconds":3732032388,"fraction":2213943570},"transmit_timestamp":{"seconds":3732032388,"fraction":2215576491}},"monlist_response":"AAAAAQAAAAAAAAAAAAAAAqwRAAWpLQMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","monlist_header":{"is_response":true,"has_more":false,"version":3,"mode":7,"is_authenticated":false,"sequence_number":0,"implementation_number":"IMPL_XNTPD","request_code":"REQ_MON_GETLIST","error":"INFO_OKAY","num_items":1,"mbz":0,"item_size":48}},"timestamp":"2018-04-06T19:39:48Z"}}}

@ -0,0 +1 @@
{"ip":"172.17.0.4","domain":"target","data":{"ntp":{"status":"success","protocol":"ntp","result":{"version":3,"time":"2018-04-06T19:39:46.56800099Z","time_response":{"leap_indicator":3,"version":3,"mode":4,"stratum":0,"poll":3,"precision":-22,"root_delay":{"seconds":0,"fraction":0},"root_dispersion":{"seconds":0,"fraction":8},"reference_id":"SU5JVA==","reference_timestamp":{"seconds":0,"fraction":0},"origin_timestamp":{"seconds":0,"fraction":0},"receive_timestamp":{"seconds":3732032386,"fraction":2439545680},"transmit_timestamp":{"seconds":3732032386,"fraction":2441496926}}},"timestamp":"2018-04-06T19:39:46Z"}}}

1
schemas/testdata/ntp-openntp.json vendored Normal file

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"ntp":{"status":"success","protocol":"ntp","result":{"version":3,"time":"2018-04-06T19:39:39.477943897Z","time_response":{"leap_indicator":3,"version":3,"mode":4,"stratum":0,"poll":0,"precision":-29,"root_delay":{"seconds":0,"fraction":0},"root_dispersion":{"seconds":0,"fraction":0},"reference_id":"AAAAAA==","reference_timestamp":{"seconds":0,"fraction":0},"origin_timestamp":{"seconds":0,"fraction":0},"receive_timestamp":{"seconds":3732032379,"fraction":2052753407},"transmit_timestamp":{"seconds":3732032379,"fraction":2052788223}}},"timestamp":"2018-04-06T19:39:39Z"}}}

1
schemas/testdata/pop3-banner.json vendored Normal file

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"pop3":{"status":"success","protocol":"pop3","result":{"banner":"+OK\r\n"},"timestamp":"2018-04-06T19:40:08Z"}}}

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"pop3":{"status":"success","protocol":"pop3","result":{"banner":"+OK\r\n","quit":"+OK\r\n"},"timestamp":"2018-04-06T19:40:10Z"}}}

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"pop3":{"status":"success","protocol":"pop3","result":{"banner":"+OK\r\n","help":"-ERR\r\n","quit":"+OK\r\n"},"timestamp":"2018-04-06T19:40:12Z"}}}

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"pop3":{"status":"success","protocol":"pop3","result":{"banner":"+OK\r\n","noop":"-ERR\r\n","help":"-ERR\r\n","quit":"+OK\r\n"},"timestamp":"2018-04-06T19:40:14Z"}}}

@ -0,0 +1 @@
{"ip":"172.17.0.12","domain":"target","data":{"postgres":{"status":"success","protocol":"postgres","result":{"supported_versions":"FATAL: unsupported frontend protocol 0.0: server supports 2.0 to 3.0","protocol_error":{"code":"0A000","file":"postmaster.c","line":"2065","message":"unsupported frontend protocol 255.255: server supports 2.0 to 3.0","routine":"ProcessStartupPacket","severity":"FATAL","severity_v":"FATAL"},"startup_error":{"code":"28000","file":"postmaster.c","line":"2175","message":"no PostgreSQL user name specified in startup packet","routine":"ProcessStartupPacket","severity":"FATAL","severity_v":"FATAL"},"is_ssl":false},"timestamp":"2018-04-06T19:41:29Z"}}}

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
{"ip":"172.17.0.4","domain":"target","data":{"postgres":{"status":"success","protocol":"postgres","result":{"supported_versions":"FATAL: unsupported frontend protocol 0.0: server supports 1.0 to 3.0","protocol_error":{"code":"0A000","file":"postmaster.c","line":"1995","message":"unsupported frontend protocol 255.255: server supports 1.0 to 3.0","routine":"ProcessStartupPacket","severity":"FATAL"},"startup_error":{"code":"28000","file":"postmaster.c","line":"2090","message":"no PostgreSQL user name specified in startup packet","routine":"ProcessStartupPacket","severity":"FATAL"},"is_ssl":false},"timestamp":"2018-04-06T19:41:06Z"}}}

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
{"ip":"172.17.0.6","domain":"target","data":{"postgres":{"status":"success","protocol":"postgres","result":{"supported_versions":"FATAL: unsupported frontend protocol 0.0: server supports 1.0 to 3.0","protocol_error":{"code":"0A000","file":"postmaster.c","line":"2010","message":"unsupported frontend protocol 255.255: server supports 1.0 to 3.0","routine":"ProcessStartupPacket","severity":"FATAL"},"startup_error":{"code":"28000","file":"postmaster.c","line":"2118","message":"no PostgreSQL user name specified in startup packet","routine":"ProcessStartupPacket","severity":"FATAL"},"is_ssl":false},"timestamp":"2018-04-06T19:41:11Z"}}}

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
{"ip":"172.17.0.8","domain":"target","data":{"postgres":{"status":"success","protocol":"postgres","result":{"supported_versions":"FATAL: unsupported frontend protocol 0.0: server supports 1.0 to 3.0","protocol_error":{"code":"0A000","file":"postmaster.c","line":"2015","message":"unsupported frontend protocol 255.255: server supports 1.0 to 3.0","routine":"ProcessStartupPacket","severity":"FATAL"},"startup_error":{"code":"28000","file":"postmaster.c","line":"2125","message":"no PostgreSQL user name specified in startup packet","routine":"ProcessStartupPacket","severity":"FATAL"},"is_ssl":false},"timestamp":"2018-04-06T19:41:17Z"}}}

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
{"ip":"172.17.0.10","domain":"target","data":{"postgres":{"status":"success","protocol":"postgres","result":{"supported_versions":"FATAL: unsupported frontend protocol 0.0: server supports 1.0 to 3.0","protocol_error":{"code":"0A000","file":"postmaster.c","line":"2031","message":"unsupported frontend protocol 255.255: server supports 1.0 to 3.0","routine":"ProcessStartupPacket","severity":"FATAL","severity_v":"FATAL"},"startup_error":{"code":"28000","file":"postmaster.c","line":"2141","message":"no PostgreSQL user name specified in startup packet","routine":"ProcessStartupPacket","severity":"FATAL","severity_v":"FATAL"},"is_ssl":false},"timestamp":"2018-04-06T19:41:23Z"}}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"redis":{"status":"success","protocol":"redis","result":{"commands":["PING","INFO","NONEXISTENT","QUIT"],"raw_command_output":["LU5PQVVUSCBBdXRoZW50aWNhdGlvbiByZXF1aXJlZC4NCg==","LU5PQVVUSCBBdXRoZW50aWNhdGlvbiByZXF1aXJlZC4NCg==","LUVSUiB1bmtub3duIGNvbW1hbmQgJ05PTkVYSVNURU5UJw0K","K09LDQo="],"ping_response":"(Error: NOAUTH Authentication required.)","info_response":"(Error: NOAUTH Authentication required.)","quit_response":"OK","nonexistent_response":"(Error: ERR unknown command 'NONEXISTENT')"},"timestamp":"2018-04-06T19:41:52Z"}}}

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"redis":{"status":"success","protocol":"redis","result":{"commands":["PING","INFO","NONEXISTENT","QUIT"],"raw_command_output":["LU5PQVVUSCBBdXRoZW50aWNhdGlvbiByZXF1aXJlZC4NCg==","LU5PQVVUSCBBdXRoZW50aWNhdGlvbiByZXF1aXJlZC4NCg==","LUVSUiB1bmtub3duIGNvbW1hbmQgJ05PTkVYSVNURU5UJw0K","K09LDQo="],"ping_response":"(Error: NOAUTH Authentication required.)","info_response":"(Error: NOAUTH Authentication required.)","quit_response":"OK","nonexistent_response":"(Error: ERR unknown command 'NONEXISTENT')"},"timestamp":"2018-04-06T19:41:50Z"}}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
schemas/testdata/smtp-00.json vendored Normal file

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"smtp":{"status":"success","protocol":"smtp","result":{"banner":"220 ba06a6536f7e ESMTP qpsmtpd 0.94 ready; send us your mail, but not your spam.\r\n"},"timestamp":"2018-04-06T19:42:03Z"}}}

1
schemas/testdata/smtp-ehlo.03.json vendored Normal file

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"smtp":{"status":"success","protocol":"smtp","result":{"banner":"220 ba06a6536f7e ESMTP qpsmtpd 0.94 ready; send us your mail, but not your spam.\r\n","ehlo":"501 ehlo requires domain/address - see RFC-2821 4.1.1.1\r\n"},"timestamp":"2018-04-06T19:42:10Z"}}}

1
schemas/testdata/smtp-ehlo.04.json vendored Normal file

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"smtp":{"status":"success","protocol":"smtp","result":{"banner":"220 ba06a6536f7e ESMTP qpsmtpd 0.94 ready; send us your mail, but not your spam.\r\n","ehlo":"250-ba06a6536f7e Hi Unknown [172.17.0.4]\r\n250-PIPELINING\r\n250 8BITMIME\r\n"},"timestamp":"2018-04-06T19:42:12Z"}}}

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"smtp":{"status":"success","protocol":"smtp","result":{"banner":"220 ba06a6536f7e ESMTP qpsmtpd 0.94 ready; send us your mail, but not your spam.\r\n","ehlo":"250-ba06a6536f7e Hi Unknown [172.17.0.4]\r\n250-PIPELINING\r\n250 8BITMIME\r\n","quit":"221 ba06a6536f7e closing connection. Have a wonderful day.\r\n"},"timestamp":"2018-04-06T19:42:14Z"}}}

1
schemas/testdata/smtp-helo.01.json vendored Normal file

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"smtp":{"status":"success","protocol":"smtp","result":{"banner":"220 ba06a6536f7e ESMTP qpsmtpd 0.94 ready; send us your mail, but not your spam.\r\n","helo":"501 helo requires domain/address - see RFC-2821 4.1.1.1\r\n"},"timestamp":"2018-04-06T19:42:05Z"}}}

1
schemas/testdata/smtp-helo.02.json vendored Normal file

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"smtp":{"status":"success","protocol":"smtp","result":{"banner":"220 ba06a6536f7e ESMTP qpsmtpd 0.94 ready; send us your mail, but not your spam.\r\n","helo":"250 ba06a6536f7e Hi Unknown [172.17.0.4]; I am so happy to meet you.\r\n"},"timestamp":"2018-04-06T19:42:08Z"}}}

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"smtp":{"status":"success","protocol":"smtp","result":{"banner":"220 ba06a6536f7e ESMTP qpsmtpd 0.94 ready; send us your mail, but not your spam.\r\n","help":"214-This is qpsmtpd 0.94\r\n214-See http://smtpd.develooper.com/\r\n214 To report bugs or send comments, mail to \u003cask@develooper.com\u003e.\r\n","quit":"221 ba06a6536f7e closing connection. Have a wonderful day.\r\n"},"timestamp":"2018-04-06T19:42:16Z"}}}

1
schemas/testdata/ssh-ssh.json vendored Normal file

@ -0,0 +1 @@
{"ip":"172.17.0.3","domain":"target","data":{"ssh":{"status":"success","protocol":"ssh","result":{"server_id":{"raw":"SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.4","version":"2.0","software":"OpenSSH_7.2p2","comment":"Ubuntu-4ubuntu2.4"},"server_key_exchange":{"cookie":"dl2LAEeZ7cvx0xQrjs3PXw==","kex_algorithms":["curve25519-sha256@libssh.org","ecdh-sha2-nistp256","ecdh-sha2-nistp384","ecdh-sha2-nistp521","diffie-hellman-group-exchange-sha256","diffie-hellman-group14-sha1"],"host_key_algorithms":["ssh-rsa","rsa-sha2-512","rsa-sha2-256","ecdsa-sha2-nistp256","ssh-ed25519"],"client_to_server_ciphers":["chacha20-poly1305@openssh.com","aes128-ctr","aes192-ctr","aes256-ctr","aes128-gcm@openssh.com","aes256-gcm@openssh.com"],"server_to_client_ciphers":["chacha20-poly1305@openssh.com","aes128-ctr","aes192-ctr","aes256-ctr","aes128-gcm@openssh.com","aes256-gcm@openssh.com"],"client_to_server_macs":["umac-64-etm@openssh.com","umac-128-etm@openssh.com","hmac-sha2-256-etm@openssh.com","hmac-sha2-512-etm@openssh.com","hmac-sha1-etm@openssh.com","umac-64@openssh.com","umac-128@openssh.com","hmac-sha2-256","hmac-sha2-512","hmac-sha1"],"server_to_client_macs":["umac-64-etm@openssh.com","umac-128-etm@openssh.com","hmac-sha2-256-etm@openssh.com","hmac-sha2-512-etm@openssh.com","hmac-sha1-etm@openssh.com","umac-64@openssh.com","umac-128@openssh.com","hmac-sha2-256","hmac-sha2-512","hmac-sha1"],"client_to_server_compression":["none","zlib@openssh.com"],"server_to_client_compression":["none","zlib@openssh.com"],"first_kex_follows":false,"reserved":0},"algorithm_selection":{"dh_kex_algorithm":"curve25519-sha256@libssh.org","host_key_algorithm":"ecdsa-sha2-nistp256","client_to_server_alg_group":{"cipher":"aes128-ctr","mac":"hmac-sha2-256","compression":"none"},"server_to_client_alg_group":{"cipher":"aes128-ctr","mac":"hmac-sha2-256","compression":"none"}},"key_exchange":{"curve25519_sha256_params":{"server_public":"d4LbboNPD+8feM4s2PjROJW07xbSpBq/rQSldP8SnAI="},"server_signature":{"parsed":{"algorithm":"ecdsa-sha2-nistp256","value":"AAAAIFqqEqz8qdIqvCHDUQzepCw/fRpyQFHaHjkLvg9C+NJ7AAAAIFRVKDWwRPnaRlrvL3147jTgAf4qAehT4D3Q/RW/LvlX"},"raw":"AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAABIAAAAIFqqEqz8qdIqvCHDUQzepCw/fRpyQFHaHjkLvg9C+NJ7AAAAIFRVKDWwRPnaRlrvL3147jTgAf4qAehT4D3Q/RW/LvlX","h":"haFWxro3i4labGImawWJNSwaYHLTXHuGPkftgpn2/Fw="},"server_host_key":{"ecdsa_public_key":{"b":"WsY12Ko6k+ez671VdpiGvGUdBrDMU7D2O848PifSYEs=","curve":"P-256","gx":"axfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpY=","gy":"T+NC4v4af5uO5+tKfA+eFivOM1drMV7Oy7ZAaDe/UfU=","length":256,"n":"/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVE=","p":"/////wAAAAEAAAAAAAAAAAAAAAD///////////////8=","x":"3QgLyFDQbJyY6jJjNOzE4CzMaNC4Yd7Kg94UehDQ+2w=","y":"qKKVU7Mj4ISCphTGoa/fpv9XVVP9EPJ4tXmYdvAbzgs="},"raw":"AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBN0IC8hQ0GycmOoyYzTsxOAszGjQuGHeyoPeFHoQ0PtsqKKVU7Mj4ISCphTGoa/fpv9XVVP9EPJ4tXmYdvAbzgs=","algorithm":"ecdsa-sha2-nistp256","fingerprint_sha256":"691e8c65d86720d072fc5610f8976df184af64a91aea986a2de55a1abc0179dc"}}},"timestamp":"2018-04-06T19:42:32Z"}}}

1
schemas/testdata/telnet-telnet.json vendored Normal file

@ -0,0 +1 @@
{"ip":"172.17.0.2","domain":"target","data":{"telnet":{"status":"success","protocol":"telnet","result":{"banner":"Ubuntu 16.04.3 LTS\r\n5a3511f30de7 login: ","will":[{"name":"Suppress Go Ahead","value":3},{"name":"Status","value":5},{"name":"Suppress Go Ahead","value":3},{"name":"Echo","value":1}],"do":[{"name":"Terminal Type","value":24},{"name":"Terminal Speed","value":32},{"name":"X Display Location","value":35},{"name":"New Environment Option","value":39},{"name":"Echo","value":1},{"name":"Negotiate About Window Size","value":31},{"name":"Remote Flow Control","value":33}]},"timestamp":"2018-04-06T19:42:46Z"}}}

59
schemas/tests.py Normal file

@ -0,0 +1,59 @@
import logging
import sys
import collections
import itertools
import json
import os
import pprint
import os.path
from imp import load_source
import unittest
import zgrab2
logging.basicConfig(stream=sys.stderr)
logger = logging.getLogger("zgrab2-schema-tests")
import zschema
import zschema.registry
def get_data_dir():
return os.path.join(os.path.dirname(os.path.abspath(__file__)), 'testdata')
def get_data_file(file):
return os.path.join(get_data_dir(), file)
def get_data_files():
dir = get_data_dir()
files = os.listdir(dir)
return [
file for file in files if file.endswith(".json")
]
def get_schemas():
return [ item for item in zgrab2.scan_response_types ]
class SchemaTests(unittest.TestCase):
def test_schema(self):
for schema in get_schemas():
logger.error("checking schema %s", schema)
recname = "zgrab2-" + schema
record = zschema.registry.get_schema(recname)
record.to_bigquery(recname)
record.to_es()
record.to_flat("zgrab", schema)
def test_docs(self):
for schema in get_schemas():
logger.error("checking docs %s", schema)
recname = "zgrab2-" + schema
record = zschema.registry.get_schema(recname)
record.docs_es(recname)
record.docs_bq(recname)
def test_validate(self):
record = zschema.registry.get_schema("zgrab2")
for file in get_data_files():
with open(get_data_file(file)) as fp:
record.validate(json.load(fp))