Skip to content

Commit

Permalink
#314 Add TLP tags to cases and attributes exported to MISP
Browse files Browse the repository at this point in the history
  • Loading branch information
To-om committed Oct 19, 2017
1 parent 70fdc24 commit 7dd1d5a
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 11 deletions.
12 changes: 11 additions & 1 deletion thehive-misp/app/connectors/misp/JsonFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,22 @@ object JsonFormat {
value,
tags))

val tlpWrites: Writes[Long] = Writes[Long] {
case 0 JsString("tlp:white")
case 1 JsString("tlp:green")
case 2 JsString("tlp:amber")
case 3 JsString("tlp:red")
case _ JsString("tlp:amber")
}

implicit val exportedAttributeWrites: Writes[ExportedMispAttribute] = Writes[ExportedMispAttribute] { attribute
Json.obj(
"category" attribute.category,
"type" attribute.tpe,
"value" attribute.value.fold[String](identity, _.name),
"comment" attribute.comment)
"comment" attribute.comment,
"Tag" Json.arr(
Json.obj("name" tlpWrites.writes(attribute.tlp))))
}

implicit val mispArtifactWrites: Writes[MispArtifact] = OWrites[MispArtifact] { artifact
Expand Down
1 change: 0 additions & 1 deletion thehive-misp/app/connectors/misp/MispConnection.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,4 @@ case class MispConnection(
.withHttpHeaders(
"Authorization" key,
"Accept" "application/json")

}
26 changes: 18 additions & 8 deletions thehive-misp/app/connectors/misp/MispExport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import scala.util.{ Success, Try }
import play.api.libs.json.{ JsObject, Json }

import akka.stream.scaladsl.Sink
import connectors.misp.JsonFormat.tlpWrites
import models.{ Artifact, Case }
import services.{ AlertSrv, ArtifactSrv }
import JsonFormat.exportedAttributeWrites
Expand Down Expand Up @@ -48,15 +49,15 @@ class MispExport @Inject() (

attrIndex
.filter {
case (ExportedMispAttribute(_, category, tpe, value, _), index) attrIndex.exists {
case (ExportedMispAttribute(_, `category`, `tpe`, `value`, _), otherIndex) otherIndex >= index
case (ExportedMispAttribute(_, category, tpe, _, value, _), index) attrIndex.exists {
case (ExportedMispAttribute(_, `category`, `tpe`, _, `value`, _), otherIndex) otherIndex >= index
case _ true
}
}
.map(_._1)
}

def createEvent(mispConnection: MispConnection, title: String, severity: Long, date: Date, attributes: Seq[ExportedMispAttribute]): Future[(String, Seq[ExportedMispAttribute])] = {
def createEvent(mispConnection: MispConnection, title: String, severity: Long, tlp: Long, date: Date, attributes: Seq[ExportedMispAttribute]): Future[(String, Seq[ExportedMispAttribute])] = {
val mispEvent = Json.obj(
"Event" Json.obj(
"distribution" 0,
Expand All @@ -65,7 +66,9 @@ class MispExport @Inject() (
"info" title,
"date" dateFormat.format(date),
"published" false,
"Attribute" attributes))
"Attribute" attributes,
"Tag" Json.arr(
Json.obj("name" tlpWrites.writes(tlp)))))
mispConnection("events")
.post(mispEvent)
.map { mispResponse
Expand All @@ -92,7 +95,7 @@ class MispExport @Inject() (

def exportAttribute(mispConnection: MispConnection, eventId: String, attribute: ExportedMispAttribute): Future[Artifact] = {
val mispResponse = attribute match {
case ExportedMispAttribute(_, _, _, Right(attachment), comment)
case ExportedMispAttribute(_, _, _, _, Right(attachment), comment)
attachmentSrv
.source(attachment.id)
.runReduce(_ ++ _)
Expand All @@ -111,11 +114,18 @@ class MispExport @Inject() (
mispConnection("events/upload_sample").post(body)
}
case attr mispConnection(s"attributes/add/$eventId").post(Json.toJson(attr))

}

mispResponse.map {
case response if response.status / 100 == 2 attribute.artifact
case response if response.status / 100 == 2
// then add tlp tag
// doesn't work with file artifact (malware sample attribute)
(response.json \ "Attribute" \ "id").asOpt[String]
.foreach { attributeId
mispConnection("/attributes/addTag")
.post(Json.obj("attribute" attributeId, "tag" tlpWrites.writes(attribute.tlp)))
}
attribute.artifact
case response
val json = response.json
val message = (json \ "message").asOpt[String]
Expand All @@ -135,7 +145,7 @@ class MispExport @Inject() (
(eventId, initialExportesArtifacts, existingAttributes) maybeEventId.fold {
val simpleAttributes = uniqueAttributes.filter(_.value.isLeft)
// if no event is associated to this case, create a new one
createEvent(mispConnection, caze.title(), caze.severity(), caze.startDate(), simpleAttributes).map {
createEvent(mispConnection, caze.title(), caze.severity(), caze.tlp(), caze.startDate(), simpleAttributes).map {
case (eventId, exportedAttributes) (eventId, exportedAttributes.map(a Success(a.artifact)), exportedAttributes.map(_.value.map(_.name)))
}
} { eventId // if an event already exists, retrieve its attributes in order to export only new one
Expand Down
1 change: 1 addition & 0 deletions thehive-misp/app/connectors/misp/MispModel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ case class ExportedMispAttribute(
artifact: Artifact,
tpe: String,
category: String,
tlp: Long,
value: Either[String, Attachment],
comment: Option[String])

Expand Down
2 changes: 1 addition & 1 deletion thehive-misp/app/connectors/misp/MispSrv.scala
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class MispSrv @Inject() (
logger.error(s"Artifact $artifact has neither data nor attachment")
sys.error("???")
}
ExportedMispAttribute(artifact, tpe, category, value, artifact.message())
ExportedMispAttribute(artifact, tpe, category, artifact.tlp(), value, artifact.message())
}
.runWith(Sink.seq)
}
Expand Down

0 comments on commit 7dd1d5a

Please sign in to comment.