Tracee > Execution > Process Standard Input Output Over Socket Detected
HIGH
Source
Tracee
ID
TRC-101
Version
2
Date
1 Dec 2022

Process Standard Input Output Over Socket Detected

A process has its standard input/output redirected to a socket. This behaviour is the base of a Reverse Shell attack, which is when an interactive shell being invoked from a target machine back to the attacker’s machine, giving it interactive control over the target. Adversaries may use a Reverse Shell to retain control over a compromised target while bypassing security measures like network firewalls.

MITRE ATT&CK

Execution: Unix Shell

Go Source

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package main

import (
	"fmt"

	"github.com/aquasecurity/tracee/signatures/helpers"
	"github.com/aquasecurity/tracee/types/detect"
	"github.com/aquasecurity/tracee/types/protocol"
	"github.com/aquasecurity/tracee/types/trace"
)

type StdioOverSocket struct {
	cb         detect.SignatureHandler
	legitPorts []string
}

func (sig *StdioOverSocket) Init(cb detect.SignatureHandler) error {
	sig.cb = cb
	sig.legitPorts = []string{"", "0"}
	return nil
}

func (sig *StdioOverSocket) GetMetadata() (detect.SignatureMetadata, error) {
	return detect.SignatureMetadata{
		ID:          "TRC-101",
		Version:     "2",
		Name:        "Process standard input/output over socket detected",
		Description: "A process has its standard input/output redirected to a socket. This behaviour is the base of a Reverse Shell attack, which is when an interactive shell being invoked from a target machine back to the attacker's machine, giving it interactive control over the target. Adversaries may use a Reverse Shell to retain control over a compromised target while bypassing security measures like network firewalls.",
		Properties: map[string]interface{}{
			"Severity":             3,
			"Category":             "execution",
			"Technique":            "Unix Shell",
			"Kubernetes_Technique": "",
			"id":                   "attack-pattern--a9d4b653-6915-42af-98b2-5758c4ceee56",
			"external_id":          "T1059.004",
		},
	}, nil
}

func (sig *StdioOverSocket) GetSelectedEvents() ([]detect.SignatureEventSelector, error) {
	return []detect.SignatureEventSelector{
		{Source: "tracee", Name: "security_socket_connect", Origin: "*"},
		{Source: "tracee", Name: "socket_dup", Origin: "*"},
	}, nil
}

func (sig *StdioOverSocket) OnEvent(event protocol.Event) error {

	eventObj, ok := event.Payload.(trace.Event)
	if !ok {
		return fmt.Errorf("invalid event")
	}

	var sockfd int
	var err error

	switch eventObj.EventName {

	case "security_socket_connect":

		sockfd, err = helpers.GetTraceeIntArgumentByName(eventObj, "sockfd")
		if err != nil {
			return err
		}

	case "socket_dup":

		sockfd, err = helpers.GetTraceeIntArgumentByName(eventObj, "newfd")
		if err != nil {
			return err
		}

	}

	if sockfd != 0 && sockfd != 1 && sockfd != 2 {
		return nil
	}

	remoteAddr, err := helpers.GetRawAddrArgumentByName(eventObj, "remote_addr")
	if err != nil {
		return err
	}

	supportedFamily, err := helpers.IsInternetFamily(remoteAddr)
	if err != nil {
		return err
	}
	if !supportedFamily {
		return nil
	}

	port, err := helpers.GetPortFromRawAddr(remoteAddr)
	if err != nil {
		return err
	}

	for _, legitPort := range sig.legitPorts {
		if port == legitPort {
			return nil
		}
	}

	ip, err := helpers.GetIPFromRawAddr(remoteAddr)
	if err != nil {
		return err
	}

	metadata, err := sig.GetMetadata()
	if err != nil {
		return err
	}
	sig.cb(detect.Finding{
		SigMetadata: metadata,
		Event:       event,
		Data: map[string]interface{}{
			"IP address":      ip,
			"Port":            port,
			"File descriptor": sockfd,
		},
	})

	return nil
}

func (sig *StdioOverSocket) OnSignal(s detect.Signal) error {
	return nil
}
func (sig *StdioOverSocket) Close() {}