{"id":279,"date":"2015-02-22T10:50:40","date_gmt":"2015-02-22T10:50:40","guid":{"rendered":"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/?page_id=279"},"modified":"2017-03-28T16:01:32","modified_gmt":"2017-03-28T16:01:32","slug":"the-orchids-language","status":"publish","type":"page","link":"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/?page_id=279","title":{"rendered":"The Orchids language"},"content":{"rendered":"<p>Orchids works by detecting patterns, possibly quite complex, in flows of incoming events.\u00a0 Those patterns are described in rules, typically loaded by the <code>$OCONF\/orchids-rules.conf<\/code> configuration file. In turn, those rules must be written in the Orchids language, described below.<\/p>\n<h2>Example<\/h2>\n<p>A typical example of a rule would be the following, known as the pid tracker (<code>$OCONF\/rules\/pid_tracker_audit.rule<\/code>):<\/p>\n<pre>#include \"linux64syscall.h\"\r\n\r\nrule pidtrack synchronize($pid)\r\n{\r\n  state init\r\n  {\r\n    expect (.auditd.syscall==SYS_clone ||\r\n\t    .auditd.syscall==SYS_fork ||\r\n\t    .auditd.syscall==SYS_vfork)\r\n      goto newpid;\r\n  }\r\n\r\n  state newpid! {\r\n    $pid = .auditd.exit;\r\n    $uid = .auditd.euid;\r\n    $gid = .auditd.egid;\r\n\r\n    case ($uid==0) goto end; \/* everything root does is OK *\/\r\n    else goto wait;\r\n  }\r\n\r\n  state wait!\r\n  {\r\n    expect (.auditd.pid == $pid &amp;&amp;\r\n\t    .auditd.syscall == SYS_execve &amp;&amp;\r\n\t    (.auditd.uid != .auditd.euid || .auditd.gid != .auditd.egid) &amp;&amp; \/* hack *\/\r\n\t    .auditd.success == \"yes\")\r\n      goto update_uid_gid;\r\n\r\n    expect (.auditd.pid == $pid &amp;&amp;\r\n\t    (.auditd.syscall == SYS_setresuid ||\r\n\t     .auditd.syscall == SYS_setreuid ||\r\n\t     .auditd.syscall == SYS_setuid) &amp;&amp;\r\n\t    .auditd.success == \"yes\")\r\n      goto update_setuid;\r\n\r\n    expect (.auditd.pid == $pid &amp;&amp;\r\n\t    (.auditd.syscall == SYS_setresgid ||\r\n\t     .auditd.syscall == SYS_setregid ||\r\n\t     .auditd.syscall == SYS_setgid) &amp;&amp;\r\n\t    .auditd.success == \"yes\")\r\n      goto update_setgid;\r\n\r\n    expect (.auditd.pid == $pid &amp;&amp;\r\n\t    .auditd.syscall == SYS_exit)\r\n      goto end;\r\n\r\n    expect (.auditd.syscall == SYS_kill &amp;&amp;\r\n\t    .auditd.a0 == $pid &amp;&amp;\r\n\t    .auditd.a1 == 9)\r\n      goto end;\r\n\r\n    expect (.auditd.pid == $pid &amp;&amp;\r\n\t    (.auditd.euid != $uid || .auditd.egid != $gid))\r\n      goto alert;\r\n  }\r\n\r\n  state update_uid_gid!\r\n  {\r\n    $uid = .auditd.euid;\r\n    $gid = .auditd.egid;\r\n\r\n    case ($uid==0) goto end; \/* everything root does is OK *\/\r\n    else goto wait;\r\n  }\r\n\r\n  state update_setuid!\r\n  {\r\n    case (.auditd.egid != $gid) goto alert;\r\n    else goto update_uid_gid;\r\n  }\r\n\r\n  state update_setgid!\r\n  {\r\n    case (.auditd.euid != $uid) goto alert;\r\n    else goto update_uid_gid;\r\n  }\r\n\r\n  state alert!\r\n  {\r\n    $newuid = .auditd.euid;\r\n    $newgid = .auditd.egid;\r\n    print_string (\"Alert report :\\n\");\r\n\r\n    print_string (\"Privilege escalation by uid=\");\r\n    print_string (str_from_uint($uid));\r\n    print_string (\", now \");\r\n    print_string (str_from_uint($newuid));\r\n    print_string (\", gid=\");\r\n    print_string (str_from_uint($gid));\r\n    print_string (\", now \");\r\n    print_string (str_from_uint($newgid));\r\n    print_string (\", pid=\");\r\n    print_string (str_from_uint($pid));\r\n    print_string (\"\\n\");\r\n    report();\r\n  }\r\n\r\n  state end!\r\n  {\r\n    \/* all went well *\/\r\n  }\r\n}\r\n<\/pre>\n<p>This reads, roughly, as follows.\u00a0 We assume that Orchids reads from a source of events provided by the Linux auditd daemon, configured thanks to the <a href=\"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/?page_id=103\">auditd module<\/a>.\u00a0 Each new event received will have Orchids launch a new thread for rule <code>pidtrack<\/code>, starting at state <code>init<\/code>. This expects to see a Linux system call that creates a new process.<\/p>\n<p>Once such an Orchids thread has found one, it goes to state <code>newpid<\/code>. There is stores the pid of the created process, which happens to be the exit code <code>.auditd.exit<\/code> of the fork or clone primitive, into a local variable <code>$pid<\/code>. It also stores the current effective user id and group id into appropriate variables. If the effective user id is not root, it then goes to the main state of that rule, <code>wait<\/code>.<\/p>\n<p>When in the <code>wait<\/code> state, the Orchids thread will wait upon one of 6 possible kinds of events, each described by an <code>expect<\/code> clause. For example, the first one expects the monitored process (with pid stored in <code>$pid<\/code>) to call the Linux primitive <code>execve()<\/code> with a modified effective user id or a modified group id. This is legitimate, and happens in case we execute processes with the setuid or setgid bit set. If that happens, that thread will go to state <code>update_uid_gid<\/code>, which will update the values of the variables <code>$uid<\/code> and <code>$gid<\/code> that hold our current view of what the current effective user id and group id of process <code>$pid<\/code> are.<\/p>\n<p>The next 4 <code>expect<\/code> clauses describe other legitimate cases where the effective user id or the group id of process <code>$pid<\/code> changes.<\/p>\n<p>The final <code>expect<\/code> clause detects cases where a system call has been made with unexpected effective user id or group id. In that case, the Orchids thread goes to state <code>alert<\/code>, which prints a message and calls <code>report()<\/code> to produce alert reports in a variety of formats.<\/p>\n<p>If\u00a0 a state, such as <code>wait<\/code>, has several <code>expect<\/code> clauses, then it will wait on <em>all<\/em> of them.\u00a0 The most effective way to understand what it does is to imagine that Orchids will fork as many subthreads as there are <code>expect<\/code> clauses, each one waiting on an event satisfying the boolean condition immediately following the <code>expect<\/code> keyword.\u00a0\u00a0 Once one is found, the Orchids thread goes to the state mentioned after the <code>goto<\/code> keyword.<\/p>\n<p>States marked with a <code>!<\/code> sign are <em>commit<\/em> states.\u00a0 When you enter such a state, all the other subthreads waiting on alternative <code>expect<\/code> conditions are killed, and only the current one is kept.\u00a0 Let us be more precise.\u00a0 Each thread takes part in a thread <em>group<\/em>.\u00a0 For each new event read, for each rule whose first state expects a condition that matches that event, a new thread group is created, with just one thread in it.\u00a0 When a thread reaches a state with multiple <code>expect<\/code> clauses, it forks as many subthreads as there are <code>expect<\/code> clauses.\u00a0 Those subthreads are in the same thread group as the parent thread.\u00a0\u00a0 (As a special case, any state with no <code>expect<\/code> will simply fork no subthread, and terminate.\u00a0 This is what states <code>alert<\/code> and <code>end<\/code> do.) When a thread reaches a commit state, it first kills all the other threads that are in the same thread group: it <em>commits<\/em> to the path of events that it has just found, and disregards all other candidate paths.<\/p>\n<p>Finally, our example rule exhibits another peculiar feature: the <code>synchronized($pid)<\/code> phrase after the rule name, right at the beginning. That instructs Orchids to only keep one thread group, among all with the same rule, whose threads will have the same value of <code>$pid<\/code>. In other words, imagine Orchids starts monitoring events through the <code>pidtrack<\/code> rule and discovers that <code>$pid<\/code> should be set to, say, 102 (when it sets it, in state <code>newpid<\/code>).\u00a0 Imagine it already had an active thread group that already monitors pid number 102.\u00a0 Then Orchids will kill the newer thread group, and only keep the older one.<\/p>\n<h2>Syntax<\/h2>\n<p>The grammar of the Orchids language is given in <a title=\"Backus-Naur form\" href=\"https:\/\/en.wikipedia.org\/wiki\/Backus%E2%80%93Naur_Form\">Backus-Naur Form<\/a>, with some standard extensions.\u00a0 Tokens are given in typewriter script between single quotes, e.g., &#8216;<code>rule<\/code>&#8216;.\u00a0 Productions are given in italic, e.g., <em>rule<\/em>.\u00a0 A star means repetition of zero, one or more items, while a plus sign means repetition of one of more items.\u00a0 Parenthesis are used to group symbols or productions.\u00a0 Square brackets denote optional sequences.<\/p>\n<h3>Grammar<\/h3>\n<p><em>orchids-file<\/em> ::= <em>rule<\/em>*<\/p>\n<p><em>rule<\/em> ::= &#8216;<code>rule<\/code>&#8216; SYMNAME [&#8216;<code>synchronize<\/code>&#8216;\u00a0 &#8216;<code>(<\/code>&#8216;\u00a0 <em>sync_var_list<\/em>\u00a0 &#8216;<code>)<\/code>&#8216; ]\u00a0\u00a0 &#8216;<code>{<\/code>&#8216;\u00a0 <em>state<\/em><sup>+<\/sup>\u00a0 &#8216;<code>}<\/code>&#8216;<\/p>\n<p><em>sync_var_list<\/em> ::= VARIABLE (&#8216;<code>,<\/code>&#8216; VARIABLE)*<\/p>\n<p><em>state<\/em> ::= &#8216;<code>state<\/code>&#8216; SYMNAME &#8216; <em>state_option*\u00a0<\/em><code>{<\/code>&#8216;\u00a0 <em><a title=\"Statements\" href=\"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/?page_id=286\">statement<\/a>* actions<\/em>\u00a0&#8216;<code>}<\/code>&#8216;<\/p>\n<p><em>state_option<\/em>\u00a0::= \u00a0&#8216;<code>!<\/code>&#8216;<\/p>\n<p><a title=\"Statements\" href=\"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/?page_id=286\"><em>statement<\/em><\/a> ::= <em><a title=\"Expressions\" href=\"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/?page_id=283\">expr<\/a> &#8216;<code>;<\/code>&#8216; <\/em>| <em>conditional <\/em>| <em>split-regexp<\/em><br \/>\n<em>conditional<\/em> ::= &#8216;<code>if<\/code>&#8216; <a title=\"Expressions\" href=\"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/?page_id=283\"><em>expr<\/em><\/a> &#8216;<code>then<\/code>&#8216; <a title=\"Statements\" href=\"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/?page_id=286\"><em>statement<\/em><\/a> [&#8216;<code>else<\/code>&#8216; <a title=\"Statements\" href=\"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/?page_id=286\"><em>statement<\/em><\/a>] &#8216;<code>;<\/code>&#8216;<br \/>\n<em>split-regexp<\/em> ::= &#8216;<code>split<\/code>&#8216; STRING &#8216;<code>\/<\/code>&#8216; <em>optional_var_list<\/em> &#8216;<code>\/<\/code>&#8216; <em>expr<\/em> &#8216;<code>;<\/code>&#8216;<\/p>\n<p style=\"text-align: left;\"><em>actions<\/em> ::=\u00a0<em>transition<\/em>* | <em>cases<\/em><\/p>\n<p style=\"text-align: left;\"><em>optional_var_list<\/em> ::=<br \/>\n| VARIABLE (&#8216;<code>,<\/code>&#8216; VARIABLE)*<\/p>\n<p><em>transition<\/em> ::=<br \/>\n&#8216;<code>expect<\/code>&#8216; &#8216;<code>(<\/code>&#8216; <a title=\"Expressions\" href=\"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/?page_id=283\"><em>expr<\/em><\/a> &#8216;<code>)<\/code>&#8216; &#8216;<code>goto<\/code>&#8216; SYMNAME<br \/>\n| &#8216;<code>expect<\/code>&#8216; &#8216;<code>(<\/code>&#8216; <a title=\"Expressions\" href=\"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/?page_id=283\"><em>expr<\/em><\/a> &#8216;<code>)<\/code>&#8216; &#8216;<code>{<\/code>&#8216; <em><a title=\"Statements\" href=\"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/?page_id=286\">statement<\/a>* actions<\/em>\u00a0&#8216;<code>}<\/code>&#8216;<\/p>\n<p><em>cases<\/em>\u00a0::= [&#8216;<code>case<\/code>&#8216;\u00a0&#8216;<code>(<\/code>&#8216;\u00a0<a title=\"Expressions\" href=\"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/?page_id=283\"><em>expr<\/em><\/a>\u00a0&#8216;<code>)<\/code>&#8216;\u00a0&#8216;<code>goto<\/code>&#8216; SYMNAME &#8216;<code>;<\/code>&#8216;\u00a0&#8216;<code>else<\/code>&#8216;]*\u00a0&#8216;<code>goto<\/code>&#8216; SYMNAME<\/p>\n<h3>Tokens<\/h3>\n<p>SYMNAME:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0 [<code><\/code><code>a<\/code>&#8211;<code>z_<\/code>][<code>A<\/code>&#8211;<code>Za<\/code>&#8211;<code>z0<\/code>&#8211;<code>9_.<\/code>]*<br \/>\nused for rule names, state names, function names<\/p>\n<p>VARIABLE:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <code>$<\/code>[<code>A<\/code>&#8211;<code>Za<\/code>&#8211;<code>z_<\/code>][<code>A<\/code>&#8211;<code>Za<\/code>&#8211;<code>z0<\/code>&#8211;<code>9_.<\/code>]*<br \/>\nvariable names; note that they start with &#8216;<code>$<\/code>&#8216;<\/p>\n<p>LOGICAL:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 [<code>A<\/code>&#8211;<code>Z<\/code>][<code>A<\/code>&#8211;<code>Za<\/code>&#8211;<code>z0<\/code>&#8211;<code>9_.<\/code>]*<br \/>\nlogical variable names, as used in database comprehensions; can also be used just like variables, but cannot be assigned to<\/p>\n<p>STRING:<br \/>\nstring constant, enclosed in double quotes, as in C<\/p>\n<ul>\n<li>newlines are forbidden\u2014use <code>\\n<\/code> to insert one<\/li>\n<li>octal codes <code>\\<\/code>[<code>0<\/code>&#8211;<code>7<\/code>]{1,3} allowed (including <code>\\0<\/code>)<\/li>\n<li>other special characters: <code>\\n<\/code> (newline), <code>\\t<\/code> (tab), <code>\\r<\/code> (carriage return), <code>\\b<\/code> (backspace), <code>\\f<\/code> (form feed)<\/li>\n<li>backslash otherwise escapes following character, as in <code>\\\"<\/code><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Other tokens are described on the relevant pages, notably that of <a title=\"Expressions\" href=\"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/?page_id=283\">expressions<\/a>.\u00a0 For example, field names start with a dot, and are of the form <code>.<\/code><em>module<code>.<\/code>field<\/em>; precisely, they obey the regular expression <code>.<\/code>[<code>A<\/code>&#8211;<code>Za<\/code>&#8211;<code>z0<\/code>&#8211;<code>9_<\/code>]+<code>.<\/code>[<code>A<\/code>&#8211;<code>Za<\/code>&#8211;<code>z0<\/code>&#8211;<code>9_.<\/code>]*<em><br \/>\n<\/em><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Orchids works by detecting patterns, possibly quite complex, in flows of incoming events.\u00a0 Those patterns are described in rules, typically loaded by the $OCONF\/orchids-rules.conf configuration file. In turn, those rules must be written in the Orchids language, described below. Example A typical example of a rule would be the following, known as the pid tracker &hellip; <a href=\"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/?page_id=279\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">The Orchids language<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"open","template":"","meta":{"footnotes":""},"class_list":["post-279","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/index.php?rest_route=\/wp\/v2\/pages\/279","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=279"}],"version-history":[{"count":15,"href":"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/index.php?rest_route=\/wp\/v2\/pages\/279\/revisions"}],"predecessor-version":[{"id":562,"href":"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/index.php?rest_route=\/wp\/v2\/pages\/279\/revisions\/562"}],"wp:attachment":[{"href":"https:\/\/projects.lsv.ens-paris-saclay.fr\/orchidsdoc\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=279"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}