Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 48 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
# Features

- DNS/HTTP(S)/SMTP(S)/LDAP Interaction
- IPv4 and IPv6 support
- CLI / Web / Burp / ZAP / Docker client
- AES encryption with zero logging
- Automatic ACME based Wildcard TLS w/ Auto Renewal
Expand Down Expand Up @@ -118,7 +119,7 @@ You can configure your PDCP_API_KEY in two ways:
This will generate a unique payload that can be used for OOB testing with minimal interaction information in the output.

```console
interactsh-client
$ interactsh-client

_ __ __ __
(_)___ / /____ _________ ______/ /______/ /_
Expand All @@ -144,7 +145,7 @@ interactsh-client
`interactsh-client` with `-sf, -session-file` flag can be used store/read the current session information from user defined file which is useful to resume the same session to poll the interactions even after the client gets stopped or closed.

```console
interactsh-client -sf interact.session
$ interactsh-client -sf interact.session

_ __ __ __
(_)___ / /____ _________ ______/ /______/ /_
Expand All @@ -171,7 +172,7 @@ interactsh-client -sf interact.session
Running the `interactsh-client` in **verbose mode** (v) to see the whole request and response, along with an output file to analyze afterwards.

```console
interactsh-client -v -o interactsh-logs.txt
$ interactsh-client -v -o interactsh-logs.txt

_ __ __ __
(_)___ / /____ _________ ______/ /______/ /_
Expand Down Expand Up @@ -262,7 +263,7 @@ docker run projectdiscovery/interactsh-client:latest
```

```console
docker run projectdiscovery/interactsh-client:latest
$ docker run projectdiscovery/interactsh-client:latest

_ __ __ __
(_)___ / /____ _________ ______/ /______/ /_
Expand Down Expand Up @@ -341,7 +342,7 @@ Usage:
Flags:
INPUT:
-d, -domain string[] single/multiple configured domain to use for server
-ip string public ip address to use for interactsh server
-ip string[] public ip address(es) to use for interactsh server (comma-separated,supports both IPv4 & IPv6)
-lip, -listen-ip string public ip address to listen on (default "0.0.0.0")
-e, -eviction int number of days to persist interaction data in memory (default 30)
-ne, -no-eviction disable periodic data eviction from memory
Expand Down Expand Up @@ -448,7 +449,7 @@ A number of needed flags are configured automatically to run `interactsh-server`
## Running Interactsh Server

```console
interactsh-server -domain interact.sh
$ interactsh-server -domain interact.sh

_ __ __ __
(_)___ / /____ _________ ______/ /______/ /_
Expand All @@ -473,7 +474,7 @@ interactsh-server -domain interact.sh
Multiple domain names can be given in the same way as above to run the same interactsh server across multiple **configured domains**.

```console
interactsh-server -d oast.pro,oast.me
$ interactsh-server -d oast.pro,oast.me

_ __ __ __
(_)___ / /____ _________ ______/ /______/ /_
Expand All @@ -495,6 +496,34 @@ interactsh-server -d oast.pro,oast.me
[DNS] Listening on UDP 46.101.25.250:53
```

## Interactsh Server with IPv4 and IPv6

Interactsh server supports both IPv4 and IPv6 addresses. You can specify multiple IP addresses using the `-ip` flag, and the server will respond with the appropriate A (IPv4) or AAAA (IPv6) records in DNS responses.

```console
$ interactsh-server -d oast.pro -ip 192.0.2.1,2001:db8::1

_ __ __ __
(_)___ / /____ _________ ______/ /______/ /_
/ / __ \/ __/ _ \/ ___/ __ '/ ___/ __/ ___/ __ \
/ / / / / /_/ __/ / / /_/ / /__/ /_(__ ) / / /
/_/_/ /_/\__/\___/_/ \__,_/\___/\__/____/_/ /_/ 1.0.5

projectdiscovery.io

[INF] Configured IP addresses: 192.0.2.1, 2001:db8::1
[INF] Listening with the following services:
[HTTPS] Listening on TCP 46.101.25.250:443
[HTTP] Listening on TCP 46.101.25.250:80
[SMTPS] Listening on TCP 46.101.25.250:587
[LDAP] Listening on TCP 46.101.25.250:389
[SMTP] Listening on TCP 46.101.25.250:25
[DNS] Listening on TCP 46.101.25.250:53
[DNS] Listening on UDP 46.101.25.250:53
```

The server will automatically detect and categorize IPv4 and IPv6 addresses, returning appropriate DNS records based on the query type.

<table>
<td>

