⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spp_ssh.c

📁 入侵检测SNORT.最近更新的基于网络检测的IDS.希望能给大家带来方便.
💻 C
📖 第 1 页 / 共 2 页
字号:
			            _dpd.streamAPI->stop_inspection(             				packetp->stream_session_ptr,             				packetp,             				SSN_DIR_BOTH, -1, 0 ); 					}				}			   }			}			else			{				/* 				 * Have seen a server response, so 				 * this appears to be a valid exchange.				 * Reset suspicious byte count to zero.				 */				sessp->num_client_bytes = 0;			}		}		else		{			/* Have already examined more than the limit			 * of encrypted packets. Both the Gobbles and			 * the CRC32 attacks occur during authentication			 * and therefore cannot be used late in an 			 * encrypted session. For performance purposes,			 * stop examining this session.			 */			_dpd.streamAPI->stop_inspection( 				packetp->stream_session_ptr, 				packetp, 				SSN_DIR_BOTH, -1, 0 );            		}	}    PREPROC_PROFILE_END(sshPerfStats);}/* Retrieves the SSH data block registered with the stream  * session associated w/ the current packet. If none exists, * allocates it and registers it with the stream API.  * * PARAMETERS: * * packetp:	Pointer to the packet from which/in which to * 		retrieve/store the SSH data block. * * RETURNS:	Pointer to an SSH data block, upon success. *		NULL, upon failure. */SSHData* GetSSHData( SFSnortPacket* packetp ){	SSHData* datap = NULL;	/* Sanity check(s) */	if (( !packetp ) || ( !packetp->stream_session_ptr ))	{		return NULL;	}	/* Attempt to get a previously allocated SSH block. If none exists, 	 * allocate and register one with the stream layer.	 */	datap = _dpd.streamAPI->get_application_data( 			packetp->stream_session_ptr, 			PP_SSH );	if ( !datap )	{		datap = malloc( sizeof( SSHData ));		if ( !datap )			return NULL;		/* Initialize to known state. */		memset( datap, 0, sizeof( SSHData ));		/*Register the new SSH data block in the stream session. */		_dpd.streamAPI->set_application_data( 				packetp->stream_session_ptr, 				PP_SSH, datap, FreeSSHData );	}	return datap;}/* Registered as a callback with our SSH data blocks when  * they are added to the underlying stream session. Called * by the stream preprocessor when a session is about to be * destroyed. *  * PARAMETERS: * * idatap:	Pointer to the moribund data. * * RETURNS:	Nothing. */static voidFreeSSHData( void* idatap ){	if ( idatap )	{		free( idatap );	}}/* Validates given port as an SSH server port. * * PARAMETERS: * * port:	Port to validate. * * RETURNS:	SSH_TRUE, if the port is indeed an SSH server port. *		SSH_FALSE, otherwise. */static INLINE intCheckSSHPort( u_int16_t port ){    if ( ssh_config.ports[ PORT_INDEX(port) ] & CONV_PORT( port ) )    {        return SSH_TRUE;    }    return SSH_FALSE;}/* Checks if the string 'str' is 'max' bytes long or longer.  * Returns 0 if 'str' is less than or equal to 'max' bytes; * returns 1 otherwise.*/static INLINE int SSHCheckStrlen(char *str, int max) {    while(*(str++) && max--) ;    if(max > 0) return 0;   /* str size is <= max bytes */    return 1;}/* Attempts to process current packet as a protocol version exchange * packet. This function will be called if either the client or server * protocol version message (or both) has not been sent. * * PARAMETERS: * * sessionp:    Pointer to SSH data for packet's session. * packetp:	Pointer to the packet to inspect. * direction: 	Which direction the packet is going. * known_port:  A pre-configured or default server port is involved. *  * RETURNS:	SSH_SUCCESS, if successfully processed a proto exch msg *		SSH_FAILURE, otherwise. */static intProcessSSHProtocolVersionExchange( SSHData* sessionp, SFSnortPacket* packetp, 	u_int8_t direction, u_int8_t known_port ){	char* version_stringp = (char*) packetp->payload;		u_int8_t version;	/* Get the version. */	if ( packetp->payload_size >= 6 &&          !strncasecmp( version_stringp, "SSH-1.", 6))	{		if (( packetp->payload_size > 7 ) && ( version_stringp[6] == '9') 			&& (version_stringp[7] == '9'))		{			/* SSH 1.99 which is the same as SSH2.0 */			version = SSH_VERSION_2;		}		else		{			version = SSH_VERSION_1;		}		/* CAN-2002-0159 */        /* Verify the version string is not greater than          * SSH_MAX_PROTOVERS_STRING.          * We've already verified the first 6 bytes, so we'll start         * check from &version_string[6] */        if( (ssh_config.EnabledAlerts & SSH_ALERT_SECURECRT ) &&            /* First make sure the payload itself is sufficiently large */             (packetp->payload_size > SSH_MAX_PROTOVERS_STRING) &&            /* CheckStrlen will check if the version string up to              * SSH_MAX_PROTOVERS_STRING+1 since there's no reason to              * continue checking after that point*/             (SSHCheckStrlen(&version_stringp[6], SSH_MAX_PROTOVERS_STRING-6)))        {            ALERT(SSH_EVENT_SECURECRT, SSH_EVENT_SECURECRT_STR);        }	}	else if ( packetp->payload_size >= 6 &&               !strncasecmp( version_stringp, "SSH-2.", 6))	{		version = SSH_VERSION_2;	}	else	{		/* Not SSH on SSH port, CISCO vulnerability */		if ((direction == SSH_DIR_FROM_CLIENT) && 			( known_port != 0 ) && 			( ssh_config.EnabledAlerts & 				SSH_ALERT_PROTOMISMATCH ))		{            ALERT(SSH_EVENT_PROTOMISMATCH, SSH_EVENT_PROTOMISMATCH_STR);		}		return SSH_FAILURE;	}	/* Saw a valid protocol exchange message. Mark the session	 * according to the direction. 	 */	switch( direction )	{		case SSH_DIR_FROM_SERVER:			sessionp->state_flags |= SSH_FLG_SERV_IDSTRING_SEEN;			break;		case SSH_DIR_FROM_CLIENT:			sessionp->state_flags |= SSH_FLG_CLIENT_IDSTRING_SEEN;			break;	}	sessionp->version = version;	return SSH_SUCCESS;	}/* Called to process SSH1 key exchange or SSH2 key exchange init  * messages.  On failure, inspection will be continued, but the packet * will be alerted on, and ignored. * * PARAMETERS: * * sessionp:    Pointer to SSH data for packet's session. * packetp:	Pointer to the packet to inspect. * direction: 	Which direction the packet is going. *  * RETURN:	SSH_SUCCESS, if a valid key exchange message is processed  *		SSH_FAILURE, otherwise. */static int ProcessSSHKeyInitExchange( SSHData* sessionp, SFSnortPacket* packetp, 	u_int8_t direction ){		SSH2Packet* ssh2packetp = NULL;	if ( sessionp->version == SSH_VERSION_1 )	{		u_int32_t length;		u_int8_t padding_length;		u_int8_t message_type;	    /*          * Validate packet payload.         * First 4 bytes should have the SSH packet length,          * minus any padding.         */		if ( packetp->payload_size < 4 )        {            if(ssh_config.EnabledAlerts & SSH_ALERT_PAYSIZE)            {                ALERT(SSH_EVENT_PAYLOAD_SIZE, SSH_PAYLOAD_SIZE_STR);            }			return SSH_FAILURE;        }		/* 		 * SSH1 key exchange is very simple and 		 * consists of only two messages, a server		 * key and a client key message.`		 */		length = ntohl( *((u_int32_t*) packetp->payload) );	    /* Packet payload should be larger than length, due to padding. */		if ( packetp->payload_size < length )		{            if(ssh_config.EnabledAlerts & SSH_ALERT_PAYSIZE)            {                   ALERT(SSH_EVENT_PAYLOAD_SIZE, SSH_PAYLOAD_SIZE_STR);            }			return SSH_FAILURE;		}		padding_length = (u_int8_t)(8 - (length % 8));        /*          * With the padding calculated, verify payload is sufficiently large         * to include the message type.         */        if ( packetp->payload_size < padding_length + 4 + 1)        {            if(ssh_config.EnabledAlerts & SSH_ALERT_PAYSIZE)            {                ALERT(SSH_EVENT_PAYLOAD_SIZE, SSH_PAYLOAD_SIZE_STR);            }			return SSH_FAILURE;        }        		message_type = 		     *( (u_int8_t*) (packetp->payload + padding_length + 4));		switch( message_type )		{			case SSH_MSG_V1_SMSG_PUBLIC_KEY: 				if ( direction == SSH_DIR_FROM_SERVER )				{					sessionp->state_flags |= 						SSH_FLG_SERV_PKEY_SEEN;				}				else if ( ssh_config.EnabledAlerts & 					SSH_ALERT_WRONGDIR )				{					/* Server msg not from server. */                    ALERT(SSH_EVENT_WRONGDIR, SSH_EVENT_WRONGDIR_STR);				}				break;			case SSH_MSG_V1_CMSG_SESSION_KEY:				if ( direction == SSH_DIR_FROM_CLIENT )				{					sessionp->state_flags |= 						SSH_FLG_CLIENT_SKEY_SEEN;				}				else if ( ssh_config.EnabledAlerts & 					SSH_ALERT_WRONGDIR )				{					/* Client msg not from client. */                     ALERT(SSH_EVENT_WRONGDIR, SSH_EVENT_WRONGDIR_STR);				}				break;			default:				/* Invalid msg type */				break;		}		/* Once the V1 key exchange is done, remainder of 		 * communications are encrypted.		 */		if ( (sessionp->state_flags & SSH_FLG_V1_KEYEXCH_DONE) ==			SSH_FLG_V1_KEYEXCH_DONE )		{			sessionp->state_flags |= SSH_FLG_SESS_ENCRYPTED;		}	}	else if ( sessionp->version == SSH_VERSION_2 )	{        /* We want to overlay the payload on our data packet struct,         * so first verify that the payload size is big enough.         * This may legitimately occur such as in the case of a          * retransmission.         */        if ( packetp->payload_size < sizeof(SSH2Packet) )        {			return SSH_FAILURE;        }        		/* Overlay the SSH2 binary data packet struct on the packet */		ssh2packetp = (SSH2Packet*) packetp->payload;		if (( packetp->payload_size < SSH2_HEADERLEN + 1) || 			( packetp->payload_size < ntohl(ssh2packetp->packet_length) ))		{			/* Invalid packet length. */			return SSH_FAILURE;		}		switch ( packetp->payload[SSH2_HEADERLEN] )		{			case SSH_MSG_KEXINIT:				sessionp->state_flags |= 					(direction == SSH_DIR_FROM_SERVER ?						SSH_FLG_SERV_KEXINIT_SEEN :						SSH_FLG_CLIENT_KEXINIT_SEEN );				break;			default:				/* Unrecognized message type. */				break;		}	}	else	{        if(ssh_config.EnabledAlerts & SSH_ALERT_UNRECOGNIZED)        {		    /* Unrecognized version. */            ALERT(SSH_EVENT_VERSION, SSH_VERSION_STR);        }		return SSH_FAILURE;	}		return SSH_SUCCESS;}/* Called to process SSH2 key exchange msgs (key exch init msgs already * processed earlier). On failure, inspection will be continued, but the  * packet will be alerted on, and ignored. *  * PARAMETERS:  * * sessionp:    Pointer to SSH data for packet's session. * packetp:	Pointer to the packet to inspect. * direction: 	Which direction the packet is going. *  * RETURN:	SSH_SUCCESS, if a valid key exchange message is processed  *		SSH_FAILURE, otherwise. */static intProcessSSHKeyExchange( SSHData* sessionp, SFSnortPacket* packetp, 	u_int8_t direction ){	SSH2Packet* ssh2packetp = NULL;    if ( packetp->payload_size < sizeof(SSH2Packet) )    {		/* Invalid packet length. */		return SSH_FAILURE;    }        	ssh2packetp = (SSH2Packet*) packetp->payload;	if (( packetp->payload_size < SSH2_HEADERLEN + 1 ) || 		( packetp->payload_size < ntohl(ssh2packetp->packet_length) ))	{        if(ssh_config.EnabledAlerts & SSH_ALERT_PAYSIZE)        {		    /* Invalid packet length. */            ALERT(SSH_EVENT_PAYLOAD_SIZE, SSH_PAYLOAD_SIZE_STR);        }		return SSH_FAILURE;	}	switch( packetp->payload[SSH2_HEADERLEN] )	{		case SSH_MSG_KEXDH_INIT:			if ( direction == SSH_DIR_FROM_CLIENT )			{				sessionp->state_flags |= 					SSH_FLG_KEXDH_INIT_SEEN;			}			else if ( ssh_config.EnabledAlerts & 					SSH_ALERT_WRONGDIR )			{				/* Client msg from server. */                ALERT(SSH_EVENT_WRONGDIR, SSH_EVENT_WRONGDIR_STR);			}			break;		case SSH_MSG_KEXDH_REPLY:			if ( direction == SSH_DIR_FROM_SERVER )			{				/* KEXDH_REPLY has the same msg			 	 * type as the new style GEX_REPLY				 */				sessionp->state_flags |= 					SSH_FLG_KEXDH_REPLY_SEEN | 					SSH_FLG_GEX_REPLY_SEEN;			}			else if ( ssh_config.EnabledAlerts & 					SSH_ALERT_WRONGDIR )			{				/* Server msg from client. */                ALERT(SSH_EVENT_WRONGDIR, SSH_EVENT_WRONGDIR_STR);			}			break;		case SSH_MSG_KEXDH_GEX_REQ:			if ( direction == SSH_DIR_FROM_CLIENT )			{				sessionp->state_flags |= 					SSH_FLG_GEX_REQ_SEEN;			}			else if ( ssh_config.EnabledAlerts & 					SSH_ALERT_WRONGDIR )			{				/* Server msg from client. */                ALERT(SSH_EVENT_WRONGDIR, SSH_EVENT_WRONGDIR_STR);			}			break;		case SSH_MSG_KEXDH_GEX_GRP:			if ( direction == SSH_DIR_FROM_SERVER )			{				sessionp->state_flags |= 					SSH_FLG_GEX_GRP_SEEN;			}			else if ( ssh_config.EnabledAlerts & 					SSH_ALERT_WRONGDIR )			{				/* Client msg from server. */                ALERT(SSH_EVENT_WRONGDIR, SSH_EVENT_WRONGDIR_STR);			}			break;		case SSH_MSG_KEXDH_GEX_INIT:			if ( direction == SSH_DIR_FROM_CLIENT )			{				sessionp->state_flags |= 					SSH_FLG_GEX_INIT_SEEN;			}			else if ( ssh_config.EnabledAlerts & 					SSH_ALERT_WRONGDIR )			{				/* Server msg from client. */                ALERT(SSH_EVENT_WRONGDIR, SSH_EVENT_WRONGDIR_STR);			}			break;		case SSH_MSG_NEWKEYS:			/* This message is required to complete the			 * key exchange. Both server and client should			 * send one, but as per Alex Kirk's note on this, 			 * in some implementations the server does not			 * actually send this message. So receving a new 			 * keys msg from the client is sufficient.			 */			if ( direction == SSH_DIR_FROM_CLIENT )			{				sessionp->state_flags |= SSH_FLG_NEWKEYS_SEEN;			}			break;		default:			/* Unrecognized message type. */			break;	}	/* If either an old-style or new-style Diffie Helman exchange	 * has completed, the session will enter encrypted mode. 	 */	if (( (sessionp->state_flags &		SSH_FLG_V2_DHOLD_DONE) == SSH_FLG_V2_DHOLD_DONE ) 		|| ( (sessionp->state_flags & 			SSH_FLG_V2_DHNEW_DONE) == SSH_FLG_V2_DHNEW_DONE ))	{		sessionp->state_flags |= 			SSH_FLG_SESS_ENCRYPTED;	}	return SSH_SUCCESS;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -