static bool process_ssh1_key_exchange(SSHData *sessionp, Packet *p, uint8_t direction);
static bool process_ssh2_kexinit(SSHData *sessionp, Packet *p, uint8_t direction);
static bool process_ssh2_key_exchange(SSHData *sessionp, Packet *p, uint8_t direction);
+bool is_us_ascii(const char *str, uint16_t size);
unsigned SshFlowData::inspector_id = 0;
{
SshEvent event(SSH_VALIDATION, SSH_INVALID_VERSION, "", pkt_direction, p);
DataBus::publish(pub_id, SshEventIds::STATE_CHANGE, event, p->flow);
+ if (sessp->version == NON_SSH_TRAFFIC)
+ sessp->ssh_aborted = true;
}
}
else if (!(sessp->state_flags & search_dir_keyinit))
}
}
+bool is_us_ascii(const char *str, uint16_t size)
+{
+ for (uint16_t i = 0, count = 0; i < size; i++)
+ {
+ if ((((unsigned char)*str < 32) or (unsigned char)*str > 127) and
+ (((unsigned char)*str != 10 ) and ((unsigned char)*str != 13)))
+ {
+ if ((count == 0) && (unsigned char)*str == '-')
+ {
+ count++;
+ str++;
+ continue;
+ }
+ return false;
+ }
+ str++;
+ }
+ return true;
+}
+
static bool process_ssh_version_string(
SSH_PROTO_CONF* config, SSHData* sessionp, Packet* p, uint8_t direction)
{
// so we will ignore them.
return true;
}
+
+ if (!(is_us_ascii((const char*) p->data + 4, p->dsize - 4)))
+ {
+ sessionp->version = NON_SSH_TRAFFIC;
+ return false;
+ }
+
const char *proto_ver = (const char *)p->data + sizeof(SSH_BANNER) - 1;
const char *proto_ver_end = (const char *)memchr(proto_ver, '-', p->dsize - sizeof(SSH_BANNER));
if (!proto_ver_end)
sessionp->version = SSH_VERSION_1;
}
}
- else
+ else if (((proto_ver[0] >= '3') and (proto_ver[0] <= '9')) and proto_ver[1] == '.')
{
DetectionEngine::queue_event(GID_SSH, SSH_EVENT_VERSION);
sessionp->version = SSH_VERSION_UNKNOWN;
return false;
}
+ else
+ {
+ sessionp->version = NON_SSH_TRAFFIC;
+ return false;
+ }
/* Saw a valid protocol exchange message. Mark the session
* according to the direction.
#define SSH_VERSION_UNKNOWN (0x0)
#define SSH_VERSION_1 (0x1)
#define SSH_VERSION_2 (0x2)
+#define NON_SSH_TRAFFIC (0xF)
// Per-session data block containing current state
// of the SSH inspector for the session.
uint16_t num_enc_pkts; // encrypted packets seen on this session
uint16_t num_client_bytes; // bytes of encrypted data sent by client without a server response
uint32_t state_flags; // Bit vector describing the current state of the session
+ bool ssh_aborted; // Set when the session is not a ssh traffic
};
class SshFlowData : public snort::FlowData
{ CountType::SUM, "total_bytes", "total number of bytes processed" },
{ CountType::NOW, "concurrent_sessions", "total concurrent ssh sessions" },
{ CountType::MAX, "max_concurrent_sessions", "maximum concurrent ssh sessions" },
+ { CountType::SUM, "aborted_sessions", "total session aborted" },
{ CountType::END, nullptr, nullptr }
};