Expand Down Expand Up @@ -564,7 +593,7 @@ stream {
**Configured Domains**

```console
interactsh-server -d oast.pro,oast.me
$ interactsh-server -d oast.pro,oast.me

_ __ __ __
(_)___ / /____ _________ ______/ /______/ /_
Expand All @@ -590,7 +619,7 @@ interactsh-server -d oast.pro,oast.me

Index page for http server can be customized while running custom interactsh server using `-http-index` flag.

```console
```bash
interactsh-server -d hackwithautomation.com -http-index banner.html
```

Expand All @@ -605,7 +634,7 @@ Interactsh http server optionally enables file hosting to help in security testi

To use this feature, `-http-directory` flag can be used which accepts diretory as input and files are served under `/s/` directory.

```console
```bash
interactsh-server -d hackwithautomation.com -http-directory ./paylods
```

Expand All @@ -623,7 +652,7 @@ The following query parameter names are supported - `body`, `header`, `status` a
- **delay** (response time)

```console
curl -i 'https://hackwithautomation.com/x?status=307&body=this+is+example+body&delay=1&header=header1:value1&header=header1:value12'
$ curl -i 'https://hackwithautomation.com/x?status=307&body=this+is+example+body&delay=1&header=header1:value1&header=header1:value12'

HTTP/2 307
header1: value1
Expand All @@ -648,7 +677,7 @@ this is example body
To enable `wildcard` interaction for configured Interactsh domain `wildcard` flag can be used with implicit authentication protection via the `auth` flag if the `token` flag is omitted.

```console
interactsh-server -domain hackwithautomation.com -wildcard
$ interactsh-server -domain hackwithautomation.com -wildcard

_ __ __ __
(_)___ / /____ _________ ______/ /______/ /_
Expand All @@ -674,7 +703,7 @@ interactsh-server -domain hackwithautomation.com -wildcard
As default, Interactsh server support LDAP interaction for the payload included in [search query](https://ldapwiki.com/wiki/LDAP%20Query%20Examples), additionally `ldap` flag can be used for complete logging.

```console
interactsh-server -domain hackwithautomation.com -sa -ldap
$ interactsh-server -domain hackwithautomation.com -sa -ldap

_ __ __ __
(_)___ / /____ _________ ______/ /______/ /_
Expand All @@ -699,7 +728,7 @@ The length of the interactsh payload is **33** by default, consisting of **20**


```console
interactsh-server -d hackwithautomation.com -cidl 4 -cidn 6
$ interactsh-server -d hackwithautomation.com -cidl 4 -cidn 6

_ __ __ __
(_)___ / /____ _________ ______/ /______/ /_
Expand All @@ -723,7 +752,7 @@ interactsh-server -d hackwithautomation.com -cidl 4 -cidn 6
**Note:** It is important and required to use same length on both side (**client** and **server**), otherwise co-relation will not work.

```console
interactsh-client -s hackwithautomation.com -cidl 4 -cidn 6
$ interactsh-client -s hackwithautomation.com -cidl 4 -cidn 6

_ __ __ __
(_)___ / /____ _________ ______/ /______/ /_
Expand All @@ -745,7 +774,7 @@ The [certmagic](https://github.com/caddyserver/certmagic) library is used by def


```console
interactsh-server -d hackwithautomation.com -cert hackwithautomation.com.crt -privkey hackwithautomation.com.key
$ interactsh-server -d hackwithautomation.com -cert hackwithautomation.com.crt -privkey hackwithautomation.com.key

_ __ __ __
(_)___ / /____ _________ ______/ /______/ /_
Expand Down Expand Up @@ -802,14 +831,14 @@ $ sudo interactsh-server -smb -skip-acme -debug -domain localhost
### Responder
[Responder](https://github.com/lgandx/Responder) is wrapped in a docker container exposing various service ports via docker port forwarding. The interactions are retrieved by monitoring the shared log file `Responder-Session.log` in the temp folder. To use it on a self-hosted instance, it's necessary first to build the docker container and tag it as `interactsh`(docker daemon must be configured correctly and with port forwarding capabilities):

```console
```bash
docker build . -t interactsh
```

Then run the service with:

```console
$ sudo interactsh-server -responder -d localhost
```bash
sudo interactsh-server -responder -d localhost
```

On default settings, the daemon listens on the following ports:
Expand Down
14 changes: 10 additions & 4 deletions cmd/interactsh-server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"os"
"os/signal"
"path/filepath"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -44,7 +45,7 @@ func main() {

flagSet.CreateGroup("input", "Input",
flagSet.StringSliceVarP(&cliOptions.Domains, "domain", "d", []string{}, "single/multiple configured domain to use for server", goflags.CommaSeparatedStringSliceOptions),
flagSet.StringVar(&cliOptions.IPAddress, "ip", "", "public ip address to use for interactsh server"),
flagSet.StringSliceVarP(&cliOptions.IPAddresses, "ip", "i", []string{}, "public IP address(es) to use for interactsh server (comma-separated, supports both IPv4 & IPv6)", goflags.CommaSeparatedStringSliceOptions),
flagSet.StringVarP(&cliOptions.ListenIP, "listen-ip", "lip", "0.0.0.0", "public ip address to listen on"),
flagSet.IntVarP(&cliOptions.Eviction, "eviction", "e", 30, "number of days to persist interaction data in memory"),
flagSet.BoolVarP(&cliOptions.NoEviction, "no-eviction", "ne", false, "disable periodic data eviction from memory"),
Expand Down Expand Up @@ -149,7 +150,7 @@ func main() {
gologger.Fatal().Msgf("CorrelationIdNonceLength (cidn) must be at least %d\n", settings.CorrelationIdNonceLengthMinimum)
}

if cliOptions.IPAddress == "" && cliOptions.ListenIP == "0.0.0.0" {
if len(cliOptions.IPAddresses) == 0 && cliOptions.ListenIP == "0.0.0.0" {
publicIP, _ := getPublicIP()
outboundIP, _ := iputil.GetSourceIP("scanme.sh")

Expand Down Expand Up @@ -179,7 +180,11 @@ func main() {
gologger.Fatal().Msgf("%s\nNo bindable address could be found for port %d\nPlease ensure to have proper privileges and/or choose the correct ip:\n%s\n", err, cliOptions.DnsPort, addressesBuilder.String())
}
cliOptions.ListenIP = bindableIP
cliOptions.IPAddress = publicIP
cliOptions.IPAddresses = append(cliOptions.IPAddresses, publicIP)
}

if len(cliOptions.IPAddresses) > 0 {
gologger.Info().Msgf("Configured IP addresses: %s\n", strings.Join(cliOptions.IPAddresses, ", "))
}

for _, domain := range cliOptions.Domains {
Expand Down Expand Up @@ -424,8 +429,9 @@ func main() {
network = "TCP"
port = serverOptions.LdapPort
}
address := net.JoinHostPort(serverOptions.ListenIP, strconv.Itoa(port))
if status {
gologger.Silent().Msgf("[%s] Listening on %s %s:%d", service, network, serverOptions.ListenIP, port)
gologger.Silent().Msgf("[%s] Listening on %s %s", service, network, address)
} else if fatal {
gologger.Fatal().Msgf("The %s %s service has unexpectedly stopped", network, service)
} else {
Expand Down
38 changes: 36 additions & 2 deletions pkg/options/server_options.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package options

import (
"net"

"github.com/projectdiscovery/goflags"
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/interactsh/pkg/server"
)

Expand All @@ -12,7 +15,7 @@ type CLIServerOptions struct {
Debug bool
Domains goflags.StringSlice
DnsPort int
IPAddress string
IPAddresses goflags.StringSlice
ListenIP string
HttpPort int
HttpsPort int
Expand Down Expand Up @@ -57,10 +60,25 @@ type CLIServerOptions struct {
}

func (cliServerOptions *CLIServerOptions) AsServerOptions() *server.Options {
var ipAddresses []net.IP

for _, ipAddress := range cliServerOptions.IPAddresses {
parsedIP := net.ParseIP(ipAddress)
if parsedIP != nil {
ipAddresses = append(ipAddresses, parsedIP)
} else {
if cliServerOptions.Debug {
gologger.Warning().Msgf("Invalid IP address '%s' will be ignored\n", ipAddress)
}
}
}

ipAddresses = uniqueIPs(ipAddresses)

return &server.Options{
Domains: cliServerOptions.Domains,
DnsPort: cliServerOptions.DnsPort,
IPAddress: cliServerOptions.IPAddress,
IPAddresses: ipAddresses,
ListenIP: cliServerOptions.ListenIP,
HttpPort: cliServerOptions.HttpPort,
HttpsPort: cliServerOptions.HttpsPort,
Expand Down Expand Up @@ -95,3 +113,19 @@ func (cliServerOptions *CLIServerOptions) AsServerOptions() *server.Options {
HeaderServer: cliServerOptions.HeaderServer,
}
}

// uniqueIPs removes duplicate IP addresses from a slice
func uniqueIPs(ips []net.IP) []net.IP {
seen := make(map[string]bool)
result := []net.IP{}

for _, ip := range ips {
key := ip.String()
if !seen[key] {
seen[key] = true
result = append(result, ip)
}
}

return result
}
Loading
Loading