From 8de522d67748c75dd1e63ab26c6f896336e8fe79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B8=D0=B2?= Date: Fri, 24 Jun 2022 22:23:06 -0600 Subject: [PATCH 01/11] feat: backup JARs --- jar/backup.go | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ jar/walker.go | 7 ++++++ log4jscanner.go | 13 +++++++++-- 3 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 jar/backup.go diff --git a/jar/backup.go b/jar/backup.go new file mode 100644 index 0000000..aede039 --- /dev/null +++ b/jar/backup.go @@ -0,0 +1,59 @@ +package jar + +import ( + "fmt" + "io" + "os" + "path/filepath" + "strings" +) + +func BackupFiles(jar string) { + pathdst := filepath.Join(".", "backup") + if _, err := os.Stat(pathdst); os.IsNotExist(err) { + err := os.Mkdir(pathdst, os.ModePerm) + if err != nil { + fmt.Errorf("create backup %v", err) + } + } + + jarSplit := strings.Split(jar, "/") + + if len(jarSplit) == 3 { + pathdst = pathdst + "/" + jarSplit[2] + ".bak" + } + + if len(jarSplit) == 4 { + pathdst = pathdst + "/" + jarSplit[3] + ".bak" + } + + _, err := copyJars(jar, pathdst) + if err != nil { + fmt.Errorf("copy file %v ", err) + } +} + +func copyJars(src, dst string) (int64, error) { + sourceFileStat, err := os.Stat(src) + if err != nil { + return 0, err + } + + if !sourceFileStat.Mode().IsRegular() { + return 0, fmt.Errorf("%s is not a regular file", src) + } + + source, err := os.Open(src) + if err != nil { + return 0, err + } + defer source.Close() + + destination, err := os.Create(dst) + if err != nil { + return 0, err + } + defer destination.Close() + nBytes, err := io.Copy(destination, source) + return nBytes, err +} diff --git a/jar/walker.go b/jar/walker.go index d7fee31..6c119d5 100644 --- a/jar/walker.go +++ b/jar/walker.go @@ -51,6 +51,8 @@ type Walker struct { // Rewrite indicates if the Walker should rewrite JARs in place as it // iterates through the filesystem. Rewrite bool + + Backup bool // SkipDir, if provided, allows the walker to skip certain directories // as it scans. SkipDir func(path string, de fs.DirEntry) bool @@ -133,6 +135,10 @@ func (w *walker) skipDir(path string, d fs.DirEntry) bool { } func (w *walker) visit(p string, d fs.DirEntry) error { + if w.Backup { + BackupFiles(w.filepath(p)) + } + if d.IsDir() || !d.Type().IsRegular() { return nil } @@ -215,5 +221,6 @@ func (w *walker) visit(p string, d fs.DirEntry) error { return fmt.Errorf("overwriting %s: %v", p, err) } w.handleRewrite(p, r) + return nil } diff --git a/log4jscanner.go b/log4jscanner.go index fdad047..cbade13 100644 --- a/log4jscanner.go +++ b/log4jscanner.go @@ -40,6 +40,7 @@ Flags: -f, --force Don't skip network and userland filesystems. (smb,nfs,afs,fuse) -w, --rewrite Rewrite vulnerable JARs as they are detected. -v, --verbose Print verbose logs to stderr. + -b, --backup Make a backup of the scanned files `) } @@ -49,8 +50,8 @@ var skipDirs = map[string]bool{ ".git": true, "node_modules": true, ".idea": true, - ".svn": true, - ".p4root": true, + ".svn": true, + ".p4root": true, // TODO(ericchiang): expand } @@ -63,6 +64,8 @@ func main() { v bool force bool f bool + backup bool + b bool toSkip []string ) appendSkip := func(dir string) error { @@ -76,6 +79,8 @@ func main() { flag.BoolVar(&v, "v", false, "") flag.BoolVar(&force, "force", false, "") flag.BoolVar(&f, "f", false, "") + flag.BoolVar(&b, "b", false, "") + flag.BoolVar(&backup, "backup", false, "") flag.Func("s", "", appendSkip) flag.Func("skip", "", appendSkip) flag.Usage = usage @@ -94,6 +99,9 @@ func main() { if w { rewrite = w } + if b { + backup = b + } log.SetFlags(log.LstdFlags | log.Lshortfile) logf := func(format string, v ...interface{}) { if verbose { @@ -103,6 +111,7 @@ func main() { seen := 0 walker := jar.Walker{ Rewrite: rewrite, + Backup: backup, SkipDir: func(path string, d fs.DirEntry) bool { seen++ if seen%5000 == 0 { From 60bb68daf7d3ae15085867afbb49df57a41b75dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B8=D0=B2?= <54087279+KenethSandoval@users.noreply.github.com> Date: Mon, 27 Jun 2022 15:36:25 -0600 Subject: [PATCH 02/11] Add license and test file --- jar/backup.go | 13 +++++++++++++ jar/backup_test.go | 13 +++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 jar/backup_test.go diff --git a/jar/backup.go b/jar/backup.go index aede039..3bf1e32 100644 --- a/jar/backup.go +++ b/jar/backup.go @@ -1,3 +1,16 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. package jar import ( diff --git a/jar/backup_test.go b/jar/backup_test.go new file mode 100644 index 0000000..c4774e0 --- /dev/null +++ b/jar/backup_test.go @@ -0,0 +1,13 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. \ No newline at end of file From 854997bfac91aef48ffc50dd06fd2f14716cc660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B8=D0=B2?= Date: Mon, 27 Jun 2022 19:03:54 -0600 Subject: [PATCH 03/11] add package backup_test --- jar/backup_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jar/backup_test.go b/jar/backup_test.go index c4774e0..a282e10 100644 --- a/jar/backup_test.go +++ b/jar/backup_test.go @@ -10,4 +10,5 @@ // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and -// limitations under the License. \ No newline at end of file +// limitations under the License. +package jar From f12ad9f0542d53b196ba2d573de3f13eb57f955c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B8=D0=B2?= <54087279+KenethSandoval@users.noreply.github.com> Date: Tue, 28 Jun 2022 11:32:36 -0600 Subject: [PATCH 04/11] Change year in headers files --- jar/backup.go | 2 +- jar/backup_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jar/backup.go b/jar/backup.go index 3bf1e32..e2dfdaa 100644 --- a/jar/backup.go +++ b/jar/backup.go @@ -1,4 +1,4 @@ -// Copyright 2021 Google LLC +// Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/jar/backup_test.go b/jar/backup_test.go index a282e10..aa90e9b 100644 --- a/jar/backup_test.go +++ b/jar/backup_test.go @@ -1,4 +1,4 @@ -// Copyright 2021 Google LLC +// Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. From 72c120cda08a4435531a9462ab7f78edf9285ed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B8=D0=B2?= Date: Tue, 28 Jun 2022 22:16:01 -0600 Subject: [PATCH 05/11] resolve observations --- jar/backup.go | 42 +++++++++++++++++++++++------------------- jar/walker.go | 12 ++++++++---- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/jar/backup.go b/jar/backup.go index 3bf1e32..882db71 100644 --- a/jar/backup.go +++ b/jar/backup.go @@ -18,32 +18,36 @@ import ( "io" "os" "path/filepath" - "strings" ) -func BackupFiles(jar string) { - pathdst := filepath.Join(".", "backup") - if _, err := os.Stat(pathdst); os.IsNotExist(err) { - err := os.Mkdir(pathdst, os.ModePerm) - if err != nil { - fmt.Errorf("create backup %v", err) - } - } +// backupFile makes copies JARs file in the backup folder +func backupFile(jarPath string, jarSource string, jarFile string) error { + pathdst := filepath.Join(jarPath, "backup") - jarSplit := strings.Split(jar, "/") - - if len(jarSplit) == 3 { - pathdst = pathdst + "/" + jarSplit[2] + ".bak" + err := makeDirIfNotExist(pathdst) + if err != nil { + return err } - if len(jarSplit) == 4 { - pathdst = pathdst + "/" + jarSplit[3] + ".bak" - } + jarDst := pathdst + "/" + jarFile + ".bak" - _, err := copyJars(jar, pathdst) + _, err = copyJars(jarSource, jarDst) if err != nil { - fmt.Errorf("copy file %v ", err) + return err + } + return nil +} + +// makeDirIfNotExist make folder to copies file from +// directory to scan +func makeDirIfNotExist(src string) error { + if _, err := os.Stat(src); os.IsNotExist(err) { + err := os.Mkdir(src, os.ModePerm) + if err != nil { + return fmt.Errorf("creating backup directory: %v", err) + } } + return nil } func copyJars(src, dst string) (int64, error) { @@ -53,7 +57,7 @@ func copyJars(src, dst string) (int64, error) { } if !sourceFileStat.Mode().IsRegular() { - return 0, fmt.Errorf("%s is not a regular file", src) + return 0, fmt.Errorf("%s is not a regular file:", src) } source, err := os.Open(src) diff --git a/jar/walker.go b/jar/walker.go index 6c119d5..2328c64 100644 --- a/jar/walker.go +++ b/jar/walker.go @@ -51,7 +51,7 @@ type Walker struct { // Rewrite indicates if the Walker should rewrite JARs in place as it // iterates through the filesystem. Rewrite bool - + // Backup indicates if the Walker should create a backups from JARs Backup bool // SkipDir, if provided, allows the walker to skip certain directories // as it scans. @@ -135,9 +135,6 @@ func (w *walker) skipDir(path string, d fs.DirEntry) bool { } func (w *walker) visit(p string, d fs.DirEntry) error { - if w.Backup { - BackupFiles(w.filepath(p)) - } if d.IsDir() || !d.Type().IsRegular() { return nil @@ -184,6 +181,13 @@ func (w *walker) visit(p string, d fs.DirEntry) error { return nil } + if w.Backup { + err := backupFile(w.dir, w.filepath(p), p) + if err != nil { + return fmt.Errorf("backup: %v", err) + } + } + dest := w.filepath(p) // Ensure temp file is created in the same directory as the file we want to // rewrite to improve the chances of ending up on the same filesystem. On From 1a60040db12abc6b51e3418acf1062d5534e4a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B8=D0=B2?= Date: Wed, 29 Jun 2022 18:37:05 -0600 Subject: [PATCH 06/11] remove backup_test --- jar/backup_test.go | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 jar/backup_test.go diff --git a/jar/backup_test.go b/jar/backup_test.go deleted file mode 100644 index aa90e9b..0000000 --- a/jar/backup_test.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -package jar From f87d1e3e9a238d619e9b4e644e2c9b716f128d3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B8=D0=B2?= Date: Wed, 29 Jun 2022 18:45:44 -0600 Subject: [PATCH 07/11] add punctuation for comments --- jar/walker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jar/walker.go b/jar/walker.go index 2328c64..c8c74ec 100644 --- a/jar/walker.go +++ b/jar/walker.go @@ -51,7 +51,7 @@ type Walker struct { // Rewrite indicates if the Walker should rewrite JARs in place as it // iterates through the filesystem. Rewrite bool - // Backup indicates if the Walker should create a backups from JARs + // Backup indicates if the Walker should create a backups from JARs. Backup bool // SkipDir, if provided, allows the walker to skip certain directories // as it scans. From 3ebe4f30c0e465e0e0d3ed3eca04ee7974c18c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B8=D0=B2?= Date: Wed, 29 Jun 2022 18:47:09 -0600 Subject: [PATCH 08/11] include mode in error message --- jar/backup.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jar/backup.go b/jar/backup.go index 9f38e17..98698bd 100644 --- a/jar/backup.go +++ b/jar/backup.go @@ -56,8 +56,8 @@ func copyJars(src, dst string) (int64, error) { return 0, err } - if !sourceFileStat.Mode().IsRegular() { - return 0, fmt.Errorf("%s is not a regular file:", src) + if m := sourceFileStat.Mode(); !m.IsRegular() { + return 0, fmt.Errorf("%s is not a regular file: %s", src, m) } source, err := os.Open(src) From 942a879ae47da364d99d238374ab2f3925ea1d11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B8=D0=B2?= Date: Wed, 29 Jun 2022 19:14:03 -0600 Subject: [PATCH 09/11] resolve conversations --- jar/backup.go | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/jar/backup.go b/jar/backup.go index 98698bd..3860cdd 100644 --- a/jar/backup.go +++ b/jar/backup.go @@ -17,36 +17,16 @@ import ( "fmt" "io" "os" - "path/filepath" ) // backupFile makes copies JARs file in the backup folder func backupFile(jarPath string, jarSource string, jarFile string) error { - pathdst := filepath.Join(jarPath, "backup") + pathdst := jarPath + "/" + jarFile + ".bak" - err := makeDirIfNotExist(pathdst) + _, err := copyJars(jarSource, pathdst) if err != nil { return err } - - jarDst := pathdst + "/" + jarFile + ".bak" - - _, err = copyJars(jarSource, jarDst) - if err != nil { - return err - } - return nil -} - -// makeDirIfNotExist make folder to copies file from -// directory to scan -func makeDirIfNotExist(src string) error { - if _, err := os.Stat(src); os.IsNotExist(err) { - err := os.Mkdir(src, os.ModePerm) - if err != nil { - return fmt.Errorf("creating backup directory: %v", err) - } - } return nil } From 64c398796b2d233c422449cf3a6e4ba33edfa734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B8=D0=B2?= Date: Wed, 29 Jun 2022 20:06:28 -0600 Subject: [PATCH 10/11] combine 3 into 1 --- jar/backup.go | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ jar/walker.go | 11 ++++++++++ log4jscanner.go | 13 +++++++++-- 3 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 jar/backup.go diff --git a/jar/backup.go b/jar/backup.go new file mode 100644 index 0000000..26bead3 --- /dev/null +++ b/jar/backup.go @@ -0,0 +1,57 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package jar + +import ( + "fmt" + "io" + "os" + "path/filepath" +) + +// backupFile makes copies JARs file in the backup folder +func backupFile(jarPath, jarSource, jarFile string) error { + pathdst := filepath.Join(jarPath, jarFile+".bak") + + _, err := copyJars(jarSource, pathdst) + if err != nil { + return err + } + return nil +} + +func copyJars(src, dst string) (int64, error) { + sourceFileStat, err := os.Stat(src) + if err != nil { + return 0, err + } + + if m := sourceFileStat.Mode(); !m.IsRegular() { + return 0, fmt.Errorf("%s is not a regular file: %s", src, m) + } + + source, err := os.Open(src) + if err != nil { + return 0, err + } + defer source.Close() + + destination, err := os.Create(dst) + if err != nil { + return 0, err + } + defer destination.Close() + nBytes, err := io.Copy(destination, source) + return nBytes, err +} diff --git a/jar/walker.go b/jar/walker.go index d7fee31..c8c74ec 100644 --- a/jar/walker.go +++ b/jar/walker.go @@ -51,6 +51,8 @@ type Walker struct { // Rewrite indicates if the Walker should rewrite JARs in place as it // iterates through the filesystem. Rewrite bool + // Backup indicates if the Walker should create a backups from JARs. + Backup bool // SkipDir, if provided, allows the walker to skip certain directories // as it scans. SkipDir func(path string, de fs.DirEntry) bool @@ -133,6 +135,7 @@ func (w *walker) skipDir(path string, d fs.DirEntry) bool { } func (w *walker) visit(p string, d fs.DirEntry) error { + if d.IsDir() || !d.Type().IsRegular() { return nil } @@ -178,6 +181,13 @@ func (w *walker) visit(p string, d fs.DirEntry) error { return nil } + if w.Backup { + err := backupFile(w.dir, w.filepath(p), p) + if err != nil { + return fmt.Errorf("backup: %v", err) + } + } + dest := w.filepath(p) // Ensure temp file is created in the same directory as the file we want to // rewrite to improve the chances of ending up on the same filesystem. On @@ -215,5 +225,6 @@ func (w *walker) visit(p string, d fs.DirEntry) error { return fmt.Errorf("overwriting %s: %v", p, err) } w.handleRewrite(p, r) + return nil } diff --git a/log4jscanner.go b/log4jscanner.go index fdad047..cbade13 100644 --- a/log4jscanner.go +++ b/log4jscanner.go @@ -40,6 +40,7 @@ Flags: -f, --force Don't skip network and userland filesystems. (smb,nfs,afs,fuse) -w, --rewrite Rewrite vulnerable JARs as they are detected. -v, --verbose Print verbose logs to stderr. + -b, --backup Make a backup of the scanned files `) } @@ -49,8 +50,8 @@ var skipDirs = map[string]bool{ ".git": true, "node_modules": true, ".idea": true, - ".svn": true, - ".p4root": true, + ".svn": true, + ".p4root": true, // TODO(ericchiang): expand } @@ -63,6 +64,8 @@ func main() { v bool force bool f bool + backup bool + b bool toSkip []string ) appendSkip := func(dir string) error { @@ -76,6 +79,8 @@ func main() { flag.BoolVar(&v, "v", false, "") flag.BoolVar(&force, "force", false, "") flag.BoolVar(&f, "f", false, "") + flag.BoolVar(&b, "b", false, "") + flag.BoolVar(&backup, "backup", false, "") flag.Func("s", "", appendSkip) flag.Func("skip", "", appendSkip) flag.Usage = usage @@ -94,6 +99,9 @@ func main() { if w { rewrite = w } + if b { + backup = b + } log.SetFlags(log.LstdFlags | log.Lshortfile) logf := func(format string, v ...interface{}) { if verbose { @@ -103,6 +111,7 @@ func main() { seen := 0 walker := jar.Walker{ Rewrite: rewrite, + Backup: backup, SkipDir: func(path string, d fs.DirEntry) bool { seen++ if seen%5000 == 0 { From 3fe86ddc3606757ea516919f454830c8430a6d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B8=D0=B2?= Date: Wed, 29 Jun 2022 20:10:40 -0600 Subject: [PATCH 11/11] resolve --- jar/backup.go | 1 - 1 file changed, 1 deletion(-) diff --git a/jar/backup.go b/jar/backup.go index 26bead3..545e3b3 100644 --- a/jar/backup.go +++ b/jar/backup.go @@ -23,7 +23,6 @@ import ( // backupFile makes copies JARs file in the backup folder func backupFile(jarPath, jarSource, jarFile string) error { pathdst := filepath.Join(jarPath, jarFile+".bak") - _, err := copyJars(jarSource, pathdst) if err != nil { return err