fire-marshal-ebay 0.0.1-security.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fire-marshal-ebay might be problematic. Click here for more details.
- package/PadBuster/LICENSE +202 -0
- package/PadBuster/README +16 -0
- package/PadBuster/padBuster.pl +889 -0
- package/confused/.github/workflows/codeql-analysis.yml +67 -0
- package/confused/.github/workflows/golangci-lint.yml +28 -0
- package/confused/.goreleaser.yml +40 -0
- package/confused/CHANGELOG.md +31 -0
- package/confused/LICENSE +21 -0
- package/confused/README.md +93 -0
- package/confused/composer.go +105 -0
- package/confused/confused +0 -0
- package/confused/interfaces.go +11 -0
- package/confused/main.go +104 -0
- package/confused/mvn.go +120 -0
- package/confused/mvnparser.go +139 -0
- package/confused/npm.go +210 -0
- package/confused/packages.json +86 -0
- package/confused/pip.go +99 -0
- package/confused/util.go +11 -0
- package/index.js +47 -0
- package/package.json +9 -4
- package/synackAPI/Dockerfile +36 -0
- package/synackAPI/README.md +238 -0
- package/synackAPI/RHINOSPIDER/burpOOS.txt +25 -0
- package/synackAPI/RHINOSPIDER/burpScope.txt +1 -0
- package/synackAPI/RHINOSPIDER/scope.txt +1 -0
- package/synackAPI/bot.py +72 -0
- package/synackAPI/checkCerts.py +67 -0
- package/synackAPI/connect.py +9 -0
- package/synackAPI/currentTarget +24 -0
- package/synackAPI/getAnalytics.py +40 -0
- package/synackAPI/getHydra.py +46 -0
- package/synackAPI/getPayouts.py +11 -0
- package/synackAPI/getscope.py +123 -0
- package/synackAPI/polling.py +27 -0
- package/synackAPI/register.py +7 -0
- package/synackAPI/requirements.txt +7 -0
- package/synackAPI/synack.py +1046 -0
- package/synackAPI/synstats.py +54 -0
- package/synackAPI/target.py +17 -0
- package/README.md +0 -5
@@ -0,0 +1,67 @@
|
|
1
|
+
# For most projects, this workflow file will not need changing; you simply need
|
2
|
+
# to commit it to your repository.
|
3
|
+
#
|
4
|
+
# You may wish to alter this file to override the set of languages analyzed,
|
5
|
+
# or to provide custom queries or build logic.
|
6
|
+
#
|
7
|
+
# ******** NOTE ********
|
8
|
+
# We have attempted to detect the languages in your repository. Please check
|
9
|
+
# the `language` matrix defined below to confirm you have the correct set of
|
10
|
+
# supported CodeQL languages.
|
11
|
+
#
|
12
|
+
name: "CodeQL"
|
13
|
+
|
14
|
+
on:
|
15
|
+
push:
|
16
|
+
branches: [ main ]
|
17
|
+
pull_request:
|
18
|
+
# The branches below must be a subset of the branches above
|
19
|
+
branches: [ main ]
|
20
|
+
schedule:
|
21
|
+
- cron: '15 8 * * 1'
|
22
|
+
|
23
|
+
jobs:
|
24
|
+
analyze:
|
25
|
+
name: Analyze
|
26
|
+
runs-on: ubuntu-latest
|
27
|
+
|
28
|
+
strategy:
|
29
|
+
fail-fast: false
|
30
|
+
matrix:
|
31
|
+
language: [ 'go' ]
|
32
|
+
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
33
|
+
# Learn more:
|
34
|
+
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
35
|
+
|
36
|
+
steps:
|
37
|
+
- name: Checkout repository
|
38
|
+
uses: actions/checkout@v2
|
39
|
+
|
40
|
+
# Initializes the CodeQL tools for scanning.
|
41
|
+
- name: Initialize CodeQL
|
42
|
+
uses: github/codeql-action/init@v1
|
43
|
+
with:
|
44
|
+
languages: ${{ matrix.language }}
|
45
|
+
# If you wish to specify custom queries, you can do so here or in a config file.
|
46
|
+
# By default, queries listed here will override any specified in a config file.
|
47
|
+
# Prefix the list here with "+" to use these queries and those in the config file.
|
48
|
+
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
49
|
+
|
50
|
+
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
51
|
+
# If this step fails, then you should remove it and run the build manually (see below)
|
52
|
+
- name: Autobuild
|
53
|
+
uses: github/codeql-action/autobuild@v1
|
54
|
+
|
55
|
+
# ℹ️ Command-line programs to run using the OS shell.
|
56
|
+
# 📚 https://git.io/JvXDl
|
57
|
+
|
58
|
+
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
59
|
+
# and modify them (or add more) to build your code if your project
|
60
|
+
# uses a compiled language
|
61
|
+
|
62
|
+
#- run: |
|
63
|
+
# make bootstrap
|
64
|
+
# make release
|
65
|
+
|
66
|
+
- name: Perform CodeQL Analysis
|
67
|
+
uses: github/codeql-action/analyze@v1
|
@@ -0,0 +1,28 @@
|
|
1
|
+
name: golangci-lint
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
tags:
|
5
|
+
- v*
|
6
|
+
branches:
|
7
|
+
- main
|
8
|
+
pull_request:
|
9
|
+
jobs:
|
10
|
+
golangci:
|
11
|
+
name: lint
|
12
|
+
runs-on: ubuntu-latest
|
13
|
+
steps:
|
14
|
+
- uses: actions/checkout@v2
|
15
|
+
- name: golangci-lint
|
16
|
+
uses: golangci/golangci-lint-action@v2
|
17
|
+
with:
|
18
|
+
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
|
19
|
+
version: v1.29
|
20
|
+
|
21
|
+
# Optional: working directory, useful for monorepos
|
22
|
+
# working-directory: somedir
|
23
|
+
|
24
|
+
# Optional: golangci-lint command line arguments.
|
25
|
+
# args: --issues-exit-code=0
|
26
|
+
|
27
|
+
# Optional: show only new issues if it's a pull request. The default value is `false`.
|
28
|
+
# only-new-issues: true
|
@@ -0,0 +1,40 @@
|
|
1
|
+
builds:
|
2
|
+
- id: confused
|
3
|
+
binary: confused
|
4
|
+
flags:
|
5
|
+
- -trimpath
|
6
|
+
env:
|
7
|
+
- CGO_ENABLED=0
|
8
|
+
asmflags:
|
9
|
+
- all=-trimpath={{.Env.GOPATH}}
|
10
|
+
gcflags:
|
11
|
+
- all=-trimpath={{.Env.GOPATH}}
|
12
|
+
ldflags: |
|
13
|
+
-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.CommitDate}} -extldflags '-static'
|
14
|
+
goos:
|
15
|
+
- linux
|
16
|
+
- windows
|
17
|
+
- freebsd
|
18
|
+
- openbsd
|
19
|
+
- darwin
|
20
|
+
goarch:
|
21
|
+
- amd64
|
22
|
+
- 386
|
23
|
+
- arm
|
24
|
+
- arm64
|
25
|
+
ignore:
|
26
|
+
- goos: freebsd
|
27
|
+
goarch: arm64
|
28
|
+
|
29
|
+
archives:
|
30
|
+
- id: tgz
|
31
|
+
format: tar.gz
|
32
|
+
replacements:
|
33
|
+
darwin: macOS
|
34
|
+
format_overrides:
|
35
|
+
- goos: windows
|
36
|
+
format: zip
|
37
|
+
|
38
|
+
signs:
|
39
|
+
- artifacts: checksum
|
40
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
- main
|
4
|
+
- New
|
5
|
+
- Changed
|
6
|
+
|
7
|
+
- v0.4
|
8
|
+
- New
|
9
|
+
- npm: In case package was found, also check if all the package versions have been unpublished. This makes the package vulnerable to takeover
|
10
|
+
- npm: Check for http & https and GitHub version references
|
11
|
+
- MVN (Maven) support
|
12
|
+
- Changed
|
13
|
+
- Fixed a bug where the pip requirements.txt parser processes a 'tilde equals' sign.
|
14
|
+
- Fixed an issue that would detect git repository urls as matches
|
15
|
+
|
16
|
+
- v0.3
|
17
|
+
- New
|
18
|
+
- PHP (composer) support
|
19
|
+
- Command line parameter to let the user to flag namespaces as known-safe
|
20
|
+
- Changed
|
21
|
+
- Python (pypi) dependency definition files that use line continuation are now parsed correctly
|
22
|
+
- Revised the output to clarify the usage
|
23
|
+
- Fixed npm package.json file parsing issues when the source file is not following the specification
|
24
|
+
|
25
|
+
- v0.2
|
26
|
+
- Changed
|
27
|
+
- npm registry checkup url
|
28
|
+
- Throttle the rate of requests in case of 429 (Too many requests) responses
|
29
|
+
|
30
|
+
- v0.1
|
31
|
+
- Initial release
|
package/confused/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2021 Visma Security, Joona Hoikkala
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# Confused
|
2
|
+
|
3
|
+
A tool for checking for lingering free namespaces for private package names referenced in dependency configuration
|
4
|
+
for Python (pypi) `requirements.txt`, JavaScript (npm) `package.json`, PHP (composer) `composer.json` or MVN (maven) `pom.xml`.
|
5
|
+
|
6
|
+
## What is this all about?
|
7
|
+
|
8
|
+
On 9th of February 2021, a security researcher Alex Birsan [published an article](https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610)
|
9
|
+
that touched different resolve order flaws in dependency management tools present in multiple programming language ecosystems.
|
10
|
+
|
11
|
+
Microsoft [released a whitepaper](https://azure.microsoft.com/en-gb/resources/3-ways-to-mitigate-risk-using-private-package-feeds/)
|
12
|
+
describing ways to mitigate the impact, while the root cause still remains.
|
13
|
+
|
14
|
+
## Interpreting the tool output
|
15
|
+
|
16
|
+
`confused` simply reads through a dependency definition file of an application and checks the public package repositories
|
17
|
+
for each dependency entry in that file. It will proceed to report all the package names that are not found in the public
|
18
|
+
repositories - a state that implies that a package might be vulnerable to this kind of attack, while this vector has not
|
19
|
+
yet been exploited.
|
20
|
+
|
21
|
+
This however doesn't mean that an application isn't already being actively exploited. If you know your software is using
|
22
|
+
private package repositories, you should ensure that the namespaces for your private packages have been claimed by a
|
23
|
+
trusted party (typically yourself or your company).
|
24
|
+
|
25
|
+
### Known false positives
|
26
|
+
|
27
|
+
Some packaging ecosystems like npm have a concept called "scopes" that can be either private or public. In short it means
|
28
|
+
a namespace that has an upper level - the scope. The scopes are not inherently visible publicly, which means that `confused`
|
29
|
+
cannot reliably detect if it has been claimed. If your application uses scoped package names, you should ensure that a
|
30
|
+
trusted party has claimed the scope name in the public repositories.
|
31
|
+
|
32
|
+
## Installation
|
33
|
+
|
34
|
+
- [Download](https://github.com/visma-prodsec/confused/releases/latest) a prebuilt binary from [releases page](https://github.com/visma-prodsec/confused/releases/latest), unpack and run!
|
35
|
+
|
36
|
+
_or_
|
37
|
+
- If you have recent go compiler installed: `go get -u github.com/visma-prodsec/confused` (the same command works for updating)
|
38
|
+
|
39
|
+
_or_
|
40
|
+
- git clone https://github.com/visma-prodsec/confused ; cd confused ; go get ; go build
|
41
|
+
|
42
|
+
## Usage
|
43
|
+
```
|
44
|
+
Usage:
|
45
|
+
./confused [-l LANGUAGENAME] depfilename.ext
|
46
|
+
|
47
|
+
Usage of ./confused:
|
48
|
+
-l string
|
49
|
+
Package repository system. Possible values: "pip", "npm", "composer", "mvn" (default "npm")
|
50
|
+
-s string
|
51
|
+
Comma-separated list of known-secure namespaces. Supports wildcards
|
52
|
+
-v Verbose output
|
53
|
+
|
54
|
+
```
|
55
|
+
|
56
|
+
## Example
|
57
|
+
|
58
|
+
### Python (PyPI)
|
59
|
+
```
|
60
|
+
./confused -l pip requirements.txt
|
61
|
+
|
62
|
+
Issues found, the following packages are not available in public package repositories:
|
63
|
+
[!] internal_package1
|
64
|
+
|
65
|
+
```
|
66
|
+
|
67
|
+
### JavaScript (npm)
|
68
|
+
```
|
69
|
+
./confused -l npm package.json
|
70
|
+
|
71
|
+
Issues found, the following packages are not available in public package repositories:
|
72
|
+
[!] internal_package1
|
73
|
+
[!] @mycompany/internal_package1
|
74
|
+
[!] @mycompany/internal_package2
|
75
|
+
|
76
|
+
# Example when @mycompany private scope has been registered in npm, using -s
|
77
|
+
./confused -l npm -s '@mycompany/*' package.json
|
78
|
+
|
79
|
+
Issues found, the following packages are not available in public package repositories:
|
80
|
+
[!] internal_package1
|
81
|
+
```
|
82
|
+
|
83
|
+
|
84
|
+
### Maven (mvn)
|
85
|
+
```
|
86
|
+
./confused -l mvn pom.xml
|
87
|
+
|
88
|
+
Issues found, the following packages are not available in public package repositories:
|
89
|
+
[!] internal
|
90
|
+
[!] internal/package1
|
91
|
+
[!] internal/_package2
|
92
|
+
|
93
|
+
```
|
@@ -0,0 +1,105 @@
|
|
1
|
+
package main
|
2
|
+
|
3
|
+
import (
|
4
|
+
"encoding/json"
|
5
|
+
"fmt"
|
6
|
+
"io/ioutil"
|
7
|
+
"net/http"
|
8
|
+
"time"
|
9
|
+
)
|
10
|
+
|
11
|
+
type ComposerJSON struct {
|
12
|
+
Require map[string]string `json:"require"`
|
13
|
+
RequireDev map[string]string `json:"require-dev"`
|
14
|
+
}
|
15
|
+
|
16
|
+
type ComposerLookup struct {
|
17
|
+
Packages []string
|
18
|
+
Verbose bool
|
19
|
+
}
|
20
|
+
|
21
|
+
func NewComposerLookup(verbose bool) PackageResolver {
|
22
|
+
return &ComposerLookup{Packages: []string{}, Verbose: verbose}
|
23
|
+
}
|
24
|
+
|
25
|
+
func (c *ComposerLookup) ReadPackagesFromFile(filename string) error {
|
26
|
+
rawfile, err := ioutil.ReadFile(filename)
|
27
|
+
if err != nil {
|
28
|
+
return err
|
29
|
+
}
|
30
|
+
|
31
|
+
data := ComposerJSON{}
|
32
|
+
err = json.Unmarshal([]byte(rawfile), &data)
|
33
|
+
if err != nil {
|
34
|
+
return err
|
35
|
+
}
|
36
|
+
|
37
|
+
for pkgname := range data.Require {
|
38
|
+
c.Packages = append(c.Packages, pkgname)
|
39
|
+
}
|
40
|
+
|
41
|
+
for pkgname := range data.RequireDev {
|
42
|
+
c.Packages = append(c.Packages, pkgname)
|
43
|
+
}
|
44
|
+
|
45
|
+
return nil
|
46
|
+
}
|
47
|
+
|
48
|
+
func (c *ComposerLookup) PackagesNotInPublic() []string {
|
49
|
+
notavail := []string{}
|
50
|
+
for _, pkg := range c.Packages {
|
51
|
+
if pkg == "php" {
|
52
|
+
continue
|
53
|
+
}
|
54
|
+
|
55
|
+
if !c.isAvailableInPublic(pkg, 0) {
|
56
|
+
notavail = append(notavail, pkg)
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
return notavail
|
61
|
+
}
|
62
|
+
|
63
|
+
func (c *ComposerLookup) isAvailableInPublic(pkgname string, retry int) bool {
|
64
|
+
if retry > 3 {
|
65
|
+
fmt.Printf(" [W] Maximum number of retries exhausted for package %s\n", pkgname)
|
66
|
+
|
67
|
+
return false
|
68
|
+
}
|
69
|
+
|
70
|
+
if c.Verbose {
|
71
|
+
fmt.Printf("Checking: https://packagist.org/packages/%s : ", pkgname)
|
72
|
+
}
|
73
|
+
|
74
|
+
client := &http.Client{
|
75
|
+
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
76
|
+
return http.ErrUseLastResponse
|
77
|
+
},
|
78
|
+
}
|
79
|
+
|
80
|
+
resp, err := client.Get("https://packagist.org/packages/" + pkgname)
|
81
|
+
if err != nil {
|
82
|
+
fmt.Printf(" [W] Error when trying to request https://packagist.org/packages/%s : %s\n", pkgname, err)
|
83
|
+
|
84
|
+
return false
|
85
|
+
}
|
86
|
+
defer resp.Body.Close()
|
87
|
+
|
88
|
+
if c.Verbose {
|
89
|
+
fmt.Printf("%s\n", resp.Status)
|
90
|
+
}
|
91
|
+
|
92
|
+
if resp.StatusCode == http.StatusOK {
|
93
|
+
return true
|
94
|
+
}
|
95
|
+
|
96
|
+
if resp.StatusCode == 429 {
|
97
|
+
fmt.Printf(" [!] Server responded with 429 (Too many requests), throttling and retrying..\n")
|
98
|
+
time.Sleep(10 * time.Second)
|
99
|
+
retry = retry + 1
|
100
|
+
|
101
|
+
c.isAvailableInPublic(pkgname, retry)
|
102
|
+
}
|
103
|
+
|
104
|
+
return false
|
105
|
+
}
|
Binary file
|
@@ -0,0 +1,11 @@
|
|
1
|
+
package main
|
2
|
+
|
3
|
+
// A PackageResolver resolves package information from a file
|
4
|
+
//
|
5
|
+
// ReadPackagesFromFile should take a filepath as input and parse relevant package information into a struct and then return any errors encountered while reading or unmarshalling the file.
|
6
|
+
//
|
7
|
+
// PackagesNotInPublic should determine whether or not a package is not available in a public package repository and return a slice of all packages not available in a public package repository.
|
8
|
+
type PackageResolver interface {
|
9
|
+
ReadPackagesFromFile(string) error
|
10
|
+
PackagesNotInPublic() []string
|
11
|
+
}
|
package/confused/main.go
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
/*
|
2
|
+
Package main implements an automated Dependency Confusion scanner.
|
3
|
+
|
4
|
+
Original research provided by Alex Birsan.
|
5
|
+
|
6
|
+
Original blog post detailing Dependency Confusion : https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610 .
|
7
|
+
*/
|
8
|
+
package main
|
9
|
+
|
10
|
+
import (
|
11
|
+
"flag"
|
12
|
+
"fmt"
|
13
|
+
"os"
|
14
|
+
"path/filepath"
|
15
|
+
"strings"
|
16
|
+
)
|
17
|
+
|
18
|
+
func main() {
|
19
|
+
var resolver PackageResolver
|
20
|
+
lang := ""
|
21
|
+
verbose := false
|
22
|
+
filename := ""
|
23
|
+
safespaces := ""
|
24
|
+
flag.StringVar(&lang, "l", "npm", "Package repository system. Possible values: \"pip\", \"npm\", \"composer\", \"mvn\"")
|
25
|
+
flag.StringVar(&safespaces, "s", "", "Comma-separated list of known-secure namespaces. Supports wildcards")
|
26
|
+
flag.BoolVar(&verbose, "v", false, "Verbose output")
|
27
|
+
flag.Parse()
|
28
|
+
|
29
|
+
// Check that we have a filename
|
30
|
+
if flag.NArg() == 0 {
|
31
|
+
Help()
|
32
|
+
flag.Usage()
|
33
|
+
os.Exit(1)
|
34
|
+
}
|
35
|
+
|
36
|
+
filename = flag.Args()[0]
|
37
|
+
if lang == "pip" {
|
38
|
+
resolver = NewPythonLookup(verbose)
|
39
|
+
} else if lang == "npm" {
|
40
|
+
resolver = NewNPMLookup(verbose)
|
41
|
+
} else if lang == "composer" {
|
42
|
+
resolver = NewComposerLookup(verbose)
|
43
|
+
} else if lang == "mvn" {
|
44
|
+
resolver = NewMVNLookup(verbose)
|
45
|
+
} else {
|
46
|
+
fmt.Printf("Unknown package repository system: %s\n", lang)
|
47
|
+
os.Exit(1)
|
48
|
+
}
|
49
|
+
err := resolver.ReadPackagesFromFile(filename)
|
50
|
+
if err != nil {
|
51
|
+
fmt.Printf("Encountered an error while trying to read packages from file: %s\n", err)
|
52
|
+
os.Exit(1)
|
53
|
+
}
|
54
|
+
outputPackages := removeSafe(resolver.PackagesNotInPublic(), safespaces)
|
55
|
+
PrintResult(outputPackages)
|
56
|
+
}
|
57
|
+
|
58
|
+
// Help outputs tool usage and help
|
59
|
+
func Help() {
|
60
|
+
fmt.Printf("Usage:\n %s [-l LANGUAGENAME] depfilename.ext\n", os.Args[0])
|
61
|
+
}
|
62
|
+
|
63
|
+
// PrintResult outputs the result of the scanner
|
64
|
+
func PrintResult(notavail []string) {
|
65
|
+
if len(notavail) == 0 {
|
66
|
+
fmt.Printf("[*] All packages seem to be available in the public repositories. \n\n" +
|
67
|
+
"In case your application uses private repositories please make sure that those namespaces in \n" +
|
68
|
+
"public repositories are controlled by a trusted party.\n\n")
|
69
|
+
return
|
70
|
+
}
|
71
|
+
fmt.Printf("Issues found, the following packages are not available in public package repositories:\n")
|
72
|
+
for _, n := range notavail {
|
73
|
+
fmt.Printf(" [!] %s\n", n)
|
74
|
+
}
|
75
|
+
os.Exit(1)
|
76
|
+
}
|
77
|
+
|
78
|
+
// removeSafe removes known-safe package names from the slice
|
79
|
+
func removeSafe(packages []string, safespaces string) []string {
|
80
|
+
retSlice := []string{}
|
81
|
+
safeNamespaces := []string{}
|
82
|
+
var ignored bool
|
83
|
+
safeTmp := strings.Split(safespaces, ",")
|
84
|
+
for _, s := range safeTmp {
|
85
|
+
safeNamespaces = append(safeNamespaces, strings.TrimSpace(s))
|
86
|
+
}
|
87
|
+
for _, p := range packages {
|
88
|
+
ignored = false
|
89
|
+
for _, s := range safeNamespaces {
|
90
|
+
ok, err := filepath.Match(s, p)
|
91
|
+
if err != nil {
|
92
|
+
fmt.Printf(" [W] Encountered an error while trying to match a known-safe namespace %s : %s\n", s, err)
|
93
|
+
continue
|
94
|
+
}
|
95
|
+
if ok {
|
96
|
+
ignored = true
|
97
|
+
}
|
98
|
+
}
|
99
|
+
if !ignored {
|
100
|
+
retSlice = append(retSlice, p)
|
101
|
+
}
|
102
|
+
}
|
103
|
+
return retSlice
|
104
|
+
}
|
package/confused/mvn.go
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
package main
|
2
|
+
|
3
|
+
import (
|
4
|
+
"encoding/json"
|
5
|
+
"encoding/xml"
|
6
|
+
"fmt"
|
7
|
+
"io/ioutil"
|
8
|
+
"log"
|
9
|
+
"net/http"
|
10
|
+
"strings"
|
11
|
+
"time"
|
12
|
+
)
|
13
|
+
|
14
|
+
// NPMLookup represents a collection of npm packages to be tested for dependency confusion.
|
15
|
+
type MVNLookup struct {
|
16
|
+
Packages []MVNPackage
|
17
|
+
Verbose bool
|
18
|
+
}
|
19
|
+
|
20
|
+
type MVNPackage struct {
|
21
|
+
Group string
|
22
|
+
Artifact string
|
23
|
+
Version string
|
24
|
+
}
|
25
|
+
|
26
|
+
// NewNPMLookup constructs an `MVNLookup` struct and returns it.
|
27
|
+
func NewMVNLookup(verbose bool) PackageResolver {
|
28
|
+
return &MVNLookup{Packages: []MVNPackage{}, Verbose: verbose}
|
29
|
+
}
|
30
|
+
|
31
|
+
// ReadPackagesFromFile reads package information from an npm package.json file
|
32
|
+
//
|
33
|
+
// Returns any errors encountered
|
34
|
+
func (n *MVNLookup) ReadPackagesFromFile(filename string) error {
|
35
|
+
rawfile, err := ioutil.ReadFile(filename)
|
36
|
+
if err != nil {
|
37
|
+
return err
|
38
|
+
}
|
39
|
+
|
40
|
+
fmt.Print("Checking: filename: " + filename + "\n")
|
41
|
+
|
42
|
+
var project MavenProject
|
43
|
+
if err := xml.Unmarshal([]byte(rawfile), &project); err != nil {
|
44
|
+
log.Fatalf("unable to unmarshal pom file. Reason: %s\n", err)
|
45
|
+
}
|
46
|
+
|
47
|
+
for _, dep := range project.Dependencies {
|
48
|
+
n.Packages = append(n.Packages, MVNPackage{dep.GroupId, dep.ArtifactId, dep.Version})
|
49
|
+
}
|
50
|
+
|
51
|
+
for _, dep := range project.Build.Plugins {
|
52
|
+
n.Packages = append(n.Packages, MVNPackage{dep.GroupId, dep.ArtifactId, dep.Version})
|
53
|
+
}
|
54
|
+
|
55
|
+
for _, build := range project.Profiles {
|
56
|
+
for _, dep := range build.Build.Plugins {
|
57
|
+
n.Packages = append(n.Packages, MVNPackage{dep.GroupId, dep.ArtifactId, dep.Version})
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
return nil
|
62
|
+
}
|
63
|
+
|
64
|
+
// PackagesNotInPublic determines if an npm package does not exist in the public npm package repository.
|
65
|
+
//
|
66
|
+
// Returns a slice of strings with any npm packages not in the public npm package repository
|
67
|
+
func (n *MVNLookup) PackagesNotInPublic() []string {
|
68
|
+
notavail := []string{}
|
69
|
+
for _, pkg := range n.Packages {
|
70
|
+
if !n.isAvailableInPublic(pkg, 0) {
|
71
|
+
notavail = append(notavail, pkg.Group + "/" + pkg.Artifact)
|
72
|
+
}
|
73
|
+
}
|
74
|
+
return notavail
|
75
|
+
}
|
76
|
+
|
77
|
+
// isAvailableInPublic determines if an npm package exists in the public npm package repository.
|
78
|
+
//
|
79
|
+
// Returns true if the package exists in the public npm package repository.
|
80
|
+
func (n *MVNLookup) isAvailableInPublic(pkg MVNPackage, retry int) bool {
|
81
|
+
if retry > 3 {
|
82
|
+
fmt.Printf(" [W] Maximum number of retries exhausted for package: %s\n", pkg.Group)
|
83
|
+
return false
|
84
|
+
}
|
85
|
+
if pkg.Group == "" {
|
86
|
+
return true
|
87
|
+
}
|
88
|
+
|
89
|
+
group := strings.Replace(pkg.Group, ".", "/",-1)
|
90
|
+
if n.Verbose {
|
91
|
+
fmt.Print("Checking: https://repo1.maven.org/maven2/"+group+"/ ")
|
92
|
+
}
|
93
|
+
resp, err := http.Get("https://repo1.maven.org/maven2/"+group+"/")
|
94
|
+
if err != nil {
|
95
|
+
fmt.Printf(" [W] Error when trying to request https://repo1.maven.org/maven2/"+group+"/ : %s\n", err)
|
96
|
+
return false
|
97
|
+
}
|
98
|
+
defer resp.Body.Close()
|
99
|
+
if n.Verbose {
|
100
|
+
fmt.Printf("%s\n", resp.Status)
|
101
|
+
}
|
102
|
+
if resp.StatusCode == http.StatusOK {
|
103
|
+
npmResp := NpmResponse{}
|
104
|
+
body, _ := ioutil.ReadAll(resp.Body)
|
105
|
+
_ = json.Unmarshal(body, &npmResp)
|
106
|
+
if npmResp.NotAvailable() {
|
107
|
+
if n.Verbose {
|
108
|
+
fmt.Printf("[W] Package %s was found, but all its versions are unpublished, making anyone able to takeover the namespace.\n", pkg.Group)
|
109
|
+
}
|
110
|
+
return false
|
111
|
+
}
|
112
|
+
return true
|
113
|
+
} else if resp.StatusCode == 429 {
|
114
|
+
fmt.Printf(" [!] Server responded with 429 (Too many requests), throttling and retrying...\n")
|
115
|
+
time.Sleep(10 * time.Second)
|
116
|
+
retry = retry + 1
|
117
|
+
n.isAvailableInPublic(pkg, retry)
|
118
|
+
}
|
119
|
+
return false
|
120
|
+
}
|