Skip to content

Commit

Permalink
Some scaffolding for a JAR patcher
Browse files Browse the repository at this point in the history
  • Loading branch information
freeqaz committed Dec 15, 2021
1 parent bec65fd commit 02a9e73
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 7 deletions.
52 changes: 48 additions & 4 deletions tools/log4shell/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func scanCommand(c *cli.Context) error {
return nil
}

func hotpatchCommand(c *cli.Context) error {
func hotPatchCommand(c *cli.Context) error {
enableGlobalFlags(c)

ip := c.String("ip")
Expand All @@ -104,6 +104,38 @@ func hotpatchCommand(c *cli.Context) error {
return nil
}

func jarPatchCommand(c *cli.Context) error {
enableGlobalFlags(c)

fileName := c.String("file-name")

if fileName == "" {
log.Info().Msg("Public IP not provided. Binding to the local network interface.")
panic("must specify a valid file name to patch")
}

file, err := os.Open(path)
if err != nil {
log.Warn().
Str("path", path).
Err(err).
Msg("unable to open archive")
panic("unable to open specified file")
}

fileInfo, err := file.Stat()

if err != nil {
panic("unable to read file info")
}

findings := scan.SearchArchiveForVulnerableFiles(fileName, file, fileInfo.Size(), false)

// TODO: Do something with these findings to actually patch them in-place. Either that or add the patching to `SearchArchiveForVulnerableFiles` above.

return nil
}

func main() {
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix

Expand Down Expand Up @@ -164,16 +196,28 @@ func main() {
Action: scanCommand,
},
{
Name: "hotpatch",
Name: "in-memory-hot-patch",
Aliases: []string{"s"},
Usage: "Perform a live hotpatch of a system by exploiting the log4shell vulnerability for immediate mitigation. The payload executed patches the running process to prevent further payloads from being able to be executed.",
Usage: "Perform a live hot patch of a system by exploiting the log4shell vulnerability for immediate mitigation. The payload executed patches the running process to prevent further payloads from being able to be executed.",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "ip",
Usage: "If testing locally, set this to a local network interface (view available interfaces with ifconfig/ipconfig). If using on a remote server, set this value to the publicly accessible IP address of the server.",
},
},
Action: hotpatchCommand,
Action: hotPatchCommand,
},
{
Name: "patch-local-jar",
Aliases: []string{"s"},
Usage: "Patches a specified JAR or WAR file against log4shell by injecting a fixed version of the vulnerable code into vulnerable log4j instances found within it.",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "file-name",
Usage: "Patches the specified file (must be a valid JAR or WAR file).",
},
},
Action: jarPatchCommand,
},
},
}
Expand Down
29 changes: 29 additions & 0 deletions tools/log4shell/patch/patch-local-jar.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2021 by LunaSec (owned by Refinery Labs, Inc)
//
// 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
//
// http://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 patch

import (
"fmt"
ldapmsg "github.com/lor00x/goldap/message"
"github.com/lunasec-io/lunasec/tools/log4shell/constants"
"github.com/rs/zerolog/log"
"io/ioutil"
golog "log"
)

import (
"github.com/vjeantet/ldapserver"
)

7 changes: 4 additions & 3 deletions tools/log4shell/scan/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func scanArchive(path string, file *zip.File, onlyScanArchives bool) (findings [
archiveReader := bytes.NewReader(buffer)
archiveSize := int64(len(buffer))

return scanArchiveForVulnerableFiles(newPath, archiveReader, archiveSize, onlyScanArchives)
return SearchArchiveForVulnerableFiles(newPath, archiveReader, archiveSize, onlyScanArchives)
}

func scanFile(path string, file *zip.File, onlyScanArchives bool) (findings []types.Finding) {
Expand Down Expand Up @@ -125,7 +125,8 @@ func scanFile(path string, file *zip.File, onlyScanArchives bool) (findings []ty
return
}

func scanArchiveForVulnerableFiles(path string, reader io.ReaderAt, size int64, onlyScanArchives bool) (findings []types.Finding) {
// SearchArchiveForVulnerableFiles Takes in a given JAR or WAR file and searches it for findings.
func SearchArchiveForVulnerableFiles(path string, reader io.ReaderAt, size int64, onlyScanArchives bool) (findings []types.Finding) {
zipReader, err := zip.NewReader(reader, size)
if err != nil {
log.Warn().
Expand Down Expand Up @@ -157,7 +158,7 @@ func scanLocatedArchive(path string, info os.FileInfo, onlyScanArchives bool) (f
}
defer file.Close()

return scanArchiveForVulnerableFiles(path, file, info.Size(), onlyScanArchives)
return SearchArchiveForVulnerableFiles(path, file, info.Size(), onlyScanArchives)
}

// SearchDirsForVulnerableClassFiles walks each search dir looking for .class files in archives which have a hash
Expand Down

0 comments on commit 02a9e73

Please sign in to comment.