mirror of
https://github.com/bettercap/bettercap
synced 2025-08-22 14:24:38 -07:00
wip: added support for the redirect rules.
This commit is contained in:
parent
0922c0a5fa
commit
c395038d56
1 changed files with 48 additions and 44 deletions
|
@ -1,10 +1,7 @@
|
|||
package rdp_proxy
|
||||
|
||||
// TESTING:
|
||||
//
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os/exec"
|
||||
"io/ioutil"
|
||||
golog "log"
|
||||
|
@ -29,7 +26,6 @@ type RdpProxy struct {
|
|||
port int
|
||||
startPort int
|
||||
cmd string
|
||||
targets string // TODO
|
||||
active map[string]exec.Cmd
|
||||
}
|
||||
|
||||
|
@ -43,8 +39,7 @@ func NewRdpProxy(s *session.Session) *RdpProxy {
|
|||
queueNum: 0,
|
||||
port: 3389,
|
||||
startPort: 40000,
|
||||
cmd: "pyrdp-mitm",
|
||||
targets: "<All Subnets>",
|
||||
cmd: "pyrdp-mitm.py",
|
||||
active: make(map[string]exec.Cmd),
|
||||
}
|
||||
|
||||
|
@ -61,30 +56,8 @@ func NewRdpProxy(s *session.Session) *RdpProxy {
|
|||
mod.AddParam(session.NewIntParameter("rdp.proxy.queue.num", "0", "NFQUEUE number to bind to."))
|
||||
mod.AddParam(session.NewIntParameter("rdp.proxy.port", "3389", "RDP port to intercept."))
|
||||
mod.AddParam(session.NewIntParameter("rdp.proxy.start", "40000", "Starting port for pyrdp sessionss"))
|
||||
mod.AddParam(session.NewStringParameter("rdp.proxy.command", "pyrdp-mitm", "", "The PyRDP base command to launch the man-in-the-middle."))
|
||||
mod.AddParam(session.NewStringParameter("rdp.proxy.targets", "<All Subnets>", "", "A comma delimited list of destination IPs or CIDRs to target."))
|
||||
|
||||
/* NOTES
|
||||
* - The RDP port
|
||||
* - The target source IPs (This can actually be handled by ARP.Spoof)
|
||||
* - The target destination IPs
|
||||
* - Starting Port
|
||||
* - Maximum Instances (future)
|
||||
* - RDP Command (if not pyrdp-mitm)
|
||||
*
|
||||
* FUTURE WORK:
|
||||
* - Centralized Instance of pyrdp
|
||||
*/
|
||||
|
||||
// mod.AddParam(session.NewStringParameter("rdp.proxy.targets",
|
||||
// session.ParamSubnet,
|
||||
// "",
|
||||
// "Comma separated list of IP addresses, also supports nmap style IP ranges."))
|
||||
|
||||
// TODO: Should support comma separated subnets
|
||||
// mod.AddParam(session.NewStringParameter("rdp.proxy.targets", "3389", session.IPv4RangeValidator "RDP port to intercept."))
|
||||
|
||||
|
||||
mod.AddParam(session.NewStringParameter("rdp.proxy.command", "pyrdp-mitm.py", "", "The PyRDP base command to launch the man-in-the-middle."))
|
||||
mod.AddParam(session.NewStringParameter("rdp.proxy.out", "./", "", "The output directory for PyRDP artifcats."))
|
||||
return mod
|
||||
}
|
||||
|
||||
|
@ -93,7 +66,7 @@ func (mod RdpProxy) Name() string {
|
|||
}
|
||||
|
||||
func (mod RdpProxy) Description() string {
|
||||
return "A Linux only module that relies on NFQUEUEs in order to man-in-the-middle RDP sessions."
|
||||
return "A Linux-only module that relies on NFQUEUEs and PyRDP in order to man-in-the-middle RDP sessions."
|
||||
}
|
||||
|
||||
func (mod RdpProxy) Author() string {
|
||||
|
@ -110,12 +83,15 @@ func (mod *RdpProxy) destroyQueue() {
|
|||
mod.queue = nil
|
||||
}
|
||||
|
||||
// Starts or stops a particular proxy instances.
|
||||
func (mod *RdpProxy) pyRdp(target net.Addr) (err error) {
|
||||
// Adds the firewall rule for proxy instance.
|
||||
func (mod *RdpProxy) doProxy(addr string, port string, enable bool) (err error) {
|
||||
_, err = core.Exec("iptables", []string { "-t", "nat",
|
||||
"-I", "BCAPRDP", "1",
|
||||
"-p" "tcp" "--dport", fmt.Sprintf("%d", mod.port),
|
||||
"-j" "REDIRECT" "--to-ports", fmt.Sprintf("%d", mod.instancePort),
|
||||
"-d", addr,
|
||||
"-p", "tcp",
|
||||
"--dport", fmt.Sprintf("%d", mod.port),
|
||||
"-j", "REDIRECT",
|
||||
"--to-ports", port,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
@ -153,7 +129,14 @@ func (mod *RdpProxy) Configure() (err error) {
|
|||
golog.SetOutput(ioutil.Discard)
|
||||
mod.destroyQueue()
|
||||
|
||||
if err, mod.queueNum = mod.IntParam("rdp.proxy.queue.num"); err != nil {
|
||||
// TODO: Param validation and hydration
|
||||
if err, mod.port = mod.IntParam("rdp.proxy.port"); err != nil {
|
||||
return
|
||||
} else if err, mod.cmd = mod.StringParam("rdp.proxy.command"); err != nil {
|
||||
return
|
||||
} else if err, mod.queueNum = mod.IntParam("rdp.proxy.queue.num"); err != nil {
|
||||
return
|
||||
} else if _, err = exec.LookPath(mod.cmd); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -176,24 +159,44 @@ func (mod *RdpProxy) Configure() (err error) {
|
|||
} else if err = mod.configureFirewall(true); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Note: It is probably a good idea to verify whether this call is serialized.
|
||||
func (mod *RdpProxy) handleRdpConnection(payload *nfqueue.Payload) int {
|
||||
|
||||
// 1. Determine source and target addresses.
|
||||
p := gopacket.NewPacket(payload.Data, layers.LayerTypeIPv4, gopacket.Default)
|
||||
src, sport := p.NetworkLayer().NetworkFlow().Src(), p.TransportLayer().TransportFlow().Src()
|
||||
dst, dport := p.NetworkLayer().NetworkFlow().Dst(), p.TransportLayer().TransportFlow().Dst()
|
||||
mod.Info("Connection [%v:%v -> %v:%v]", src, sport, dst, dport)
|
||||
|
||||
// TODO: Don't log here and connect a pipe to the process instead.
|
||||
mod.Info("CONNECT [%s:%v -> %v:%v]", src, sport, dst, dport)
|
||||
target := fmt.Sprintf("%v:%v", dst, dport)
|
||||
|
||||
// 2. Check if the destination IP already has a PYRDP session active, if so, do nothing.
|
||||
// 3. Otherwise:
|
||||
// 3.1. Spawn a PYRDP instance on a fresh port
|
||||
// 3.2. Add a NAT rule in the firewall for this particular target IP
|
||||
// Force a retransmit to trigger the new firewall rules.
|
||||
// TODO: Find a more efficient way to do this.
|
||||
if _, ok := mod.active[target]; !ok {
|
||||
// 3.1. Otherwise, create a proxy agent and firewall rules.
|
||||
args := []string{
|
||||
"-l", fmt.Sprintf("%d", mod.startPort),
|
||||
// "-o", mod.outpath,
|
||||
// "-i", "-d"
|
||||
target,
|
||||
}
|
||||
|
||||
// 3.2. Spawn pyrdp proxy instance
|
||||
cmd := exec.Command(mod.cmd, args...)
|
||||
// _stderr, _ := cmd.StderrPipe()
|
||||
if err := cmd.Start(); err != nil {
|
||||
// XXX: Failed to start the rdp proxy... accept connection transparently and log?
|
||||
}
|
||||
|
||||
// 3.3. Add a NAT rule in the firewall for this particular target IP
|
||||
mod.doProxy(dst.String(), fmt.Sprintf("%d", mod.startPort), true)
|
||||
mod.active[target] = *cmd
|
||||
mod.startPort += 1
|
||||
}
|
||||
|
||||
// Force a retransmit to trigger the new firewall rules. (TODO: Find a more efficient way to do this.)
|
||||
payload.SetVerdict(nfqueue.NF_DROP)
|
||||
return 0
|
||||
}
|
||||
|
@ -222,6 +225,7 @@ func (mod *RdpProxy) Start() error {
|
|||
}
|
||||
|
||||
func (mod *RdpProxy) Stop() error {
|
||||
mod.Info("Stopping!")
|
||||
return mod.SetRunning(false, func() {
|
||||
mod.queue.StopLoop()
|
||||
mod.configureFirewall(false)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue