From 07abec1108c69cf1f85ae039066e90f14eaca78a Mon Sep 17 00:00:00 2001 From: "Tyler St. Onge" Date: Fri, 25 Sep 2020 17:39:10 -0400 Subject: added subscription model for reporter actors --- .idea/misc.xml | 2 +- .idea/modules/honeypot.iml | 4 ++-- config.json | 6 ++++++ src/main/scala/com/tylerstonge/honeypot/Main.scala | 2 +- .../scala/com/tylerstonge/honeypot/Supervisor.scala | 17 +++++++++++++++-- .../tylerstonge/honeypot/ftp/FtpFileReceiver.scala | 5 ++++- .../com/tylerstonge/honeypot/ftp/FtpHandler.scala | 15 +++++++++------ .../tylerstonge/honeypot/messages/MFoundFile.scala | 3 +++ .../honeypot/messages/MFoundPassword.scala | 3 +++ .../honeypot/messages/MFoundUsername.scala | 3 +++ .../honeypot/messages/MStartReporter.scala | 3 +++ .../tylerstonge/honeypot/reporter/LogReporter.scala | 20 ++++++++++++++++++++ 12 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 src/main/scala/com/tylerstonge/honeypot/messages/MFoundFile.scala create mode 100644 src/main/scala/com/tylerstonge/honeypot/messages/MFoundPassword.scala create mode 100644 src/main/scala/com/tylerstonge/honeypot/messages/MFoundUsername.scala create mode 100644 src/main/scala/com/tylerstonge/honeypot/messages/MStartReporter.scala create mode 100644 src/main/scala/com/tylerstonge/honeypot/reporter/LogReporter.scala diff --git a/.idea/misc.xml b/.idea/misc.xml index 089b153..085f700 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/.idea/modules/honeypot.iml b/.idea/modules/honeypot.iml index bfee88d..289e978 100644 --- a/.idea/modules/honeypot.iml +++ b/.idea/modules/honeypot.iml @@ -1,6 +1,6 @@ - - + + diff --git a/config.json b/config.json index 792f931..7e5f5f5 100644 --- a/config.json +++ b/config.json @@ -5,5 +5,11 @@ "type": "ftp", "port": 21 } + ], + "reporters": [ + { + "name": "basic-reporter", + "type": "console-logger" + } ] } \ No newline at end of file diff --git a/src/main/scala/com/tylerstonge/honeypot/Main.scala b/src/main/scala/com/tylerstonge/honeypot/Main.scala index 0d47de4..80a9088 100644 --- a/src/main/scala/com/tylerstonge/honeypot/Main.scala +++ b/src/main/scala/com/tylerstonge/honeypot/Main.scala @@ -4,5 +4,5 @@ import akka.actor.{ActorSystem, Props} object Main extends App { val system = ActorSystem("honeypot_system") - val listener = system.actorOf(Props[Supervisor], name = "honeypot-supervisor") + val supervisor = system.actorOf(Props[Supervisor], name = "honeypot-supervisor") } \ No newline at end of file diff --git a/src/main/scala/com/tylerstonge/honeypot/Supervisor.scala b/src/main/scala/com/tylerstonge/honeypot/Supervisor.scala index 25f1154..a6551e7 100644 --- a/src/main/scala/com/tylerstonge/honeypot/Supervisor.scala +++ b/src/main/scala/com/tylerstonge/honeypot/Supervisor.scala @@ -5,7 +5,8 @@ import java.nio.file.Paths import akka.actor.{Actor, Props} import akka.event.{Logging, LoggingAdapter} import com.tylerstonge.honeypot.ftp.FtpListener -import com.tylerstonge.honeypot.messages.MStartComponent +import com.tylerstonge.honeypot.messages.{MStartComponent, MStartReporter} +import com.tylerstonge.honeypot.reporter.LogReporter import org.typelevel.jawn.ast.{JArray, JParser} @@ -15,6 +16,9 @@ class Supervisor extends Actor { override def preStart: Unit = { val cfg = JParser.parseFromFile(Paths.get("config.json").toFile).get + cfg.get("reporters").asInstanceOf[JArray].vs.foreach(r => { + self ! MStartReporter(r.get("name").asString, r.get("type").asString) + }) cfg.get("components").asInstanceOf[JArray].vs.foreach(c => { self ! MStartComponent(c.get("name").asString, c.get("type").asString, c.get("port").asInt) }) @@ -26,6 +30,7 @@ class Supervisor extends Actor { override def receive: Receive = { case msg: MStartComponent => startComponent(msg) + case msg: MStartReporter => startReporter(msg) case _ => log.debug("supervisor received unhandled message") } @@ -33,7 +38,15 @@ class Supervisor extends Actor { log.info("starting component :: {}", msg.name) msg.ctype match { case "ftp" => context.actorOf(FtpListener.props(msg.port), name = msg.name) - case _ => log.error("unknown component type: ", msg.ctype, msg.name); + case _ => log.error("unknown component type: {}", msg.ctype); + } + } + + private def startReporter(msg: MStartReporter): Unit = { + log.info("starting reporter :: {}", msg.name) + msg.rtype match { + case "console-logger" => context.actorOf(Props[LogReporter], name = msg.name) + case _ => log.error("unknown reporter type: {}", msg.rtype); } } } \ No newline at end of file diff --git a/src/main/scala/com/tylerstonge/honeypot/ftp/FtpFileReceiver.scala b/src/main/scala/com/tylerstonge/honeypot/ftp/FtpFileReceiver.scala index fa54d28..bf74e8b 100644 --- a/src/main/scala/com/tylerstonge/honeypot/ftp/FtpFileReceiver.scala +++ b/src/main/scala/com/tylerstonge/honeypot/ftp/FtpFileReceiver.scala @@ -10,6 +10,7 @@ import akka.event.{Logging, LoggingAdapter} import akka.io.Tcp._ import akka.io.{IO, Tcp} import akka.util.{ByteString, ByteStringBuilder} +import com.tylerstonge.honeypot.messages.{MFoundFile, MFoundPassword} object FtpFileReceiver { @@ -18,6 +19,7 @@ object FtpFileReceiver { class FtpFileReceiver(port: Int, controller: ActorRef) extends Actor { + val path = "/home/dropkick/honeypot/" val log: LoggingAdapter = Logging(context.system, this) IO(Tcp)(context.system) ! Bind(self, new InetSocketAddress("127.0.0.1", port)) val fileData: ByteStringBuilder = ByteString.newBuilder @@ -40,7 +42,8 @@ class FtpFileReceiver(port: Int, controller: ActorRef) extends Actor { fileData.addAll(data) case PeerClosed => log.debug("peer closed connection, writing file to disk") - val out = Files.newByteChannel(new File("C:\\Users\\dropkick\\Documents\\dev\\honeypot\\" + this.name).toPath, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE) + val out = Files.newByteChannel(new File(this.path + "/" + this.name).toPath, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE) + context.system.eventStream.publish(MFoundFile(this.path + "/" + this.name)) out.write(fileData.result().toByteBuffer) out.close() controller.tell(Write(ByteString.apply("226 File transferred.\n")), context.parent) diff --git a/src/main/scala/com/tylerstonge/honeypot/ftp/FtpHandler.scala b/src/main/scala/com/tylerstonge/honeypot/ftp/FtpHandler.scala index 46263c6..b7b6f03 100644 --- a/src/main/scala/com/tylerstonge/honeypot/ftp/FtpHandler.scala +++ b/src/main/scala/com/tylerstonge/honeypot/ftp/FtpHandler.scala @@ -4,6 +4,7 @@ import akka.actor.{Actor, ActorRef, Props} import akka.event.{Logging, LoggingAdapter} import akka.io.Tcp.{PeerClosed, Received, Write} import akka.util.ByteString +import com.tylerstonge.honeypot.messages.{MFoundPassword, MFoundUsername} import scala.util.Random @@ -18,21 +19,23 @@ class FtpHandler(client: ActorRef) extends Actor { override def receive: Receive = { case Received(data) => client ! Write(ByteString.apply(parse(sanitize(data)))) case PeerClosed => - log.info("peer closed connection") + log.debug("peer closed connection") context.stop(self) } def parse(msg: Array[String]): String = msg(0) match { case "user" => - log.info("attempted login with username: {}", msg(1)) + log.debug("attempted login with username: {}", msg(1)) + context.system.eventStream.publish(MFoundUsername(msg(1))) "331 Please specify password.\n" case "pass" => - log.info("attempted login with password: {}", msg(1)) + log.debug("attempted login with password: {}", msg(1)) + context.system.eventStream.publish(MFoundPassword(msg(1))) "230 Login successful.\n" case "pwd" => "257 \"/\" is the current directory\n" case "quit" => "221 Goodbye.\n" case "pasv" => - log.info("entering passive mode") + log.debug("entering passive mode") val r = new Random() val p1 = r.nextInt(200) val p2 = r.nextInt(200) @@ -40,10 +43,10 @@ class FtpHandler(client: ActorRef) extends Actor { Thread.sleep(256) "227 entering passive mode (127,0,0,1," + p1 + "," + p2 + ")\n" case "stor" => - log.info("stor: {}", msg(1)) + log.debug("stor: {}", msg(1)) "150 File status okay; about to open data connection.\n" case _ => - log.info("unsupported command received: {}", msg.mkString(" ")) + log.debug("unsupported command received: {}", msg.mkString(" ")) "451 Requested action aborted. Local error in processing.\n" } diff --git a/src/main/scala/com/tylerstonge/honeypot/messages/MFoundFile.scala b/src/main/scala/com/tylerstonge/honeypot/messages/MFoundFile.scala new file mode 100644 index 0000000..5d7791a --- /dev/null +++ b/src/main/scala/com/tylerstonge/honeypot/messages/MFoundFile.scala @@ -0,0 +1,3 @@ +package com.tylerstonge.honeypot.messages + +case class MFoundFile(filename: String) diff --git a/src/main/scala/com/tylerstonge/honeypot/messages/MFoundPassword.scala b/src/main/scala/com/tylerstonge/honeypot/messages/MFoundPassword.scala new file mode 100644 index 0000000..eaa98dc --- /dev/null +++ b/src/main/scala/com/tylerstonge/honeypot/messages/MFoundPassword.scala @@ -0,0 +1,3 @@ +package com.tylerstonge.honeypot.messages + +case class MFoundPassword(password: String) diff --git a/src/main/scala/com/tylerstonge/honeypot/messages/MFoundUsername.scala b/src/main/scala/com/tylerstonge/honeypot/messages/MFoundUsername.scala new file mode 100644 index 0000000..23c613a --- /dev/null +++ b/src/main/scala/com/tylerstonge/honeypot/messages/MFoundUsername.scala @@ -0,0 +1,3 @@ +package com.tylerstonge.honeypot.messages + +case class MFoundUsername(username: String) \ No newline at end of file diff --git a/src/main/scala/com/tylerstonge/honeypot/messages/MStartReporter.scala b/src/main/scala/com/tylerstonge/honeypot/messages/MStartReporter.scala new file mode 100644 index 0000000..b76c12a --- /dev/null +++ b/src/main/scala/com/tylerstonge/honeypot/messages/MStartReporter.scala @@ -0,0 +1,3 @@ +package com.tylerstonge.honeypot.messages + +case class MStartReporter(name: String, rtype: String) diff --git a/src/main/scala/com/tylerstonge/honeypot/reporter/LogReporter.scala b/src/main/scala/com/tylerstonge/honeypot/reporter/LogReporter.scala new file mode 100644 index 0000000..9b3f28f --- /dev/null +++ b/src/main/scala/com/tylerstonge/honeypot/reporter/LogReporter.scala @@ -0,0 +1,20 @@ +package com.tylerstonge.honeypot.reporter + +import akka.actor.{Actor, Props} +import akka.event.{Logging, LoggingAdapter} +import com.tylerstonge.honeypot.messages.{MFoundFile, MFoundPassword, MFoundUsername} + +class LogReporter extends Actor { + + val log: LoggingAdapter = Logging(context.system, this) + + context.system.eventStream.subscribe(self, classOf[MFoundUsername]) + context.system.eventStream.subscribe(self, classOf[MFoundPassword]) + context.system.eventStream.subscribe(self, classOf[MFoundFile]) + + override def receive: Receive = { + case msg: MFoundUsername => log.info(">> REPORTER >> :: {}", msg.username) + case msg: MFoundPassword => log.info(">> REPORTER >> :: {}", msg.password) + case msg: MFoundFile => log.info(">> REPORTER >> :: {}", msg.filename) + } +} -- cgit v1.1