From f5ff7d37d863a95e74bafc98842d52385b588553 Mon Sep 17 00:00:00 2001 From: goodlandsecurity Date: Wed, 8 May 2024 10:47:35 -0500 Subject: [PATCH 1/2] add stairwell expansion module and update misp-objects to a193e03 --- README.md | 3 +- docs/index.md | 1 + documentation/README.md | 20 +++ documentation/logos/stairwell.png | Bin 0 -> 9229 bytes misp_modules/lib/misp-objects | 2 +- misp_modules/modules/expansion/__init__.py | 2 +- misp_modules/modules/expansion/stairwell.py | 149 ++++++++++++++++++++ 7 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 documentation/logos/stairwell.png create mode 100644 misp_modules/modules/expansion/stairwell.py diff --git a/README.md b/README.md index d8e041ca7..3229f0900 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,7 @@ For more information: [Extending MISP with Python modules](https://www.misp-proj * [Socialscan](misp_modules/modules/expansion/socialscan.py) - a hover module to check if an email address or a username is used on different online platforms, using the [socialscan](https://github.com/iojw/socialscan) python library * [SophosLabs Intelix](misp_modules/modules/expansion/sophoslabs_intelix.py) - SophosLabs Intelix is an API for Threat Intelligence and Analysis (free tier available). [SophosLabs](https://aws.amazon.com/marketplace/pp/B07SLZPMCS) * [sourcecache](misp_modules/modules/expansion/sourcecache.py) - a module to cache a specific link from a MISP instance. +* [stairwell](misp_modules/modules/expansion/stairwell.py) - an expansion module to enrich hash observables with the Stairwell API * [STIX2 pattern syntax validator](misp_modules/modules/expansion/stix2_pattern_syntax_validator.py) - a module to check a STIX2 pattern syntax. * [ThreatCrowd](misp_modules/modules/expansion/threatcrowd.py) - an expansion module for [ThreatCrowd](https://www.threatcrowd.org/). * [threatminer](misp_modules/modules/expansion/threatminer.py) - an expansion module to expand from [ThreatMiner](https://www.threatminer.org/). @@ -577,7 +578,7 @@ cd ../ ## Documentation -In order to provide documentation about some modules that require specific input / output / configuration, the [doc](doc) directory contains detailed information about the general purpose, requirements, features, input and ouput of each of these modules: +In order to provide documentation about some modules that require specific input / output / configuration, the [index.md](docs/index.md) file within the [docs](docs) directory contains detailed information about the general purpose, requirements, features, input and ouput of each of these modules: - ***description** - quick description of the general purpose of the module, as the one given by the moduleinfo - **requirements** - special libraries needed to make the module work diff --git a/docs/index.md b/docs/index.md index b3c588f93..35681f69d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -65,6 +65,7 @@ For more information: [Extending MISP with Python modules](https://www.circl.lu/ * [Sigma queries](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/sigma_queries.py) - Experimental expansion module querying a sigma rule to convert it into all the available SIEM signatures. * [Sigma syntax validator](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/sigma_syntax_validator.py) - Sigma syntax validator. * [sourcecache](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/sourcecache.py) - a module to cache a specific link from a MISP instance. +* [stairwell](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/stairwell.py) - an expansion module to enrich hash observables with the Stairwell API * [STIX2 pattern syntax validator](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/stix2_pattern_syntax_validator.py) - a module to check a STIX2 pattern syntax. * [ThreatCrowd](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/threatcrowd.py) - an expansion module for [ThreatCrowd](https://www.threatcrowd.org/). * [threatminer](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/threatminer.py) - an expansion module to expand from [ThreatMiner](https://www.threatminer.org/). diff --git a/documentation/README.md b/documentation/README.md index ecc18972f..fd7c3bd1f 100644 --- a/documentation/README.md +++ b/documentation/README.md @@ -1582,6 +1582,26 @@ Module to cache web pages of analysis reports, OSINT sources. The module returns ----- +#### [stairwell](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/stairwell.py) + + + +An expansion module to enrich hash observables with the Stairwell API. +- **features**: +>This module takes a file hash as input and queries the Stairwell API. It will create a misp-object with the additional enrichment intel. +- **input**: +>MD5, SHA1, or SHA256 +- **output**: +>A stairwell misp-object with additional enrichment intel. +- **references**: +>https://docs.stairwell.com +- **requirements**: +>- json +>- pymisp +>- requests + +----- + #### [stix2_pattern_syntax_validator](https://github.com/MISP/misp-modules/tree/main/misp_modules/modules/expansion/stix2_pattern_syntax_validator.py) diff --git a/documentation/logos/stairwell.png b/documentation/logos/stairwell.png new file mode 100644 index 0000000000000000000000000000000000000000..76f6e2428e804f74783f72f239222f4a4c38cc67 GIT binary patch literal 9229 zcmbVy2RzmP{{J~<_R0teA!Hom*du#K_Q*ImI655T;Min^vRC$wtjdTG5t5ZnlugJy zA+!Hc-M)Rh-}}3d`#6Q)WzK0F_+W@ zJj|zoR+uH`hGQ?MB?kaJjU_sP;9{PcZB%u&0018j03aw7064<1f<6HN9v}c<%?bdJ zNCN<9T{2(Xk^%sLbWme8J1s2$H%93K03S#Rz{XHO%o_lt2b^2OPylNn!!Ozq$oW$T z3nLT&U_Jro!MFh>ztiWTq9R}b9L)V3dlz$^zpOCV`SbU?0>s%90#NjZL!6lv5nccQ zejMh)NO3@dLIUx?A2bjP8;}tGotDJNrgQ(LBLD*B0{@CM7weZd_gw5>G$ua)Ku%9V zO$~ELxk=bcD9S0j2)ZajjErm~M0gw}1O&n20${MXpt!g&SVR~sCMd{*ln@jGi3xxO z1prwr46PU_fs3jMrs$-v&o5x|by5aQt#o1f#z6CcDDVGZR&Ik{l8G0j0q zU`Qt@62gpff;+oQprl#9Ye-<|b2dLK^LG{G9cfl$EgfbBgd3Dugb&0AVwE9eW@eUh zv$d1ZRaE{7$2>{1Iv|lQ68!vLUS51&LVO4}dwv0NadCc-Aitm>FGhpc-P;)nLGe1f zU;Sa^Uv?Cs?lx{P7bFbf%zSPaVvX=XO0%+_JNotd5hoM{`^%HF`_Hs63G$yy_yzbt z{Qm^QB>OAAzoAeNm;VSt!tDNouXD+NgxT8sa^>RT2LE0NTN{2T9O?vhM!I8g0{=P5#L&(W9+zqjB=Wu(sYmQX;z5pH@e5F4nBfYkR={LcET zjz6?@U??cuSP_Pa#~ou^Mo<(4`ic5e^e0pa`&33(C^Wh{1vExuz>LIf&M1?6RLo4azQws7hD11YzMRVaD$xJ@wduh>i2z$ z^`NeQ=l)9ohn*Mmd>}E@U-p02{U=}WziJ5mR}D-#{>jS^?%%`vnf-sy?nkE$+@Wq5 z-Sfed`Ty8netP@e%3pPm!YnEY1ve-JiEz_LAmB3JcT6e%KiR(_&ex5EF4P?X|31_P z&M>45rhxy%{u8C`2E!!rqlcKTe24tb`%~ZeFE=vcB0mAYGyepb{1f1J=5GL78wn%~ z35WiDD!xyX931&~?qAb%zE?_MjuU%nRur!-)DGeSN3zQ3At5j~FDM*t2}jr?EYH^> zGcWUh7`z`N@pm6m{QnS+6ozN>qc?vK=f95puM_Wo8One3CiP=SlaRA@|KDQxeh9cg z+}xr1-Y!sS*7MGIxY((^rDaOuyHuoKcA?7s@ZhEB9Xk%8L|ef`e=@ZRN<%gI z3s!P+IMfw2T?=`YD$z`-Q4=;~b=-WT`zZLpQ^#`avLwSKpLc`~y1AUua+LQ%d2F-b z)%=L%W-o;7%(v!)zKqmV$g;j;dcUl<*WuQ;nS_ zWy{?M5iGN%*^}e;=N4(I{}Wj_kXxJiP=g>O!Nc2*sYMV**(<2%-BC@L;S7HX`=&LU ziN%cWL=ZH0Z!{TUy`WjTwQwlvnoP+hE~d;FzyOrK1$?z2F+V}L{<<+utVG^BfGFSpW)*6fXa9L@5k3r$xg zb5`p<`ZDz4!OZgZZAJT^9gT0`^uFgTxX`NxCQ`ep9!bxWk~H6hBQ_pKI|Hp3{p193 zrpv{PE0!U`^WmNGes|JIQZ*~EO9%xxHP{?LG&8F|`rm>FYBBM0R1E~XU4|Aph zasoqq?_9!gIw`7AUUzAsS3Cd?tYjD0xvZ00O7dgamS-gPaV0Y7JL`Q_uSEtqs(mv^ zq|X%I9`QN^zHLh{71_W(Fs>~4fcFxad^l|GUah`aqSzvcdsm~cDjN#vutPs);AAcW z++6OjTEG%>GmKv8xdR&#R?x_$2d~~TNTe?i)SgPU9VB4(;a`M}VR4?ZN4qSIL^rpQ z`(7jk8sdQ`rl7!9175M7CjIxjrys`9v0mv}6L%WSWuF{r!)w=yRvNOypUXN<2A;X2 zjmAtS2JK7tyx6X$$uhv#`0evq?s;MCFVRIBwg3`DAClwwl_6Y4Mf-kq9ecTHc!qPr^gQgS|0suIf7Tg(!} z7e-NrqY54NHgtV8RqnPEmf{Te;C`>sO~R{AkoK06M1569-y=V^#TP_1$`S(=iPzlL zA&#Qa=j0TE?g8uNJSPMPq=2d_JfEcOUIA}Bu6){gFb%O#N+#JrjUDkdw+&T=bF_b1 z2+D zI59~1<+kh4K@iqU)oQgeetLcuTOp)yLu!yzXwk_pTEc6u2^n^1v{Uy*9sR6X^%CXv;`l`} zy~!#tLaof(S7fU7G^2dYKd0_XuXoDj!Uk;OQaK^K5~HHrW3j_c3cI=H1*@b1skX{4 zs|2NR2~fM28dx)$o5qlfK&yb_Q~rvJK223fq)un%ZElt1`cF&F>1Gt&8fB^YLO^a{ z$+WMo;YdL}KV7HAldn?T*U5FvFV`TZ^6wh~`8d3cq^b8DeXvTS#`hBZsaf4jt6 z3sAi^K0?Y1rrP5Kc3*v~8$2O-E#4M4D-@6vhV?$UA@%m|v8%-qs_=?(^Z#T&EtoQKyOto7N&QfyXw=E*kPsDOU8pd%yBXqiA$py znMt-jP^*pa6wokAY65yahvS=R>JZi2pKe}LbNeh`W3(ZJKh1{jib;DO!dG>>#~Ck- zdX$E5BUrWm1eI25+N88Rmr{C2Ecb>ulkcu=9_K<%60@nXWV^1>j9qe1zZbgC@8D*2 z_6*?6@BKUZ*(Eg2)@$+yO)FMG!UMz?ku33rxm2~>Q8>)RX^<|FaGU4KG30t38FyV< z?T^&uNyQD-kvh!6c@H|(KeN`ICaF2qypf+uyz?So;H`$){UENkj$Eju_Qbn=d!E>f zxF4>$Tv+32Mi!0U-sWb+tjufa^}11S$0Te>vzL7B0_hX;C!R!5L>nwar6%5_`m5Xx#l0am_UQD%`Z~>jF zn&KAr!Q{J{mYL6@5t%-2K)$v(B{96J+xB}ow%2S3TrUl+TH>WDp z4cRD>oDR4^zVANOS6=9bRPd30z`aS!pfQ?D+8%=4A7EIM%cL>f!=r5O@QD3uzkiDP zF&@6%tL$q|9mKt_6!K5%+zC#A)xq+9MY%-y(OHZ(2g-Gn)Ijtr{b!G&lz21WUJxS(UEfL7o` zpQ%xvsBW?+10@rbh{POdP_N0(MDO?uG77 z)0EddHkxs$UBQ0r-c>-c#E7eMK!rl{anS%YMU%Lp&j{u6g`c4+f`|0@P=!J1@19N+ z$9&1ZsZ))m9b2JFgK7wE4fR*y^&+O0JfRGGFcLCYa-AdrF+-G?rxj;)wUbyNqqOsq z>w=&t3Cs5GM0Nn)>b3o)nUaPik?3NBbcUALNjLqBn)w!~k1OxI&fcFeq~vYIO5P1^ z?;4j#a~^O0vz>SXk&-(xvtHPl|G9PYw#|Om7kg?jn0nliOz|B%oe+yP3IOH zrY(h|BgUJMyz<<1>Ct9g_&TDFaZYJGwuNwfp}$+4BBHZ9cH>4`o@S`4BaK0L_@3A; z)z603M!U_Zij9^?x~tb1i1yeUp5-7fw*s8wO-~dPM?@&EJh`4U*&T`7C}lV!&##D* z^x>(U+r8_aoGy|G3SsrG$2k_6hE1-Bw2u#8vRt?FYpq!mr+K-J?Gv=aO}j9-DX-BS zww>JFxm*ee{}}JcFk8MeJ>~S4OAP0-V2dZJoHCU0B=aF(@)S=Myb7yx|K{pkEWmo?U){Gq!(L@y*K zUvubP!*7rydT*GU&%(i!V`Kz*#o~#Yz~SeSaF)$BOWRdtRyD9y&Q?4M-D+UflyX)&F+dvSZM3#XHf$N&%rAVksT>)bVnU6V#}T8BGm$PBqPB5U*1gc-lY zx}S37Op_KGFDHAV-$`C-Cvjc9(rFckYHwxpOV1Hi?(JcD|N4-^g%<$5#El6=dqmFj zSC`4=#1x48jiFfi0y;23Y=u}8yB=kRqpEeD##6(dtwY9M2G}jjPe#Id3so(BZCOto z!Mf?I!iaq+jm%fA^|SeFdD29Kxu_z7;M<)jejeq0u*1w2L1cVlAPu|}7=-l@_u;T>%jc%%i=&rs=S~kIR?O+FbPW4inOoqWB z5AOAQbp-FoYc+TuJYUyxda!~k7iLYW7sSCdX%#C;?=dXVZ8hG*PN(t#UlDl3mxCH^E>`CS@x&jo(h z;p=j6OK(C|JEE?{xrzf%ue!DC9TS2@yg%k+l#@oD-+la+;4SypAqmC@8~5p4ZRbmu zX=r`w1-<8vf@?)RSS))4s*3CAG{Yon`Zh(X4hcnM>E~~$97PGDRy2nzf}2-gs%+KH zzSj60bopx1@k@is)AG@ZQ-w7LCN=Bh0R$_fA93lh{-x@Cl2j~yp-Dc)3KW-G9blc~ zOgboP!)0GGsaCvTF83AgcC4aWm1F*;$#FDeWd| zp;7j3r_~VYyP*y?DxQWek3B7|i8JA7C3@c+NVRVT5%qM;11i5X9HxXX%AXB}28^qg z=vAXZO15EvJDKJKw^T}%=es$OG8RwJl{WZYIWObhzu}TJe&4$b!Rt3=+&Q_V8Y&#A zJGfgg$3B@B{kVaKX~MQ$Qe&aq|cpR8lBF&n%)@b1c67r7bmn=uR8Slwy z3?h$`U*!9-hdL|Gj|fYLZ7;7NHLs|TxZ7u+#;PP#@py3M7G~WM4|I|zTvA}pqP`=N zchd~ujCVh{bG9AS5+y_3uD*V;Xb^ExxM`nc?D(BF5BlRBf&hMIe8W$&)@SSd)p=xR z@g#f;Uu;JYbuRZuUe3rryLp(l_4!`RYv#}hdLq)zXZ?t?3S4a&Rc0BY{;udslN+eE zZdpm)-E<<@MNruECrG*ADESAC#AO`=>{kQNPNI1VZYG6JB)nd&Hs45!d8>H4)L~NQ ztuC)>Lc)6$?V1JP3*XOd4RP{U+U&#~ZoCOaa1wV98Ts?ACZ>+9E)V$PGXu%%ChgtZ zjc!YXeN9E11~0udj(DlZ=i@uFsc+O}d{Ng6r&rNm*SICVpaS9a^p%&T^Vu%=p3HRk zaDr+7$F^dAvr%(PdypXrcmsX8i}mKnESMaA5NPa-#{9BIcFj;uY@<{E$%f|_F48(* zu{X*j98}Vy@<};C9nJMVJ7~2&uB3)-Guj3cuZVl_OO*4T5f0=|JRt2ag+{?|bxa(@J}q4Xw(K%~=m>Mgt>|Fy6Ac(_B05y_KJ>-0lXt1- zu@#cC($I2+o*Gouey;E`cKK$1!GO<7=L;U!ahp47@2+{uK;QZ&BD8~_EIrfoG7U49 zH~CwHw5XvyKz$@ZHuxefd&OwQxVgGvF;|24Eo1$~m#?uItDZ3lbuw*m9?wh251Hzq zx!=$CD^%dtjt4cf9+u2K7WHfQSk=zKt@q=b6q!j@3XEyB3W{Gg%l)!;z2Ic1tko^( z7Bl_25h@lfjP)&$wmW$8_#JkN|GX@L%GWn*lQ~a=T^hh2)XKv{bp89Z#=e1DGb4a< zAAHC;XNSp(Y**%&IPwRsw(qCj<0=*R4=&;hke)Wv0?9_i7K>?|%ymsS|&v|a;|1-O!;gU?&nH-5_GWs^)9gZskrOa57t~-1K9}h%n?OI zABAygci`5SLBp1#*X)ikt) zdI<){+ovTh-kVQu&s<}d^FK`%y{}m|ok*vm8LyhW#;M)Hrqyb}t`(5ugmykhKH&d*g> z?m1UmW()fp&9SW-i6mncsTU;}5L!&eoNd`ETRDp2M3R$_1!m^%G4=%PXy;dPjxmdq zlmVVjwsi$UR;Og{7!ak1S<@h1NCs@;Q_Com)&V{?rIt`puy&0T&Q(iQUHz0@O&9_3 zpVLzcVhry6LyxhbFc@)ydChHjPnOiSaUzd3^P2R-nkN zsF}~9xM5)5gRk^5kAPj1qnE4`=_8XD68%bxWfZ?WO|YJ1WA{k(O~Cw7;^MYgpAL@G zskW3O_7zL}I;tb?%!DhzVwSn0rgvW?WuSY{KhglXuxLxmL8&)%u3I3Loy18o%9B>PM{?(&)LLYA0kW`Xopl z434R7znrJaWVAZDNJp~#bxLbYii8XFOw^P9rn8$mRY5CT8dbqK%-oljrc#<<8AdYjnnRRe`Sm9c)A4K^bWOOubz%mNyY&}|iaXy#CB52qcUDfQ&;OxB NP3fj$rM%VM{|AV@tMvc? literal 0 HcmV?d00001 diff --git a/misp_modules/lib/misp-objects b/misp_modules/lib/misp-objects index 9c8b95042..a193e03ad 160000 --- a/misp_modules/lib/misp-objects +++ b/misp_modules/lib/misp-objects @@ -1 +1 @@ -Subproject commit 9c8b9504257c65459cfedf4f3231aee74f77dbe3 +Subproject commit a193e03ad200baddcdc0d5fad1cc1d8bd1276b7f diff --git a/misp_modules/modules/expansion/__init__.py b/misp_modules/modules/expansion/__init__.py index 9b5150cbe..8cb745afd 100644 --- a/misp_modules/modules/expansion/__init__.py +++ b/misp_modules/modules/expansion/__init__.py @@ -20,7 +20,7 @@ 'trustar_enrich', 'recordedfuture', 'html_to_markdown', 'socialscan', 'passive-ssh', 'qintel_qsentry', 'mwdb', 'hashlookup', 'mmdb_lookup', 'ipqs_fraud_and_risk_scoring', 'clamav', 'jinja_template_rendering','hyasinsight', 'variotdbs', 'crowdsec', - 'extract_url_components', 'ipinfo', 'whoisfreaks', 'ip2locationio', 'vysion'] + 'extract_url_components', 'ipinfo', 'whoisfreaks', 'ip2locationio', 'vysion', 'stairwell'] minimum_required_fields = ('type', 'uuid', 'value') diff --git a/misp_modules/modules/expansion/stairwell.py b/misp_modules/modules/expansion/stairwell.py new file mode 100644 index 000000000..c9acfc894 --- /dev/null +++ b/misp_modules/modules/expansion/stairwell.py @@ -0,0 +1,149 @@ +import json +import re +import requests +from pymisp import MISPEvent, MISPObject +from . import check_input_attribute, checking_error, standard_error_message + + +misperrors = { + 'error': 'Error' +} +mispattributes = { + 'input': [ + 'md5', + 'sha1', + 'sha256' + ], + 'format': 'misp_standard' +} +moduleinfo = { + 'version': '0.1', + 'author': 'goodlandsecurity', + 'description': 'Enrich hash observables with the Stairwell API', + 'module-type': ['expansion'] +} +moduleconfig = ["apikey"] + + +def parse_response(response: dict): + attribute_mapping = { + 'environments': {'type': 'comment', 'object_relation': 'environment', 'distribution': 5}, + 'imphash': {'type': 'imphash', 'object_relation': 'impash', 'distribution': 5}, + 'magic': {'type': 'comment', 'object_relation': 'magic', 'distribution': 5}, + 'malEval': { + 'probabilityBucket': {'type': 'comment', 'object_relation': 'malEval-probability', 'distribution': 5}, + 'severity': {'type': 'comment', 'object_relation': 'malEval-severity', 'distribution': 5} + }, + 'md5': {'type': 'md5', 'object_relation': 'md5', 'distribution': 5}, + 'mimeType': {'type': 'mime-type', 'object_relation': 'mime-type', 'distribution': 5}, + 'sha1': {'type': 'sha1', 'object_relation': 'sha1', 'distribution': 5}, + 'sha256': {'type': 'sha256', 'object_relation': 'sha256', 'distribution': 5}, + 'shannonEntropy': {'type': 'float', 'object_relation': 'entropy', 'distribution': 5}, + 'size': {'type': 'size-in-bytes', 'object_relation': 'size-in-bytes', 'distribution': 5}, + 'stairwellFirstSeenTime': {'type': 'datetime', 'object_relation': 'stairwell-first-seen', 'distribution': 5}, + 'tlsh': {'type': 'tlsh', 'object_relation': 'tlsh', 'distribution': 5}, + 'yaraRuleMatches': {'type': 'text', 'object_relation': 'yara-rule-match', 'comment': 'matching Stairwell yara rule name', 'distribution': 5} + } + environments_mapping = { + "NCS2SM-YHB2KT-SAFUDX-JC7F6WYA": "Florian's Open Rules", + "VR9Z98-4KU7ZC-PCNFEG-FURQ66FW": "Jotti", + "D7W6M6-BA9BS4-BQ23Z4-NKCNWQ96": "Malshare", + "D4447Q-WJJL6P-W7ME89-WHXJK8TW": "Malware Bazaar", + "XAKLND-DKWP3Z-56RL88-6XJ5NH46": "Pro Rules", + "GMEELM-K226XF-F95XZL-7VEJFKZ6": "Public Samples", + "5HEG8N-9T7UPG-8SZJ7T-2J4XSDC6": "RH-ISAC", + "2NN2BJ-HDVQHS-49824H-2SEDBBLJ": "RH-ISAC Malware Sharing", + "VCZTNF-8S76AK-LUU53W-2SWFFZWJ": "Stairwell Experimental Rules", + "GEG6FU-MRARGF-TLTM6X-H6MGDT5E": "Stairwell Methodology Rules", + "EB3DXY-3ZYFVH-6HNKJQ-GAPKHESS": "Stairwell OSINT Rules", + "NQNJM6-5LSCAF-3MC5FJ-W8EKGW6N": "Stairwell Research Rules", + "TT9GM5-JUMD8H-9828FL-GAW5NNXE": "stairwell-public-verdicts", + "MKYSAR-3XN9MB-3VAK3R-888ZJUTJ": "Threat Report Feeds", + "6HP5R3-ZM7DAN-RB4732-X6QPCJ36": "Virusshare", + "TV6WCV-7Y79LE-BK79EY-C8GUEY46": "vxintel" + } + + misp_event = MISPEvent() + misp_object = MISPObject('stairwell') + for feature, attribute in attribute_mapping.items(): + if feature in response.keys() and response[feature]: + if feature == 'yaraRuleMatches': + for rule in response[feature]: + env_pattern = r'\b[A-Z0-9]{6}-[A-Z0-9]{6}-[A-Z0-9]{6}-[A-Z0-9]{8}\b' + env = re.findall(env_pattern, rule.split('yaraRules/')[0])[0] + misp_attribute = { + 'value': rule.split('yaraRules/')[1], + 'comment': f'Rule from: {environments_mapping.get(env, "Unknown UUID!")}' + } + misp_attribute.update(attribute) + misp_object.add_attribute(**misp_attribute) + elif feature == 'environments': + for env in response[feature]: + misp_attribute = { + 'value': environments_mapping.get(env, f'Unknown Environment: {env}'), + 'comment': 'Hash observed in' + } + misp_attribute.update(attribute) + misp_object.add_attribute(**misp_attribute) + elif feature == 'malEval': + for attr in attribute: + misp_attribute = {'value': response[feature][attr]} + misp_attribute.update(attribute[attr]) + misp_object.add_attribute(**misp_attribute) + else: + misp_attribute = {'value': response[feature]} + misp_attribute.update(attribute) + attr = misp_object.add_attribute(**misp_attribute) + if feature in ('md5', 'sha1', 'sha256'): + for label in response['malEval']['labels']: + attr.add_tag(label) + misp_event.add_object(**misp_object) + + event = json.loads(misp_event.to_json()) + results = {'Object': event['Object']} + + return {'results': results} + + +def handler(q=False): + if q is False: + return False + request = json.loads(q) + if not request.get('config') or not request['config'].get('apikey'): + misperrors['error'] = 'A Stairwell api key is required for this module!' + return misperrors + if not request.get('attribute') or not check_input_attribute(request['attribute'], requirements=('type', 'value')): + misperrors['error'] = f'{standard_error_message}, {checking_error}.' + return misperrors + attribute = request['attribute'] + if attribute['type'] not in mispattributes['input']: + misperrors['error'] = 'Unsupported attribute type!' + return misperrors + + headers = { + "Accept": "application/json", + "Authorization": request['config']['apikey'], + "User-Agent": f"misp-module {__file__} {moduleinfo['version']}" + } + url = f"https://app.stairwell.com/v1/objects/{attribute['value']}/metadata" + response = requests.get(url=url, headers=headers).json() + + if response.get('code') == 16: # bad auth + return {'error': f"{response['message']} Is api key valid?"} + elif response.get('code') == 5: # not found + return {'error': f"{attribute['type']}:{attribute['value']} {response['message']}"} + elif response.get('code') == 2: # encoding/hex: invalid byte + return {'error': response['message']} + elif response.get('code'): # catchall for potential unforeseen errors + return {'error': response['message'], 'code': response['code']} + else: + return parse_response(response) + + +def introspection(): + return mispattributes + + +def version(): + moduleinfo['config'] = moduleconfig + return moduleinfo From a0572f480279d3f566a6312e47416746282c266d Mon Sep 17 00:00:00 2001 From: goodlandsecurity Date: Thu, 9 May 2024 08:19:49 -0500 Subject: [PATCH 2/2] forgot the json documentation --- documentation/website/expansion/stairwell.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 documentation/website/expansion/stairwell.json diff --git a/documentation/website/expansion/stairwell.json b/documentation/website/expansion/stairwell.json new file mode 100644 index 000000000..211597833 --- /dev/null +++ b/documentation/website/expansion/stairwell.json @@ -0,0 +1,14 @@ +{ + "description": "Module to query the Stairwell API to get additional information about the input hash attribute", + "logo": "stairwell.png", + "requirements": [ + "Access to Stairwell platform (apikey)" + ], + "input": "A hash attribute (md5, sha1, sha256).", + "output": "File object related to the input attribute found on Stairwell platform.", + "references": [ + "https://stairwell.com", + "https://docs.stairwell.com" + ], + "features": "The module takes a hash attribute as input and queries Stariwell's API to fetch additional data about it. The result, if the payload is observed in Stariwell, is a file object describing the file the input hash is related to." +} \ No newline at end of file