github.com/castai/kvisor@v1.7.1-0.20240516114728-b3572a2607b5/pkg/ebpftracer/signature/socks5_detected_test.go (about)

     1  package signature
     2  
     3  import (
     4  	"testing"
     5  
     6  	v1 "github.com/castai/kvisor/api/v1/runtime"
     7  	"github.com/castai/kvisor/pkg/containers"
     8  	"github.com/castai/kvisor/pkg/ebpftracer/events"
     9  	"github.com/castai/kvisor/pkg/ebpftracer/types"
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  var socks5ClientRequestData = []byte{
    14  	// IPv4 header
    15  	0x45, 0x00, 0x00, 0x38, 0x3c, 0x23, 0x40, 0x00,
    16  	0x40, 0x06, 0x00, 0x9b, 0x7f, 0x00, 0x00, 0x01,
    17  	0x7f, 0x00, 0x00, 0x01, 0xae, 0x20, 0x04, 0x38,
    18  	0xed, 0xbb, 0x47, 0xad, 0x77, 0x45, 0x5a, 0x21,
    19  	0x80, 0x18, 0x02, 0x00, 0xfe, 0x2c, 0x00, 0x00,
    20  	0x01, 0x01, 0x08, 0x0a, 0x3c, 0xfe, 0xe8, 0x88,
    21  	0x3c, 0xfe, 0xe8, 0x88, 0x05, 0x02,
    22  
    23  	// SOCKS5 start
    24  	0x00, 0x01,
    25  }
    26  
    27  var socks5ServerMethodSelectData = []byte{
    28  	// IPv4 header
    29  	0x45, 0x00, 0x00, 0x36, 0x29, 0x67, 0x40, 0x00,
    30  	0x40, 0x06, 0x13, 0x59, 0x7f, 0x00, 0x00, 0x01,
    31  	0x7f, 0x00, 0x00, 0x01, 0x04, 0x38, 0xae, 0x20,
    32  	0x77, 0x45, 0x5a, 0x21, 0xed, 0xbb, 0x47, 0xb1,
    33  	0x80, 0x18, 0x02, 0x00, 0xfe, 0x2a, 0x00, 0x00,
    34  	0x01, 0x01, 0x08, 0x0a, 0x3c, 0xfe, 0xe8, 0x89,
    35  	0x3c, 0xfe, 0xe8, 0x88,
    36  
    37  	// SOCKS5 start
    38  	0x05, 0x00,
    39  }
    40  
    41  var socks5ClientConnectRequestData = []byte{
    42  	// IPv4 header
    43  	0x45, 0x00, 0x00, 0x3e, 0x3c, 0x25, 0x40, 0x00,
    44  	0x40, 0x06, 0x00, 0x93, 0x7f, 0x00, 0x00, 0x01,
    45  	0x7f, 0x00, 0x00, 0x01, 0xae, 0x20, 0x04, 0x38,
    46  	0xed, 0xbb, 0x47, 0xb1, 0x77, 0x45, 0x5a, 0x23,
    47  	0x80, 0x18, 0x02, 0x00, 0xfe, 0x32, 0x00, 0x00,
    48  	0x01, 0x01, 0x08, 0x0a, 0x3c, 0xfe, 0xe8, 0x9b,
    49  	0x3c, 0xfe, 0xe8, 0x89,
    50  
    51  	// SOCKS5 start
    52  	0x05,
    53  	0x01, //connect
    54  	0x00,
    55  	0x01, // IPv4
    56  	// IP data of 142.250.185.99
    57  	0x8e, 0xfa, 0xb9, 0x63,
    58  	// Port 80
    59  	0x00, 0x50,
    60  }
    61  
    62  var socks5ServerConnectResponseData = []byte{
    63  	// IPv4 header
    64  	0x45, 0x00, 0x00, 0x3e, 0x29, 0x69, 0x40, 0x00,
    65  	0x40, 0x06, 0x13, 0x4f, 0x7f, 0x00, 0x00, 0x01,
    66  	0x7f, 0x00, 0x00, 0x01, 0x04, 0x38, 0xae, 0x20,
    67  	0x77, 0x45, 0x5a, 0x23, 0xed, 0xbb, 0x47, 0xbb,
    68  	0x80, 0x18, 0x02, 0x00, 0xfe, 0x32, 0x00, 0x00,
    69  	0x01, 0x01, 0x08, 0x0a, 0x3c, 0xfe, 0xe8, 0xc9,
    70  	0x3c, 0xfe, 0xe8, 0x9b,
    71  
    72  	// SOCKS5 start
    73  	0x05,
    74  	0x00, // success
    75  	0x00,
    76  	0x01, // IPv4
    77  	// IP data of 10.244.0.22
    78  	0x0a, 0xf4, 0x00, 0x16,
    79  	// Port 52330
    80  	0xcc, 0x6a,
    81  }
    82  
    83  func TestSOCKS5DetectedSignature(t *testing.T) {
    84  	type eventWithFinding struct {
    85  		event           types.Event
    86  		expectedFinding *v1.SignatureFinding
    87  	}
    88  
    89  	type testCase struct {
    90  		title  string
    91  		events []eventWithFinding
    92  	}
    93  
    94  	testCases := []testCase{
    95  		{
    96  			title: "should detect socks5 server",
    97  			events: []eventWithFinding{
    98  				{
    99  					event: types.Event{
   100  						Context: &types.EventContext{
   101  							EventID:  events.NetPacketSOCKS5Base,
   102  							Ts:       11,
   103  							CgroupID: 10,
   104  							Pid:      99,
   105  							Retval:   types.FlagPacketIngress,
   106  						},
   107  						Container: &containers.Container{
   108  							ID:       "123",
   109  							Name:     "name-123",
   110  							CgroupID: 10,
   111  						},
   112  						Args: types.NetPacketSOCKS5BaseArgs{
   113  							Payload: socks5ClientRequestData,
   114  						},
   115  					},
   116  				},
   117  				{
   118  					event: types.Event{
   119  						Context: &types.EventContext{
   120  							EventID:  events.NetPacketSOCKS5Base,
   121  							Ts:       12,
   122  							CgroupID: 10,
   123  							Pid:      99,
   124  							Retval:   types.FlagPacketEgress,
   125  						},
   126  						Container: &containers.Container{
   127  							ID:       "123",
   128  							Name:     "name-123",
   129  							CgroupID: 10,
   130  						},
   131  						Args: types.NetPacketSOCKS5BaseArgs{
   132  							Payload: socks5ServerMethodSelectData,
   133  						},
   134  					},
   135  				},
   136  				{
   137  					event: types.Event{
   138  						Context: &types.EventContext{
   139  							EventID:  events.NetPacketSOCKS5Base,
   140  							Ts:       13,
   141  							CgroupID: 10,
   142  							Pid:      99,
   143  							Retval:   types.FlagPacketIngress,
   144  						},
   145  						Container: &containers.Container{
   146  							ID:       "123",
   147  							Name:     "name-123",
   148  							CgroupID: 10,
   149  						},
   150  						Args: types.NetPacketSOCKS5BaseArgs{
   151  							Payload: socks5ClientConnectRequestData,
   152  						},
   153  					},
   154  					expectedFinding: &v1.SignatureFinding{
   155  						Data: &v1.SignatureFinding_Socks5Detected{
   156  							Socks5Detected: &v1.SOCKS5DetectedFinding{
   157  								Role:          v1.SOCKS5Role_SOCKS5_ROLE_SERVER,
   158  								FlowDirection: v1.FlowDirection_FLOW_INGRESS,
   159  								CmdOrReply:    0x01,
   160  								AddressType:   v1.SOCKS5AddressType_SOCKS5_ADDRESS_TYPE_IPv4,
   161  								Address:       []byte{0x8e, 0xfa, 0xb9, 0x63},
   162  								Port:          80,
   163  							},
   164  						},
   165  					},
   166  				},
   167  				{
   168  					event: types.Event{
   169  						Context: &types.EventContext{
   170  							EventID:  events.NetPacketSOCKS5Base,
   171  							Ts:       13,
   172  							CgroupID: 10,
   173  							Pid:      99,
   174  							Retval:   types.FlagPacketEgress,
   175  						},
   176  						Container: &containers.Container{
   177  							ID:       "123",
   178  							Name:     "name-123",
   179  							CgroupID: 10,
   180  						},
   181  						Args: types.NetPacketSOCKS5BaseArgs{
   182  							Payload: socks5ServerConnectResponseData,
   183  						},
   184  					},
   185  					expectedFinding: &v1.SignatureFinding{
   186  						Data: &v1.SignatureFinding_Socks5Detected{
   187  							Socks5Detected: &v1.SOCKS5DetectedFinding{
   188  								Role:          v1.SOCKS5Role_SOCKS5_ROLE_SERVER,
   189  								FlowDirection: v1.FlowDirection_FLOW_EGRESS,
   190  								CmdOrReply:    0x00,
   191  								AddressType:   v1.SOCKS5AddressType_SOCKS5_ADDRESS_TYPE_IPv4,
   192  								Address:       []byte{0x0a, 0xf4, 0x00, 0x16},
   193  								Port:          52330,
   194  							},
   195  						},
   196  					},
   197  				},
   198  			},
   199  		},
   200  		{
   201  			title: "should detect socks5 client",
   202  			events: []eventWithFinding{
   203  				{
   204  					event: types.Event{
   205  						Context: &types.EventContext{
   206  							EventID:  events.NetPacketSOCKS5Base,
   207  							Ts:       11,
   208  							CgroupID: 10,
   209  							Pid:      99,
   210  							Retval:   types.FlagPacketEgress,
   211  						},
   212  						Container: &containers.Container{
   213  							ID:       "123",
   214  							Name:     "name-123",
   215  							CgroupID: 10,
   216  						},
   217  						Args: types.NetPacketSOCKS5BaseArgs{
   218  							Payload: socks5ClientRequestData,
   219  						},
   220  					},
   221  				},
   222  				{
   223  					event: types.Event{
   224  						Context: &types.EventContext{
   225  							EventID:  events.NetPacketSOCKS5Base,
   226  							Ts:       12,
   227  							CgroupID: 10,
   228  							Pid:      99,
   229  							Retval:   types.FlagPacketIngress,
   230  						},
   231  						Container: &containers.Container{
   232  							ID:       "123",
   233  							Name:     "name-123",
   234  							CgroupID: 10,
   235  						},
   236  						Args: types.NetPacketSOCKS5BaseArgs{
   237  							Payload: socks5ServerMethodSelectData,
   238  						},
   239  					},
   240  				},
   241  				{
   242  					event: types.Event{
   243  						Context: &types.EventContext{
   244  							EventID:  events.NetPacketSOCKS5Base,
   245  							Ts:       13,
   246  							CgroupID: 10,
   247  							Pid:      99,
   248  							Retval:   types.FlagPacketEgress,
   249  						},
   250  						Container: &containers.Container{
   251  							ID:       "123",
   252  							Name:     "name-123",
   253  							CgroupID: 10,
   254  						},
   255  						Args: types.NetPacketSOCKS5BaseArgs{
   256  							Payload: socks5ClientConnectRequestData,
   257  						},
   258  					},
   259  					expectedFinding: &v1.SignatureFinding{
   260  						Data: &v1.SignatureFinding_Socks5Detected{
   261  							Socks5Detected: &v1.SOCKS5DetectedFinding{
   262  								Role:          v1.SOCKS5Role_SOCKS5_ROLE_CLIENT,
   263  								FlowDirection: v1.FlowDirection_FLOW_EGRESS,
   264  								CmdOrReply:    0x01,
   265  								AddressType:   v1.SOCKS5AddressType_SOCKS5_ADDRESS_TYPE_IPv4,
   266  								Address:       []byte{0x8e, 0xfa, 0xb9, 0x63},
   267  								Port:          80,
   268  							},
   269  						},
   270  					},
   271  				},
   272  				{
   273  					event: types.Event{
   274  						Context: &types.EventContext{
   275  							EventID:  events.NetPacketSOCKS5Base,
   276  							Ts:       13,
   277  							CgroupID: 10,
   278  							Pid:      99,
   279  							Retval:   types.FlagPacketIngress,
   280  						},
   281  						Container: &containers.Container{
   282  							ID:       "123",
   283  							Name:     "name-123",
   284  							CgroupID: 10,
   285  						},
   286  						Args: types.NetPacketSOCKS5BaseArgs{
   287  							Payload: socks5ServerConnectResponseData,
   288  						},
   289  					},
   290  					expectedFinding: &v1.SignatureFinding{
   291  						Data: &v1.SignatureFinding_Socks5Detected{
   292  							Socks5Detected: &v1.SOCKS5DetectedFinding{
   293  								Role:          v1.SOCKS5Role_SOCKS5_ROLE_CLIENT,
   294  								FlowDirection: v1.FlowDirection_FLOW_INGRESS,
   295  								CmdOrReply:    0x00,
   296  								AddressType:   v1.SOCKS5AddressType_SOCKS5_ADDRESS_TYPE_IPv4,
   297  								Address:       []byte{0x0a, 0xf4, 0x00, 0x16},
   298  								Port:          52330,
   299  							},
   300  						},
   301  					},
   302  				},
   303  			},
   304  		},
   305  		{
   306  			title: "should detect socks5 on only connect message",
   307  			events: []eventWithFinding{
   308  				{
   309  					event: types.Event{
   310  						Context: &types.EventContext{
   311  							EventID:  events.NetPacketSOCKS5Base,
   312  							Ts:       13,
   313  							CgroupID: 10,
   314  							Pid:      99,
   315  							Retval:   types.FlagPacketEgress,
   316  						},
   317  						Container: &containers.Container{
   318  							ID:       "123",
   319  							Name:     "name-123",
   320  							CgroupID: 10,
   321  						},
   322  						Args: types.NetPacketSOCKS5BaseArgs{
   323  							Payload: socks5ClientConnectRequestData,
   324  						},
   325  					},
   326  					expectedFinding: &v1.SignatureFinding{
   327  						Data: &v1.SignatureFinding_Socks5Detected{
   328  							Socks5Detected: &v1.SOCKS5DetectedFinding{
   329  								Role:          v1.SOCKS5Role_SOCKS5_ROLE_UNKNOWN,
   330  								FlowDirection: v1.FlowDirection_FLOW_EGRESS,
   331  								CmdOrReply:    0x01,
   332  								AddressType:   v1.SOCKS5AddressType_SOCKS5_ADDRESS_TYPE_IPv4,
   333  								Address:       []byte{0x8e, 0xfa, 0xb9, 0x63},
   334  								Port:          80,
   335  							},
   336  						},
   337  					},
   338  				},
   339  			},
   340  		},
   341  	}
   342  
   343  	for _, test := range testCases {
   344  		t.Run(test.title, func(t *testing.T) {
   345  			r := require.New(t)
   346  
   347  			signature, err := NewSOCKS5DetectedSignature(SOCKS5DetectionSignatureConfig{})
   348  			r.NoError(err)
   349  
   350  			for i, e := range test.events {
   351  				result := signature.OnEvent(&e.event)
   352  
   353  				if e.expectedFinding == nil {
   354  					r.Nil(result)
   355  					continue
   356  				}
   357  				r.Equal(e.expectedFinding, result, "match finding for event nr. %d: %d", i, e.event.Context.EventID)
   358  			}
   359  		})
   360  	}
   361  }