Repeat and ordering

41 views
Skip to first unread message

Florent Ramière

unread,
Sep 10, 2017, 4:55:53 PM9/10/17
to Gremlin-users
Hello guys,

  I am quite new into gremlin, after a few trials and errors and grasping the rough ideas, I find gremlin fascinating ! Congrats guys !
  
  My question is around enforcing order in my traversals
  

g.addV("machine").property("ip","127.0.0.1").property("role","attacker").as("attacker")
.addV("machine").property("ip","127.0.0.2").property("role","userLambda").as("userLambda")
.addV("machine").property("ip","127.0.0.3").property("type","oracle").property("role","oracleAttacked").as("oracleAttacked")
.addV("machine").property("ip","127.0.0.4").property("type","oracle").property("role","oracleNoProblemo").as("oracleNoProblemo")
.addV("machine").property("ip","127.0.0.5").property("role","bastion1").as("bastion1")
.addV("machine").property("ip","127.0.0.6").property("type","bastion2").as("bastion2")
.addV("machine").property("ip","127.0.0.7").property("type","bastion3").as("bastion3")
.addV("machine").property("ip","127.0.0.8").property("type","bastion4").as("bastion4")
// attack via multiple bastion rebounds
.addE("jdbc").from("attacker").to("oracleAttacked")
.property("state","REFUSED")
.addE("ssh").from("attacker").to("oracleAttacked")
.property("state","REFUSED")
.addE("ssh").from("attacker").to("bastion1")
.property("state","OK")
.addE("ssh").from("bastion1").to("bastion2")
.property("state","OK")
.addE("ssh").from("bastion2").to("bastion3")
.property("state","OK")
.addE("ssh").from("bastion3").to("bastion4")
.property("state","OK")
.addE("ssh").from("bastion4").to("oracleAttacked")
.property("state","OK")
.addE("jdbc").from("oracleAttacked").to("oracleAttacked")
.property("state","OK")
// user lambda
.addE("jdbc").from("userLambda").to("oracleAttacked")
.property("state","OK")
.addE("ssh").from("userLambda").to("oracleAttacked")
.property("state","REFUSED")
.addE("jdbc").from("userLambda").to("oracleNoProblemo")
.property("state","OK")

I want to look for machines that are attacked. Basically it's detecting the machine which has been compromised: 
  • a user tried to connect with jdbc without success, 
  • a user tried ssh directly without success,
  • a user logged in db locally using a series of bastions. 
  
g.V().match(
__.as("potentialAttacked").hasLabel("machine").has("type","oracle"),
__.as("potentialAttacked").inE("jdbc").has("state","OK").outV().where(eq("potentialAttacked")),
__.as("potentialAttacked").inE("ssh").has("state","REFUSED").outV().as("potentialAttacker")

)
.select("potentialAttacker")
.repeat(outE("ssh").has("state","OK").inV()).until(where(eq("potentialAttacked")))
    
  All is fine and good: we have our match.
  
  Now the question is when we add dates : http://www.gremlinbin.com/bin/view/59b5a1c365a3c
  
g.addV("machine").property("ip","127.0.0.1").property("role","attacker").as("attacker")
.addV("machine").property("ip","127.0.0.2").property("role","userLambda").as("userLambda")
.addV("machine").property("ip","127.0.0.3").property("type","oracle").property("role","oracleAttacked").as("oracleAttacked")
.addV("machine").property("ip","127.0.0.4").property("type","oracle").property("role","oracleNoProblemo").as("oracleNoProblemo")
.addV("machine").property("ip","127.0.0.5").property("role","bastion1").as("bastion1")
.addV("machine").property("ip","127.0.0.6").property("type","bastion2").as("bastion2")
.addV("machine").property("ip","127.0.0.7").property("type","bastion3").as("bastion3")
 .addV("machine").property("ip","127.0.0.8").property("type","bastion4").as("bastion4")
 // attack via multiple bastion rebounds
.addE("jdbc").from("attacker").to("oracleAttacked")
.property("state","REFUSED")
.property("date",1)
.addE("ssh").from("attacker").to("oracleAttacked")
.property("state","REFUSED")
.property("date",2)
.addE("ssh").from("attacker").to("bastion1")
.property("state","OK")
.property("date",3)
.addE("ssh").from("bastion1").to("bastion2")
.property("state","OK")
.property("date",4)
.addE("ssh").from("bastion2").to("bastion3")
.property("state","OK")
.property("date",5)
.addE("ssh").from("bastion3").to("bastion4")
.property("state","OK")
.property("date",6)
.addE("ssh").from("bastion4").to("oracleAttacked")
.property("state","OK")
.property("date",7)
.addE("jdbc").from("oracleAttacked").to("oracleAttacked")
.property("state","OK")
.property("date",8)
// user lambda
.addE("jdbc").from("userLambda").to("oracleAttacked")
.property("state","OK")
.property("date",1)
.addE("ssh").from("userLambda").to("oracleAttacked")
.property("state","REFUSED")
.property("date",2)
.addE("jdbc").from("userLambda").to("oracleNoProblemo")
.property("state","OK")
 .property("date",3)
       All the edges dates are sequential to simplify things.
       Now I want to change the expression "a user logged in db locally using a series of bastions" into "a user logged in db locally using a series of bastions which edges are in chronological order"

       I tried -without success- many variations of this :
g.V().match(
__.as("potentialAttacked").hasLabel("machine").has("type","oracle"),
__.as("potentialAttacked").inE("jdbc").has("state","OK").as("jdbcOk").outV().where(eq("potentialAttacked")),
__.as("potentialAttacked").inE("ssh").has("state","REFUSED").as("sshKo").outV().as("potentialAttacker")
)
.select("potentialAttacker")
.repeat(
outE("ssh").match(
__.as("ok").has("state","OK").inV().as("nextMachine"),
__.as("ok").has("date", lte(select("nextMachine").inE("ssh").values("date")))
)
).until(
where(eq("potentialAttacked"))
)

Do you guys have hints/references on this matter ?


Cheers !
Florent

Daniel Kuppitz

unread,
Sep 11, 2017, 9:21:00 AM9/11/17
to gremli...@googlegroups.com
This query should do the trick:

g.V().match(
    __.as("potentialAttacked").hasLabel("machine").has("type","oracle"),
    __.as("potentialAttacked").inE("jdbc").has("state","OK").as("jdbcOk").outV().where(eq("potentialAttacked")),
    __.as("potentialAttacked").inE("ssh").has("state","REFUSED").as("sshKo").outV().as("potentialAttacker")
  ).select("potentialAttacker").
    repeat(
      outE("ssh").has("state","OK").
      or(__.not(select("x")),                                /* it's either the very first edge */
         __.select(last, "x").where(gte("x")).by("date")).   /* or it's date is greater than or equal to the last edge's date */
      as("x").inV()
    ).until(where(eq("potentialAttacked")))

It doesn't work on GremlinBin (I guess that"s still a pretty old version), but works just fine in the Gremlin console (using TP 3.3.0).

Cheers,
Daniel


--
You received this message because you are subscribed to the Google Groups "Gremlin-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gremlin-users/64f6f019-23f9-484b-8fee-99f1a19c5a04%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages