First commit!

This commit is contained in:
sda 2022-11-06 15:51:33 +01:00
parent 283cf9630f
commit 64daa44e9f
225 changed files with 94329 additions and 1 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
__pycache__/
*.py[cod]
*$py.class
*.sqlite3
node_modules/

201
LICENSE.txt Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

740
NOTICE.txt Normal file
View File

@ -0,0 +1,740 @@
Copyright (C) 2022 Félix Aimé. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
The SpyGuard project is released under the Apache License, Version 2.0.
This license applies to all code developed by Félix Aimé.
The SpyGuard project contains third-party software that are under different
licenses. This file contains a list of the third-party code and licensing
terms. Please note, however, that this file may not contain all the
licenses of all third-party software used in SpyGuard.
=======
SOFTWARE CODE
Information about third-party software code used in the development of Spyguard.
TinyCheck (commit ab3f5b584e8d1d23650f638948f28734e62b4e56)
Licensed under the Apache License, Version 2.0
-----
Copyright (C) 2020 AO Kaspersky Lab. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
The TinyCheck project is released under the Apache License, Version 2.0. This license applies to all code developed by Kaspersky.
The TinyCheck project contains third-party software that are under different licenses. This file contains a list of the third-party code and licensing terms. Please note, however, that this file may not contain all the licenses of all third-party software used in TinyCheck. So, please check the top of all the files for any additional license statements.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-----
SQLite (Public Domain)
The author disclaims copyright to this source code. In place of
a legal notice, here is a blessing:
May you do good and not evil.
May you find forgiveness for yourself and forgive others.
May you share freely, never taking more than you give.
-----
dnsutils 9.11.5
Copyright: 2004-2017, Internet Systems Consortium, Inc. ("ISC")
1996-2003, Internet Software Consortium
2012, Vadim Goncharov
2009-2012, John Eaglesham
2008, Damien Miller
2004, 2008, Nominet, Ltd.
2004, Masarykova universita
1997-2003, Kungliga Tekniska Högskolan
2002, Nuno M. Rodrigues.
2002, Stichting NLnet, Netherlands
2000-2002, Japan Network Information Center.
2001, Jake Burkholder
1996-2001, Nominum, Inc.
1995-2000, Network Associates, Inc.
2000, Aaron D. Gifford
1999-2000, Nortel Networks Corporation
1996, David Mazieres
1993, Digital Equipment Corporation.
1990, 1993, The Regents of the University of California.
License: ISC and BSD-2-clause and BSD-3-clause and BSD-4-clause
Files: bin/tests/system/chain/
doc/misc/docbook-options.pl
Copyright: 2016-2017, Internet Systems Consortium, Inc. ("ISC")
License: MPL-2.0 or ISC
Files: unit/atf-src/
Copyright: 2007-2012, The NetBSD Foundation, Inc.
License: BSD-2-clause
Files: contrib/idn/
Copyright: 2000-2002, Japan Network Information Center
License: BSD-4-clause
Files: debian/
Copyright: 2007-2017 LaMont Jones
2013-2017 Michael Gilbert
2017 Ondřej Surý
2008-2016 Jamie Strandboge
License: ISC or MPL-2.0
License: ISC
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
.
THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
License: BSD-2-clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
.
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
License: BSD-3-clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
.
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
License: BSD-4-clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
.
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
.
3. All advertising materials mentioning features or use of this
software must display the following acknowledgement: This product
includes software developed by the the organization .
.
4. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
.
THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License: MPL-2.0
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0.
.
On Debian systems, the full copy of MPL-2.0 can be found at
/usr/share/common-licenses/MPL-2.0
-----
-----
node.js 12.0
Copyright Joyent, Inc. and other Node contributors.
-----
Distributed under the terms of the MIT License
-----
Node's license follows:
====
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
====
This license applies to all parts of Node that are not externally maintained libraries. The externally maintained libraries used by Node are:
- V8, located at deps/v8. V8's license follows:
"""
This license applies to all parts of V8 that are not externally maintained libraries.The externally maintained libraries used by V8 are:
- PCRE test suite, located in
test/mjsunit/third_party/regexp-pcre.js.This is based on the test suite from PCRE-7.3, which is copyrighted by the University of Cambridge and Google, Inc.The copyright notice and license are embedded in regexp-pcre.js.
- Layout tests, located in test/mjsunit/third_party.These are based on layout tests from webkit.org which are copyrighted by Apple Computer, Inc. and released under a 3-clause BSD license.
- Strongtalk assembler, the basis of the files assembler-arm-inl.h, assembler-arm.cc, assembler-arm.h, assembler-ia32-inl.h, assembler-ia32.cc, assembler-ia32.h, assembler-x64-inl.h, assembler-x64.cc, assembler-x64.h, assembler-mips-inl.h, assembler-mips.cc, assembler-mips.h, assembler.cc and assembler.h. This code is copyrighted by Sun Microsystems Inc. and released under a 3-clause BSD license.
- Valgrind client API header, located at third_party/valgrind/valgrind.h This is release under the BSD license.
These libraries have their own licenses; we recommend you read them, as their terms may differ from the terms below.
Copyright 2006-2012, the V8 project authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
- C-Ares, an asynchronous DNS client, located at deps/cares. C-Ares license follows:
"""
Copyright 1998 by the Massachusetts Institute of Technology.
Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of M.I.T. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission.
M.I.T. makes no representations about the suitability of this software for any purpose.It is provided "as is" without express or implied warranty.
"""
- OpenSSL located at deps/openssl. OpenSSL is cryptographic software written by Eric Young (eay@cryptsoft.com) to provide SSL/TLS encryption. OpenSSL's license follows:
"""
/====================================================================
Copyright (c) 1998-2011 The OpenSSL Project.All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this
software must display the following acknowledgment:
"This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact openssl-core@openssl.org.
5. Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" appear in their names without prior written permission of the OpenSSL Project.
6. Redistributions of any form whatsoever must retain the following acknowledgment:
"This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)"
THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
====================================================================
"""
- HTTP Parser, located at deps/http_parser. HTTP Parser's license follows:
"""
http_parser.c is based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev.
Additional changes are licensed under the same terms as NGINX and copyright Joyent, Inc. and other Node contributors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
- Closure Linter is located at tools/closure_linter. Closure's license follows:
"""
Copyright (c) 2007, Google Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
- tools/cpplint.py is a C++ linter. Its license follows:
"""
Copyright (c) 2009 Google Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
- lib/punycode.js is copyright 2011 Mathias Bynens <http://mathiasbynens.be/>
and released under the MIT license.
"""
Punycode.js <http://mths.be/punycode>
Copyright 2011 Mathias Bynens <http://mathiasbynens.be/>
Available under MIT license <http://mths.be/mit>
"""
- tools/gyp. GYP is a meta-build system. GYP's license follows:
"""
Copyright (c) 2009 Google Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
- Zlib at deps/zlib. zlib's license follows:
"""
/zlib.h -- interface of the 'zlib' general purpose compression library
version 1.2.8, April 28th, 2013
Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied warranty.In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jean-loup GaillyMark Adler
jloup@gzip.orgmadler@alumni.caltech.edu
*/
"""
- npm is a package manager program located at deps/npm.
npm's license follows:
"""
Copyright (c) Isaac Z. Schlueter
All rights reserved.
npm is released under the Artistic 2.0 License.
The text of the License follows:
--------
The Artistic License 2.0
Copyright (c) 2000-2006, The Perl Foundation.
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
Preamble
This license establishes the terms under which a given free software Package may be copied, modified, distributed, and/or redistributed.
The intent is that the Copyright Holder maintains some artistic control over the development of that Package while still keeping the Package available as open source and free software.
You are always permitted to make arrangements wholly outside of this license directly with the Copyright Holder of a given Package. If the terms of this license do not permit the full use that you propose to make of the Package, you should contact the Copyright Holder and seek a different licensing arrangement.
Definitions
"Copyright Holder" means the individual(s) or organization(s) named in the copyright notice for the entire Package.
"Contributor" means any party that has contributed code or other material to the Package, in accordance with the Copyright Holder's procedures.
"You" and "your" means any person who would like to copy, distribute, or modify the Package.
"Package" means the collection of files distributed by the Copyright Holder, and derivatives of that collection and/or of those files. A given Package may consist of either the Standard Version, or a Modified Version.
"Distribute" means providing a copy of the Package or making it accessible to anyone else, or in the case of a company or organization, to others outside of your company or organization.
"Distributor Fee" means any fee that you charge for Distributing this Package or providing support for this Package to another party. It does not mean licensing fees.
"Standard Version" refers to the Package if it has not been modified, or has been modified only in ways explicitly requested by the Copyright Holder.
"Modified Version" means the Package, if it has been changed, and such changes were not explicitly requested by the Copyright Holder.
"Original License" means this Artistic License as Distributed with the Standard Version of the Package, in its current version or as it may be modified by The Perl Foundation in the future.
"Source" form means the source code, documentation source, and configuration files for the Package.
"Compiled" form means the compiled bytecode, object code, binary, or any other form resulting from mechanical transformation or translation of the Source form.
Permission for Use and Modification Without Distribution
(1)You are permitted to use the Standard Version and create and use Modified Versions for any purpose without restriction, provided that you do not Distribute the Modified Version.
Permissions for Redistribution of the Standard Version
(2)You may Distribute verbatim copies of the Source form of the Standard Version of this Package in any medium without restriction, either gratis or for a Distributor Fee, provided that you duplicate all of the original copyright notices and associated disclaimers. At your discretion, such verbatim copies may or may not include a Compiled form of the Package.
(3)You may apply any bug fixes, portability changes, and other modifications made available from the Copyright Holder. The resulting Package will still be considered the Standard Version, and as such will be subject to the Original License.
Distribution of Modified Versions of the Package as Source
(4)You may Distribute your Modified Version as Source (either gratis or for a Distributor Fee, and with or without a Compiled form of the Modified Version) provided that you clearly document how it differs from the Standard Version, including, but not limited to, documenting any non-standard features, executables, or modules, and provided that you do at least ONE of the following:
(a)make the Modified Version available to the Copyright Holder of the Standard Version, under the Original License, so that the Copyright Holder may include your modifications in the Standard Version.
(b)ensure that installation of your Modified Version does not prevent the user installing or running the Standard Version. In addition, the Modified Version must bear a name that is different from the name of the Standard Version.
(c)allow anyone who receives a copy of the Modified Version to make the Source form of the Modified Version available to others under
(i)the Original License or
(ii)a license that permits the licensee to freely copy, modify and redistribute the Modified Version using the same licensing terms that apply to the copy that the licensee received, and requires that the Source form of the Modified Version, and of any works derived from it, be made freely available in that license fees are prohibited but Distributor Fees are allowed.
Distribution of Compiled Forms of the Standard Version or Modified Versions without the Source
(5)You may Distribute Compiled forms of the Standard Version without the Source, provided that you include complete instructions on how to get the Source of the Standard Version. Such instructions must be valid at the time of your distribution. If these instructions, at any time while you are carrying out such distribution, become invalid, you must provide new instructions on demand or cease further istribution.
If you provide valid instructions or cease distribution within thirty days after you become aware that the instructions are invalid, then you do not forfeit any of your rights under this license.
(6)You may Distribute a Modified Version in Compiled form without the Source, provided that you comply with Section 4 with respect to the Source of the Modified Version.
Aggregating or Linking the Package
(7)You may aggregate the Package (either the Standard Version or Modified Version) with other packages and Distribute the resulting aggregation provided that you do not charge a licensing fee for the Package. Distributor Fees are permitted, and licensing fees for other components in the aggregation are permitted. The terms of this license apply to the use and Distribution of the Standard or Modified Versions as included in the aggregation.
(8) You are permitted to link Modified and Standard Versions with other works, to embed the Package in a larger work of your own, or to build stand-alone binary or bytecode versions of applications that include the Package, and Distribute the result without restriction, provided the result does not expose a direct interface to the Package.
Items That are Not Considered Part of a Modified Version
(9) Works (including, but not limited to, modules and scripts) that merely extend or make use of the Package, do not, by themselves, cause the Package to be a Modified Version. In addition, such works are not considered parts of the Package itself, and are not subject to the terms of this license.
General Provisions
(10)Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license.
(11)If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license.
(12)This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder.
(13)This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed.
(14)Disclaimer of Warranty:
THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------
"Node.js" and "node" trademark Joyent, Inc. npm is not officially part of the Node.js project, and is neither owned by nor officially affiliated with Joyent, Inc.
Packages published in the npm registry (other than the Software and its included dependencies) are not part of npm itself, are the sole property of their respective maintainers, and are not covered by this license.
"npm Logo" created by Mathias Pettersson and Brian Hammond, used with permission.
"Gubblebum Blocky" font Copyright (c) by Tjarda Koster, http://jelloween.deviantart.com included for use in the npm website and documentation, used with permission.
This program uses several Node modules contained in the node_modules/ subdirectory, according to the terms of their respective licenses.
"""
- tools/doc/node_modules/marked. Marked is a Markdown parser. Marked's license follows:
"""
Copyright (c) 2011-2012, Christopher Jeffrey (https://github.com/chjj/)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
- test/gc/node_modules/weak. Node-weak is a node.js addon that provides garbage collector notifications. Node-weak's license follows:
"""
Copyright (c) 2011, Ben Noordhuis <info@bnoordhuis.nl>
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
"""
- wrk is located at tools/wrk. wrk's license follows:
"""
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
"""
- ICU's license follows:
From http://source.icu-project.org/repos/icu/icu/trunk/license.html
"""
ICU License - ICU 1.8.1 and later
COPYRIGHT AND PERMISSION NOTICE
Copyright (c) 1995-2014 International Business Machines Corporation and others
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, provided that the above copyright notice(s) and this permission notice appear in all copies of the Software and that both the above copyright notice(s) and this permission notice appear in supporting documentation.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder.
All trademarks and registered trademarks mentioned herein are the property of their respective owners.
Third-Party Software Licenses
This section contains third-party software notices and/or additional terms for licensed third-party software components included within ICU libraries.
1. Unicode Data Files and Software
COPYRIGHT AND PERMISSION NOTICE
Copyright © 1991-2014 Unicode, Inc. All rights reserved.
Distributed under the Terms of Use in
http://www.unicode.org/copyright.html.
Permission is hereby granted, free of charge, to any person obtaining a copy of the Unicode data files and any associated documentation (the "Data Files") or Unicode software and any associated documentation (the "Software") to deal in the Data Files or Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Data Files or Software, and to permit persons to whom the Data Files or Software are furnished to do so, provided that
(a) this copyright and permission notice appear with all copies of the Data Files or Software,
(b) this copyright and permission notice appear in associated documentation, and
(c) there is clear notice in each modified Data File or in the Software as well as in the documentation associated with the Data File(s) or Software that the data or software has been modified.
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA FILES OR SOFTWARE.
Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in these Data Files or Software without prior written authorization of the copyright holder.
2. Chinese/Japanese Word Break Dictionary Data (cjdict.txt)
The Google Chrome software developed by Google is licensed under the BSD license. Other software included in this distribution is provided under other licenses, as set forth below.
The BSD License
http://opensource.org/licenses/bsd-license.php
Copyright (C) 2006-2008, Google Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The word list in cjdict.txt are generated by combining three word lists listed below with further processing for compound word breaking. The frequency is generated with an iterative training against Google web corpora.
Libtabe (Chinese)
- https://sourceforge.net/project/?group_id=1519
- Its license terms and conditions are shown below.
IPADIC (Japanese)
- http://chasen.aist-nara.ac.jp/chasen/distribution.html
- Its license terms and conditions are shown below.
---------COPYING.libtabe ---- BEGIN--------------------
Copyrighy (c) 1999 TaBE Project.
Copyright (c) 1999 Pai-Hsiang Hsiao.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
. Neither the name of the TaBE Project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Copyright (c) 1999 Computer Systems and Communication Lab, Institute of Information Science, Academia Sinica.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
. Neither the name of the Computer Systems and Communication Lab nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Copyright 1996 Chih-Hao Tsai @ Beckman Institute, University of Illinois
c-tsai4@uiuc.eduhttp://casper.beckman.uiuc.edu/~c-tsai4
---------------COPYING.libtabe-----END------------------------------------
---------------COPYING.ipadic-----BEGIN------------------------------------
Copyright 2000, 2001, 2002, 2003 Nara Institute of Science and Technology.All Rights Reserved.
Use, reproduction, and distribution of this software is permitted. Any copy of this software, whether in its original form or modified, must include both the above copyright notice and the following paragraphs.
Nara Institute of Science and Technology (NAIST), the copyright holders, disclaims all warranties with regard to this software, including all implied warranties of merchantability and fitness, in no event shall NAIST be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortuous action, arising out of or in connection with the use or performance of this software.
A large portion of the dictionary entries originate from ICOT Free Software.The following conditions for ICOT Free Software applies to the current dictionary as well.
Each User may also freely distribute the Program, whether in its original form or modified, to any third party or parties, PROVIDED that the provisions of Section 3 ("NO WARRANTY") will ALWAYS appear on, or be attached to, the Program, which is distributed substantiallyin the same form as set out herein and that such intended distribution, if actually made, will neither violate or otherwise contravene any of the laws and regulations of the countries having jurisdiction over the User or the intended distribution itself.
NO WARRANTY
The program was produced on an experimental basis in the course of the research and development conducted during the project and is provided to users as so produced on an experimental basis.Accordingly, the program is provided without any warranty whatsoever, whether express, implied, statutory or otherwise.The term "warranty" used herein includes, but is not limited to, any warranty of the quality, performance, merchantability and fitness for a particular purpose of the program and the nonexistence of any infringement or violation of any right of any third party.
Each user of the program will agree and understand, and be deemed to have agreed and understood, that there is no warranty whatsoever for the program and, accordingly, the entire risk arising from or otherwise connected with the program is assumed by the user.
Therefore, neither ICOT, the copyright holder, or any other organization that participated in or was otherwise related to the development of the program and their respective officials, directors, officers and other employees shall be held liable for any and all damages, including, without limitation, general, special, incidental and consequential damages, arising out of or otherwise in connection with the use or inability to use the program or any product, material or result produced or otherwise obtained by using the program, regardless of whether they have been advised of, or otherwise had knowledge of, the possibility of such damages at any time during the project or thereafter. Each user will be deemed to have agreed to the foregoing by his or her commencement of use of the program. The term "use" as used herein includes, but is not limited to, the use, modification, copying and distribution of the program and the production of secondary products from the program.
In the case where the program, whether in its original form or modified, was distributed or delivered to or received by a user from any person, organization or entity other than ICOT, unless it makes or grants independently of ICOT any specific warranty to the user in writing, such person, organization or entity, will also be exempted from and not be held liable to the user for any such damages as noted above as far as the program is concerned.
---------------COPYING.ipadic-----END------------------------------------
3. Lao Word Break Dictionary Data (laodict.txt)
Copyright (c) 2013 International Business Machines Corporation and others. All Rights Reserved.
Project:http://code.google.com/p/lao-dictionary/
Dictionary: http://lao-dictionary.googlecode.com/git/Lao-Dictionary.txt
License:http://lao-dictionary.googlecode.com/git/Lao-Dictionary-LICENSE.txt
(copied below)
This file is derived from the above dictionary, with slight modifications.
--------------------------------------------------------------------------------
Copyright (C) 2013 Brian Eugene Wilson, Robert Martin Campbell.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
4. Burmese Word Break Dictionary Data (burmesedict.txt) Copyright (c) 2014 International Business Machines Corporation and others. All Rights Reserved.
This list is part of a project hosted at: github.com/kanyawtech/myanmar-karen-word-lists
--------------------------------------------------------------------------------
Copyright (c) 2013, LeRoy Benjamin Sharon
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name Myanmar Karen Word Lists, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
5. Time Zone Database
ICU uses the public domain data and code derived from Time Zone Database for its time zone support. The ownership of the TZ database is explained in BCP 175: Procedure for Maintaining the Time Zone Database section 7.
7. Database Ownership
The TZ database itself is not an IETF Contribution or an IETF document. Rather it is a pre-existing and regularly updated work that is in the public domain, and is intended to remain in the public domain. Therefore, BCPs 78 [RFC5378] and 79 [RFC3979] do not apply to the TZ Database or contributions that individuals make to it.
Should any claims be made and substantiated against the TZ Database, the organization that is providing the IANA Considerations defined in this RFC, under the memorandum of understanding with the IETF, currently ICANN, may act in accordance with all competent court orders. No ownership claims will be made by ICANN or the IETF Trust on the database or the code. Any person making a contribution to the database or code waives all rights to future claims in that contribution or in the TZ Database.
"""
simple-keyboard 2.32.0
Copyright (c) 2019 Francisco Hodge
-----
Distributed under the terms of the MIT License
-----
==
the MIT License
==
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the"Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
suricata & nmcli
-----
Distributed under the terms of the GNU General Public License Version 2, June 1991
-----
Version 2, June 1991 Copyright © 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
24.1.1. Preamble
The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free softwareto make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundations software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.
We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.
Also, for each authors protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors reputations.
Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyones free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification follow.
24.1.2. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The “Program”, below, refers to any such program or work, and a “work based on the Program” means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term “modification”.) Each licensee is addressed as “you”.
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Programs source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.
c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.
7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and “any later version”, you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
24.1.3. NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
24.1.4. How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.
<one line to give the programs name and a brief idea of what it does.> Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w. This is free software, and you are welcome to redistribute it under certain conditions; type `show c for details.
The hypothetical commands `show w` and `show c` should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w and `show c`; they could even be mouse-clicks or menu itemswhatever suits your program.
You should also get your employer (if you work as a programmer) or your school, if any, to sign a “copyright disclaimer” for the program, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice
This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License.

View File

@ -1 +1,81 @@
README
![title](https://user-images.githubusercontent.com/25131750/200111909-e0d10587-014a-410c-be05-e7e89cf6c9f5.gif)
### Description
SpyGuard is a forked and enhanced version of [TinyCheck](https://github.com/KasperskyLab/TinyCheck), developed by the same author when he was working at Kaspersky. SpyGuard's main objective is to detect signs of compromise by monitoring network flows transmitted by a device.
As it uses WiFi, SpyGuard can be used against a wide range of devices, such as smartphones, laptops, IOTs or workstations. To do its job, the analysis engine of SpyGuard is using Indicators of Compromise (IOCs), anomaly detection and is supported by [Suricata](https://suricata.io).
### Installation
You need a debian-like operating system to install it easly by using the provided bash script. Once you've cloned the repository, just launch `install.sh` as root. Here are the command lines to the that:
```
cd /tmp/ && git clone https://github.com/SpyGuard/spyguard
cd spyguard && sudo bash install.sh
```
Once installed, you can go to the backend interface located at `https://localhost:8443` to manage the device and setup the right network interfaces to get it working. Please look at the [dedicated wiki page](https://github.com/SpyGuard/spyguard/wiki/Installing-SpyGuard) to get some tips regarding it.
> Please check prior the installation that your Linux distribution is using `nmcli` to manage networks. If you want to install it on a Raspberry Pi
> you need to activate it via the `raspi-config` interface.
### Smartphone analysis best practices
* Do the interception in a public place (library, restaurant...) or common place (office, home...);
* Intercept the network communications of the device for at least 10 minutes;
* Interact with the analysed device during the interception (reboot it, take a photo, send a message...);
### SpyGuard and Stalkerware threat
The indicators of compromise (IOCs) linked to stalkerware are now fully managed by [ECHAP](https://echap.eu.org), a French association working against cyberviolence. Even though stalkerware still remains a threat, remember that most of digital violence and surveillance is done by using simple means, such as hacking cloud & mail accounts. Therefore, we encourage you to consult the [ECHAP guides](https://echap.eu.org/ressources/) and apply their advice to your digital life alongside of device checks.
> It is worth mentioning that the IOCs are distributed under the **Creative Common BY-NC-SA** licence.
> This imply a **non commercial use** of them. Please respect this licence and ask ECHAP for any question related to that.
### Commercial use
You can use SpyGuard in a commercial product. However, you can't use SpyGuard as the name of your product and youre still required to follow the terms and conditions that the Apache License imposes, like refering to the SpyGuard project in customer documentation. Moreover, a sweet note to explain your use to the author is always appreciated, please see the contact below.
### Contact
If you need an express help or specific developements or your own needs, do not hesitate to contact [the author](https://twitter.com/felixaime) via Twitter or by sending an email at spyguard@protonmail.com. A bug? Do not hesitate to open a [new issue](https://github.com/SpyGuard/spyguard/issues).
### They have contributed to or helped this project
<p float="left">
<a href="https://echap.eu.org"><img src="https://user-images.githubusercontent.com/25131750/200112980-80adc6e6-c922-471d-ab50-9821b2ed484c.png" width="150" /></a>&nbsp;&nbsp;
<a href="https://www.sekoia.io"><img src="https://user-images.githubusercontent.com/25131750/200112989-f18c29a7-c947-4eb6-95e4-997fc97c5b4d.png" height="90" /></a>
</p>
To work, Spyguard is using a lot of awesome opensource projects, libraries, and fonts, kudos to them:
[Dumpcap](https://tshark.dev/capture/dumpcap/),
[Dig](https://github.com/tigeli/bind-utils),
[Suricata](https://suricata.io/),
[NetworkManager](https://github.com/NetworkManager/NetworkManager),
[Python](https://www.python.org),
[VueJS](https://vuejs.org),
[Pip](https://github.com/pypa/pip),
[pydig](https://pypi.org/project/pydig/),
[pymisp](https://pypi.org/project/pymisp),
[netaddr](https://pypi.org/project/netaddr),
[pyyaml](https://pypi.org/project/pyyaml),
[flask](https://pypi.org/project/flask),
[flask_httpauth](https://pypi.org/project/flask_httpauth),
[pyjwt](https://pypi.org/project/pyjwt),
[sqlalchemy](https://pypi.org/project/sqlalchemy),
[psutil](https://pypi.org/project/psutil),
[pyudev](https://pypi.org/project/pyudev),
[qrcode](https://pypi.org/project/qrcode),
[netifaces](https://pypi.org/project/netifaces),
[weasyprint](https://pypi.org/project/weasyprint),
[python-whois](https://pypi.org/project/python-whois),
[publicsuffix2](https://pypi.org/project/publicsuffix2),
[six](https://pypi.org/project/six),
[Exo2 font](https://github.com/NDISCOVER/Exo-2.0),
[Virtual Keyboard](https://virtual-keyboard.js.org/vuejs/),
[OpenSSL](https://www.openssl.org),
[Spectre CSS](https://picturepan2.github.io/spectre/).
Icons and design created via [Figma](https://www.figma.com).

0
analysis/__init__.py Executable file
View File

79
analysis/analysis.py Executable file
View File

@ -0,0 +1,79 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from classes.engine import Engine
from classes.report import Report
import sys
import json
import os
"""
This file is called by the frontend to do the analysis.
"""
def analyze(capture_folder):
"""This method analyse a pcap. It:
1. Launches the detection engine which uses suricata;
2. Save the results inside the "assets" subfolder of the capture folder;
3. Generates the PDF report and save it in the capture folder.
Args:
capture_folder (str): The capture folder (eg. /tmp/45FB392D/)
"""
if os.path.isdir(capture_folder):
alerts = {}
# Create the assets folder.
if not os.path.isdir(os.path.join(capture_folder, "assets")):
os.mkdir(os.path.join(capture_folder, "assets"))
# Starts the engine and get alerts
engine = Engine(capture_folder)
engine.start_engine()
alerts = engine.get_alerts()
analysis_duration = (engine.analysis_end-engine.analysis_start).seconds
# alerts.json writing.
with open(os.path.join(capture_folder, "assets/alerts.json"), "w") as f:
report = {"high": [], "moderate": [], "low": []}
for alert in alerts:
if alert["level"] == "High":
report["high"].append(alert)
if alert["level"] == "Moderate":
report["moderate"].append(alert)
if alert["level"] == "Low":
report["low"].append(alert)
f.write(json.dumps(report, indent=4, separators=(',', ': ')))
# records.json writing.
with open(os.path.join(capture_folder, "assets/records.json"), "w") as f:
f.write(json.dumps(engine.records, indent=4, separators=(',', ': ')))
# detection_methods.json writing.
with open(os.path.join(capture_folder, "assets/detection_methods.json"), "w") as f:
f.write(json.dumps(engine.detection_methods, indent=4, separators=(',', ': ')))
# errors.json writing.
with open(os.path.join(capture_folder, "assets/errors.json"), "w") as f:
f.write(json.dumps(engine.errors, indent=4, separators=(',', ': ')))
# Generate the PDF report
report = Report(capture_folder, analysis_duration)
report.generate_report()
else:
print("The folder doesn't exist.")
def usage():
"""Shows the usage output."""
print(""" Usage: python analysis.py [capture_folder] where [capture_folder] is a folder containing a capture.pcap file """)
if __name__ == "__main__":
if len(sys.argv) == 2:
analyze(sys.argv[1])
else:
usage()

739
analysis/classes/engine.py Executable file
View File

@ -0,0 +1,739 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import os
import re
import subprocess as sp
import sys
from datetime import datetime
from ipaddress import IPv4Address, IPv6Address
import ssl
import socket
import OpenSSL
import requests
import pydig
import whois
from publicsuffix2 import get_sld
from netaddr import IPAddress, IPNetwork
from classes.jarm import get_jarm
from utils import get_config, get_iocs, get_whitelist
class Engine():
def __init__(self, capture_directory):
# Set some vars.
self.analysis_start = datetime.now()
self.connected = self.check_internet()
self.working_dir = capture_directory
self.assets_dir = f"{capture_directory}/assets/"
self.rules_file = "/tmp/rules.rules"
self.pcap_path = os.path.join(self.working_dir, "capture.pcap")
self.records = []
self.alerts = []
self.dns = []
self.files = []
self.whitelist = []
self.uncategorized = []
self.analysed = []
self.dns_failed = []
self.dns_checked = []
self.cert_checked = []
self.errors = []
self.analysis_end = None
# Get configuration
self.heuristics_analysis = get_config(("analysis", "heuristics"))
self.iocs_analysis = get_config(("analysis", "iocs"))
self.whitelist_analysis = get_config(("analysis", "whitelist"))
self.active_analysis = get_config(("analysis", "active"))
self.userlang = get_config(("frontend", "user_lang"))
self.max_ports = get_config(("analysis", "max_ports"))
self.http_default_ports = get_config(("analysis", "http_default_ports"))
self.tls_default_ports = get_config(("analysis", "tls_default_ports"))
self.free_issuers = get_config(("analysis", "free_issuers"))
self.max_alerts = get_config(("analysis", "max_alerts"))
self.indicators_types = get_config(("analysis", "indicators_types"))
# Save detection methods used.
self.detection_methods = { "iocs" : self.iocs_analysis,
"heuristics" : self.heuristics_analysis,
"active" : self.active_analysis }
# Retreive IOCs.
if self.iocs_analysis:
self.bl_cidrs = [[IPNetwork(cidr[0]), cidr[1]] for cidr in get_iocs("cidr")]
self.bl_hosts = get_iocs("ip4addr") + get_iocs("ip6addr")
self.tor_nodes = self.get_tor_nodes()
self.bl_domains = get_iocs("domain")
self.bl_freedns = get_iocs("freedns")
self.bl_certs = get_iocs("sha1cert")
self.bl_jarms = get_iocs("jarm")
self.bl_nameservers = get_iocs("ns")
self.bl_tlds = get_iocs("tld")
# Retreive whitelisted items.
if self.whitelist_analysis:
self.wl_cidrs = [IPNetwork(cidr) for cidr in get_whitelist("cidr")]
self.wl_hosts = get_whitelist("ip4addr") + get_whitelist("ip6addr") + self.get_public_ip()
self.wl_domains = get_whitelist("domain")
# Load template language
if not re.match("^[a-z]{2,3}$", self.userlang): self.userlang = "en"
with open(os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), "locales/{}.json".format(self.userlang))) as f:
self.template = json.load(f)["alerts"]
def check_internet(self) -> bool:
"""Check the internet link just with a small http request
to an URL present in the configuration
Returns:
bool: True if everything works.
"""
try:
url = get_config(("network", "internet_check"))
requests.get(url, timeout=3)
return True
except:
return False
def get_public_ip(self) -> list:
"""Get the public IP address
Returns:
list: list containing the public IP address.
"""
if self.connected:
try:
return [requests.get("https://api.ipify.org", timeout=3).text]
except:
return []
else:
return []
def start_engine(self):
""" This method starts suricata and then launch the
parsers to analyse the output logs.
"""
# Parse the eve.json file.
self.parse_eve_file()
# For each type of records, check it against heuristics.
for record in self.records:
if self.whitelist_analysis: self.check_whitelist(record)
self.check_domains(record)
self.check_flow(record)
self.check_tls(record)
self.check_http(record)
# Check for failed DNS answers (if spyguard not connected)
for dnsname in list(set(self.dns_failed)):
self.check_dnsname(dnsname)
def parse_eve_file(self):
"""This method parses the eve.json file produced by suricata.
For each record, it look at the record type and then append the self.record
dictionnary which contains valuable data to look at suspicious stuff.
"""
for record in open(f"{self.assets_dir}eve.json", "r").readlines():
record = json.loads(record)
try:
if "flow" in record:
if "app_proto" not in record: record["app_proto"] = "failed"
proto = { "name" : record["app_proto"].upper() if record["app_proto"] != "failed" else record["proto"].upper(), "port" : record["dest_port"] if "dest_port" in record else -1 }
if record["dest_ip"] not in [r["ip_dst"] for r in self.records]:
self.records.append({
"ip_dst" : record["dest_ip"],
"whitelisted" : False,
"suspicious" : False,
"protocols" : [proto],
"domains" : [],
"certificates" : []
})
else:
for rec in self.records:
if record["dest_ip"] == rec["ip_dst"]:
if proto not in rec["protocols"]:
rec["protocols"].append(proto)
except Exception as e:
self.errors.append(f"Issue when processing the following eve record (flow): {json.dumps(record)}")
for record in open(f"{self.assets_dir}eve.json", "r").readlines():
record = json.loads(record)
try:
if "tls" in record:
for rec in self.records:
if record["dest_ip"] == rec["ip_dst"]:
if "version" in record["tls"]:
if float(record["tls"]["version"].split(" ")[1]) < 1.3 and not "session_resumed" in record["tls"]:
if record["tls"] not in rec["certificates"]:
record["tls"]["port"] = record["dest_port"]
rec["certificates"].append(record["tls"])
else:
if "sni" in record["tls"] and record["tls"]["sni"] not in [c["sni"] for c in rec["certificates"]]:
rec["certificates"].append({ "sni" : record["tls"]["sni"], "version" : record["tls"]["version"], "port" : record["dest_port"] })
else:
rec["certificates"].append({ "version" : record["tls"]["version"], "port" : record["dest_port"] })
except Exception as e:
self.errors.append(f"Issue when processing the following eve record (tls): {json.dumps(record)}")
for record in open(f"{self.assets_dir}eve.json", "r").readlines():
record = json.loads(record)
try:
if "http" in record:
for rec in self.records:
if record["dest_ip"] == rec["ip_dst"]:
d = { "hostname" : record["http"]["hostname"] }
if "http_user_agent" in record["http"]:
d["user-agent"] = record["http"]["http_user_agent"]
if "http" in rec:
if not d in rec["http"]:
rec["http"].append(d)
else:
rec["http"] = [d]
except Exception as e:
self.errors.append(f"Issue when processing the following eve record (http): {json.dumps(record)}")
for record in open(f"{self.assets_dir}eve.json", "r").readlines():
record = json.loads(record)
try:
if "dns" in record:
if record["dns"]["type"] == "answer":
for rec in self.records:
if record["dns"]["rcode"] == "NOERROR":
if "grouped" in record["dns"]:
if "A" in record["dns"]["grouped"] and rec["ip_dst"] in record["dns"]["grouped"]["A"]:
if record["dns"]["rrname"] not in rec["domains"]:
rec["domains"].append(record["dns"]["rrname"])
elif "AAAA" in record["dns"]["grouped"] and rec["ip_dst"] in record["dns"]["grouped"]["AAAA"]:
if record["dns"]["rrname"] not in rec["domains"]:
rec["domains"].append(record["dns"]["rrname"])
elif record["dns"]["rcode"] == "SERVFAIL":
self.dns_failed.append(record["dns"]["rrname"])
except Exception as e:
self.errors.append(f"Issue when processing the following eve record (dns answer): {json.dumps(record)}")
# This pass is if SpyGuard is not connected to Internet.
# We still analyze the un answered DNS queries.
for record in open(f"{self.assets_dir}eve.json", "r").readlines():
record = json.loads(record)
try:
if "dns" in record:
if record["dns"]["type"] == "query":
if record["dns"]["rrname"] not in sum([r["domains"] for r in self.records], []):
self.records.append({
"ip_dst" : "--",
"whitelisted" : False,
"suspicious" : False,
"protocols" : [{"name" : "DNS", "port" : "53"}],
"domains" : [record["dns"]["rrname"]],
"certificates" : []
})
except Exception as e:
self.errors.append(f"Issue when processing the following eve record (dns query): {json.dumps(record)}")
for record in open(f"{self.assets_dir}eve.json", "r").readlines():
record = json.loads(record)
try:
if "alert" in record and record["event_type"] == "alert":
for rec in self.records:
if record["dest_ip"] == rec["ip_dst"]:
rec["suspicious"] = True
self.alerts.append({"title": self.template["SNORT-01"]["title"].format(record["alert"]["signature"]),
"description": self.template["SNORT-01"]["description"].format(rec["ip_dst"]),
"host": rec["ip_dst"],
"level": "High",
"id": "SNORT-01"})
except Exception as e:
self.errors.append(f"Issue when processing the following eve record (dns answer): {json.dumps(record)}")
def check_whitelist(self, record):
""" This method is asked on each record. It:
1. Check if the associated IP(v4/6) Address can be whitelisted
2. Check if one of the associated domain names can be whitelisted.
If its the case, the "whitelisted" key of the record is set to True.
Therefore, the record will be ignored for the rest of the analysis.
Args:
record (dict): record to be processed.
"""
try:
assert IPv4Address(record["ip_dst"])
if IPv4Address('224.0.0.0') <= IPv4Address(record["ip_dst"]) <= IPv4Address('239.255.255.255'):
record["whitelisted"] = True
return
for cidr in self.wl_cidrs:
if IPAddress(record["ip_dst"]) in cidr:
record["whitelisted"] = True
return
for ip in self.wl_hosts:
if record["ip_dst"] == ip:
record["whitelisted"] = True
return
except:
pass
try:
assert IPv6Address(record["ip_dst"])
if [record["ip_dst"].startswith(prefix) for prefix in ["fe80", "fc00", "ff02"]]:
record["whitelisted"] = True
return
for ip in self.wl_hosts:
if record["ip_dst"] == ip:
record["whitelisted"] = True
return
except:
pass
# We check if at least one of the associated
# domains is whitelisted
for dom in self.wl_domains:
for domain in record["domains"]:
if domain.endswith(dom):
record["whitelisted"] = True
return
def check_domains(self, record):
"""Check the domains associated to each record.
First this method checks if the record is whitelisted. If not:
1. Leverage a low alert if the record don't have any associated DNSName
2. Check each domain associated to the record by calling check_dnsname.
Args:
record (dict): record to be processed.
"""
if record["whitelisted"]: return
if self.heuristics_analysis:
# Otherwise, we alert the user that an IP haven't been resolved by
# a DNS answer during the session...
if record["domains"] == []:
record["suspicious"] = True
self.alerts.append({"title": self.template["PROTO-05"]["title"].format(record["ip_dst"]),
"description": self.template["PROTO-05"]["description"].format(record["ip_dst"]),
"host": record["ip_dst"],
"level": "Low",
"id": "PROTO-05"})
# Check each associated domain.
for domain in record["domains"]:
if self.check_dnsname(domain):
record["suspicious"] = True
def check_dnsname(self, dnsname):
"""Check a domain name against a set of IOCs / heuristics.
1. Check if the parent domain is blacklisted.
2. Check if the parent domain is a Free DNS.
3. Check if the domain extension is a suspicious TLD.
4. Check if the name servers associated to the domain are suspicious.
5. Check if the domain have been registered recently - less than one year.
Args:
record (dict): record to be processed.
Returns:
supicious (bool) : if an alert has been leveraged.
"""
suspicious = False
if self.iocs_analysis:
for domain in self.bl_domains:
if dnsname.endswith(domain[0]) and any(t in self.indicators_types for t in [domain[1], "all"]):
if domain[1] == "dual":
suspicious = True
self.alerts.append({"title": self.template["IOC-12"]["title"],
"description": self.template["IOC-12"]["description"].format(domain[0]),
"host": domain[0],
"level": "Low",
"id": "IOC-12"})
elif domain[1] == "tracker":
suspicious = True
self.alerts.append({"title": self.template["IOC-04"]["title"].format(domain[0], "tracker"),
"description": self.template["IOC-04"]["description"].format(domain[0], "tracker"),
"host": domain[0],
"level": "Low",
"id": "IOC-04"})
elif domain[1] == "doh":
suspicious = True
self.alerts.append({"title": self.template["IOC-13"]["title"].format(f"{dnsname}"),
"description": self.template["IOC-13"]["description"].format(f"{dnsname}"),
"host": dnsname,
"level": "Low",
"id": "IOC-13"})
else:
suspicious = True
self.alerts.append({"title": self.template["IOC-03"]["title"].format(dnsname, domain[1].upper()),
"description": self.template["IOC-03"]["description"].format(dnsname),
"host": dnsname,
"level": "High",
"id": "IOC-03"})
for domain in self.bl_freedns:
if dnsname.endswith(domain[0]) and any(t in self.indicators_types for t in [domain[1], "all"]):
suspicious = True
self.alerts.append({"title": self.template["IOC-05"]["title"].format(dnsname),
"description": self.template["IOC-05"]["description"].format(dnsname),
"host": dnsname,
"level": "Moderate",
"id": "IOC-05"})
if self.heuristics_analysis:
for domain in self.bl_tlds:
if dnsname.endswith(domain[0]) and any(t in self.indicators_types for t in [domain[1], "all"]):
suspicious = True
self.alerts.append({"title": self.template["IOC-06"]["title"].format(dnsname),
"description": self.template["IOC-06"]["description"].format(dnsname, domain[0]),
"host": dnsname,
"level": "Low",
"id": "IOC-06"})
if self.active_analysis and self.connected:
domain = get_sld(dnsname)
if domain not in self.dns_checked:
self.dns_checked.append(domain)
try:
name_servers = pydig.query(domain, "NS")
if len(name_servers):
for ns in self.bl_nameservers:
if name_servers[0].endswith(".{}.".format(ns[0])) and any(t in self.indicators_types for t in [ns[1], "all"]):
suspicious = True
self.alerts.append({"title": self.template["ACT-01"]["title"].format(dnsname, name_servers[0]),
"description": self.template["ACT-01"]["description"].format(dnsname),
"host": dnsname,
"level": "Moderate",
"id": "ACT-01"})
except Exception as e:
self.errors.append(f"Issue when doing a dig NS query to {domain}, are you connected? Error: {str(e)}")
try:
whois_record = whois.whois(domain)
creation_date = whois_record.creation_date if type(whois_record.creation_date) is not list else whois_record.creation_date[0]
creation_days = abs((datetime.now() - creation_date).days)
if creation_days < 365:
suspicious = True
self.alerts.append({"title": self.template["ACT-02"]["title"].format(dnsname, creation_days),
"description": self.template["ACT-02"]["description"].format(dnsname),
"host": dnsname,
"level": "Moderate",
"id": "ACT-02"})
except Exception as e:
self.errors.append(f"Issue when doing a WHOIS query to {domain}, are you connected? Error: {str(e)}")
return suspicious
def check_flow(self, record):
"""Check a network flow against a set of IOCs / heuristics.
1. Check if the IP Address is blacklisted
2. Check if the IP Address is inside a blacklisted CIDR
3. Check if the UDP or ICMP protocol is going outside of the local network.
4. Check if the HTTP protocol is not using default HTTP ports.
5. Check if the network flow is using a port > 1024.
Args:
record (dict): record to be processed.
Returns:
supicious (bool) : if an alert has been leveraged.
"""
if record["whitelisted"]: return
resolved_host = record["domains"][0] if len(record["domains"]) else record["ip_dst"]
if self.iocs_analysis:
for host in self.bl_hosts:
if record["ip_dst"] == host[0] and any(t in self.indicators_types for t in [host[1], "all"]):
if host[1] == "dual":
record["suspicious"] = True
self.alerts.append({"title": self.template["IOC-12"]["title"],
"description": self.template["IOC-12"]["description"].format(resolved_host),
"host": resolved_host,
"level": "Low",
"id": "IOC-12"})
if host[1] == "tracker":
record["suspicious"] = True
self.alerts.append({"title": self.template["IOC-04"]["title"].format(resolved_host, "tracker"),
"description": self.template["IOC-04"]["description"].format(resolved_host, "tracker"),
"host": resolved_host,
"level": "Low",
"id": "IOC-04"})
elif host[1] == "doh":
if 443 in [p["port"] for p in record["protocols"]]:
record["suspicious"] = True
self.alerts.append({"title": self.template["IOC-13"]["title"].format(f"{resolved_host}"),
"description": self.template["IOC-13"]["description"].format(f"{resolved_host}"),
"host": resolved_host,
"level": "Low",
"id": "IOC-13"})
else:
record["suspicious"] = True
self.alerts.append({"title": self.template["IOC-01"]["title"].format(resolved_host, record["ip_dst"], host[1].upper()),
"description": self.template["IOC-01"]["description"].format(f"{resolved_host} ({record['ip_dst']})"),
"host": resolved_host,
"level": "High",
"id": "IOC-01"})
break
for host in self.tor_nodes:
if record["ip_dst"] == host:
record["suspicious"] = True
self.alerts.append({"title": self.template["IOC-11"]["title"].format(resolved_host, record["ip_dst"]),
"description": self.template["IOC-11"]["description"].format(f"{resolved_host} ({record['ip_dst']})"),
"host": resolved_host,
"level": "High",
"id": "IOC-11"})
break
for cidr in self.bl_cidrs:
try:
if IPAddress(record["ip_dst"]) in cidr[0] and any(t in self.indicators_types for t in [cidr[1], "all"]):
record["suspicious"] = True
self.alerts.append({"title": self.template["IOC-02"]["title"].format(resolved_host, cidr[0], cidr[1].upper()),
"description": self.template["IOC-02"]["description"].format(record["ip_dst"]),
"host": resolved_host,
"level": "Moderate",
"id": "IOC-02"})
except:
continue
if self.heuristics_analysis:
for protocol in record["protocols"]:
if protocol["name"] in ["UDP", "ICMP", "IPV6-ICMP"]:
record["suspicious"] = True
self.alerts.append({"title": self.template["PROTO-01"]["title"].format(protocol["name"], resolved_host),
"description": self.template["PROTO-01"]["description"].format(protocol["name"], resolved_host),
"host": resolved_host,
"level": "Moderate",
"id": "PROTO-01"})
try:
if protocol["port"] >= int(self.max_ports):
record["suspicious"] = True
self.alerts.append({"title": self.template["PROTO-02"]["title"].format("", resolved_host, self.max_ports),
"description": self.template["PROTO-02"]["description"].format("", resolved_host, protocol["port"]),
"host": resolved_host,
"level": "Low",
"id": "PROTO-02"})
except:
pass
if protocol["name"] == "HTTP":
record["suspicious"] = True
self.alerts.append({"title": self.template["PROTO-03"]["title"].format(resolved_host),
"description": self.template["PROTO-03"]["description"].format(resolved_host),
"host": resolved_host,
"level": "Low",
"id": "PROTO-03"})
if protocol["name"] == "HTTP" and protocol["port"] not in self.http_default_ports:
record["suspicious"] = True
self.alerts.append({"title": self.template["PROTO-04"]["title"].format(resolved_host, protocol["port"]),
"description": self.template["PROTO-04"]["description"].format(resolved_host, protocol["port"]),
"host": resolved_host,
"level": "Moderate",
"id": "PROTO-04"})
def check_tls(self, record):
"""Check a TLS protocol and certificates against a set of IOCs / heuristics.
Note since TLS 1.3, the certificate is not exchanged in clear text, therefore
we need to check it "actively" via the method active_check_ssl.
1. Check if the TLS record is not using default TLS ports.
2. Check if one of the certificates is a free one, like Let's Encrypt.
3. Check if the certificate is auto-signed.
4. If the certificate has an SNI, check the domain by calling check_dnsname.
Args:
record (dict): record to be processed.
Returns:
supicious (bool) : if an alert has been leveraged.
"""
if record["whitelisted"]: return
resolved_host = record["domains"][0] if len(record["domains"]) else record["ip_dst"]
for certificate in record["certificates"]:
try:
if "sni" in certificate and certificate["sni"] not in record["domains"]:
if certificate["sni"]:
if self.check_dnsname(certificate["sni"]):
record["suspicious"] = True
if certificate["port"] not in self.tls_default_ports:
record["suspicious"] = True
self.alerts.append({"title": self.template["SSL-01"]["title"].format(certificate["port"], resolved_host),
"description": self.template["SSL-01"]["description"].format(resolved_host),
"host": resolved_host,
"level": "Moderate",
"id": "SSL-01"})
if float(certificate["version"].split(" ")[1]) < 1.3 and "issuerdn" in certificate:
if certificate["issuerdn"] in self.free_issuers:
record["suspicious"] = True
self.alerts.append({"title": self.template["SSL-02"]["title"].format(resolved_host),
"description": self.template["SSL-02"]["description"],
"host": resolved_host,
"level": "Moderate",
"id": "SSL-02"})
elif certificate["issuerdn"] == certificate["subject"]:
record["suspicious"] = True
self.alerts.append({"title": self.template["SSL-03"]["title"].format(resolved_host),
"description": self.template["SSL-03"]["description"].format(resolved_host),
"host": resolved_host,
"level": "Moderate",
"id": "SSL-03"})
else:
if self.active_analysis and self.connected:
if "sni" in certificate:
if certificate["sni"] not in self.cert_checked:
self.cert_checked.append(certificate["sni"])
if self.active_check_ssl(certificate["sni"], certificate["port"]):
record["suspicious"] = True
break
else:
if resolved_host not in self.cert_checked:
self.cert_checked.append(resolved_host)
if self.active_check_ssl(resolved_host, certificate["port"]):
record["suspicious"] = True
break
except Exception as e:
self.errors.append(f"Issue when processing the following certificate (check_tls): {json.dumps(certificate)}")
def get_tor_nodes(self) -> list:
"""Get a list of TOR nodes from dan.me.uk.
Returns:
list: list of TOR nodes
"""
nodes = []
if os.path.exists("/tmp/tor_nodes.lst"):
with open("/tmp/tor_nodes.lst", "r") as f:
for l in f.readlines():
nodes.append(l.strip())
else:
if self.connected:
try:
nodes_list = requests.get("https://www.dan.me.uk/torlist/", timeout=10).text
with open("/tmp/tor_nodes.lst", "w+") as f:
f.write(nodes_list)
for l in nodes_list.splitlines():
nodes.append(l.strip())
except:
self.errors.append(f"Issue when trying to get TOR nodes from dan.me.uk")
return nodes
def check_http(self, record):
"""Check the HTTP hostname against a set of IOCs / heuristics.
Args:
record (dict): record to be processed.
Returns:
supicious (bool) : if an alert has been leveraged.
"""
if record["whitelisted"]: return
if "http" in record:
for http in record["http"]:
if http["hostname"] not in record["domains"]:
if re.match("^[a-z\.0-9\-]+\.[a-z\-]{2,}$", http["hostname"]):
if http["hostname"]:
if self.check_dnsname(http["hostname"]):
record["suspicious"] = True
def active_check_ssl(self, host, port):
"""This method:
1. Check the issuer and subject of a certificate directly by connecting
to the remote server in order to bypass TLS 1.3+ restrictions.
Most of this method was been taken from: https://tinyurl.com/3vsvhu79
2. Get the JARM of the remote server by using the standard poc library
from sales force.
Args:
host (str): Host to connect to
port (int): Port to connect to
"""
try:
suspect = False
context = ssl.create_default_context()
conn = socket.create_connection((host, port))
sock = context.wrap_socket(conn, server_hostname=host)
sock.settimeout(5)
try:
der_cert = sock.getpeercert(True)
finally:
sock.close()
if "der_cert" in locals():
certificate = ssl.DER_cert_to_PEM_cert(der_cert)
x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, certificate)
issuer = dict(x509.get_issuer().get_components())
subject = dict(x509.get_subject().get_components())
certhash = x509.digest("sha1").decode("utf8").replace(":", "").lower()
issuer = ", ".join(f"{k.decode('utf8')}={v.decode('utf8')}" for k, v in issuer.items())
subject = ", ".join(f"{k.decode('utf8')}={v.decode('utf8')}" for k, v in subject.items())
if issuer in self.free_issuers:
self.alerts.append({"title": self.template["SSL-02"]["title"].format(host),
"description": self.template["SSL-02"]["description"],
"host": host,
"level": "Moderate",
"id": "SSL-02"})
suspect = True
if issuer == subject:
self.alerts.append({"title": self.template["SSL-03"]["title"].format(host),
"description": self.template["SSL-03"]["description"].format(host),
"host": host,
"level": "Moderate",
"id": "SSL-03"})
suspect = True
if self.iocs_analysis:
for cert in self.bl_certs:
if cert[0] == certhash and any(t in self.indicators_types for t in [cert[1], "all"]):
self.alerts.append({"title": self.template["SSL-04"]["title"].format(host, cert[1].upper()),
"description": self.template["SSL-04"]["description"].format(host),
"host": host,
"level": "High",
"id": "SSL-04"})
suspect = True
if self.bl_jarms:
host_jarm = get_jarm(host, port)
for jarm in self.bl_jarms:
if jarm[0] == host_jarm and any(t in self.indicators_types for t in [jarm[1], "all"]):
self.alerts.append({"title": self.template["SSL-05"]["title"].format(host, cert[1].upper()),
"description": self.template["SSL-05"]["description"].format(host),
"host": host,
"level": "High",
"id": "SSL-05"})
suspect = True
return suspect
except:
self.errors.append(f"Issue when trying to grab the SSL certificate located at {host}:{port}")
return False
def get_alerts(self):
"""Retrieves the alerts triggered during the analysis
Returns:
list: list of the alerts.
"""
self.analysis_end = datetime.now()
return [dict(t) for t in {tuple(d.items()) for d in self.alerts}]

477
analysis/classes/jarm.py Normal file
View File

@ -0,0 +1,477 @@
# Version 1.0 (November 2020)
#
# Created by:
# John Althouse
# Andrew Smart
# RJ Nunaly
# Mike Brady
#
# Converted to Python by:
# Caleb Yu
#
# Copyright (c) 2020, salesforce.com, inc.
# All rights reserved.
# Licensed under the BSD 3-Clause license.
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
#
from __future__ import print_function
import codecs
import socket
import struct
import os
import random
import hashlib
import ipaddress
#Randomly choose a grease value
def choose_grease():
grease_list = [b"\x0a\x0a", b"\x1a\x1a", b"\x2a\x2a", b"\x3a\x3a", b"\x4a\x4a", b"\x5a\x5a", b"\x6a\x6a", b"\x7a\x7a", b"\x8a\x8a", b"\x9a\x9a", b"\xaa\xaa", b"\xba\xba", b"\xca\xca", b"\xda\xda", b"\xea\xea", b"\xfa\xfa"]
return random.choice(grease_list)
def packet_building(jarm_details):
payload = b"\x16"
#Version Check
if jarm_details[2] == "TLS_1.3":
payload += b"\x03\x01"
client_hello = b"\x03\x03"
elif jarm_details[2] == "SSLv3":
payload += b"\x03\x00"
client_hello = b"\x03\x00"
elif jarm_details[2] == "TLS_1":
payload += b"\x03\x01"
client_hello = b"\x03\x01"
elif jarm_details[2] == "TLS_1.1":
payload += b"\x03\x02"
client_hello = b"\x03\x02"
elif jarm_details[2] == "TLS_1.2":
payload += b"\x03\x03"
client_hello = b"\x03\x03"
#Random values in client hello
client_hello += os.urandom(32)
session_id = os.urandom(32)
session_id_length = struct.pack(">B", len(session_id))
client_hello += session_id_length
client_hello += session_id
#Get ciphers
cipher_choice = get_ciphers(jarm_details)
client_suites_length = struct.pack(">H", len(cipher_choice))
client_hello += client_suites_length
client_hello += cipher_choice
client_hello += b"\x01" #cipher methods
client_hello += b"\x00" #compression_methods
#Add extensions to client hello
extensions = get_extensions(jarm_details)
client_hello += extensions
#Finish packet assembly
inner_length = b"\x00"
inner_length += struct.pack(">H", len(client_hello))
handshake_protocol = b"\x01"
handshake_protocol += inner_length
handshake_protocol += client_hello
outer_length = struct.pack(">H", len(handshake_protocol))
payload += outer_length
payload += handshake_protocol
return payload
def get_ciphers(jarm_details):
selected_ciphers = b""
#Two cipher lists: NO1.3 and ALL
if jarm_details[3] == "ALL":
list = [b"\x00\x16", b"\x00\x33", b"\x00\x67", b"\xc0\x9e", b"\xc0\xa2", b"\x00\x9e", b"\x00\x39", b"\x00\x6b", b"\xc0\x9f", b"\xc0\xa3", b"\x00\x9f", b"\x00\x45", b"\x00\xbe", b"\x00\x88", b"\x00\xc4", b"\x00\x9a", b"\xc0\x08", b"\xc0\x09", b"\xc0\x23", b"\xc0\xac", b"\xc0\xae", b"\xc0\x2b", b"\xc0\x0a", b"\xc0\x24", b"\xc0\xad", b"\xc0\xaf", b"\xc0\x2c", b"\xc0\x72", b"\xc0\x73", b"\xcc\xa9", b"\x13\x02", b"\x13\x01", b"\xcc\x14", b"\xc0\x07", b"\xc0\x12", b"\xc0\x13", b"\xc0\x27", b"\xc0\x2f", b"\xc0\x14", b"\xc0\x28", b"\xc0\x30", b"\xc0\x60", b"\xc0\x61", b"\xc0\x76", b"\xc0\x77", b"\xcc\xa8", b"\x13\x05", b"\x13\x04", b"\x13\x03", b"\xcc\x13", b"\xc0\x11", b"\x00\x0a", b"\x00\x2f", b"\x00\x3c", b"\xc0\x9c", b"\xc0\xa0", b"\x00\x9c", b"\x00\x35", b"\x00\x3d", b"\xc0\x9d", b"\xc0\xa1", b"\x00\x9d", b"\x00\x41", b"\x00\xba", b"\x00\x84", b"\x00\xc0", b"\x00\x07", b"\x00\x04", b"\x00\x05"]
elif jarm_details[3] == "NO1.3":
list = [b"\x00\x16", b"\x00\x33", b"\x00\x67", b"\xc0\x9e", b"\xc0\xa2", b"\x00\x9e", b"\x00\x39", b"\x00\x6b", b"\xc0\x9f", b"\xc0\xa3", b"\x00\x9f", b"\x00\x45", b"\x00\xbe", b"\x00\x88", b"\x00\xc4", b"\x00\x9a", b"\xc0\x08", b"\xc0\x09", b"\xc0\x23", b"\xc0\xac", b"\xc0\xae", b"\xc0\x2b", b"\xc0\x0a", b"\xc0\x24", b"\xc0\xad", b"\xc0\xaf", b"\xc0\x2c", b"\xc0\x72", b"\xc0\x73", b"\xcc\xa9", b"\xcc\x14", b"\xc0\x07", b"\xc0\x12", b"\xc0\x13", b"\xc0\x27", b"\xc0\x2f", b"\xc0\x14", b"\xc0\x28", b"\xc0\x30", b"\xc0\x60", b"\xc0\x61", b"\xc0\x76", b"\xc0\x77", b"\xcc\xa8", b"\xcc\x13", b"\xc0\x11", b"\x00\x0a", b"\x00\x2f", b"\x00\x3c", b"\xc0\x9c", b"\xc0\xa0", b"\x00\x9c", b"\x00\x35", b"\x00\x3d", b"\xc0\x9d", b"\xc0\xa1", b"\x00\x9d", b"\x00\x41", b"\x00\xba", b"\x00\x84", b"\x00\xc0", b"\x00\x07", b"\x00\x04", b"\x00\x05"]
#Change cipher order
if jarm_details[4] != "FORWARD":
list = cipher_mung(list, jarm_details[4])
#Add GREASE to beginning of cipher list (if applicable)
if jarm_details[5] == "GREASE":
list.insert(0,choose_grease())
#Generate cipher list
for cipher in list:
selected_ciphers += cipher
return selected_ciphers
def cipher_mung(ciphers, request):
output = []
cipher_len = len(ciphers)
#Ciphers backward
if (request == "REVERSE"):
output = ciphers[::-1]
#Bottom half of ciphers
elif (request == "BOTTOM_HALF"):
if (cipher_len % 2 == 1):
output = ciphers[int(cipher_len/2)+1:]
else:
output = ciphers[int(cipher_len/2):]
#Top half of ciphers in reverse order
elif (request == "TOP_HALF"):
if (cipher_len % 2 == 1):
output.append(ciphers[int(cipher_len/2)])
#Top half gets the middle cipher
output += cipher_mung(cipher_mung(ciphers, "REVERSE"),"BOTTOM_HALF")
#Middle-out cipher order
elif (request == "MIDDLE_OUT"):
middle = int(cipher_len/2)
# if ciphers are uneven, start with the center. Second half before first half
if (cipher_len % 2 == 1):
output.append(ciphers[middle])
for i in range(1, middle+1):
output.append(ciphers[middle + i])
output.append(ciphers[middle - i])
else:
for i in range(1, middle+1):
output.append(ciphers[middle-1 + i])
output.append(ciphers[middle - i])
return output
def get_extensions(jarm_details):
extension_bytes = b""
all_extensions = b""
grease = False
#GREASE
if jarm_details[5] == "GREASE":
all_extensions += choose_grease()
all_extensions += b"\x00\x00"
grease = True
#Server name
all_extensions += extension_server_name(jarm_details[0])
#Other extensions
extended_master_secret = b"\x00\x17\x00\x00"
all_extensions += extended_master_secret
max_fragment_length = b"\x00\x01\x00\x01\x01"
all_extensions += max_fragment_length
renegotiation_info = b"\xff\x01\x00\x01\x00"
all_extensions += renegotiation_info
supported_groups = b"\x00\x0a\x00\x0a\x00\x08\x00\x1d\x00\x17\x00\x18\x00\x19"
all_extensions += supported_groups
ec_point_formats = b"\x00\x0b\x00\x02\x01\x00"
all_extensions += ec_point_formats
session_ticket = b"\x00\x23\x00\x00"
all_extensions += session_ticket
#Application Layer Protocol Negotiation extension
all_extensions += app_layer_proto_negotiation(jarm_details)
signature_algorithms = b"\x00\x0d\x00\x14\x00\x12\x04\x03\x08\x04\x04\x01\x05\x03\x08\x05\x05\x01\x08\x06\x06\x01\x02\x01"
all_extensions += signature_algorithms
#Key share extension
all_extensions += key_share(grease)
psk_key_exchange_modes = b"\x00\x2d\x00\x02\x01\x01"
all_extensions += psk_key_exchange_modes
#Supported versions extension
if (jarm_details[2] == "TLS_1.3") or (jarm_details[7] == "1.2_SUPPORT"):
all_extensions += supported_versions(jarm_details, grease)
#Finish assembling extensions
extension_length = len(all_extensions)
extension_bytes += struct.pack(">H", extension_length)
extension_bytes += all_extensions
return extension_bytes
#Client hello server name extension
def extension_server_name(host):
ext_sni = b"\x00\x00"
ext_sni_length = len(host)+5
ext_sni += struct.pack(">H", ext_sni_length)
ext_sni_length2 = len(host)+3
ext_sni += struct.pack(">H", ext_sni_length2)
ext_sni += b"\x00"
ext_sni_length3 = len(host)
ext_sni += struct.pack(">H", ext_sni_length3)
ext_sni += host.encode()
return ext_sni
#Client hello apln extension
def app_layer_proto_negotiation(jarm_details):
ext = b"\x00\x10"
if (jarm_details[6] == "RARE_APLN"):
#Removes h2 and http/1.1
alpns = [b"\x08\x68\x74\x74\x70\x2f\x30\x2e\x39", b"\x08\x68\x74\x74\x70\x2f\x31\x2e\x30", b"\x06\x73\x70\x64\x79\x2f\x31", b"\x06\x73\x70\x64\x79\x2f\x32", b"\x06\x73\x70\x64\x79\x2f\x33", b"\x03\x68\x32\x63", b"\x02\x68\x71"]
else:
#All apln extensions in order from weakest to strongest
alpns = [b"\x08\x68\x74\x74\x70\x2f\x30\x2e\x39", b"\x08\x68\x74\x74\x70\x2f\x31\x2e\x30", b"\x08\x68\x74\x74\x70\x2f\x31\x2e\x31", b"\x06\x73\x70\x64\x79\x2f\x31", b"\x06\x73\x70\x64\x79\x2f\x32", b"\x06\x73\x70\x64\x79\x2f\x33", b"\x02\x68\x32", b"\x03\x68\x32\x63", b"\x02\x68\x71"]
#apln extensions can be reordered
if jarm_details[8] != "FORWARD":
alpns = cipher_mung(alpns, jarm_details[8])
all_alpns = b""
for alpn in alpns:
all_alpns += alpn
second_length = len(all_alpns)
first_length = second_length+2
ext += struct.pack(">H", first_length)
ext += struct.pack(">H", second_length)
ext += all_alpns
return ext
#Generate key share extension for client hello
def key_share(grease):
ext = b"\x00\x33"
#Add grease value if necessary
if grease == True:
share_ext = choose_grease()
share_ext += b"\x00\x01\x00"
else:
share_ext = b""
group = b"\x00\x1d"
share_ext += group
key_exchange_length = b"\x00\x20"
share_ext += key_exchange_length
share_ext += os.urandom(32)
second_length = len(share_ext)
first_length = second_length+2
ext += struct.pack(">H", first_length)
ext += struct.pack(">H", second_length)
ext += share_ext
return ext
#Supported version extension for client hello
def supported_versions(jarm_details, grease):
if (jarm_details[7] == "1.2_SUPPORT"):
#TLS 1.3 is not supported
tls = [b"\x03\x01", b"\x03\x02", b"\x03\x03"]
else:
#TLS 1.3 is supported
tls = [b"\x03\x01", b"\x03\x02", b"\x03\x03", b"\x03\x04"]
#Change supported version order, by default, the versions are from oldest to newest
if jarm_details[8] != "FORWARD":
tls = cipher_mung(tls, jarm_details[8])
#Assemble the extension
ext = b"\x00\x2b"
#Add GREASE if applicable
if grease == True:
versions = choose_grease()
else:
versions = b""
for version in tls:
versions += version
second_length = len(versions)
first_length = second_length+1
ext += struct.pack(">H", first_length)
ext += struct.pack(">B", second_length)
ext += versions
return ext
#Send the assembled client hello using a socket
def send_packet(packet, destination_host, destination_port):
try:
#Determine if the input is an IP or domain name
try:
if (type(ipaddress.ip_address(destination_host)) == ipaddress.IPv4Address) or (type(ipaddress.ip_address(destination_host)) == ipaddress.IPv6Address):
raw_ip = True
ip = (destination_host, destination_port)
except ValueError as e:
ip = (None, None)
raw_ip = False
#Connect the socket
if ":" in destination_host:
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
sock.settimeout(10)
sock.connect((destination_host, destination_port, 0, 0))
else:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(10)
sock.connect((destination_host, destination_port))
#Resolve IP if given a domain name
if raw_ip == False:
ip = sock.getpeername()
sock.sendall(packet)
#Receive server hello
data = sock.recv(1484)
#Close socket
sock.shutdown(socket.SHUT_RDWR)
sock.close()
return bytearray(data), ip[0]
#Timeout errors result in an empty hash
except socket.timeout as e:
sock.close()
return "TIMEOUT", ip[0]
except Exception as e:
sock.close()
return None, ip[0]
#If a packet is received, decipher the details
def read_packet(data, jarm_details):
try:
if data == None:
return "|||"
jarm = ""
#Server hello error
if data[0] == 21:
selected_cipher = b""
return "|||"
#Check for server hello
elif (data[0] == 22) and (data[5] == 2):
server_hello_length = int.from_bytes(data[3:5], "big")
counter = data[43]
#Find server's selected cipher
selected_cipher = data[counter+44:counter+46]
#Find server's selected version
version = data[9:11]
#Format
jarm += codecs.encode(selected_cipher, 'hex').decode('ascii')
jarm += "|"
jarm += codecs.encode(version, 'hex').decode('ascii')
jarm += "|"
#Extract extensions
extensions = (extract_extension_info(data, counter, server_hello_length))
jarm += extensions
return jarm
else:
return "|||"
except Exception as e:
return "|||"
#Deciphering the extensions in the server hello
def extract_extension_info(data, counter, server_hello_length):
try:
#Error handling
if (data[counter+47] == 11):
return "|"
elif (data[counter+50:counter+53] == b"\x0e\xac\x0b") or (data[82:85] == b"\x0f\xf0\x0b"):
return "|"
elif counter+42 >= server_hello_length:
return "|"
count = 49+counter
length = int(codecs.encode(data[counter+47:counter+49], 'hex'), 16)
maximum = length+(count-1)
types = []
values = []
#Collect all extension types and values for later reference
while count < maximum:
types.append(data[count:count+2])
ext_length = int(codecs.encode(data[count+2:count+4], 'hex'), 16)
if ext_length == 0:
count += 4
values.append("")
else:
values.append(data[count+4:count+4+ext_length])
count += ext_length+4
result = ""
#Read application_layer_protocol_negotiation
alpn = find_extension(b"\x00\x10", types, values)
result += str(alpn)
result += "|"
#Add formating hyphens
add_hyphen = 0
while add_hyphen < len(types):
result += codecs.encode(types[add_hyphen], 'hex').decode('ascii')
add_hyphen += 1
if add_hyphen == len(types):
break
else:
result += "-"
return result
#Error handling
except IndexError as e:
result = "|"
return result
#Matching cipher extensions to values
def find_extension(ext_type, types, values):
iter = 0
#For the APLN extension, grab the value in ASCII
if ext_type == b"\x00\x10":
while iter < len(types):
if types[iter] == ext_type:
return ((values[iter][3:]).decode())
iter += 1
else:
while iter < len(types):
if types[iter] == ext_type:
return values[iter].hex()
iter += 1
return ""
#Custom fuzzy hash
def jarm_hash(jarm_raw):
#If jarm is empty, 62 zeros for the hash
if jarm_raw == "|||,|||,|||,|||,|||,|||,|||,|||,|||,|||":
return "0"*62
fuzzy_hash = ""
handshakes = jarm_raw.split(",")
alpns_and_ext = ""
for handshake in handshakes:
components = handshake.split("|")
#Custom jarm hash includes a fuzzy hash of the ciphers and versions
fuzzy_hash += cipher_bytes(components[0])
fuzzy_hash += version_byte(components[1])
alpns_and_ext += components[2]
alpns_and_ext += components[3]
#Custom jarm hash has the sha256 of alpns and extensions added to the end
sha256 = (hashlib.sha256(alpns_and_ext.encode())).hexdigest()
fuzzy_hash += sha256[0:32]
return fuzzy_hash
#Fuzzy hash for ciphers is the index number (in hex) of the cipher in the list
def cipher_bytes(cipher):
if cipher == "":
return "00"
list = [b"\x00\x04", b"\x00\x05", b"\x00\x07", b"\x00\x0a", b"\x00\x16", b"\x00\x2f", b"\x00\x33", b"\x00\x35", b"\x00\x39", b"\x00\x3c", b"\x00\x3d", b"\x00\x41", b"\x00\x45", b"\x00\x67", b"\x00\x6b", b"\x00\x84", b"\x00\x88", b"\x00\x9a", b"\x00\x9c", b"\x00\x9d", b"\x00\x9e", b"\x00\x9f", b"\x00\xba", b"\x00\xbe", b"\x00\xc0", b"\x00\xc4", b"\xc0\x07", b"\xc0\x08", b"\xc0\x09", b"\xc0\x0a", b"\xc0\x11", b"\xc0\x12", b"\xc0\x13", b"\xc0\x14", b"\xc0\x23", b"\xc0\x24", b"\xc0\x27", b"\xc0\x28", b"\xc0\x2b", b"\xc0\x2c", b"\xc0\x2f", b"\xc0\x30", b"\xc0\x60", b"\xc0\x61", b"\xc0\x72", b"\xc0\x73", b"\xc0\x76", b"\xc0\x77", b"\xc0\x9c", b"\xc0\x9d", b"\xc0\x9e", b"\xc0\x9f", b"\xc0\xa0", b"\xc0\xa1", b"\xc0\xa2", b"\xc0\xa3", b"\xc0\xac", b"\xc0\xad", b"\xc0\xae", b"\xc0\xaf", b'\xcc\x13', b'\xcc\x14', b'\xcc\xa8', b'\xcc\xa9', b'\x13\x01', b'\x13\x02', b'\x13\x03', b'\x13\x04', b'\x13\x05']
count = 1
for bytes in list:
strtype_bytes = codecs.encode(bytes, 'hex').decode('ascii')
if cipher == strtype_bytes:
break
count += 1
hexvalue = str(hex(count))[2:]
#This part must always be two bytes
if len(hexvalue) < 2:
return_bytes = "0" + hexvalue
else:
return_bytes = hexvalue
return return_bytes
#This captures a single version byte based on version
def version_byte(version):
if version == "":
return "0"
options = "abcdef"
count = int(version[3:4])
byte = options[count]
return byte
def ParseNumber(number):
if number.startswith('0x'):
return int(number[2:], 16)
else:
return int(number)
def get_jarm(destination_host, destination_port):
#Select the packets and formats to send
#Array format = [destination_host,destination_port,version,cipher_list,cipher_order,GREASE,RARE_APLN,1.3_SUPPORT,extension_orders]
tls1_2_forward = [destination_host, destination_port, "TLS_1.2", "ALL", "FORWARD", "NO_GREASE", "APLN", "1.2_SUPPORT", "REVERSE"]
tls1_2_reverse = [destination_host, destination_port, "TLS_1.2", "ALL", "REVERSE", "NO_GREASE", "APLN", "1.2_SUPPORT", "FORWARD"]
tls1_2_top_half = [destination_host, destination_port, "TLS_1.2", "ALL", "TOP_HALF", "NO_GREASE", "APLN", "NO_SUPPORT", "FORWARD"]
tls1_2_bottom_half = [destination_host, destination_port, "TLS_1.2", "ALL", "BOTTOM_HALF", "NO_GREASE", "RARE_APLN", "NO_SUPPORT", "FORWARD"]
tls1_2_middle_out = [destination_host, destination_port, "TLS_1.2", "ALL", "MIDDLE_OUT", "GREASE", "RARE_APLN", "NO_SUPPORT", "REVERSE"]
tls1_1_middle_out = [destination_host, destination_port, "TLS_1.1", "ALL", "FORWARD", "NO_GREASE", "APLN", "NO_SUPPORT", "FORWARD"]
tls1_3_forward = [destination_host, destination_port, "TLS_1.3", "ALL", "FORWARD", "NO_GREASE", "APLN", "1.3_SUPPORT", "REVERSE"]
tls1_3_reverse = [destination_host, destination_port, "TLS_1.3", "ALL", "REVERSE", "NO_GREASE", "APLN", "1.3_SUPPORT", "FORWARD"]
tls1_3_invalid = [destination_host, destination_port, "TLS_1.3", "NO1.3", "FORWARD", "NO_GREASE", "APLN", "1.3_SUPPORT", "FORWARD"]
tls1_3_middle_out = [destination_host, destination_port, "TLS_1.3", "ALL", "MIDDLE_OUT", "GREASE", "APLN", "1.3_SUPPORT", "REVERSE"]
#Possible versions: SSLv3, TLS_1, TLS_1.1, TLS_1.2, TLS_1.3
#Possible cipher lists: ALL, NO1.3
#GREASE: either NO_GREASE or GREASE
#APLN: either APLN or RARE_APLN
#Supported Verisons extension: 1.2_SUPPPORT, NO_SUPPORT, or 1.3_SUPPORT
#Possible Extension order: FORWARD, REVERSE
queue = [tls1_2_forward, tls1_2_reverse, tls1_2_top_half, tls1_2_bottom_half, tls1_2_middle_out, tls1_1_middle_out, tls1_3_forward, tls1_3_reverse, tls1_3_invalid, tls1_3_middle_out]
jarm = ""
#Assemble, send, and decipher each packet
iterate = 0
while iterate < len(queue):
payload = packet_building(queue[iterate])
server_hello, ip = send_packet(payload, destination_host, destination_port)
#Deal with timeout error
if server_hello == "TIMEOUT":
jarm = "|||,|||,|||,|||,|||,|||,|||,|||,|||,|||"
break
ans = read_packet(server_hello, queue[iterate])
jarm += ans
iterate += 1
if iterate == len(queue):
break
else:
jarm += ","
#Fuzzy hash
return jarm_hash(jarm)

475
analysis/classes/report.py Executable file

File diff suppressed because one or more lines are too long

147
analysis/locales/de.json Executable file
View File

@ -0,0 +1,147 @@
{
"alerts": {
"PROTO-01": {
"title": "Es besteht {} Kommunikationsverbindung zu {} außerhalb des lokalen Netzwerks.",
"description": "Das Protokoll {} wird häufig in internen Netzwerken verwendet. Bitte überprüfen Sie, ob der Host {} andere Warnungen verursacht hat, was auf bösartiges Verhalten hindeuten kann."
},
"PROTO-02": {
"title": "{} Verbindung zu {} zu einem Port größer als oder gleich {}.",
"description": "{} Verbindungen zu {} über den Port {} wurden erkannt. Die Verwendung eines nicht standardmäßigen Ports ist manchmal ein Merkmal für bösartige Aktivitäten. Wir empfehlen, die Reputation dieses Hosts zu überprüfen, indem Sie sich andere Warnungen ansehen und im Internet danach suchen."
},
"PROTO-03": {
"title": "Mit dem Host {} wurde per HTTP kommuniziert.",
"description": "Ihr Gerät hat mit dem Host {} über das unverschlüsselte HTTP-Protokoll kommuniziert. Auch wenn dieses Verhalten an sich nicht bösartig ist, ist es ungewöhnlich, dass von Smartphone-Anwendungen, die im Hintergrund laufen, HTTP-Kommunikationen ausgehen. Bitte überprüfen Sie die Reputation des Hosts anhand einer Internetsuche."
},
"PROTO-04": {
"title": "Mit dem Host {} wurde über einen nicht standardmäßigen Port ({}) per HTTP kommuniziert.",
"description": "Ihr Gerät hat mit dem Host {} über den Port {} über das unverschlüsselte HTTP-Protokoll kommuniziert. Dieses Verhalten ist recht ungewöhnlich. Bitte überprüfen Sie die Reputation des Hosts anhand einer Internetsuche."
},
"PROTO-05": {
"title": "Der Server {} wurde während der Sitzung nicht in einer DNS-Abfrage aufgelöst.",
"description": "Das bedeutet, dass der Server {} möglicherweise in keinen Domain-Namen aufgelöst wird oder dass die Auflösung bereits vom Gerät zwischengespeichert wurde. Wenn dieser Host in anderen Warnungen vorkommt, überprüfen Sie ihn bitte."
},
"IOC-01": {
"title": "Es wurde eine Verbindung zu {} hergestellt ({}), was als {} gekennzeichnet ist.",
"description": "Der Host {} wurde aufgrund bösartiger Aktivitäten explizit auf die Sperrliste gesetzt. Ihr Gerät ist wahrscheinlich kompromittiert und muss von IT-Sicherheitsexperten genauer untersucht werden."
},
"IOC-02": {
"title": "Kommunikation mit {} unter dem CIDR {}, der als {} gekennzeichnet ist.",
"description": "Der Server {} wird in einem Netzwerk gehostet, das für bösartige Aktivitäten bekannt ist. Auch wenn dieses Verhalten an sich nicht bösartig ist, müssen Sie überprüfen, ob dieser Host auch in anderen Warnungen erwähnt wird. Wenn Sie Zweifel haben, suchen Sie im Internet nach diesem Host, um zu sehen, ob er legitim ist."
},
"IOC-03": {
"title": "Es wurde eine DNS-Abfrage zu {} ausgeführt, was als {} gekennzeichnet ist.",
"description": "Der in der Aufnahme vorkommende Domain-Name {} wurde explizit als bösartig gekennzeichnet. Dies weist darauf hin, dass Ihr Gerät wahrscheinlich kompromittiert ist und eingehend untersucht werden muss."
},
"IOC-04": {
"title": "Es wurde eine DNS-Abfrage zu {} ausgeführt, was als {} gekennzeichnet ist.",
"description": "Der in der Aufnahme vorkommende Domain-Name {} wurde explizit als Tracker gekennzeichnet. Dies weist darauf hin, dass eine der aktiven Apps Ihren Standort geografisch verfolgt."
},
"IOC-05": {
"title": "Es wurde eine DNS-Abfrage zur Domain {} ausgeführt, die einen Free-DNS-Dienst nutzt.",
"description": "Der Domain-Name {} nutzt einen Free-DNS-Dienst. Dienste dieser Art werden häufig von Cyberkriminellen oder staatlich unterstützten Angreifern bei ihren Operationen genutzt. Es ist sehr verdächtig, dass eine im Hintergrund laufende Anwendung einen solchen Dienst verwendet. Bitte untersuchen Sie das näher."
},
"IOC-06": {
"title": "Es wurde eine DNS-Abfrage zur Domain {} ausgeführt, die eine verdächtige TLD enthält.",
"description": "Der Domain-Name {} nutzt eine verdächtige Top-Level-Domain ({}). Diese nicht-generische TLD ist zwar selbst nicht bösartig, wird aber häufig von Cyberkriminellen und bei staatlich unterstützten Operationen verwendet. Bitte überprüfen Sie diese Domain anhand einer Internetsuche. Wenn dieser Host in anderen Warnungen erwähnt wird, können Sie ihn als sehr verdächtig betrachten."
},
"IOC-07": {
"title": "Ein Zertifikat, das mit {} Aktivitäten verknüpft ist, wurde in der Kommunikationsverbindung zu {} gefunden.",
"description": "Das Zertifikat ({}), das mit {} verknüpft ist, wurde explizit als bösartig gekennzeichnet. Dies weist darauf hin, dass Ihr Gerät wahrscheinlich kompromittiert ist und eine forensische Analyse benötigt."
},
"IOC-08": {
"title": "Es wurde eine HTTP-Abfrage zu {} ausgeführt, was als {} gekennzeichnet ist.",
"description": "Der in der Aufnahme vorkommende Domain-Name {} wurde explizit als bösartig gekennzeichnet. Dies weist darauf hin, dass Ihr Gerät wahrscheinlich kompromittiert ist und eingehend untersucht werden muss."
},
"IOC-09": {
"title": "Es wurde eine HTTP-Abfrage zur Domain {} ausgeführt, die einen Free-DNS-Dienst nutzt.",
"description": "Der Domain-Name {} nutzt einen Free-DNS-Dienst. Dienste dieser Art werden häufig von Cyberkriminellen oder staatlich unterstützten Angreifern bei ihren Operationen genutzt. Es ist sehr verdächtig, dass eine im Hintergrund laufende Anwendung einen solchen Dienst verwendet. Bitte untersuchen Sie das näher."
},
"IOC-10": {
"title": "Es wurde eine HTTP-Abfrage zur Domain {} ausgeführt, die eine verdächtige TLD enthält.",
"description": "Der Domain-Name {} nutzt eine verdächtige Top-Level-Domain ({}). Diese nicht-generische TLD ist zwar selbst nicht bösartig, wird aber häufig von Cyberkriminellen und bei staatlich unterstützten Operationen verwendet. Bitte überprüfen Sie diese Domain anhand einer Internetsuche. Wenn dieser Host in anderen Warnungen erwähnt wird, können Sie ihn als sehr verdächtig betrachten."
},
"IOC-11": {
"title": "Verbindung zu {} ({}), die als TOR-Knoten referenziert wird.",
"description": "Der Server {} wird als Knoten im TOR-Anonymisierungsnetzwerk referenziert. Das analysierte Gerät scheint TOR zu verwenden oder mit einem Server zu kommunizieren, der als TOR-Eingangs- oder -Ausgangsknoten konfiguriert ist. Einige Angreifer nutzen TOR auf ihren Servern, um ihre Spuren zu verwischen."
},
"IOC-12": {
"title": "Eine Anwendung fordert einen legitimen Dienst an, der möglicherweise doppelt verwendet wird."
"description": "Der Server {} wird für legitime Zwecke verwendet. Einige Angreifer können ihn jedoch verwenden, um mit ihren Implantaten zu interagieren. Es wird empfohlen, zu überprüfen, ob das analysierte Gerät eine legitime Anwendung enthält, die diesen Dienst verwendet."
},
"IOC-13": {
"title": "Mindestens eine Anwendung verwendet verschlüsselte DNS-Abfragen."
"description": "Der DNS over HTTPs server {} wurde während der Erfassung kontaktiert. Dies scheint darauf hinzuweisen, dass mindestens eine Anwendung diese Technik verwendet, um ihre DNS-Anfragen zu verschlüsseln. Diese Funktion schränkt die Scanfunktionen von SpyGuard ein. Wenn diese Funktion auf dem analysierten Gerät nicht aktiviert ist, kann es sich lohnen, herauszufinden, welche App diese Methode verwendet."
},
"ACT-01": {
"title": "Die Domain {} nutzt einen verdächtigen Nameserver ({}).",
"description": "Der Domain-Name {} nutzt einen Nameserver, der explizit mit bösartigen Aktivitäten in Verbindung gebracht wird. Viele Cyberkriminelle und staatlich unterstützte Angreifer nutzen Registrare dieser Art, weil sie Kryptowährungen und anonyme Zahlungen zulassen. Es wird empfohlen, diese Domain und die damit verknüpfte laufende Anwendung mithilfe einer forensischen Analyse des Telefons näher zu untersuchen."
},
"ACT-02": {
"title": "Die Domain {} wurde vor kurzem (vor {} Tagen) erstellt.",
"description": "Der Domainname {} ist neu. Auch wenn dies nicht von Natur aus böswillig ist, richten Angreifer häufig für jede Kampagne eine neue Infrastruktur ein, die zur Verwendung neu registrierter Domainnamen führen kann."
},
"SSL-01": {
"title": "SSL-Verbindung über einen nicht standardmäßigen Port ({})",
"description": "Es ist ungewöhnlich, dass SSL-Verbindungen von Smartphones über einen nicht standardmäßigen Port hergestellt werden. Das kann durchaus legitim sein, aber wir empfehlen dennoch, die Reputation von {} zu überprüfen. Sehen Sie sich dazu den entsprechenden WHOIS-Eintrag, das zugehörige autonome System und das Erstellungsdatum an und suchen Sie im Internet danach."
},
"SSL-02": {
"title": "Eine SSL-Verbindung zu {} verwendet ein kostenloses Zertifikat.",
"description": "Kostenlose Zertifikate wie z. B. Let's Encrypt werden gerne von Command-and-Control-Servern verwendet, die mit bösartigen Implants und Phishing-Webseiten in Verbindung stehen. Wir empfehlen, den mit diesem Zertifikat verknüpften Host zu überprüfen. Sehen Sie sich dazu seinen Domain-Namen und das Erstellungsdatum an oder überprüfen Sie die Reputation des Hosts im Internet."
},
"SSL-03": {
"title": "Das mit {} verknüpfte Zertifikat ist selbstsigniert.",
"description": "Die Verwendung von selbstsignierten Zertifikaten ist in der Infrastruktur von Angreifern weit verbreitet. Wir empfehlen, den mit diesem Zertifikat verknüpften Host {} zu überprüfen. Sehen Sie sich dazu seinen Domain-Namen (falls vorhanden), den WHOIS-Eintrag und das Erstellungsdatum an und überprüfen Sie die Reputation des Hosts im Internet."
},
"SSL-04": {
"title": "Das mit {} verknüpfte Zertifikat ist mit böswilligen Aktivitäten ({})" verknüpft,
"description": "Das mit server {} verknüpfte Zertifikat wurde explizit als bösartig eingestuft. Ihr Gerät sieht kompromittiert aus und muss von einem professionellen Team weiter untersucht werden."
},
"SSL-05": {
"title": "Die SSL-Konfiguration von {} ist mit bösartigen Aktivitäten ({})" verknüpft,
"description": "Der serverbezogene JARM-Hash {} wurde explizit mit bösartigen Aktivitäten verknüpft. Ihr Gerät ist möglicherweise kompromittiert und muss von einem professionellen Team weiter untersucht werden."
},
"ADV-01": {
"title": "Überprüfen Sie die Warnungen für {}",
"description": "Bitte überprüfen Sie die Reputation des Hosts {}. Dieser scheint bösartig zu sein, da er während der Sitzung {} Warnungen verursacht hat."
},
"SNORT-01": {
"title": "Suricata-Regel ausgelöst: {}",
"description": "Eine Netzwerkerkennungsregel wurde ausgelöst. Es ist wahrscheinlich, dass Ihr Gerät kompromittiert wurde oder verdächtiges Verhalten aufweist."
}
},
"report": {
"numbers": [
"eine",
"zwei",
"drei",
"vier",
"fünf",
"sechs",
"sieben",
"acht",
"neun"
],
"suspect_title": "Verdächtige Kommunikationsverbindungen",
"uncat_title": "Kommunikationsverbindungen ohne Kategorie",
"whitelist_title": "Kommunikationsverbindungen auf der Zulassungsliste",
"protocol": "Protokoll",
"domain": "Domain",
"dst_ip": "Ziel-IP-Adresse",
"dst_port": "Ziel-Portnummer",
"device_mac": "MAC-Adresse des Geräts",
"report_generated_on": "Bericht erstellt am",
"capture_duration": "Aufnahmedauer",
"packets_number": "Anzahl der Pakete",
"capture_sha1": "SHA1-Aufnahme",
"report_for_the_capture": "Bericht zur Aufnahme",
"report_footer": "Dieser Bericht wurde von einem SpyGuard-Gerät automatisch erstellt. Wenn Sie Fragen haben, Bugs melden oder Feedback geben möchten, kontaktieren Sie uns unter contact@spyguard.io.",
"high_msg": "Ihr Gerät scheint kompromittiert zu sein, da Sie {} Warnung(en) der Stufe \"Hoch\" haben.",
"moderate_msg": "Sie haben {} Warnungen der Stufe \"Mittel\": Ihr Gerät könnte kompromittiert sein. Bitte sehen Sie sich die Warnungen sorgfältig an.",
"low_msg": "Sie haben nur {} Warnungen der Stufe \"Niedrig\": Überprüfen Sie sie gerne.",
"none_msg": "Alles sieht gut aus kein Warnungen. Sehen Sie sich gerne auch die nicht kategorisierten Kommunikationsverbindungen an, falls welche vorhanden sind.",
"detection_methods": "Nachweismethoden",
"analysis_duration": "Analysezeit",
"instance_uuid": "Instanz von SpyGuard",
"seconds" : "zweite"
}
}

147
analysis/locales/en.json Executable file
View File

@ -0,0 +1,147 @@
{
"alerts": {
"PROTO-01": {
"title": "{} communication going outside the local network to {}.",
"description": "The {} protocol is commonly used in internal networks. Please, verify if the host {} leveraged other alerts which may indicates a possible malicious behavior."
},
"PROTO-02": {
"title": "{} connection to {} to a port over or equal to {}.",
"description": "{} connections have been seen to {} by using the port {}. The use of non-standard port can be sometimes associated to malicious activities. We recommend to check if this host has a good reputation by looking on other alerts and search it on the internet."
},
"PROTO-03": {
"title": "HTTP communications have been done to the host {}",
"description": "Your device exchanged with the host {} by using HTTP, an unencrypted protocol. Even if this behavior is not malicious by itself, it is unusual to see HTTP communications issued from smartphone applications running in the background. Please check the host reputation by searching it on the internet."
},
"PROTO-04": {
"title": "HTTP communications have been seen to the host {} on a non standard port ({}).",
"description": "Your device exchanged with the host {} by using HTTP, an unencrypted protocol on the port {}. This behavior is quite unusual. Please check the host reputation by searching it on the internet."
},
"PROTO-05": {
"title": "The server {} hasn't been resolved by any DNS query during the session",
"description": "It means that the server {} is likely not resolved by any domain name or the resolution has already been cached by the device. If the host appears in other alerts, please check it."
},
"IOC-01": {
"title": "A connection has been made to {} ({}) which is tagged as {}.",
"description": "The host {} has been explicitly blacklisted for malicious activities. Your device is likely compromised and needs to be investigated more deeply by IT security professionals."
},
"IOC-02": {
"title": "Communication to {} under the CIDR {} which is tagged as {}.",
"description": "The server {} is hosted under a network which is known to host malicious activities. Even if this behavior is not malicious by itself, you need to check if other alerts are also mentioning this host. If you have some doubts, please search this host on the internet to see if its legit or not."
},
"IOC-03": {
"title": "A DNS request have been done to {} which is tagged as {}.",
"description": "The domain name {} seen in the capture has been explicitly tagged as malicious. This indicates that your device is likely compromised and needs to be investigated deeply."
},
"IOC-04": {
"title": "A DNS request have been done to {} which is tagged as {}.",
"description": "The domain name {} seen in the capture has been explicitly tagged as a Tracker. This indicates that one of the active apps is geo-tracking your moves."
},
"IOC-05": {
"title": "A DNS request have been done to the domain {} which is a Free DNS.",
"description": "The domain name {} is using a Free DNS service. This kind of service is commonly used by cybercriminals or state-sponsored threat actors during their operations. It is very suspicious that an application running in background use this kind of service, please investigate."
},
"IOC-06": {
"title": "A DNS request have been done to the domain {} which contains a suspect TLD.",
"description": "The domain name {} is using a suspect Top Level Domain ({}). Even not malicious, this non-generic TLD is used regularly by cybercrime or state-sponsored operations. Please check this domain by searching it on an internet search engine. If other alerts are related to this host, please consider it as very suspicious."
},
"IOC-07": {
"title": "A certificate associated to {} activities have been found in the communication to {}.",
"description": "The certificate ({}) associated to {} has been explicitly tagged as malicious. This indicates that your device is likely compromised and need a forensic analysis."
},
"IOC-08": {
"title": "An HTTP request have been done to {} which is tagged as {}.",
"description": "The domain name {} seen in the capture has been explicitly tagged as malicious. This indicates that your device is likely compromised and needs to be investigated deeply."
},
"IOC-09": {
"title": "An HTTP request have been done to the domain {} which is a Free DNS.",
"description": "The domain name {} is using a Free DNS service. This kind of service is commonly used by cybercriminals or state-sponsored threat actors during their operations. It is very suspicious that an application running in background use this kind of service, please investigate."
},
"IOC-10": {
"title": "An HTTP request have been done to the domain {} which contains a suspect TLD.",
"description": "The domain name {} is using a suspect Top Level Domain ({}). Even not malicious, this non-generic TLD is used regularly by cybercrime or state-sponsored operations. Please check this domain by searching it on an internet search engine. If other alerts are related to this host, please consider it as very suspicious."
},
"IOC-11": {
"title": "Connection to {} ({}) which is referenced as a TOR node.",
"description": "The server {} is referenced as a node on the TOR anonymization network. The analyzed device appears to be using TOR or communicating with a server configured as a TOR input or output node. Some attackers use TOR on their servers to cover their tracks."
},
"IOC-12": {
"title": "An application requests a legitimate service that may have a dual use .",
"description": "The server {} is used for legitimate purposes. However, some attackers can use it to interact with their implants. It is adviced to check that the analyzed device contains a legitimate application which use this service."
},
"IOC-13": {
"title": "At least one application uses encrypted DNS queries.",
"description": "The DNS over HTTPs server {} was contacted during the capture. This seems to indicate that at least one application uses this technique to encrypt its DNS requests. This feature limits the scanning capabilities of SpyGuard. If this feature is not enabled on the analyzed device, it may be worth finding out which app is using this method."
},
"ACT-01": {
"title": "The domain {} is using a suspect nameserver ({}).",
"description": "The domain name {} is using a nameserver that has been explicitly tagged to be associated to malicious activities. Many cybercriminals and state-sponsored threat actors are using this kind of registrars because they allow cryptocurrencies and anonymous payments. It is adviced to investigate on this domain and the associated running application by doing a forensic analysis of the phone."
},
"ACT-02": {
"title": "The domain {} have been created quite recently ({} days ago).",
"description": "The domain name {} is quite new. Even this is not malicious by itself, its quite common for attackers to set up new infrastructure for each attack campaign which can lead to the use of recently registered domain names."
},
"SSL-01": {
"title": "SSL connection done on a non standard port ({}) to {}",
"description": "It is not common to see SSL connections issued from smartphones using non-standard ports. Even this can be totally legit, we recommend to check the reputation of {}, by looking at its WHOIS record, the associated autonomus system, its creation date, and by searching it the internet."
},
"SSL-02": {
"title": "An SSL connection to {} is using a free certificate.",
"description": "Free certificates — such as Let's Encrypt — are wildly used by command and control servers associated to malicious implants or phishing web pages. We recommend to check the host associated to this certificate, by looking at the domain name, its creation date, or by checking its reputation on the internet."
},
"SSL-03": {
"title": "The certificate associated to {} is self-signed.",
"description": "The use of self-signed certificates is a common thing for attacker infrastructure. We recommend to check the host {} which is associated to this certificate, by looking at the domain name (if any), its WHOIS record, its creation date, and by checking its reputation on the internet."
},
"SSL-04": {
"title": "The certificate associated with {} is linked to malicious activity ({}).",
"description": "The certificate associated with server {} has been explicitly categorized as malicious. Your device looks compromised and needs to be further investigated by a professional team."
},
"SSL-05": {
"title": "The SSL configuration of {} is linked to malicious activity ({}).",
"description": "The server-related JARM hash {} has been explicitly associated with malicious activity. Your device is possibly compromised and needs to be further investigated by a professional team."
},
"ADV-01": {
"title": "Check the alerts for {}",
"description": "Please, check the reputation of the host {}, this one seems to be malicious as it leveraged {} alerts during the session."
},
"SNORT-01": {
"title": "Suricata rule tiggered: {}",
"description": "A network detection rule has been triggered. It's likely that your device has been compromised or have some suspect behaviour."
}
},
"report": {
"numbers": [
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine"
],
"suspect_title": "Suspect communications",
"uncat_title": "Uncategorized communications",
"whitelist_title": "Whitelisted communications",
"protocol": "Protocol",
"domain": "Domain",
"dst_ip": "Dst IP address",
"dst_port": "Dst port number",
"device_mac": "Device MAC address",
"report_generated_on": "Report generated on",
"capture_duration": "Capture duration",
"packets_number": "Number of packets",
"capture_sha1": "Capture SHA1",
"report_for_the_capture": "Report for the capture",
"report_footer": "This report has been autogenerated by a SpyGuard device. For any question, bug report or feedback, please contact contact@spyguard.io.",
"high_msg": "Your device seems to be compromised as you have {} high alert(s).",
"moderate_msg": "You have {} moderate alert(s), your device might be compromised. Please look at them carefully.",
"low_msg": "You have only {} low alert(s), don't hesitate to check them.",
"none_msg": "Everything looks fine, zero alerts. Don't hesitate to check the uncategorized communications, if any.",
"detection_methods": "Detection methods",
"analysis_duration": "Analysis duration",
"instance_uuid": "SpyGuard instance",
"seconds" : "second(s)"
}
}

147
analysis/locales/es.json Executable file
View File

@ -0,0 +1,147 @@
{
"alerts": {
"PROTO-01": {
"title": "Comunicación {} saliente desde la red local hacia {}.",
"description": "El protocolo {} se usa comúnmente en redes internas. Por favor verifique si el host {} ha emitido otras alertas que puedan indicar un posible comportamiento malicioso"
},
"PROTO-02": {
"title": "Conexión {} hacia {} en un puerto superior o igual a {}.",
"description": "Se han identificado conexiones {} hacia {} usando el puerto {}. El uso de un puerto no standard puede estar asociado a actividad maliciosa. Recomendamos verificar la reputación de este host mediante la comprobación de otras alertas y búsquedas en Internet."
},
"PROTO-03": {
"title": "Se han realizado comunicaciones HTTP hacia el host {}",
"description": "Su dispositivo se ha comunicado con el host {} mediante HTTP, un protocolo sin cifrar. Aunque este comportamiento no tiene porque ser malicioso por sí mismo, no es del todo común ver comunicaciones HTTP emitidas desde aplicaciones móviles ejecutándose en segundo plano. Por favor verifique la reputación de este host mediante su búsqueda en Internet."
},
"PROTO-04": {
"title": "Se han realizado comunicaciones HTTP hacia el host {} en un puerto ({}) no standard.",
"description": "Su dispositivo se ha comunicado con el host {} mediante HTTP, un protocolo sin cifrado, en el puerto {}. Este comportamiento es bastante inusual. Por favor verifique la reputación de este host mediante su búsqueda en Internet."
},
"PROTO-05": {
"title": "El servidor {} no ha sido resuelto por ningún servidor DNS durante la sesión.",
"description": "Significa que el servidor {} probablemente no resuelve a ningún nombre de dominio o su resolución ha sido cacheada por el dispositivo. Por favor, compruebe si este host aparece en otras alertas."
},
"IOC-01": {
"title": "Se ha realizado una conexión a {} ({}) que está etiquetada como {}.",
"description": "El host {} ha sido explícitamente añadido a la lista negra por actividad maliciosa. Su dispositivo está probablemente comprometido y necesita ser investigado en profundidad por un profesional de seguridad IT."
},
"IOC-02": {
"title": "Comunicación hacia {} incluida en el CIDR {} que está etiquetada como {}.",
"description": "El servidor {} está hospedado en una red conocida por albergar actividades maliciosas. Aunque este comportamiento no es malicioso de por sí, por favor compruebe si el host aparece en otras alertas y verifique la reputación del mismo en Internet."
},
"IOC-03": {
"title": "Se ha realizado una petición DNS a {} que está etiquetada como {}.",
"description": "El dominio {} identificado en la captura ha sido explícitamente etiquetado como malicioso. Esto indica que su dispositivo está probablemente comprometido y debe ser investigado en profundidad."
},
"IOC-04": {
"title": "Se ha realizado una petición DNS a {} que está etiquetada como {}.",
"description": "El dominio {} identificado en la captura ha sido explícitamente etiquetado como Tracker. Esto indica que la aplicación asociada está monitorizando su posición geográfica."
},
"IOC-05": {
"title": "Se ha realizado una petición DNS al dominio {} que es un DNS gratuito.",
"description": "El dominio {} está usando un servicio DNS gratuito. Este tipo de servicios es comúnmente utilizado por cibercriminales y otros actores de amenazas. Es altamente sospechoso que una aplicación ejecutándose en segundo plano use este tipo de servicios. Por favor investigue."
},
"IOC-06": {
"title": "Se ha realizado una petición DNS al dominio {} que contiene un TLD sospechoso.",
"description": "El dominio {} está usando un dominio de primero nivel -TLD- ({}). Aunque no sea malicioso, este TLP no-genérico es usado por cibercriminales y otros actores de amenazas con regularidad. Verifique este dominio mediante su búsqueda en Internet. Si hay otras alertas relacionadas con este host, por favor considérelo como muy sospechoso."
},
"IOC-07": {
"title": "Un certificado asociado a actividades {} ha sido identificado en una comunicación hacia {}.",
"description": "El certificado ({}) asociado a {} ha sido explícitamente etiquetado como malicioso. Esto indica que su dispositivo está probablemente comprometido y necesita ser analizado en profundidad por un especialista forense."
},
"IOC-08": {
"title": "Se ha realizado una petición HTTP a {} que está etiquetada como {}.",
"description": "El dominio {} identificado en la captura ha sido explícitamente etiquetado como malicioso. Esto indica que su dispositivo está probablemente comprometido y debe ser investigado en profundidad."
},
"IOC-09": {
"title": "Se ha realizado una petición HTTP al dominio {} que es un DNS gratuito.",
"description": "El dominio {} está usando un servicio DNS gratuito. Este tipo de servicios es comúnmente utilizado por cibercriminales y otros actores de amenazas. Es altamente sospechoso que una aplicación ejecutándose en segundo plano use este tipo de servicios. Por favor investigue."
},
"IOC-10": {
"title": "Se ha realizado una petición HTTP al dominio {} que contiene un TLD sospechoso.",
"description": "El dominio {} está usando un dominio de primero nivel -TLD- ({}). Aunque no sea malicioso, este TLP no-genérico es usado por cibercriminales y otros actores de amenazas con regularidad. Verifique este dominio mediante su búsqueda en Internet. Si hay otras alertas relacionadas con este host, por favor considérelo como muy sospechoso."
},
"IOC-11": {
"title": "Conexión a {} ({}) a la que se hace referencia como un nodo TOR.",
"description": "El servidor {} es referenciado como un nodo en la red de anonimización TOR. El dispositivo analizado parece estar usando TOR o comunicándose con un servidor configurado como un nodo de entrada o salida de TOR. Algunos atacantes utilizan TOR en sus servidores para cubrir sus pistas."
},
"IOC-12": {
"title": "Una aplicación solicita un servicio legítimo que puede tener un doble uso .",
"description": "El servidor {} se utiliza para fines legítimos. Sin embargo, algunos atacantes pueden usarlo para interactuar con sus implantes. Se recomienda comprobar que el dispositivo analizado contiene una aplicación legítima que utiliza este servicio."
},
"IOC-13": {
"title": "Al menos una aplicación utiliza consultas DNS cifradas.",
"description": "El servidor DNS sobre HTTPs {} fue contactado durante la captura. Esto parece indicar que al menos una aplicación utiliza esta técnica para cifrar sus solicitudes de DNS. Esta característica limita las capacidades de escaneo de SpyGuard. Si esta función no está habilitada en el dispositivo analizado, puede valer la pena averiguar qué aplicación está utilizando este método."
},
"ACT-01": {
"title": "El dominio {} está usando un servidor de nombres sospechoso ({}).",
"description": "El nombre de dominio {} usa un servidor de nombres que ha sido explícitamente etiquetado como asociado a actividad maliciosa. Muchos ciberdelincuentes y otros actores de amenazas utilizan este tipo de registradores ya que aceptan criptomonedas y pagos anónimos. Se recomienda investigar este dominio y la aplicación en ejecución asociada mediante un análisis forense del dispositivo."
},
"ACT-02": {
"title": "El dominio {} se creó recientemente (hay {} días).",
"description": "El nombre de dominio {} es nuevo. Incluso esto no es intrínsecamente malicioso, es bastante común que los atacantes configuren una nueva infraestructura para cada campaña, lo que puede llevar al uso de nombres de dominio recién registrados."
},
"SSL-01": {
"title": "Conexión SSL realizada mediante un puerto no standard ({}) a {}",
"description": "Las conexiones SSL desde dispositivos móviles usando puertos no standard no son muy comunes. Aunque pudiera ser totalmente legítima, recomendamos verificar la reputación de {}, comprobando su registro WHOIS, su sistema autónomo asociado y su fecha de creación mediante su búsqueda en Internet."
},
"SSL-02": {
"title": "Conexión SSL a {} està usando un certificado gratuito",
"description": "Certificados gratuitos - como Let's Encrypt — son ampliamente utilizados por servidores de control asociados a software malicioso o webs de phishing. Recomendamos verificar el host asociado a esta certificado comprobando el nombre de dominio, su fecha de creación y verificando su reputación en Internet."
},
"SSL-03": {
"title": "El certificado asociado a {} es autofirmado.",
"description": "El uso de certificados autofirmados es un elemento común en infraestructuras utilizadas por atacantes. Recomendamos comprobar el host {} que está asociado a este certificado, especialmente su nombre de dominio (en caso de existir), su registro WHOIS, su fecha de creación y verificando su reputación en Internet."
},
"SSL-04": {
"title": "El certificado asociado con {} está vinculado a una actividad maliciosa ({}).",
"description": "El certificado asociado con server {} ha sido categorizado explícitamente como malicioso. Su dispositivo parece comprometido y necesita ser investigado por un equipo profesional."
},
"SSL-05": {
"title": "La configuración SSL de {} está vinculada a una actividad maliciosa ({}).",
"description": "El hash JARM relacionado con el servidor {} se ha asociado explícitamente con actividad maliciosa. Su dispositivo está posiblemente comprometido y necesita ser investigado por un equipo profesional."
},
"ADV-01": {
"title": "Compruebe las alertas para {}",
"description": "Por favor, verifique la reputación del host {}, ya que parece ser malicioso por aparecer en {} alertas durante la sesión."
},
"SNORT-01": {
"title": "Regla Suricata activada: {}",
"description": "Una regla de detección ha sido activada. Probablemente su dispositivo está comprometido o presenta comportamiento sospechoso."
}
},
"report": {
"numbers": [
"uno",
"dos",
"tres",
"cuatro",
"cinco",
"seis",
"siete",
"ocho",
"nueve"
],
"suspect_title": "Comunicaciones sospechosas",
"uncat_title": "Comunicaciones no categorizadas",
"whitelist_title": "Comunicaciones en lista blanca",
"protocol": "Protocolo",
"domain": "Dominio",
"dst_ip": "Dirección IP destino",
"dst_port": "Puerto destino número",
"device_mac": "Dirección MAC dispositivo",
"report_generated_on": "Informe generado en",
"capture_duration": "Duración captura",
"packets_number": "Número de paquetes",
"capture_sha1": "Captura SHA1",
"report_for_the_capture": "Informe de la captura",
"report_footer": "Este informe ha sido autogenerado por un dispositivo SpyGuard. Para cualquier pregunta, informe de fallos o feedback por favor contacte con contact@spyguard.io.",
"high_msg": "Su dispositivo parece estar comprometido ya que tiene {} alerta(s) de nivel alto.",
"moderate_msg": "Tienes {} alerta(s) de nivel moderado, su dispositivo podría estar comprometido. Por favor revíselas detenidamente.",
"low_msg": "Solamente tiene {} alertas(s) de nivel bajo, por favor revíselas.",
"none_msg": "Todo se ve bien, cero alertas. No dude en comprobar las comunicaciones no clasificadas (en caso de haberlas).",
"detection_methods": "Métodos de detección",
"analysis_duration": "Tiempo de análisis",
"instance_uuid": "Instancia de SpyGuard",
"seconds" : "segundo(s)"
}
}

147
analysis/locales/fr.json Executable file
View File

@ -0,0 +1,147 @@
{
"alerts": {
"PROTO-01": {
"title": "Une communication {} va à l'extérieur du réseau jusqu'à {}.",
"description": "Le protocole {} est généralement utilisé dans des réseaux internes. Vérifiez si le serveur {} a soulevé d'autres alertes. Ceci pourrait indiquer la présence d'une possible application malveillante."
},
"PROTO-02": {
"title": "Connexion {} vers {} sur un port au dessus ou égal à {}.",
"description": "Des connexions {} vers {} ont été vues utilisant le port {}. L'utilisation d'un numéro de port non standard peut être associé à des activités malveillantes. Nous recommandons de vérifier si ce serveur possède une bonne réputation en regardant les autres alertes et en le cherchant sur Internet."
},
"PROTO-03": {
"title": "Des communications HTTP ont été réalisées vers {}",
"description": "Votre appareil a communiqué avec le serveur {} en utilisant HTTP, un protocole non chiffré. Même si ce n'est pas malveillant en tant que tel, il est rare de voir des communications HTTP issues d'applications installées sur des smartphones exécutées en arrière plan. Il est conseillé de vérifier la réputation du serveur en le recherchant sur Internet."
},
"PROTO-04": {
"title": "Des communications HTTP ont été réalisées vers {} sur un port non standard ({}).",
"description": "Votre appareil a communiqué vers le serveur {} en utilisant HTTP, un protocole non chiffré sur le port {}. Ce type de communication peut être signe d'une activité malveillante sur votre appareil car il est très rare qu'HTTP utilise ce port. Il est conseillé de vérifier la réputation du serveur en le recherchant sur Internet."
},
"PROTO-05": {
"title": "Le serveur {} n'a pas été résolu par le protocole DNS durant la session",
"description": "Cela signifie que le serveur {} ne possède pas de nom de domaine associé ou que sa résolution a déjà été mise en cache par votre appareil. Si le serveur apparait dans d'autres alertes, merci de vérifier sa réputation."
},
"IOC-01": {
"title": "Connexion vers {} ({}) qui est tagué en tant que {}.",
"description": "Le serveur {} est connu pour être associé à des activités malveillantes. Votre appareil est surement compromis et doit être investigué plus en détails par une équipe professionnelle."
},
"IOC-02": {
"title": "Connexion vers {} appartenant au bloc réseau {} qui est tagué en tant que {}.",
"description": "Le serveur {} est hébergé dans un réseau qui est connu pour abriter des activités malveillantes. Même si ce n'est pas malveillant en tant que tel, vous devez regarder si d'autres alertes mentionnent ce serveur. Si vous avez certains doutes, recherchez sur Internet ce serveur pour savoir s'il semble être légitime ou non."
},
"IOC-03": {
"title": "Requête DNS vers le domaine {} qui est tagué en tant que {}.",
"description": "Le serveur {} vers lequel communique votre appareil a été explicitement catégorisé en tant que malveillant. Votre appareil est sûrement compromis et doit être investigué plus en détails par une équipe professionnelle."
},
"IOC-04": {
"title": "Requête DNS vers le domaine {} qui est tagué en tant que {}.",
"description": "Le nom de domaine {} vers lequel communique votre appareil a été explicitement catégorisé comme un tracker. Ceci indique d'une application active sur votre appareil est entrain de vous géo-localiser."
},
"IOC-05": {
"title": "Requête DNS vers le domaine {} qui est un domaine gratuit.",
"description": "Le nom de domaine {} utilise un service de noms de domaine gratuits. Ce type de service est couramment utilisé par les cybercriminels ou des acteurs associés à des États au cours de leurs opérations d'espionnage. Il est très suspect qu'une application exécutée en arrière-plan utilise ce type de service, veuillez enquêter."
},
"IOC-06": {
"title": "Requête DNS vers le domaine {} contenant une extension suspecte.",
"description": "Le nom de domaine {} utilise une extension suspecte ({}). Même si cela n'est pas malveillant en-soi, l'utilisation d'une extension non générique est l'apanage d'acteurs cybercriminels et étatiques durant leurs opérations. Veuillez vérifier la pertinance de ce domaine en le recherchant sur un moteur de recherche Internet. Si d'autres alertes sont liées à ce dernier, veuillez le considérer comme très suspect."
},
"IOC-07": {
"title": "Un certificat associé à des activités de {} a été vu lors de communications vers {}.",
"description": "Le certificat ({}) associé au serveur {} a été explicitement catégorisé comme malveillant. Votre appareil est sûrement compromis et doit être investigué plus en détails par une équipe professionnelle."
},
"IOC-08": {
"title": "Requête HTTP vers le domaine {} qui est tagué en tant que {}.",
"description": "Le serveur {} vers lequel communique votre appareil a été explicitement catégorisé en tant que malveillant. Votre appareil est sûrement compromis et doit être investigué plus en détails par une équipe professionnelle."
},
"IOC-09": {
"title": "Requête HTTP vers le domaine {} qui est un domaine gratuit.",
"description": "Le nom de domaine {} utilise un service de noms de domaine gratuits. Ce type de service est couramment utilisé par les cybercriminels ou des acteurs associés à des États au cours de leurs opérations d'espionnage. Il est très suspect qu'une application exécutée en arrière-plan utilise ce type de service, veuillez enquêter."
},
"IOC-10": {
"title": "Requête HTTP vers le domaine {} contenant une extension suspecte.",
"description": "Le nom de domaine {} utilise une extension suspecte ({}). Même si cela n'est pas malveillant en-soi, l'utilisation d'une extension non générique est l'apanage d'acteurs cybercriminels et étatiques durant leurs opérations. Veuillez vérifier la pertinance de ce domaine en le recherchant sur un moteur de recherche Internet. Si d'autres alertes sont liées à ce dernier, veuillez le considérer comme très suspect."
},
"IOC-11": {
"title": "Connexion vers {} ({}) qui est référencé en tant que noeud TOR.",
"description": "Le serveur {} est référencé en tant que noeud sur le réseau d'anonymisation TOR. Le dispositif analysé semble utiliser TOR ou communique avec un serveur configuré comme noeud d'entrée ou de sortie TOR. Certains attaquants utilisent TOR sur leurs serveurs afin de brouiller les pistes."
},
"IOC-12": {
"title": "Une application requête un service pouvant avoir un double emploi.",
"description": "Le serveur {} est utilisé à des fins légitimes. Toutefois, certains attaquants s'en servent pour intéragir avec leurs implants. Il est conseillé de vérifier que l'appareil analysé contient bien une application légitime utilisant ce service."
},
"IOC-13": {
"title": "Au moins une application utilise des requêtes DNS chiffrées",
"description": "Le résolveur de noms utilisant HTTPs {} a été contacté durant la capture. Ceci semble indiquer qu'au moins une application utilise cette technique permettant de chiffrer les requêtes DNS. Cette fonctionnalité limite les capacités d'analyse de SpyGuard. Si cette fonctionnalité n'est pas activée sur le dispositif analysé, il peut être intéressant de découvrir quelle application utilise cette méthode."
},
"ACT-01": {
"title": "Le domaine {} utilise un serveur de noms suspect ({}).",
"description": "Le nom de domaine {} utilise un serveur de noms qui a été explicitement catégorisé comme associé à des activités malveillantes. Plusieurs cybercriminels et acteurs étatiques utilisent ce type de serveurs de noms car ils autorisent les paiements anonymes grâce aux cryptomonnaies. Il est conseillé d'investiguer sur ce domaine et l'application s'y connectant en réalisant une analyse post-mortem de l'appareil analysé."
},
"ACT-02": {
"title": "Le domaine {} a été créé récemment (il y a {} jours).",
"description": "Le nom de domaine {} est nouveau. Même ce n'est pas malveillant en soi, il est assez courant pour les attaquants de mettre en place une nouvelle infrastructure pour chaque campagne, ce qui peut conduire à l'utilisation de noms de domaine récemment enregistrés."
},
"SSL-01": {
"title": "Connexion SSL utilisant un port non standard ({}) vers {}",
"description": "Il n'est pas commun de voir des connexions SSL issues de smartphones utiliser des ports non standards. Même si cela peut être totalement légitime, il est recommandé d'évaluer la réputation du serveur {}, en regardant son enregistrement WHOIS, son système autonome, sa date de création et en le recherchant sur Internet."
},
"SSL-02": {
"title": "Une connexion SSL vers {} utilise un certificat gratuit.",
"description": "Les certificats gratuits — tels que Let's Encrypt - sont largement utilisés par des serveurs de commande et de contrôle associés à des implants malveillants ou à des pages Web de phishing. Nous vous recommandons de vérifier le serveur associé à ce certificat, en regardant le nom de domaine, sa date de création, ou en vérifiant sa réputation sur Internet."
},
"SSL-03": {
"title": "Le certificat associé à {} est auto-signé.",
"description": "L'utilisation de certificats auto-signés est une chose courante pour des infrastructures d'attaque associées à des activités malveillantes. Nous vous recommandons de vérifier le serveur {} qui est associé à ce certificat, en regardant le nom de domaine (le cas échéant), son enregistrement WHOIS, sa date de création, et en vérifiant sa réputation sur Internet."
},
"SSL-04": {
"title": "Le certificat associé à {} est lié à des activités malveillantes ({}).",
"description": "Ce certificat associé au serveur {} a été explicitement catégorisé en tant que malveillant. Votre appareil est sûrement compromis et doit être investigué plus en détails par une équipe professionnelle."
},
"SSL-05": {
"title": "La configuration SSL de {} est associé à des activités malveillantes ({}).",
"description": "Le hash JARM lié au serveur {} a été explicitement associé à des activités malveillantes. Votre appareil est sûrement compromis et doit être investigué plus en détails par une équipe professionnelle."
},
"ADV-01": {
"title": "Vérifiez les alertes liées au serveur {}",
"description": "Merci de vérifier la réputation et les alertes liées au serveur {}, ce dernier semble malveillant, ayant engendré {} alertes durant la session de capture."
},
"SNORT-01": {
"title": "Règle suricata déclanchée : {}",
"description": "Une règle de détection de réseau a été déclenchée. Il est probable que votre appareil ait été compromis ou présente un comportement suspect."
}
},
"report": {
"numbers": [
"une",
"deux",
"trois",
"quatre",
"cinq",
"six",
"sept",
"huit",
"neuf"
],
"suspect_title": "Communications suspectes",
"uncat_title": "Communications non catégorisées",
"whitelist_title": "Communications légitimes",
"protocol": "Protocole",
"domain": "Domaine",
"dst_ip": "Adresse IP",
"dst_port": "Port",
"device_mac": "Adresse MAC de l'appareil",
"report_generated_on": "Rapport généré le ",
"capture_duration": "Durée de la capture",
"packets_number": "Nombre de paquets",
"capture_sha1": "SHA1 de la capture",
"report_for_the_capture": "Rapport pour la capture",
"report_footer": "Ce rapport a été automatiquement généré par une instance de SpyGuard. Pour toute question et retours, n'hésitez pas à contacter contact@spyguard.io.",
"high_msg": "Votre appareil semble être compromis car vous avez {} alerte(s) élevée(s).",
"moderate_msg": "Vous avez {} alerte(s) modérée(s), votre appareil peut être compromis. Regardez ces alertes en détail.",
"low_msg": "Vous avez uniquement {} alerte(s) faibles, n'hésitez pas à les consulter.",
"none_msg": "Toute semble normal, vous avez aucune alerte. Cependant, n'hésitez pas à regarder les communications non catégorisées.",
"detection_methods": "Méthodes de détection",
"analysis_duration": "Durée d'analyse",
"instance_uuid": "Instance de SpyGuard",
"seconds" : "seconde(s)"
}
}

147
analysis/locales/it.json Executable file
View File

@ -0,0 +1,147 @@
{
"alerts": {
"PROTO-01": {
"title": "{} comunicazione in uscita dalla rete locale a {}.",
"description": "Il protocollo {} è comunemente utilizzato nelle reti interne. Verificare se l'host {} ha sfruttato altri avvisi, fattore che potrebbe indicare un possibile comportamento dannoso."
},
"PROTO-02": {
"title": "{} connessione a {} tramite una porta superiore o uguale a {}.",
"description": "Sono state rilevate {} connessioni a {} tramite la porta {}. L'utilizzo di una porta non standard a volte può essere associato ad attività dannose. È consigliabile verificare se questo host ha una buona reputazione esaminando altri avvisi ed effettuando una ricerca in Internet."
},
"PROTO-03": {
"title": "Sono state generate comunicazioni HTTP dirette all'host {}",
"description": "Il dispositivo ha effettuato uno scambio con l'host {} utilizzando HTTP, un protocollo non criptato. Anche se questo comportamento non è dannoso in sé, è raro rilevare comunicazioni HTTP generate da applicazioni per smartphone in esecuzione in background. Controllare la reputazione dell'host effettuando una ricerca in Internet."
},
"PROTO-04": {
"title": "Sono state rilevate comunicazioni HTTP dirette all'host {} su una porta non standard ({}).",
"description": "Il dispositivo ha effettuato uno scambio con l'host {} utilizzando HTTP, un protocollo non criptato sulla porta {}. Questo comportamento è decisamente insolito. Controllare la reputazione dell'host effettuando una ricerca in Internet."
},
"PROTO-05": {
"title": "Il server {} non è stato risolto da nessuna query DNS durante la sessione",
"description": "Questo indica che il server {} probabilmente non è stato risolto da nessun nome di dominio o che la risoluzione è già stata memorizzata nella cache dal dispositivo. Se l'host viene visualizzato in altri avvisi, controllarlo."
},
"IOC-01": {
"title": "È stata stabilita una connessione a {} ({}) con contrassegno {}.",
"description": "L'host {} è stato esplicitamente inserito nella blacklist per attività dannose. Probabilmente il dispositivo è compromesso e deve essere esaminato più a fondo da professionisti della sicurezza IT."
},
"IOC-02": {
"title": "Comunicazione a {} con il CIDR {} con contrassegno {}.",
"description": "Il server {} è ospitato in una rete nota per l'hosting di attività dannose. Nonostante questo comportamento non sia dannoso in sé, è necessario verificare se l'host è menzionato anche in altri avvisi. In caso di dubbi, cercare l'host in Internet per scoprire se è legittimo o meno."
},
"IOC-03": {
"title": "È stata effettuata una richiesta DNS a {} con contrassegno {}.",
"description": "Il nome di dominio {} visualizzato nell'acquisizione è stato esplicitamente contrassegnato come dannoso. Questo indica che il dispositivo è potenzialmente compromesso e deve essere esaminato a fondo."
},
"IOC-04": {
"title": "È stata effettuata una richiesta DNS a {} con contrassegno {}.",
"description": "Il nome di dominio {} visualizzato nell'acquisizione è stato esplicitamente contrassegnato come Tracker. Questo indica che una delle app attive esegue la geolocalizzazione dei movimenti dell'utente."
},
"IOC-05": {
"title": "È stata effettuata una richiesta DNS al dominio {} che è un servizio Free DNS.",
"description": "Il nome di dominio {} utilizza un servizio Free DNS. Questo tipo di servizio è comunemente utilizzato durante le operazioni di criminali informatici o autori di attacchi commissionati da stati esteri. L'utilizzo di questo tipo di servizio da parte di un'applicazione in esecuzione in background è molto sospetto e richiede ulteriori indagini."
},
"IOC-06": {
"title": "È stata effettuata una richiesta DNS al dominio {} contenente un dominio di primo livello sospetto.",
"description": "Il nome di dominio {} utilizza un dominio di primo livello sospetto ({}). Anche se non dannoso, questo dominio di primo livello non generico viene utilizzato regolarmente durante le operazioni di criminali informatici o autori di attacchi commissionati da stati esteri. Controllare questo dominio effettuando una ricerca tramite un motore di ricerca Internet. Se altri avvisi sono correlati all'host, è necessario considerare questo elemento molto sospetto."
},
"IOC-07": {
"title": "Nella comunicazione a {} è stato rilevato un certificato associato ad attività {}.",
"description": "Il certificato ({}) associato a {} è stato esplicitamente contrassegnato come dannoso. Questo indica che il dispositivo è potenzialmente compromesso e necessita di un'analisi forense."
},
"IOC-08": {
"title": "È stata effettuata una richiesta HTTP a {} con contrassegno {}.",
"description": "Il nome di dominio {} visualizzato nell'acquisizione è stato esplicitamente contrassegnato come dannoso. Questo indica che il dispositivo è potenzialmente compromesso e deve essere esaminato a fondo."
},
"IOC-09": {
"title": "È stata effettuata una richiesta HTTP al dominio {} che è un servizio Free DNS.",
"description": "Il nome di dominio {} utilizza un servizio Free DNS. Questo tipo di servizio è comunemente utilizzato durante le operazioni di criminali informatici o autori di attacchi commissionati da stati esteri. L'utilizzo di questo tipo di servizio da parte di un'applicazione in esecuzione in background è molto sospetto e richiede ulteriori indagini."
},
"IOC-10": {
"title": "È stata effettuata una richiesta HTTP al dominio {} contenente un dominio di primo livello sospetto.",
"description": "Il nome di dominio {} utilizza un dominio di primo livello sospetto ({}). Anche se non dannoso, questo dominio di primo livello non generico viene utilizzato regolarmente durante le operazioni di criminali informatici o autori di attacchi commissionati da stati esteri. Controllare questo dominio effettuando una ricerca tramite un motore di ricerca Internet. Se altri avvisi sono correlati all'host, è necessario considerare questo elemento molto sospetto."
},
"IOC-11": {
"title": "Connessione a {} ({}) a cui si fa riferimento come nodo TOR.",
"description": "Il server {} è un nodo della rete di anonimizzazione TOR. Il dispositivo analizzato sembra utilizzare TOR o comunicare con un server configurato come un nodo di ingresso o di uscita TOR. Alcuni attaccanti usano TOR sui loro server per coprire le loro tracce."
},
"IOC-12": {
"title": "Un'applicazione richiede un servizio legittimo che può avere un doppio uso .",
"description": "Il server {} viene utilizzato per scopi legittimi. Tuttavia, alcuni attaccanti possono utilizzarlo per interagire con i loro impianti. Si consiglia di verificare che il dispositivo analizzato contenga un'applicazione legittima che utilizza questo servizio."
},
"IOC-13": {
"title": "Almeno un'applicazione utilizza query DNS crittografate.",
"description": "Il DNS sul server https {} è stato contattato durante la cattura. Questo sembra indicare che almeno un'applicazione utilizza questa tecnica per crittografare le sue richieste DNS. Questa funzione limita le capacità di scansione di SpyGuard. Se questa funzione non è abilitata sul dispositivo analizzato, può essere la pena scoprire quale applicazione sta utilizzando questo metodo."
},
"ACT-01": {
"title": "Il dominio {} utilizza un server dei nomi sospetto ({}).",
"description": "Il nome di dominio {} utilizza un server dei nomi che è stato esplicitamente contrassegnato come associato ad attività dannose. Molti criminali informatici e autori di attacchi commissionati da stati esteri utilizzano questo tipo di registrar poiché sono ammessi criptovalute e pagamenti anonimi. È consigliabile indagare su questo dominio e sull'applicazione in esecuzione associata eseguendo un'analisi forense del telefono."
},
"ACT-02": {
"title": "Il dominio {} è stato creato di recente ({} giorni fa)",
"description": "Il nome di dominio {} è nuovo. Anche questo non è intrinsecamente dannoso, è abbastanza comune per gli aggressori impostare una nuova infrastruttura per ogni campagna, che può portare all'uso di nomi di dominio appena registrati."
},
"SSL-01": {
"title": "Connessione SSL eseguita su una porta non standard ({}) a {}",
"description": "Non è comune rilevare connessioni SSL generate da smartphone tramite porte non standard. Anche se questo può essere del tutto legittimo, è consigliabile controllare la reputazione di {} prestando attenzione al record WHOIS, al sistema autonomo associato e alla data di creazione, nonché effettuando una ricerca in Internet."
},
"SSL-02": {
"title": "Una connessione SSL a {} utilizza un certificato gratuito.",
"description": "I certificati gratuiti, come Let's Encrypt, sono ampiamente utilizzati dai server di comando e controllo associati a insediamenti dannosi o pagine Web di phishing. È consigliabile controllare l'host associato a questo certificato, prestando attenzione al nome di dominio e alla data di creazione o verificandone la reputazione in Internet."
},
"SSL-03": {
"title": "Il certificato associato a {} è autofirmato.",
"description": "L'utilizzo di certificati autofirmati è una consuetudine per l'infrastruttura degli autori degli attacchi. È consigliabile controllare l'host {} associato a questo certificato, prestando attenzione all'eventuale nome di dominio, al record WHOIS e alla data di creazione, nonché verificandone la reputazione in Internet."
},
"SSL-04": {
"title": "Il certificato associato a {} è collegato ad attività dannose ({}).",
"description": "Il certificato associato al server {} è stato esplicitamente classificato come dannoso. Il dispositivo sembra compromesso e deve essere ulteriormente indagato da un team di professionisti."
},
"SSL-05": {
"title": "La configurazione SSL di {} è collegata ad attività dannose ({}).",
"description": "L'hash JARM relativo al server {} è stato esplicitamente associato ad attività dannose. Il dispositivo è probabilmente compromessa e deve essere ulteriormente indagato da un team di professionisti."
},
"ADV-01": {
"title": "Controllare gli avvisi per {}",
"description": "Controllare la reputazione dell'host {}, che sembra di natura dannosa poiché ha sfruttato {} avvisi durante la sessione."
},
"SNORT-01": {
"title": "Regola Suricata attivata: {}",
"description": "È stata attivata una regola di rilevamento della rete. È probabile che il dispositivo sia stato compromesso o che presenti comportamenti sospetti."
}
},
"report": {
"numbers": [
"uno",
"due",
"tre",
"quattro",
"cinque",
"sei",
"sette",
"otto",
"nove"
],
"suspect_title": "Comunicazioni sospette",
"uncat_title": "Comunicazioni non categorizzate",
"whitelist_title": "Comunicazioni inserite nella whitelist",
"protocol": "Protocollo",
"domain": "Dominio",
"dst_ip": "Indirizzo IP di destinazione",
"dst_port": "Numero della porta di destinazione",
"device_mac": "Indirizzo MAC dispositivo",
"report_generated_on": "Rapporto generato in data",
"capture_duration": "Durata acquisizione",
"packets_number": "Numero di pacchetti",
"capture_sha1": "SHA1 acquisizione",
"report_for_the_capture": "Rapporto relativo all'acquisizione",
"report_footer": "Questo rapporto è stato generato automaticamente da un dispositivo SpyGuard. Per eventuali domande, segnalazioni di bug o feedback, contattare contact@spyguard.io.",
"high_msg": "Sembra che il dispositivo sia compromesso poiché sono presenti {} avvisi con priorità elevata.",
"moderate_msg": "Sono presenti {} avvisi con priorità moderata, è possibile che il dispositivo sia compromesso. Esaminarli con attenzione.",
"low_msg": "Sono presenti solo {} avvisi con priorità bassa da controllare.",
"none_msg": "Sembra tutto a posto, non sono presenti avvisi. Controllare eventuali comunicazioni non categorizzate.",
"detection_methods": "Metodi di rilevamento",
"analysis_duration": "Tempo di analisi",
"instance_uuid": "Istanza di SpyGuard",
"seconds" : "secondi"
}
}

147
analysis/locales/pt.json Executable file
View File

@ -0,0 +1,147 @@
{
"alerts": {
"PROTO-01": {
"title": "Comunicação {} externa à rede local para {}.",
"description": "O protocolo {} é comumente usado em redes internas. Verifique se o host {} acionou outros alertas que possam indicar um possível comportamento malicioso."
},
"PROTO-02": {
"title": "Conexão {} a {} para uma porta maior ou igual a {}.",
"description": "Conexões {} foram detectadas por {} usando a porta {}. O uso da porta não padrão é comumente associado a atividades maliciosas. É recomendado verificar se esse host tem uma boa reputação verificando outros alertas e pesquisando-o na internet."
},
"PROTO-03": {
"title": "Comunicações HTTP foram realizadas com o host {}",
"description": "O dispositivo foi conectado ao host {} por meio de HTTP, um protocolo não criptografado. Mesmo que esse comportamento, por si só, não seja malicioso, é incomum que comunicações HTTP sejam estabelecidas por meio de aplicativos móveis em segundo plano. Verifique a reputação do host pesquisando-o na Internet."
},
"PROTO-04": {
"title": "Comunicações HTTP foram detectadas pelo host {} por meio de uma porta não padrão ({}).",
"description": "O dispositivo foi conectado ao host {} por meio de HTTP, um protocolo não criptografado na porta {}. Esse comportamento é incomum. Verifique a reputação do host pesquisando-o na Internet."
},
"PROTO-05": {
"title": "O servidor {} não foi resolvido por nenhuma consulta de DNS durante a sessão",
"description": "Isso significa provavelmente que o servidor {} não foi resolvido por nenhum nome de domínio ou a resolução já foi armazenada pelo dispositivo. Se o host aparecer em outros alertas, verifique-os."
},
"IOC-01": {
"title": "Uma conexão foi estabelecida com {} ({}) e marcada como {}.",
"description": "O host {} foi explicitamente bloqueado devido a atividades maliciosas. O dispositivo provavelmente foi comprometido e precisa ser analisado com cuidado por profissionais de segurança de TI."
},
"IOC-02": {
"title": "Comunicação com {} com o CIDR {} marcado como {}.",
"description": "O host {} está hospedado em uma rede que é conhecida por atividades maliciosas. Mesmo que o comportamento, por si só, não seja malicioso, é necessário verificar se outros alertas são gerados para esse host. Em caso de dúvidas, pesquise esse host na internet para verificar sua autenticidade."
},
"IOC-03": {
"title": "Uma solicitação de DNS foi feita para {}, marcado como {}.",
"description": "O nome de domínio {} visto na captura foi explicitamente marcado como malicioso. Isso indica que o dispositivo provavelmente foi comprometido e precisa ser analisado com cuidado."
},
"IOC-04": {
"title": "Uma solicitação de DNS foi feita para {}, marcado como {}.",
"description": "O nome de domínio {} visto na captura foi explicitamente marcado como um Tracker. Isso indica que um dos aplicativos ativos está rastreando sua localização."
},
"IOC-05": {
"title": "Uma solicitação de DNS foi feita para o domínio {}, que é um DNS gratuito.",
"description": "O nome de domínio {} está usando um serviço de DNS gratuito. Esse tipo de serviço é comumente usado por cibercriminosos ou agências de inteligência estatais no exercício de suas funções. É muito suspeito que aplicativos em execução em segundo plano usem esse tipo de serviço e isso deve ser analisado com cuidado."
},
"IOC-06": {
"title": "Uma solicitação de DNS foi feita para o domínio {}, que contém um TLD (domínio de nível superior) suspeito.",
"description": "O nome de domínio {} está usando um TLD suspeito ({}). Mesmo não sendo malicioso, esse TLD não genérico é frequentemente usado por cibercriminosos ou agências de inteligência estatais. Analise a reputação do domínio pesquisando-o na internet. Se outros alertas forem observados, considere esse host como muito suspeito."
},
"IOC-07": {
"title": "Um certificado associado a atividades de {} foi encontrado na comunicação para {}.",
"description": "O certificado ({}) associado a {} foi explicitamente marcado como malicioso. Isso indica que o dispositivo provavelmente foi comprometido e precisa de uma análise forense."
},
"IOC-08": {
"title": "Uma solicitação de HTTP foi feita para {}, marcado como {}.",
"description": "O nome de domínio {} visto na captura foi explicitamente marcado como malicioso. Isso indica que o dispositivo provavelmente foi comprometido e precisa ser analisado com cuidado."
},
"IOC-09": {
"title": "Uma solicitação de HTTP foi feita para o domínio {}, que é um DNS gratuito.",
"description": "O nome de domínio {} está usando um serviço de DNS gratuito. Esse tipo de serviço é comumente usado por cibercriminosos ou agências de inteligência estatais no exercício de suas funções. É muito suspeito que aplicativos em execução em segundo plano usem esse tipo de serviço e isso deve ser analisado com cuidado."
},
"IOC-10": {
"title": "Uma solicitação de HTTP foi feita para o domínio {}, que contém um TLD (domínio de nível superior) suspeito.",
"description": "O nome de domínio {} está usando um TLD suspeito ({}). Mesmo não sendo malicioso, esse TLD não genérico é frequentemente usado por cibercriminosos ou agências de inteligência estatais. Analise a reputação do domínio pesquisando-o na internet. Se outros alertas forem observados, considere esse host como muito suspeito."
},
"IOC-11": {
"title": "Conexão com {} ({}) que é referenciado como um nó TOR.",
"description": "O servidor {} é referenciado como um nó na rede de anonimização do TOR. O dispositivo analisado parece estar usando TOR ou se comunicando com um servidor configurado como um nó de entrada ou saída TOR. Alguns atacantes usam o TOR em seus servidores para cobrir seus rastros."
},
"IOC-12": {
"title": "Um aplicativo solicita um serviço legítimo que pode ter um uso duplo",
"description": "O servidor {} é usado para fins legítimos. Contudo, alguns atacantes podem usá- lo para interagir com os seus implantes. É aconselhável verificar se o dispositivo analisado contém um aplicativo legítimo que usa esse serviço."
},
"IOC-13": {
"title": "Pelo menos um aplicativo usa consultas DNS criptografadas.",
"description": "O servidor DNS over https {} foi contatado durante a captura. Isso parece indicar que pelo menos um aplicativo usa essa técnica para criptografar suas solicitações de DNS. Esse recurso limita os recursos de verificação do SpyGuard. Se esse recurso não estiver ativado no dispositivo analisado, pode valer a pena descobrir qual aplicativo está usando esse método."
},
"ACT-01": {
"title": "O domínio {} está usando um servidor de nomes suspeito ({}).",
"description": "O nome de domínio {} está usando um servidor de nomes explicitamente marcado como associado a atividades maliciosas. Muitos cibercriminosos e agentes de inteligência estatais usam esse tipo de registradores porque isso permite pagamentos com criptomoedas e anônimos. É recomendável investigar esse domínio e o aplicativo em execução por meio de uma análise forense do telefone."
},
"ACT-02": {
"title": "O domínio {} foi criado recentemente ({} dias atrás).",
"description": "O nome de domínio {} é novo. Mesmo que isso não seja intrinsecamente malicioso, é bastante comum que os invasores configurem uma nova infraestrutura para cada campanha, o que pode levar ao uso de nomes de domínio recém-registrados."
},
"SSL-01": {
"title": "Conexão SSL feita em uma porta não padrão ({}) para {}",
"description": "Não é comum ver conexões SSL a partir de dispositivos móveis usando portas não padrão. Mesmo que a conexão pareça ser autêntica, é recomendável analisar a reputação de {} verificando pesquisando na internet o registro de domínio, o sistema autônomo associado e a data de criação."
},
"SSL-02": {
"title": "Uma conexão SSL com {} está usando um certificado gratuito.",
"description": "Certificados gratuitos, como o Let's Encrypt, são amplamente usados por servidores de comando e controle associados a arquivos maliciosos ou páginas de phishing. É recomendável analisar o host associado a esse certificado verificando o nome de domínio, a data de criação ou pesquisando sua reputação na internet."
},
"SSL-03": {
"title": "O certificado associado a {} é autoassinado.",
"description": "O uso de certificados autoassinados é comum na infraestrutura de invasores. É recomendável analisar o host {} que está associado a esse certificado verificando o nome e o registro de domínio (se houver), a data de criação e sua reputação na internet."
},
"SSL-04": {
"title": "O certificado associado a {} está vinculado a atividades maliciosas ({}).",
"description": "O certificado associado ao servidor {} foi explicitamente categorizado como malicioso. Seu dispositivo parece comprometido e precisa ser investigado por uma equipe profissional."
},
"SSL-05": {
"title": "A configuração SSL de {} está ligada à atividade maliciosa ({}).",
"description": "O hash JARM {} relacionado ao servidor foi explicitamente associado à atividade maliciosa. Seu dispositivo está possivelmente comprometido e precisa ser investigado por uma equipe profissional."
},
"ADV-01": {
"title": "Verifique os alertas para {}",
"description": "Verifique a reputação do host {}, este parece ser malicioso, pois acionou alertas para {} durante a sessão."
},
"SNORT-01": {
"title": "Regra do Suricata acionada: {}",
"description": "Uma regra de detecção de rede foi acionada. É provável que o dispositivo tenha sido comprometido ou apresente comportamento suspeito."
}
},
"report": {
"numbers": [
"um",
"dois",
"três",
"quatro",
"cinco",
"seis",
"sete",
"oito",
"nove"
],
"suspect_title": "Comunicações suspeitas",
"uncat_title": "Comunicações não categorizadas",
"whitelist_title": "Comunicações permitidas",
"protocol": "Protocolo",
"domain": "Domínio",
"dst_ip": "Endereço IP do dst",
"dst_port": "Número da porta do dst",
"device_mac": "Endereço MAC do dispositivo",
"report_generated_on": "Relatório criado em",
"capture_duration": "Duração da captura",
"packets_number": "Número de pacotes",
"capture_sha1": "Captura SHA1",
"report_for_the_capture": "Relatório da captura",
"report_footer": "Este relatório foi gerado automaticamente por um dispositivo SpyGuard. Em caso de dúvidas, relatório de erros ou comentários, envie uma mensagem para contact@spyguard.io.",
"high_msg": "O dispositivo parece estar comprometido porque você tem {} alerta(s) crítico(s).",
"moderate_msg": "Você tem {} alerta(s) moderado(s), seu dispositivo pode estar comprometido. Analise-os com cuidado.",
"low_msg": "Você tem apenas {} alerta(s) leve(s), não deixe de verificá-los.",
"none_msg": "Tudo parece estar bem, zero alertas. Não deixe de verificar comunicações não categorizadas, se houver.",
"detection_methods": "Métodos de detecção",
"analysis_duration": "Tempo de análise",
"instance_uuid": "Instância do SpyGuard",
"seconds": "segunda(s)"
}
}

147
analysis/locales/ru.json Executable file
View File

@ -0,0 +1,147 @@
{
"alerts": {
"PROTO-01": {
"title": "Обнаружено подключение {}, ведущее за пределы локальной сети к {}.",
"description": "Протокол {} обычно используется во внутренних сетях. Проверьте, выдавало ли устройство {} другие предупреждения, которые могут свидетельствовать о вредоносной активности."
},
"PROTO-02": {
"title": "Подключение {} к {} установлено на порте, равном или более {}.",
"description": "Обнаружено {} подключений к {} с использованием порта {}. Использование нестандартного порта иногда может свидетельствовать о вредоносной активности. Рекомендуется проверить репутацию этого устройства, просмотрев другие предупреждения и выполнив их поиск в интернете."
},
"PROTO-03": {
"title": "Установлено HTTP-подключение к устройству {}",
"description": "Ваше устройство обменивается данными с устройством {} по незашифрованному протоколу HTTP. Даже если такое поведение само по себе не является вредоносным, фоновое исходящее HTTP-подключение является нетипичным для приложений, работающих на смартфоне в фоновом режиме. Проверьте репутацию устройства, выполнив поиск в интернете."
},
"PROTO-04": {
"title": "Установлено HTTP-подключение к устройству {} через нестандартный порт ({}).",
"description": "Ваше устройство обменивается данными с устройством {} по незашифрованному протоколу HTTP через порт {}. Такое поведение является нетипичным. Проверьте репутацию устройства, выполнив поиск в интернете."
},
"PROTO-05": {
"title": "Сервер {} не разрешался никакими DNS-запросами во время сеанса",
"description": "Это, вероятно, означает, что сервер {} не разрешен ни одним доменным именем или разрешение уже кешировано устройством. Если устройство фигурирует в других предупреждениях, проверьте его."
},
"IOC-01": {
"title": "Установлено соединение с {} ({}), отмеченным как {}.",
"description": "Устройство {} было явно занесено в черный список за выполнение вредоносных действий. Ваше устройство, вероятно, взломано. Требуется более тщательное расследование специалистами по IT-безопасности."
},
"IOC-02": {
"title": "Подключение к {}, отмеченному как {}, в рамках бесклассовой адресации {}.",
"description": "Сервер {} размещен в сети, в которой размещаются объекты, выполняющие вредоносные действия. Даже если такое поведение само по себе не является вредоносным, необходимо проверить, не упоминается ли это устройство в других предупреждениях. При наличии сомнений выполните поиск этого устройства в интернете и выясните, является ли его поведение легитимным."
},
"IOC-03": {
"title": "Выполнен DNS-запрос к {}, отмеченному как {}.",
"description": "Доменное имя {}, обнаруженное при сборе данных, явно отмечено как вредоносное. Это указывает на то, что ваше устройство, вероятно, взломано и требуется тщательное расследование."
},
"IOC-04": {
"title": "Выполнен DNS-запрос к {}, отмеченному как {}.",
"description": "Доменное имя {}, обнаруженное при сборе данных, явно отмечено как геотрекер. Это указывает, что одно из активных приложений отслеживает ваши перемещения."
},
"IOC-05": {
"title": "Выполнен DNS-запрос к домену {}, использующему бесплатную службу DNS.",
"description": "Доменное имя {} использует бесплатную службу DNS. Такие службы обычно используются киберпреступниками или спонсируемыми государством злоумышленниками для атак. Очень подозрительно, что приложение, работающее в фоновом режиме, использует такую службу. Требуется расследование."
},
"IOC-06": {
"title": "Выполнен DNS-запрос к домену {}, содержащему подозрительный домен верхнего уровня.",
"description": "Доменное имя {} использует подозрительный домен верхнего уровня ({}). Даже не являясь вредоносным, этот не универсальный домен верхнего уровня регулярно используется киберпреступниками или спонсируемыми государством злоумышленниками. Проверьте этот домен, выполнив поиск в интернете. Если с этим устройством связаны другие предупреждения, это очень подозрительно."
},
"IOC-07": {
"title": "Сертификат, связанный с действиями {}, был обнаружен при взаимодействии с {}.",
"description": "Сертификат ({}), связанный с {}, явно отмечен как вредоносный. Это указывает на то, что ваше устройство, вероятно, взломано и требуется провести экспертный анализ."
},
"IOC-08": {
"title": "Выполнен HTTP-запрос к {}, отмеченному как {}.",
"description": "Доменное имя {}, обнаруженное при сборе данных, явно отмечено как вредоносное. Это указывает на то, что ваше устройство, вероятно, взломано и требуется тщательное расследование."
},
"IOC-09": {
"title": "Выполнен HTTP-запрос к домену {}, использующему бесплатную службу DNS.",
"description": "Доменное имя {} использует бесплатную службу DNS. Такие службы обычно используются киберпреступниками или спонсируемыми государством злоумышленниками для атак. Очень подозрительно, что приложение, работающее в фоновом режиме, использует такую службу. Требуется расследование."
},
"IOC-10": {
"title": "Выполнен HTTP-запрос к домену {}, содержащему подозрительный домен верхнего уровня.",
"description": "Доменное имя {} использует подозрительный домен верхнего уровня ({}). Даже не являясь вредоносным, этот не универсальный домен верхнего уровня регулярно используется киберпреступниками или спонсируемыми государством злоумышленниками. Проверьте этот домен, выполнив поиск в интернете. Если с этим устройством связаны другие предупреждения, это очень подозрительно."
},
"IOC-11": {
"title": "Соединение с {} ({}), которое упоминается как узел TOR.",
"description": "На сервер {} ссылаются как на узел в сети анонимизации TOR. Анализируемое устройство, по-видимому, использует TOR или взаимодействует с сервером, настроенным как входной или выходной узел TOR. Некоторые злоумышленники используют TOR на своих серверах, чтобы замести следы."
},
"IOC-12": {
"title": "заявка запрашивает законную услугу, которая может иметь двойное назначение .",
"description": "Сервер {} используется в законных целях. Однако некоторые злоумышленники могут использовать его для взаимодействия со своими имплантатами. Рекомендуется проверить, что анализируемое устройство содержит законное приложение, которое использует эту службу."
},
"IOC-13": {
"title": "По крайней мере одно приложение использует зашифрованные DNS запросы",
"description": "Во время захвата был установлен контакт с DNS через сервер HTPs {}. Это, кажется, указывает на то, что по крайней мере одно приложение использует эту технику для шифрования своих DNS-запросов. Эта функция ограничивает возможности сканирования SpyGuard. Если эта функция не включена на анализируемом устройстве, возможно, стоит выяснить, какое приложение использует этот метод."
},
"ACT-01": {
"title": "Домен {} использует подозрительный сервер имен ({}).",
"description": "Доменное имя {} использует сервер имен, который явно отмечен как связанный с вредоносными действиями. Многие киберпреступники и спонсируемые государством злоумышленники пользуются такими регистраторами, поскольку они позволяют использовать криптовалюту и анонимные платежи. Рекомендуется исследовать этот домен и связанные с ним работающие приложения, выполнив экспертный анализ телефона."
},
"ACT-02": {
"title": "Домен {} был создан недавно ({} дней назад).",
"description": "Доменное имя {} новое. Даже это не является вредоносным по своей сути, злоумышленники довольно часто создают новую инфраструктуру для каждой кампании атаки, что может привести к использованию недавно зарегистрированных доменных имен."
},
"SSL-01": {
"title": "SSL-подключение к {} выполнено через нестандартный порт ({})",
"description": "SSL-подключение со смартфонов с использованием нестандартных портов является нетипичным. Даже если это действие является абсолютно легитимным, рекомендуется проверить репутацию {}, просмотрев его запись WHOIS, связанную автономную систему, дату создания, а также выполнив поиск в интернете."
},
"SSL-02": {
"title": "SSL-подключение к {} использует бесплатный сертификат.",
"description": "Бесплатные сертификаты, такие как Let's Encrypt, широко используются командными серверами, связанными со встраиваемым вредоносным кодом или фишинговыми веб-страницами. Рекомендуется проверить устройство, связанное с этим сертификатом, изучив его доменное имя, дату создания и репутацию в интернете."
},
"SSL-03": {
"title": "Сертификат, связанный с {}, является самоподписанным.",
"description": "Использование самоподписанных сертификатов типично для инфраструктуры злоумышленников. Рекомендуется проверить устройство {}, связанное с этим сертификатом, изучив его доменное имя (если имеется), запись WHOIS, дату создания и репутацию в интернете."
},
"SSL-04": {
"title": "Сертификат, связанный с {} связан с вредоносной деятельностью ({})",
"description": "Сертификат, связанный с сервером {} был явно классифицирован как вредоносный. Ваше устройство выглядит скомпрометированным и нуждается в дальнейшем исследовании профессиональной командой."
},
"SSL-05": {
"title": "Конфигурация SSL {} связана с вредоносной деятельностью ({}).",
"description": "Связанный с сервером хэш JARM {} был явно связан с вредоносной деятельностью. Ваше устройство, возможно, скомпрометировано и нуждается в дальнейшем расследовании профессиональной командой."
},
"ADV-01": {
"title": "Проверьте предупреждения для {}",
"description": "Проверьте репутацию устройства {}. Оно кажется вредоносным, поскольку для него сработало {} предупрежд. во время сеанса."
},
"SNORT-01": {
"title": "Сработало правило Suricata: {}",
"description": "Сработало правило обнаружения в сети. Вероятно, ваше устройство взломано или ведет себя подозрительно."
}
},
"report": {
"numbers": [
"один",
"два",
"три",
"четыре",
"пять",
"шесть",
"семь",
"восемь",
"девять"
],
"suspect_title": "Подозрительные подключения",
"uncat_title": "Неклассифицированные подключения",
"whitelist_title": "Разрешенные подключения",
"protocol": "Протокол",
"domain": "Домен",
"dst_ip": "IP-адрес назначения",
"dst_port": "Номер порта назначения",
"device_mac": "MAC-адрес устройства",
"report_generated_on": "Дата формирования отчета",
"capture_duration": "Продолжительность сбора данных",
"packets_number": "Количество пакетов",
"capture_sha1": "Сбор данных SHA1",
"report_for_the_capture": "Отчет для сбора данных",
"report_footer": "Этот отчет был автоматически сформирован устройством SpyGuard. С любыми вопросами, сообщениями об ошибках или отзывами обращайтесь по адресу contact@spyguard.io.",
"high_msg": "Вероятно, ваше устройство взломано, поскольку у вас {} предупрежд. высокого уровня.",
"moderate_msg": "У вас {} предупрежд. среднего уровня. Возможно, ваше устройство взломано. Внимательно изучите их.",
"low_msg": "У вас {} предупрежд. низкого уровня, проверьте их.",
"none_msg": "Предупреждения отсутствуют, система выглядит защищенной. Не забывайте проверять неклассифицированные подключения, если они имеются.",
"detection_methods": "Mетоды обнаружения",
"analysis_duration": "Время анализа",
"instance_uuid": "SpyGuard Экземпляр",
"seconds": "секунды"
}
}

74
analysis/utils.py Executable file
View File

@ -0,0 +1,74 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sqlite3
import datetime
import yaml
import sys
import json
import os
from functools import reduce
# I'm not going to use an ORM for that.
parent = os.path.split(os.path.dirname(os.path.abspath(sys.argv[0])))[0]
conn = sqlite3.connect(os.path.join(parent, "database.sqlite3"))
cursor = conn.cursor()
def get_iocs(ioc_type):
"""
Get a list of IOCs specified by their type.
:return: list of IOCs
"""
cursor.execute(
"SELECT value, tag FROM iocs WHERE type = ? ORDER BY value", (ioc_type,))
res = cursor.fetchall()
return [[r[0], r[1]] for r in res] if res is not None else []
def get_whitelist(elem_type):
"""
Get a list of whitelisted elements specified by their type.
:return: list of elements
"""
cursor.execute(
"SELECT element FROM whitelist WHERE type = ? ORDER BY element", (elem_type,))
res = cursor.fetchall()
return [r[0] for r in res] if res is not None else []
def get_config(path):
"""
Read a value from the configuration
:return: value (it can be any type)
"""
config = yaml.load(open(os.path.join(parent, "config.yaml"),
"r"), Loader=yaml.SafeLoader)
return reduce(dict.get, path, config)
def get_device(token):
"""
Read the device configuration from device.json file.
:return: dict - the device configuration
"""
try:
with open("/tmp/{}/device.json".format(token), "r") as f:
return json.load(f)
except:
pass
def get_apname():
"""
Read the current name of the Access Point from
the hostapd configuration file
:return: str - the AP name
"""
try:
with open("/tmp/hostapd.conf", "r") as f:
for l in f.readlines():
if "ssid=" in l:
return l.replace("ssid=", "").strip()
except:
pass

105
app/.gitignore vendored Executable file
View File

@ -0,0 +1,105 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port

1
app/backend/.npmrc Executable file
View File

@ -0,0 +1 @@
timeout=60000

5
app/backend/babel.config.js Executable file
View File

@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

5
app/backend/dist/css/app.b563f628.css vendored Normal file

File diff suppressed because one or more lines are too long

BIN
app/backend/dist/favicon.ico vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
app/backend/dist/fonts/Exo.73922868.ttf vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 805 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

1
app/backend/dist/index.html vendored Normal file
View File

@ -0,0 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>@felixaime/spyguard-backend</title><link href="/js/chunk-2d0a3726.bebe5116.js" rel="prefetch"><link href="/js/chunk-2d0c0c86.cf098d4b.js" rel="prefetch"><link href="/js/chunk-2d0c8321.78ca1407.js" rel="prefetch"><link href="/js/chunk-2d0c9378.fb16a6a2.js" rel="prefetch"><link href="/js/chunk-2d0cc2b4.6cd43049.js" rel="prefetch"><link href="/js/chunk-2d0cfa15.4b2166d6.js" rel="prefetch"><link href="/js/chunk-2d0e4bf5.fac73388.js" rel="prefetch"><link href="/js/chunk-2d20faf8.c983e105.js" rel="prefetch"><link href="/js/chunk-2d215cd3.f0d8ba06.js" rel="prefetch"><link href="/js/chunk-2d2245cf.ea4d33bd.js" rel="prefetch"><link href="/js/chunk-2d22d432.91ebbe55.js" rel="prefetch"><link href="/js/chunk-3c0d118e.e3f2944c.js" rel="prefetch"><link href="/css/app.b563f628.css" rel="preload" as="style"><link href="/js/app.a3c6f292.js" rel="preload" as="script"><link href="/js/chunk-vendors.dbaccf43.js" rel="preload" as="script"><link href="/css/app.b563f628.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but @felixaime/spyguard-backend doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/js/chunk-vendors.dbaccf43.js"></script><script src="/js/app.a3c6f292.js"></script></body></html>

2
app/backend/dist/js/app.a3c6f292.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0a3726"],{"01e4":function(e,t,n){"use strict";n.r(t);var a=function(){var e=this,t=e._self._c;return t("div",{staticClass:"backend-content",attrs:{id:"content"}},[t("div",{staticClass:"column col-8 col-xs-12"},[t("br"),t("p",[t("strong",[e._v("A new SpyGuard version is available ("+e._s(e.next_version)+").")]),t("br"),e.update_launched?e._e():t("span",[e._v("Please click on the button below to update your instance.")]),e.update_launched&&!e.update_finished?t("span",[e._v("Updating SpyGuard, please wait. You'll be redirected once updated.")]):e._e(),e.update_launched&&e.update_finished?t("span",{staticClass:"color-green"},[e._v("✓ Update finished!")]):e._e()]),e.update_finished?e._e():t("button",{staticClass:"btn btn-primary",class:[e.update_launched?"loading":""],on:{click:function(t){return e.launch_update()}}},[e._v("Update Spyguard")])])])},s=[],i=n("bc3a"),o=n.n(i),c={name:"update",data(){return{translation:{},update_launched:null,check_interval:null,next_version:null,current_version:null,update_finished:!1,jwt:""}},methods:{check_version:function(){o.a.get("/api/update/get-version",{timeout:6e4,headers:{"X-Token":this.jwt}}).then(e=>{e.data.status&&e.data.current_version==this.next_version&&(window.current_version=e.data.current_version,this.update_finished=!0,clearInterval(this.check_interval),setTimeout((function(){window.location.href="/"}),3e3))}).catch(e=>{console.log(e)})},launch_update:function(){o.a.get("/api/update/process",{timeout:6e4,headers:{"X-Token":this.jwt}}).then(e=>{e.data.status&&"Update successfully launched"==e.data.message&&(this.update_launched=!0,this.check_interval=setInterval(function(){this.check_version()}.bind(this),3e3))}).catch(e=>{console.log(e)})},async get_jwt(){await o.a.get("/api/get-token",{timeout:1e4}).then(e=>{e.data.token&&(this.jwt=e.data.token)}).catch(e=>console.log(e))},get_versions:function(){o.a.get("/api/update/check",{timeout:6e4,headers:{"X-Token":this.jwt}}).then(e=>{e.data.status&&(this.current_version=e.data.current_version,this.next_version=e.data.next_version,this.current_version==this.next_version&&(window.location.href="/"))}).catch(e=>{console.log(e)})}},created:function(){this.get_jwt().then(()=>{this.get_versions()})}},u=c,r=n("2877"),d=Object(r["a"])(u,a,s,!1,null,null,null);t["default"]=d.exports}}]);
//# sourceMappingURL=chunk-2d0a3726.bebe5116.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0cc2b4"],{"4d7e":function(t,s,e){"use strict";e.r(s);var a=function(){var t=this,s=t._self._c;return s("div",{staticClass:"backend-content",attrs:{id:"content"}},[s("div",{staticClass:"column col-12 col-xs-12"},[s("h3",{staticClass:"s-title"},[t._v("Search IOCs")]),s("div",{staticClass:"form-group"},[s("textarea",{directives:[{name:"model",rawName:"v-model",value:t.iocs,expression:"iocs"}],staticClass:"form-input",attrs:{id:"input-example-3",placeholder:"Paste your IOCs here",rows:"3"},domProps:{value:t.iocs},on:{input:function(s){s.target.composing||(t.iocs=s.target.value)}}})]),s("div",{staticClass:"form-group"},[s("button",{staticClass:"btn btn-primary col-12",on:{click:function(s){return t.search_iocs()}}},[t._v("Search")])]),t.results.length>0?s("div",{staticClass:"form-group"},[s("table",{staticClass:"table table-striped table-hover"},[t._m(0),s("tbody",t._l(t.results,(function(e){return s("tr",{key:e.tlp},[s("td",[t._v(t._s(e.value))]),s("td",{staticClass:"upper"},[t._v(t._s(e.tag))]),s("td",[s("label",{class:["tlp-"+e.tlp]},[t._v(t._s(e.tlp))])]),s("td",{staticClass:"capi"},[t._v(t._s(e.source))]),s("td",[s("button",{staticClass:"btn btn-sm",on:{click:function(s){return t.remove(e)}}},[t._v("Delete")])])])})),0)])]):0==t.first_search?s("div",[t.loading?s("div",[t._m(1)]):s("div",[s("div",{staticClass:"empty"},[s("p",{staticClass:"empty-title h5"},[t._v("IOC"),this.iocs.match(/[^\r\n]+/g).length>1?s("span",[t._v("s")]):t._e(),t._v(" not found.")]),s("p",{staticClass:"empty-subtitle"},[t._v("Try wildcard search to expend your search.")])])])]):t._e()])])},i=[function(){var t=this,s=t._self._c;return s("thead",[s("tr",[s("th",[t._v("Indicator")]),s("th",[t._v("Tag")]),s("th",[t._v("TLP")]),s("th",[t._v("Source")]),s("th",[t._v("Action")])])])},function(){var t=this,s=t._self._c;return s("div",{staticClass:"empty"},[s("p",{staticClass:"empty-title h5"},[s("span",{staticClass:"loading loading-lg"})]),s("p",{staticClass:"empty-subtitle"},[t._v("Finding your IOC(s)...")])])}],c=e("bc3a"),o=e.n(c),n={name:"iocs-search",data(){return{results:[],first_search:!0,jwt:"",loading:!1}},props:{},methods:{search_iocs:function(){return this.results=[],this.first_search=!1,this.loading=!0,this.iocs.match(/[^\r\n]+/g).forEach(t=>{t=t.trim(),"alert "!=t.slice(0,6)&&(t=t.replace(" ",""),t=t.replace("[",""),t=t.replace("]",""),t=t.replace("\\",""),t=t.replace("(",""),t=t.replace(")","")),o.a.get("/api/ioc/search/"+t,{timeout:1e4,headers:{"X-Token":this.jwt}}).then(t=>{t.data.results.length>0&&(this.results=[].concat(this.results,t.data.results)),this.loading=!1}).catch(t=>console.log(t))}),!0},remove:function(t){o.a.get("/api/ioc/delete/"+t.id,{timeout:1e4,headers:{"X-Token":this.jwt}}).then(s=>{s.data.status&&(this.results=this.results.filter((function(s){return s!=t})))}).catch(t=>console.log(t))},load_config:function(){o.a.get("/api/config/list",{timeout:1e4,headers:{"X-Token":this.jwt}}).then(t=>{t.data&&(this.config=t.data)}).catch(t=>console.log(t))},async get_jwt(){await o.a.get("/api/get-token",{timeout:1e4}).then(t=>{t.data.token&&(this.jwt=t.data.token)}).catch(t=>console.log(t))}},created:function(){this.get_jwt()}},l=n,r=e("2877"),u=Object(r["a"])(l,a,i,!1,null,null,null);s["default"]=u.exports}}]);
//# sourceMappingURL=chunk-2d0cc2b4.6cd43049.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0cfa15"],{6511:function(t,s,e){"use strict";e.r(s);var a=function(){var t=this;t._self._c;return t._m(0)},i=[function(){var t=this,s=t._self._c;return s("div",{staticClass:"backend-content",attrs:{id:"content"}},[s("div",{staticClass:"column col-8 col-xs-12"},[s("div",{staticClass:"container"},[s("h3",{staticClass:"s-title"},[t._v("Getting started")]),s("br"),s("p",[t._v("SpyGuard is a forked and enhanced version of TinyCheck, an application developed by Kaspersky. SpyGuard's main objective is to detect signs of compromise by monitoring network flows transmitted by a device.")]),s("p",[t._v("As it uses WiFi, SpyGuard can be used against a wide range of devices, such as smartphones, laptops, IOTs or workstations. To do its job, the analysis engine of SpyGuard is using Indicators of Compromise (IOCs), anomaly detection and is supported by Suricata. ")]),s("p",[t._v("This backend lets you configure your SpyGuard instance. You can push some IOCs for detection and whitelist elements which can be seen during legit communications in order to prevent false positives.")]),s("p",[t._v("_")])]),s("div",{staticClass:"backend-footer container grid-lg",attrs:{id:"copyright"}},[s("p",[t._v("For any question, bug report or feedback, please contact the "),s("a",{attrs:{href:"mailto:spyguard@protonmail.com",target:"_blank"}},[t._v("SpyGuard's Team")]),t._v(" or open an issue on the "),s("a",{attrs:{href:"https://github.com/SpyGuard/spyguard/issues",target:"_blank"}},[t._v("SpyGuard Github repository")]),t._v(".")])])])])}],n=e("2877"),o={},r=Object(n["a"])(o,a,i,!1,null,null,null);s["default"]=r.exports}}]);
//# sourceMappingURL=chunk-2d0cfa15.4b2166d6.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["webpack:///./src/views/home.vue","webpack:///./src/views/home.vue?46ae"],"names":["render","_vm","this","_self","_c","_m","staticRenderFns","staticClass","attrs","_v","script","component"],"mappings":"uHAAA,IAAIA,EAAS,WAAkB,IAAIC,EAAIC,KAAQD,EAAIE,MAAMC,GAAG,OAAOH,EAAII,GAAG,IAEtEC,EAAkB,CAAC,WAAY,IAAIL,EAAIC,KAAKE,EAAGH,EAAIE,MAAMC,GAAG,OAAOA,EAAG,MAAM,CAACG,YAAY,kBAAkBC,MAAM,CAAC,GAAK,YAAY,CAACJ,EAAG,MAAM,CAACG,YAAY,0BAA0B,CAACH,EAAG,MAAM,CAACG,YAAY,aAAa,CAACH,EAAG,KAAK,CAACG,YAAY,WAAW,CAACN,EAAIQ,GAAG,qBAAqBL,EAAG,MAAMA,EAAG,IAAI,CAACH,EAAIQ,GAAG,oNAAoNL,EAAG,IAAI,CAACH,EAAIQ,GAAG,0QAA0QL,EAAG,IAAI,CAACH,EAAIQ,GAAG,4MAA4ML,EAAG,IAAI,CAACH,EAAIQ,GAAG,SAASL,EAAG,MAAM,CAACG,YAAY,mCAAmCC,MAAM,CAAC,GAAK,cAAc,CAACJ,EAAG,IAAI,CAACH,EAAIQ,GAAG,iEAAiEL,EAAG,IAAI,CAACI,MAAM,CAAC,KAAO,iCAAiC,OAAS,WAAW,CAACP,EAAIQ,GAAG,qBAAqBR,EAAIQ,GAAG,6BAA6BL,EAAG,IAAI,CAACI,MAAM,CAAC,KAAO,8CAA8C,OAAS,WAAW,CAACP,EAAIQ,GAAG,gCAAgCR,EAAIQ,GAAG,e,YCDr8CC,EAAS,GAKTC,EAAY,eACdD,EACAV,EACAM,GACA,EACA,KACA,KACA,MAIa,aAAAK,E","file":"js/chunk-2d0cfa15.4b2166d6.js","sourcesContent":["var render = function render(){var _vm=this,_c=_vm._self._c;return _vm._m(0)\n}\nvar staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"backend-content\",attrs:{\"id\":\"content\"}},[_c('div',{staticClass:\"column col-8 col-xs-12\"},[_c('div',{staticClass:\"container\"},[_c('h3',{staticClass:\"s-title\"},[_vm._v(\"Getting started\")]),_c('br'),_c('p',[_vm._v(\"SpyGuard is a forked and enhanced version of TinyCheck, an application developed by Kaspersky. SpyGuard's main objective is to detect signs of compromise by monitoring network flows transmitted by a device.\")]),_c('p',[_vm._v(\"As it uses WiFi, SpyGuard can be used against a wide range of devices, such as smartphones, laptops, IOTs or workstations. To do its job, the analysis engine of SpyGuard is using Indicators of Compromise (IOCs), anomaly detection and is supported by Suricata. \")]),_c('p',[_vm._v(\"This backend lets you configure your SpyGuard instance. You can push some IOCs for detection and whitelist elements which can be seen during legit communications in order to prevent false positives.\")]),_c('p',[_vm._v(\"_\")])]),_c('div',{staticClass:\"backend-footer container grid-lg\",attrs:{\"id\":\"copyright\"}},[_c('p',[_vm._v(\"For any question, bug report or feedback, please contact the \"),_c('a',{attrs:{\"href\":\"mailto:spyguard@protonmail.com\",\"target\":\"_blank\"}},[_vm._v(\"SpyGuard's Team\")]),_vm._v(\" or open an issue on the \"),_c('a',{attrs:{\"href\":\"https://github.com/SpyGuard/spyguard/issues\",\"target\":\"_blank\"}},[_vm._v(\"SpyGuard Github repository\")]),_vm._v(\".\")])])])])\n}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./home.vue?vue&type=template&id=34abb80e&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""}

View File

@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0e4bf5"],{9217:function(t,a,e){"use strict";e.r(a);var s=function(){var t=this,a=t._self._c;return a("div",{staticClass:"backend-content",attrs:{id:"content"}},[a("div",{staticClass:"column col-8 col-xs-12"},[a("h3",{staticClass:"s-title"},[t._v("Manage database")]),a("ul",{staticClass:"tab tab-block"},[a("li",{staticClass:"tab-item"},[a("a",{class:{active:t.tabs.import},attrs:{href:"#"},on:{click:function(a){return t.switch_tab("import")}}},[t._v("Import database")])]),a("li",{staticClass:"tab-item"},[a("a",{class:{active:t.tabs.export},attrs:{href:"#"},on:{click:function(a){return t.switch_tab("export")}}},[t._v("Export database")])])]),t.tabs.export?a("div",[a("iframe",{staticClass:"frame-export",attrs:{src:t.export_url}})]):t._e(),t.tabs.import?a("div",[a("label",{staticClass:"form-upload empty",attrs:{for:"upload"}},[a("input",{staticClass:"upload-field",attrs:{type:"file",id:"upload"},on:{change:t.import_from_file}}),a("p",{staticClass:"empty-title h5"},[t._v("Drop or select a database to import.")]),a("p",{staticClass:"empty-subtitle"},[t._v("The database needs to be an export from a SpyGuard instance.")])])]):t._e()])])},i=[],o=e("bc3a"),r=e.n(o),n={name:"db-manage",data(){return{tabs:{import:!0,export:!1},jwt:""}},props:{},methods:{switch_tab:function(t){Object.keys(this.tabs).forEach(a=>{this.tabs[a]=a==t})},import_from_file:function(t){var a=new FormData;a.append("file",t.target.files[0]),r.a.post("/api/config/db/import",a,{headers:{"Content-Type":"multipart/form-data","X-Token":this.jwt}})},async get_jwt(){await r.a.get("/api/get-token",{timeout:1e4}).then(t=>{t.data.token&&(this.jwt=t.data.token)}).catch(t=>console.log(t))}},created:function(){this.get_jwt().then(()=>{this.export_url="/api/config/db/export?token="+this.jwt})}},c=n,l=e("2877"),p=Object(l["a"])(c,s,i,!1,null,null,null);a["default"]=p.exports}}]);
//# sourceMappingURL=chunk-2d0e4bf5.fac73388.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d2245cf"],{e08f:function(t,e,s){"use strict";s.r(e);var a=function(){var t=this,e=t._self._c;return e("div",{staticClass:"backend-content",attrs:{id:"content"}},[e("div",{staticClass:"column col-12 col-xs-12"},[e("h3",{staticClass:"s-title"},[t._v("Search whitelisted elements")]),e("div",{staticClass:"form-group"},[e("textarea",{directives:[{name:"model",rawName:"v-model",value:t.elements,expression:"elements"}],staticClass:"form-input",attrs:{id:"input-example-3",placeholder:"Paste the elements here",rows:"3"},domProps:{value:t.elements},on:{input:function(e){e.target.composing||(t.elements=e.target.value)}}})]),e("div",{staticClass:"form-group"},[e("button",{staticClass:"btn btn-primary col-12",on:{click:function(e){return t.search_elements()}}},[t._v("Search")])]),t.results.length>0?e("div",{staticClass:"form-group"},[e("table",{staticClass:"table table-striped table-hover"},[t._m(0),e("tbody",t._l(t.results,(function(s){return e("tr",{key:s.element},[e("td",[t._v(t._s(s.element))]),e("td",[t._v(t._s(s.type))]),e("td",[e("button",{staticClass:"btn btn-sm",on:{click:function(e){return t.remove(s)}}},[t._v("Delete")])])])})),0)])]):0==t.first_search?e("div",[e("div",{staticClass:"empty"},[e("p",{staticClass:"empty-title h5"},[t._v("Element"),this.elements.match(/[^\r\n]+/g).length>1?e("span",[t._v("s")]):t._e(),t._v(" not found.")]),e("p",{staticClass:"empty-subtitle"},[t._v("Try wildcard search to expend your search.")])])]):t._e()])])},n=[function(){var t=this,e=t._self._c;return e("thead",[e("tr",[e("th",[t._v("Element")]),e("th",[t._v("Element type")]),e("th")])])}],l=s("bc3a"),r=s.n(l),i={name:"elements-search",data(){return{results:[],first_search:!0,jwt:""}},props:{},methods:{search_elements:function(){return this.results=[],this.first_search=!1,this.elements.match(/[^\r\n]+/g).forEach(t=>{r.a.get("/api/whitelist/search/"+t.trim(),{timeout:1e4,headers:{"X-Token":this.jwt}}).then(t=>{t.data.results.length>0&&(this.results=[].concat(this.results,t.data.results))}).catch(t=>console.log(t))}),!0},remove:function(t){r.a.get("/api/whitelist/delete/"+t.id,{timeout:1e4,headers:{"X-Token":this.jwt}}).then(e=>{e.data.status&&(this.results=this.results.filter((function(e){return e!=t})))}).catch(t=>console.log(t))},async get_jwt(){await r.a.get("/api/get-token",{timeout:1e4}).then(t=>{t.data.token&&(this.jwt=t.data.token)}).catch(t=>console.log(t))}},created:function(){this.get_jwt()}},c=i,o=s("2877"),h=Object(o["a"])(c,a,n,!1,null,null,null);e["default"]=h.exports}}]);
//# sourceMappingURL=chunk-2d2245cf.ea4d33bd.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-3c0d118e"],{"42e0":function(t,e,s){t.exports=s.p+"img/network.33d31f9d.png"},"7e11":function(t,e,s){"use strict";s.r(e);var i=function(){var t=this,e=t._self._c;return e("div",{staticClass:"backend-content",attrs:{id:"content"}},[e("div",{class:{"alert-toaster-visible":t.toaster.show,"alert-toaster-hidden":!t.toaster.show}},[t._v(t._s(t.toaster.message))]),e("div",{staticClass:"column col-8 col-xs-12"},[e("h3",{staticClass:"s-title"},[t._v("Network configuration")]),e("h5",{staticClass:"s-subtitle"},[t._v("Interfaces configuration")]),e("img",{attrs:{src:s("42e0"),id:"network-thumbnail"}}),e("div",{staticClass:"container interfaces-container"},[e("div",{staticClass:"columns"},[e("div",{staticClass:"column col-6"},[e("span",{staticClass:"interface-label"},[t._v("Wireless AP interface")]),e("select",{directives:[{name:"model",rawName:"v-model",value:t.iface_in,expression:"iface_in"}],staticClass:"form-select width-full",on:{change:[function(e){var s=Array.prototype.filter.call(e.target.options,(function(t){return t.selected})).map((function(t){var e="_value"in t?t._value:t.value;return e}));t.iface_in=e.target.multiple?s:s[0]},function(e){return t.change_interface("in",t.iface_in)}]}},t._l(t.config.ifaces_in,(function(s){return e("option",{key:s,domProps:{value:s}},[t._v(" "+t._s(s.toUpperCase())+" ")])})),0)]),e("div",{staticClass:"column col-6"},[e("span",{staticClass:"interface-label"},[t._v("Internet link interface")]),e("select",{directives:[{name:"model",rawName:"v-model",value:t.iface_out,expression:"iface_out"}],staticClass:"form-select width-full",on:{change:[function(e){var s=Array.prototype.filter.call(e.target.options,(function(t){return t.selected})).map((function(t){var e="_value"in t?t._value:t.value;return e}));t.iface_out=e.target.multiple?s:s[0]},function(e){return t.change_interface("out",t.iface_out)}]}},t._l(t.config.ifaces_out,(function(s){return e("option",{key:s,domProps:{value:s}},[t._v(" "+t._s(s.toUpperCase())+" ")])})),0)])])]),e("h5",{staticClass:"s-subtitle"},[t._v("Edit SSIDs names")]),e("div",{staticClass:"form-group"},[e("table",{staticClass:"table table-striped table-hover"},[t._m(0),e("tbody",[t._l(t.config.network.ssids,(function(s){return e("tr",{key:s},[e("td",[t._v(t._s(s))]),e("td",[e("button",{staticClass:"btn btn-sm",on:{click:function(e){return t.delete_ssid(s)}}},[t._v("Delete")])])])})),e("tr",[e("td",[e("input",{directives:[{name:"model",rawName:"v-model",value:t.ssid,expression:"ssid"}],staticClass:"form-input",attrs:{type:"text",placeholder:"SSID name"},domProps:{value:t.ssid},on:{input:function(e){e.target.composing||(t.ssid=e.target.value)}}})]),e("td",[e("button",{staticClass:"btn btn-sm",on:{click:function(e){return t.add_ssid()}}},[t._v("Add")])])])],2)])])])])},n=[function(){var t=this,e=t._self._c;return e("thead",[e("tr",[e("th",[t._v("Network name")]),e("th",[t._v("Action")])])])}],a=(s("14d9"),s("bc3a")),o=s.n(a),c={name:"manageinterface",data(){return{config:{},ssid:"",iface_in:"",toaster:{show:!1,message:"",type:null}}},props:{},methods:{async get_jwt(){await o.a.get("/api/get-token",{timeout:1e4}).then(t=>{t.data.token&&(this.jwt=t.data.token)}).catch(t=>console.log(t))},load_config:function(){o.a.get("/api/config/list",{timeout:1e4,headers:{"X-Token":this.jwt}}).then(t=>{t.data&&(this.config=t.data,this.iface_in=this.config.network.in,this.iface_out=this.config.network.out,console.log(this.iface_in))}).catch(t=>console.log(t))},delete_ssid:function(t){var e=this.config.network.ssids.indexOf(t);this.config.network.ssids.splice(e,1),this.update_ssids()},add_ssid:function(){this.config.network.ssids.push(this.ssid),this.ssid="",this.update_ssids()},update_ssids:function(){o.a.get("/api/config/edit/network/ssids/"+this.config.network.ssids.join("|"),{timeout:1e4,headers:{"X-Token":this.jwt}}).then(t=>{t.data.status&&(this.toaster={show:!0,message:"Configuration updated",type:"success"},setTimeout(function(){this.toaster={show:!1}}.bind(this),1e3))}).catch(t=>console.log(t))},change_interface:function(t,e){o.a.get(`/api/config/edit/network/${t}/${e}`,{timeout:1e4,headers:{"X-Token":this.jwt}}).then(s=>{this.toaster={show:!0,message:"Configuration updated",type:"success"},setTimeout(function(){this.toaster={show:!1}}.bind(this),1e3),s.data.status&&(this.config.network[t]=e)}).catch(t=>console.log(t))}},created:function(){this.get_jwt().then(()=>{this.load_config()})}},r=c,l=s("2877"),u=Object(l["a"])(r,i,n,!1,null,null,null);e["default"]=u.exports}}]);
//# sourceMappingURL=chunk-3c0d118e.e3f2944c.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

13094
app/backend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

43
app/backend/package.json Executable file
View File

@ -0,0 +1,43 @@
{
"name": "@felixaime/spyguard-backend",
"version": "1.0.0",
"scripts": {
"serve": "vue-cli-service serve --copy --port=4201",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.21.1",
"core-js": "^3.6.5",
"vue": "^2.6.11",
"vue-router": "^3.4.5"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}

BIN
app/backend/public/favicon.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

17
app/backend/public/index.html Executable file
View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

177
app/backend/src/App.vue Executable file
View File

@ -0,0 +1,177 @@
<template>
<div class="backend-container off-canvas off-canvas-sidebar-show">
<div class="backend-navbar">
<a class="off-canvas-toggle btn btn-link btn-action" href="#sidebar">
<i class="icon icon-menu"></i>
</a>
</div>
<div class="backend-sidebar off-canvas-sidebar" id="sidebar">
<div class="backend-brand">
<h2 @click="goto_frontend()" class="title">{{ title }}</h2>
<span class="version" v-if="current_version">{{current_version}}</span>
</div>
<div class="backend-nav">
<div class="accordion-container">
<div class="accordion">
<input id="accordion-configuration" type="checkbox" name="backend-accordion-checkbox" hidden="">
<label class="accordion-header c-hand" for="accordion-configuration">Manage Device</label>
<div class="accordion-body">
<ul class="menu menu-nav">
<li class="menu-item">
<span @click="$router.push('/device/configuration')">Device config</span>
</li>
<li class="menu-item">
<span @click="$router.push('/engine/configuration')">Analysis engine</span>
</li>
<li class="menu-item">
<span @click="$router.push('/device/network')">Network config</span>
</li>
<li class="menu-item">
<span @click="$router.push('/device/db')">Manage database</span>
</li>
</ul>
</div>
</div>
<div class="accordion">
<input id="accordion-iocs" type="checkbox" name="backend-accordion-checkbox" hidden="">
<label class="accordion-header c-hand" for="accordion-iocs">Manage IOCs</label>
<div class="accordion-body">
<ul class="menu menu-nav">
<li class="menu-item">
<span @click="$router.push('/iocs/manage')">Manage IOCs</span>
</li>
<li class="menu-item">
<span @click="$router.push('/iocs/search')">Search IOCs</span>
</li>
</ul>
</div>
</div>
<div class="accordion">
<input id="accordion-whitelist" type="checkbox" name="backend-accordion-checkbox" hidden=""/>
<label class="accordion-header c-hand" for="accordion-whitelist">Manage Whitelist</label>
<div class="accordion-body">
<ul class="menu menu-nav">
<li class="menu-item">
<span @click="$router.push('/whitelist/manage')">Manage elements</span>
</li>
<li class="menu-item">
<span @click="$router.push('/whitelist/search')">Search elements</span>
</li>
</ul>
</div>
</div>
<div class="accordion">
<input id="accordion-instances" type="checkbox" name="backend-accordion-checkbox" hidden=""/>
<label class="accordion-header c-hand" for="accordion-instances">External sources</label>
<div class="accordion-body">
<ul class="menu menu-nav">
<li class="menu-item">
<span @click="$router.push('/instances/watchers')">Watchers Instances</span>
</li>
<li class="menu-item">
<span @click="$router.push('/instances/misp')">MISP Instances</span>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<a class="off-canvas-overlay" href="#close"></a>
<div class="off-canvas-content">
<div id="update-banner" v-if="update_available" @click="$router.push('/update')">A new version is available, click on the banner to install it.</div>
<transition name="fade" mode="out-in">
<router-view/>
</transition>
</div>
</div>
</template>
<style>
@import './assets/spectre.min.css';
@import './assets/spectre-exp.min.css';
@import './assets/spectre-icons.min.css';
@import './assets/custom.css';
/* Face style for router stuff. */
.fade-enter-active,
.fade-leave-active {
transition-duration: 0.3s;
transition-property: opacity;
transition-timing-function: ease;
}
.fade-enter,
.fade-leave-active {
opacity: 0
}
</style>
<script>
import axios from 'axios'
document.title = 'SpyGuard Backend'
export default {
name: 'backend',
components: {},
data() {
return {
title: "SPYGUARD",
current_version: false,
jwt: "",
update_available: false,
letters: ["SSS§ṠSSSSS","PPPþ⒫PPPP","YYYÿYYYÿYȲYY","GGḠGGGǤG¬G","UÚUUÜUɄUUU", "AAAAÄA¬AAA", "RЯRɌRRRɌʭR", "DD¬DDDDƋDD"]
}
},
methods: {
generate_random: function(min = 0, max = 1000) {
let difference = max - min;
let rand = Math.random();
rand = Math.floor( rand * difference);
rand = rand + min;
return rand;
},
goto_frontend: function() {
window.location.href= `http://${location.hostname}:8000`
},
async get_jwt() {
await axios.get(`/api/get-token`, { timeout: 10000 })
.then(response => {
if (response.data.token) {
this.jwt = response.data.token
}
})
.catch(err => (console.log(err)))
},
get_version: function() {
axios.get('/api/update/get-version', { timeout: 60000, headers: { 'X-Token': this.jwt } })
.then(response => {
if(response.data.status) this.current_version = response.data.current_version
})
.catch(error => { console.log(error) });
},
check_update: function() {
axios.get('/api/update/check', { timeout: 60000, headers: { 'X-Token': this.jwt } })
.then(response => {
if(response.data.message == "A new version is available"){
this.update_available = true;
}
})
.catch(error => { console.log(error) });
}
},
created: function() {
this.get_jwt().then(() => {
this.get_version();
this.check_update();
});
setInterval(function(){
let res = ""
this.letters.forEach(l => { res += l.charAt(this.generate_random(0, 9)) })
this.title = res;
setTimeout(function(){
this.title = "SPYGUARD";
}.bind(this), this.generate_random(30, 100));
}.bind(this), this.generate_random(500, 10000));
}
}
</script>

805
app/backend/src/assets/custom.css Executable file
View File

@ -0,0 +1,805 @@
/*
This CSS was forked from the awsome Spectre.css docs.
Spectre.css Docs | MIT License | github.com/picturepan2/spectre
*/
.off-canvas .off-canvas-toggle {
font-size: 1rem;
left: 1.5rem;
position: fixed;
top: 1rem
}
.off-canvas .off-canvas-sidebar {
width: 12rem
}
.off-canvas .off-canvas-content {
padding: 0
}
.backend-container {
min-height: 100vh
}
.backend-navbar {
height: 3.8rem;
position: fixed;
right: 0;
top: 0;
z-index: 100
}
.backend-navbar .btns {
position: absolute;
right: 1.5rem;
top: 1rem;
width: 14rem
}
.backend-navbar .algolia-autocomplete {
-ms-flex: 1 1 auto;
flex: 1 1 auto
}
.backend-sidebar .backend-nav {
bottom: 1.5rem;
-webkit-overflow-scrolling: touch;
overflow-y: auto;
padding: .5rem 1.5rem;
position: fixed;
top: 3.5rem;
width: 12rem
}
.backend-sidebar .accordion {
margin-bottom: .75rem
}
.backend-sidebar .accordion input~.accordion-header {
color: #d9d9d9;
font-size: .65rem;
font-weight: 600;
text-transform: uppercase
}
.backend-sidebar .accordion input:checked~.accordion-header {
color: #d9d9d9;
}
.backend-sidebar .accordion .menu .menu-item {
font-size: .7rem;
padding-left: 1rem;
cursor:pointer;
}
.backend-sidebar .accordion .menu .menu-item>span {
background: 0 0;
color: #FAFAFA;
display: inline-block
}
.backend-content {
-ms-flex: 1 1 auto;
flex: 1 1 auto;
padding: 0 4rem;
width: calc(100vw - 12rem);
margin-bottom: 10vh;
}
.backend-content>.container {
margin-left: 0;
max-width: 800px;
padding-bottom: 1.5rem
}
.backend-content .anchor {
color: #6362dc;
display: none;
margin-left: .2rem;
padding: 0 .2rem
}
.backend-content .anchor:focus,
.backend-content .anchor:hover {
display: inline;
text-decoration: none
}
.backend-content .s-subtitle,
.backend-content .s-title {
line-height: 1.8rem;
margin-bottom: 0;
padding-bottom: 1rem;
padding-top: 1rem;
position: static
}
@supports ((position:-webkit-sticky) or (position:sticky)) {
.backend-content .s-subtitle,
.backend-content .s-title {
position: -webkit-sticky;
position: sticky;
top: 0;
z-index: 99
}
.backend-content .s-subtitle::before,
.backend-content .s-title::before {
background: #fff;
bottom: 0;
content: "";
display: block;
left: -10px;
position: absolute;
right: -10px;
top: -5px;
z-index: -1
}
}
.backend-content .s-subtitle:hover .anchor,
.backend-content .s-title:hover .anchor {
display: inline
}
.backend-content .s-subtitle+.backend-note,
.backend-content .s-title+.backend-note {
margin-top: .4rem
}
.backend-content .backend-demo {
padding-bottom: 1rem;
padding-top: 1rem
}
.backend-content .backend-demo .card {
border: 0;
box-shadow: 0 .25rem 1rem rgba(48, 55, 66, .15);
height: 100%
}
.backend-content .column {
padding: .4rem
}
.backend-content .backend-block {
border-radius: .1rem;
padding: .4rem
}
.backend-content .backend-block.bg-gray {
background: #eef0f3
}
.backend-content .backend-shape {
height: 4.8rem;
line-height: 1.2rem;
padding: 1.8rem 0;
width: 4.8rem
}
.backend-content .backend-dot {
border-radius: 50%;
display: inline-block;
height: .5rem;
padding: 0;
width: .5rem
}
.backend-content .backend-table td,
.backend-content .backend-table th {
padding: .75rem .25rem
}
.backend-content .backend-color {
border-radius: .1rem;
margin: .25rem 0;
padding: 5rem .5rem .5rem
}
.backend-content .backend-color .color-subtitle {
font-size: .7rem;
opacity: .75
}
.backend-content .code .hljs-tag {
color: #505c6e
}
.backend-content .code .hljs-comment {
color: #bcc3ce
}
.backend-content .code .hljs-class,
.backend-content .code .hljs-number,
.backend-content .code .hljs-string,
.backend-content .code .hljs-title {
color: #5755d9
}
.backend-content .code .hljs-attribute,
.backend-content .code .hljs-built_in,
.backend-content .code .hljs-keyword,
.backend-content .code .hljs-name,
.backend-content .code .hljs-variable {
color: #d73e48
}
.backend-content .code .hljs-hexcolor,
.backend-content .code .hljs-value {
color: #505c6e
}
.backend-content .c-select-all {
-webkit-user-select: all;
-moz-user-select: all;
-ms-user-select: all;
user-select: all
}
.backend-content .panel {
height: 75vh
}
.backend-content .panel .tile {
margin: .75rem 0
}
.backend-content .parallax {
margin: 2rem auto
}
.backend-content .form-autocomplete .menu {
position: static
}
.backend-content .example-tile-icon {
align-content: space-around;
align-items: center;
background: #5755d9;
border-radius: .1rem;
color: #fff;
display: -ms-flexbox;
display: flex;
-ms-flex-align: center;
-ms-flex-line-pack: distribute;
font-size: 1.2rem;
height: 2rem;
width: 2rem
}
.backend-content .example-tile-icon .icon {
margin: auto
}
.backend-content .comparison-slider {
height: auto;
padding-bottom: 56.2222%
}
.backend-content .comparison-slider .filter-grayscale {
filter: grayscale(75%)
}
.backend-content .off-canvas {
position: relative
}
.backend-content .off-canvas .off-canvas-toggle {
left: .4rem;
position: absolute;
top: .4rem;
z-index: 1
}
.backend-brand {
color: #CCC;
height: 2rem;
left: 1.5rem;
position: fixed;
top: .85rem;
width: 72%;
position: sticky;
}
.backend-brand .backend-logo {
align-items: center;
border-radius: .1rem;
display: -ms-inline-flexbox;
display: inline-flex;
-ms-flex-align: center;
font-size: .7rem;
height: 2rem;
padding: .2rem;
width: auto
}
.backend-brand .backend-logo:focus,
.backend-brand .backend-logo:hover {
text-decoration: none
}
.backend-brand .backend-logo img {
display: inline-block;
height: auto;
width: 1.6rem
}
.backend-brand .backend-logo h2 {
display: inline-block;
font-size: .8rem;
font-weight: 700;
line-height: 1.5rem;
margin-bottom: 0;
margin-left: .5rem;
margin-right: .3rem
}
.backend-footer {
color: #bcc3ce;
padding: .5rem
}
.backend-footer a {
color: #66758c
}
@media (max-width:960px) {
.off-canvas .off-canvas-toggle {
z-index: 300
}
.off-canvas .off-canvas-content {
width: 100%
}
.backend-sidebar .backend-brand {
margin: .85rem 1.5rem;
padding: 0;
position: static
}
.backend-sidebar .backend-nav {
margin-top: 1rem;
position: static
}
.backend-sidebar .menu .menu-item>a {
padding: .3rem .4rem
}
.backend-navbar {
-webkit-backdrop-filter: blur(5px);
backdrop-filter: blur(5px);
background: rgba(247, 248, 249, .65);
left: 0
}
.backend-content {
min-width: auto;
padding: 0 1.5rem;
width: 100%
}
.backend-content .s-subtitle,
.backend-content .s-title {
padding-top: 5rem;
position: static
}
.backend-content .s-subtitle::before,
.backend-content .s-title::before {
content: none
}
}
@media (max-width:600px) {
.off-canvas .off-canvas-toggle {
left: .5rem
}
.backend-navbar .btns {
right: .9rem
}
.backend-sidebar .backend-brand {
margin: .85rem 1rem
}
.backend-sidebar .backend-nav {
padding: .5rem 1rem
}
.backend-content {
padding: 0 .5rem
}
.backend-content .backend-block {
padding: .4rem .1rem
}
}
@font-face {
font-family: 'Lobster';
font-weight: normal;
src: url('fonts/Exo.ttf') format('truetype');
}
@font-face {
font-family: "Roboto-Bold";
src: url("fonts/Roboto-Bold.eot"); /* IE9 Compat Modes */
src: url("fonts/Roboto-Bold.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */
url("fonts/Roboto-Bold.otf") format("opentype"), /* Open Type Font */
url("fonts/Roboto-Bold.svg") format("svg"), /* Legacy iOS */
url("fonts/Roboto-Bold.ttf") format("truetype"), /* Safari, Android, iOS */
url("fonts/Roboto-Bold.woff") format("woff"), /* Modern Browsers */
url("fonts/Roboto-Bold.woff2") format("woff2"); /* Modern Browsers */
font-weight: normal;
font-style: normal;
}
.off-canvas .off-canvas-sidebar {
background: #3a3a3a;
}
h1, h2, h3 {
font-family: Lobster;
color: #484848;
}
h4, h5 {
font-family: "Roboto-Bold";
color: #484848;
}
.btn {
border-radius: 5px;
}
.btn:focus, .btn:hover {
background: #494949;
border-color: #494949;
text-decoration: none;
color: #DBDBDB;
}
.btn.active, .btn:active {
background: #3a3a3a;
border-color: #3a3a3a;
color: #fff;
text-decoration: none;
}
.px150 {
width: 150px;
}
.width-full {
width: 100%;
}
.tab-block {
margin-bottom: 35px;
}
.toast {
margin-top: 5px;
margin-bottom: 5px;
}
.frame-export {
display: none;
}
.form-upload {
position: relative;
display: block;
}
.form-upload .upload-field {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
opacity: 0;
z-index:1000;
width:100%;
height:100%;
}
.tlp-white {
font-size: .6rem;
height: 1.4rem;
padding: .05rem .3rem;
background-color: #FFF;
line-height: 1.2rem;
text-transform: uppercase;
font-weight: bold;
border: 2px solid #efefef;
vertical-align: middle;
border-radius: .1rem;
}
.tlp-green {
font-size: .6rem;
height: 1.4rem;
padding: .05rem .3rem;
background-color: #199a09cf;
line-height: 1.2rem;
text-transform: uppercase;
font-weight: bold;
border: 2px solid #0f8600cf;
vertical-align: middle;
color:#FFF;
border-radius: .1rem;
}
.tlp-amber {
font-size: .6rem;
height: 1.4rem;
padding: .05rem .3rem;
background-color: #ffc000cf;
line-height: 1.2rem;
text-transform: uppercase;
font-weight: bold;
border: 2px solid #ffc000cf;
vertical-align: middle;
color:#FFF;
border-radius: .1rem;
}
.tlp-red {
font-size: .6rem;
height: 1.4rem;
padding: .05rem .3rem;
background-color: #ff0033;
line-height: 1.2rem;
text-transform: uppercase;
font-weight: bold;
border: 2px solid #ff0033;
vertical-align: middle;
color:#FFF;
border-radius: .1rem;
}
.title {
font-family: 'Lobster';
color: #FAFAFA;
cursor: pointer;
width: fit-content;
height: 2rem;
left: 1.5rem;
position: fixed;
top: .85rem;
text-transform: uppercase;
font-size: 1.3rem;
letter-spacing: 0.1rem;
}
#network-thumbnail {
width: 100%;
margin-top: 10px;
}
.interfaces-container {
margin-top:20px;
margin-bottom:40px;
}
.interface-label {
text-transform: uppercase;
font-size: 12px;
font-weight: bold;
margin-bottom: 10px;
text-align: center;
display: block;
}
.form-control:focus {
border-color: inherit;
-webkit-box-shadow: none;
box-shadow: none;
}
.form-input:focus {
border-color: inherit;
-webkit-box-shadow: none;
box-shadow: none;
}
.tab .tab-item a:focus {
box-shadow: none;
}
.shortcuts {
position: fixed;
bottom: 0;
left: 0;
z-index: 20000;
padding: 20px;
opacity: .2;
}
.shortcut {
width: 40px;
height: 40px;
margin-left: 10px;
cursor: pointer;
}
.whitespace {
height:100px;
display:block;
}
.alert-toaster-visible {
position:fixed;
right:15px;
top:15px;
padding:10px;
background-color: #484848;
border-radius: 5px;
color: #ccc;
font-size: 12px;
visibility: visible;
opacity: 1;
transition: opacity .5s linear;
}
.alert-toaster-hidden {
visibility: hidden;
opacity: 0;
transition: visibility 0s .5s, opacity .5s linear;
}
.comment-block {
padding: 10px;
font-size: 12px;
background-color: #FAFAFA;
}
.capi {
text-transform: capitalize;
}
.upper {
text-transform: uppercase;
}
/*** MISP CSS ***/
.misp-form {
/* Using CSS Grid to lay out the elements in two-dimensions: */
display: grid;
/* specifying a 0.2em gutter/gap between adjacent elements: */
gap: 0.4em;
overflow:auto;
grid-template-columns: 10em 0.5em 1fr;
width: 100%;
border-radius:.1rem;
margin-bottom: .8rem;
}
.misp-label {
/* placing all <label> elements in the grid column 1 (the first): */
grid-column: 1;
text-align: left;
padding-top: .3em;
}
.instance-offline {
background-color: #e85600;
color: #FFF;
font-size: 11px;
border-radius: 3px;
padding:3px 6px 3px 6px;
cursor: help;
}
.instance-online {
background-color: #64c800;
color: #FFF;
font-size: 11px;
border-radius: 3px;
padding:3px 6px 3px 6px;
cursor: help;
}
.misp-name {
font-size: 1rem;
font-family: "Roboto-Bold";
color: #484848;
}
.misp-name:disabled {
border-style: none;
color:inherit;
background-color: inherit;
padding: unset;
}
.misp-input {
grid-column: 3;
align-self: center;
}
.misp-input:disabled {
border-style: none;
color:inherit;
background-color: inherit;
padding: unset;
}
.misp-button {
/* positioning the <button> element in the grid-area identified
by the name of 'submit': */
grid-area: submit;
}
.loading {
margin-bottom: 12px;
display: block;
}
.loading::after {
animation: loading .5s infinite linear;
background: 0 0;
border: .1rem solid #66758c;
border-radius: 50%;
border-right-color: transparent;
border-top-color: transparent;
content: "";
display: block;
height: .8rem;
left: 50%;
margin-left: -.4rem;
margin-top: -.4rem;
opacity: 1;
padding: 0;
position: absolute;
top: 50%;
width: .8rem;
z-index: 1;
}
.loading.loading-lg::after {
height: 1.6rem;
margin-left: -.8rem;
margin-top: -.8rem;
width: 1.6rem;
}
.tooltip::after{
background:rgba(48,55,66,.95);
border-radius:3px;
bottom:100%;
color:#fff;
content:attr(data-tooltip);
display:block;
font-size: 11px;
left:50%;
max-width:320px;
opacity:0;
overflow:hidden;
padding:3px 6px 3px 6px;
pointer-events:none;
position:absolute;
text-overflow:ellipsis;
transform:translate(-50%,.4rem);
transition:opacity .2s,transform .2s;
white-space:pre;
z-index:300
}
.btn.btn-primary {
background: #3a3a3a;
border-color: #3a3a3a;
}
.read-only {
background-color: #F4F4F4;
color: #AEADAD;
}
#update-banner {
padding: 5px 20px;
background-color: #d1ff51;
cursor: pointer;
}
.version {
right: 0;
text-align: right;
background-color: #FFF;
border-radius: 5px;
font-size: 9px;
padding: 1px 3px;
color: #000;
position: absolute;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 805 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 784 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

1
app/backend/src/assets/spectre-exp.min.css vendored Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
app/backend/src/assets/spectre.min.css vendored Executable file

File diff suppressed because one or more lines are too long

10
app/backend/src/main.js Executable file
View File

@ -0,0 +1,10 @@
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = true
Vue.config.devtools = true
new Vue({
router,
render: h => h(App)
}).$mount('#app')

87
app/backend/src/router/index.js Executable file
View File

@ -0,0 +1,87 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'default',
component: () => import('../views/home.vue'),
props: true
},
{
path: '/device/configuration',
name: 'device-configuration',
component: () => import('../views/edit-configuration.vue'),
props: true
},
{
path: '/engine/configuration',
name: 'engine-configuration',
component: () => import('../views/analysis-engine.vue'),
props: true
},
{
path: '/device/network',
name: 'device-network',
component: () => import('../views/network-manage.vue'),
props: true
},
{
path: '/device/db',
name: 'db-manage',
component: () => import('../views/db-manage.vue'),
props: true
},
{
path: '/iocs/manage',
name: 'iocs-manage',
component: () => import('../views/iocs-manage.vue'),
props: true
},
{
path: '/instances/misp',
name: 'instance-misp',
component: () => import('../views/instance-misp.vue'),
props: true
},
{
path: '/instances/watchers',
name: 'instance-watchers',
component: () => import('../views/instance-watchers.vue'),
props: true
},
{
path: '/iocs/search',
name: 'iocs-search',
component: () => import('../views/iocs-search.vue'),
props: true
},
{
path: '/whitelist/manage',
name: 'whitelist-manage',
component: () => import('../views/whitelist-manage.vue'),
props: true
},
{
path: '/whitelist/search',
name: 'whitelist-search',
component: () => import('../views/whitelist-search.vue'),
props: true
},
{
path: '/update',
name: 'update',
component: () => import('../views/update.vue'),
props: true
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router

View File

@ -0,0 +1,143 @@
<template>
<div class="backend-content" id="content">
<div v-bind:class="{ 'alert-toaster-visible' : toaster.show, 'alert-toaster-hidden' : !toaster.show }">{{toaster.message}}</div>
<div class="column col-8 col-xs-12">
<h3 class="s-title">Detection engine configuration</h3>
<h5 class="s-subtitle">Detection methods</h5>
<div class="form-group">
<label class="form-switch">
<input type="checkbox" @change="local_analysis('analysis', 'heuristics')" v-model="config.analysis.heuristics">
<i class="form-icon"></i> Use heuristic detection for suspect behaviour.
</label>
<label class="form-switch">
<input type="checkbox" @change="local_analysis('analysis', 'iocs')" v-model="config.analysis.iocs">
<i class="form-icon"></i> Use Indicator of Compromise (IoC) based detection.
</label>
<label class="form-switch">
<input type="checkbox" @change="local_analysis('analysis', 'whitelist')" v-model="config.analysis.whitelist">
<i class="form-icon"></i> Use whitelist to prevent false positives.
</label>
<label class="form-switch">
<input type="checkbox" @change="local_analysis('analysis', 'active')" v-model="config.analysis.active">
<i class="form-icon"></i> Use active analysis (Dig, Whois, OpenSSL...).
</label>
<label class="form-switch">
<input type="checkbox" @change="switch_iocs_types('all')" :checked="config.analysis.indicators_types.includes('all')">
<i class="form-icon"></i> Detect threats by using all IOCs.
</label>
</div>
<div class="form-group" v-if="!config.analysis.indicators_types.includes('all')">
<h5 class="s-subtitle">IOCs categories</h5>
<label class="form-switch" v-for="tag in iocs_tags" :key="tag">
<input type="checkbox" @change="switch_iocs_types(tag)" :checked="config.analysis.indicators_types.includes(tag)">
<i class="form-icon"></i> Use IOCs related to {{ tag.toUpperCase() }} threat.
</label>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'analysis-engine',
data() {
return {
config: {},
check_certificate: false,
certificate: "",
iocs_tags: [],
toaster: { show: false, message : "", type : null }
}
},
props: {},
methods: {
switch_config: function(cat, key) {
axios.get(`/api/config/switch/${cat}/${key}`, {
timeout: 10000,
headers: { 'X-Token': this.jwt }
}).then(response => {
if (response.data.status) {
if (response.data.message == "Key switched to true") {
this.toaster = { show : true, message : "Configuration updated", type : "success" }
setTimeout(function () { this.toaster = { show : false } }.bind(this), 1000)
this.config[cat][key] = true
} else if (response.data.message == "Key switched to false") {
this.toaster = { show : true, message : "Configuration updated", type : "success" }
setTimeout(function () { this.toaster = { show : false } }.bind(this), 1000)
this.config[cat][key] = false
} else {
this.toaster = { show : true, message : "The key doesn't exist", type : "error" }
setTimeout(function () { this.toaster = { show : false } }.bind(this), 1000)
}
}
})
.catch(err => (console.log(err)))
},
local_analysis: function(cat, key) {
this.switch_config(cat, key);
if (this.config.analysis.remote != false)
this.switch_config("analysis", "remote");
},
load_config: function() {
axios.get(`/api/config/list`, {
timeout: 10000,
headers: { 'X-Token': this.jwt }
}).then(response => {
if (response.data) {
this.config = response.data
this.config.backend.password = ""
console.log(this.config.analysis.indicators_types);
}
})
.catch(err => (console.log(err)))
},
async get_jwt() {
await axios.get(`/api/get-token`, { timeout: 10000 })
.then(response => {
if (response.data.token) {
this.jwt = response.data.token
}
})
.catch(err => (console.log(err)))
},
get_iocs_tags: function() {
axios.get(`/api/ioc/get/tags`, {
timeout: 10000,
headers: {'X-Token': this.jwt}
})
.then(response => {
if(response.data.tags) this.iocs_tags = response.data.tags
})
.catch(err => (console.log(err)));
},
switch_iocs_types: function(tag) {
if (this.config.analysis.indicators_types.includes(tag)){
axios.get(`/api/config/ioc-type/delete/${tag}`, {
timeout: 10000,
headers: { 'X-Token': this.jwt }
}).then(response => {
if (response.data.status) { this.load_config(); }
})
.catch(err => (console.log(err)))
} else {
axios.get(`/api/config/ioc-type/add/${tag}`, {
timeout: 10000,
headers: { 'X-Token': this.jwt }
}).then(response => {
if (response.data.status) { this.load_config(); }
})
.catch(err => (console.log(err)))
this.load_config();
}
}
},
created: function() {
this.get_jwt().then(() => {
this.load_config();
this.get_iocs_tags();
});
}
}
</script>

View File

@ -0,0 +1,75 @@
<template>
<div class="backend-content" id="content">
<div class="column col-8 col-xs-12">
<h3 class="s-title">Manage database</h3>
<ul class="tab tab-block">
<li class="tab-item">
<a href="#" v-on:click="switch_tab('import')" v-bind:class="{ active: tabs.import }">Import database</a>
</li>
<li class="tab-item">
<a href="#" v-on:click="switch_tab('export')" v-bind:class="{ active: tabs.export }">Export database</a>
</li>
</ul>
<div v-if="tabs.export">
<iframe :src="export_url" class="frame-export"></iframe>
</div>
<div v-if="tabs.import">
<label class="form-upload empty" for="upload">
<input type="file" class="upload-field" id="upload" @change="import_from_file">
<p class="empty-title h5">Drop or select a database to import.</p>
<p class="empty-subtitle">The database needs to be an export from a SpyGuard instance.</p>
</label>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'db-manage',
data() {
return {
tabs: { "import" : true, "export" : false },
jwt:""
}
},
props: { },
methods: {
switch_tab: function(tab) {
Object.keys(this.tabs).forEach(key => {
if( key == tab ){
this.tabs[key] = true
} else {
this.tabs[key] = false
}
});
},
import_from_file: function(ev) {
var formData = new FormData();
formData.append("file", ev.target.files[0]);
axios.post('/api/config/db/import', formData, {
headers: {
"Content-Type" : "multipart/form-data",
"X-Token" : this.jwt
}
})
},
async get_jwt(){
await axios.get(`/api/get-token`, { timeout: 10000 })
.then(response => {
if(response.data.token){
this.jwt = response.data.token
}
})
.catch(err => (console.log(err)))
}
},
created: function() {
this.get_jwt().then(() => {
this.export_url = `/api/config/db/export?token=${this.jwt}`
});
}
}
</script>

View File

@ -0,0 +1,167 @@
<template>
<div class="backend-content" id="content">
<div v-bind:class="{ 'alert-toaster-visible' : toaster.show, 'alert-toaster-hidden' : !toaster.show }">{{toaster.message}}</div>
<div class="column col-8 col-xs-12">
<h3 class="s-title">Configuration </h3>
<div class="form-group">
<label class="form-label" for="user-login">Device UUID (read-only)</label>
<div class="input-group">
<input class="form-input read-only" id="device-id" v-model="config.device_uuid" readonly="readonly">
</div>
</div>
<h5 class="s-subtitle">Device configuration</h5>
<div class="form-group">
<label class="form-switch">
<input type="checkbox" @change="switch_config('frontend', 'virtual_keyboard')" v-model="config.frontend.virtual_keyboard">
<i class="form-icon"></i> Use virtual keyboard (for touch screen)
</label>
<label class="form-switch">
<input type="checkbox" @change="switch_config('frontend', 'shutdown_option')" v-model="config.frontend.shutdown_option">
<i class="form-icon"></i> Allow the end-user to shutdown the device.
</label>
<label class="form-switch">
<input type="checkbox" @change="switch_config('frontend', 'backend_option')" v-model="config.frontend.backend_option">
<i class="form-icon"></i> Allow the end-user to access to the backend.
</label>
<label class="form-switch">
<input type="checkbox" @change="switch_config('network', 'tokenized_ssids')" v-model="config.network.tokenized_ssids">
<i class="form-icon"></i> Use tokenized SSIDs (eg. [ssid-name]-[hex-str]).
</label>
<label class="form-switch">
<input type="checkbox" @change="switch_config('frontend', 'download_links')" v-model="config.frontend.download_links">
<i class="form-icon"></i> Use in-browser download for network captures.
</label>
<label class="form-switch">
<input type="checkbox" @change="switch_config('frontend', 'sparklines')" v-model="config.frontend.sparklines">
<i class="form-icon"></i> Show background sparklines during the capture.
</label>
<label class="form-switch">
<input type="checkbox" @change="switch_config('frontend', 'remote_access')" v-model="config.frontend.remote_access">
<i class="form-icon"></i> Allow remote access to the frontend.
</label>
<label class="form-switch">
<input type="checkbox" @change="switch_config('backend', 'remote_access')" v-model="config.backend.remote_access">
<i class="form-icon"></i> Allow remote access to the backend.
</label>
</div>
<h5 class="s-subtitle">User credentials</h5>
<div class="form-group">
<div class="column col-10 col-xs-12">
<div class="form-group">
<label class="form-label" for="user-login">User login</label>
<div class="input-group">
<input class="form-input" id="user-login" type="text" v-model="config.backend.login">
<button class="btn btn-primary input-group-btn px150" @click="change_login()">Update it</button>
</div>
</div>
<div class="form-group">
<label class="form-label" for="user-login">User password</label>
<div class="input-group">
<input class="form-input" id="user-login" type="password" placeholder="●●●●●●" v-model="config.backend.password">
<button class="btn btn-primary input-group-btn px150" @click="change_password()">Update it</button>
</div>
</div>
<div class="whitespace"></div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'edit-configuration',
data() {
return {
config: {},
check_certificate: false,
certificate: "",
iocs_tags: [],
toaster: { show: false, message : "", type : null }
}
},
props: {},
methods: {
switch_config: function(cat, key) {
axios.get(`/api/config/switch/${cat}/${key}`, {
timeout: 10000,
headers: { 'X-Token': this.jwt }
}).then(response => {
if (response.data.status) {
if (response.data.message == "Key switched to true") {
this.toaster = { show : true, message : "Configuration updated", type : "success" }
setTimeout(function () { this.toaster = { show : false } }.bind(this), 1000)
this.config[cat][key] = true
} else if (response.data.message == "Key switched to false") {
this.toaster = { show : true, message : "Configuration updated", type : "success" }
setTimeout(function () { this.toaster = { show : false } }.bind(this), 1000)
this.config[cat][key] = false
} else {
this.toaster = { show : true, message : "The key doesn't exist", type : "error" }
setTimeout(function () { this.toaster = { show : false } }.bind(this), 1000)
}
}
})
.catch(err => (console.log(err)))
},
load_config: function() {
axios.get(`/api/config/list`, {
timeout: 10000,
headers: { 'X-Token': this.jwt }
}).then(response => {
if (response.data) {
this.config = response.data
this.config.backend.password = ""
}
})
.catch(err => (console.log(err)))
},
async get_jwt() {
await axios.get(`/api/get-token`, { timeout: 10000 })
.then(response => {
if (response.data.token) {
this.jwt = response.data.token
}
})
.catch(err => (console.log(err)))
},
change_login: function() {
axios.get(`/api/config/edit/backend/login/${this.config.backend.login}`, {
timeout: 10000,
headers: { 'X-Token': this.jwt }
}).then(response => {
if (response.data.status) {
this.toaster = { show : true, message : "Login changed", type : "success" }
setTimeout(function () { this.toaster = { show : false } }.bind(this), 1000)
} else {
this.toaster = { show : true, message : "Login not changed", type : "error" }
setTimeout(function () { this.toaster = { show : false } }.bind(this), 1000)
}
})
.catch(err => (console.log(err)))
},
change_password: function() {
axios.get(`/api/config/edit/backend/password/${this.config.backend.password}`, {
timeout: 10000,
headers: { 'X-Token': this.jwt }
}).then(response => {
if (response.data.status) {
this.toaster = { show : true, message : "Password changed", type : "success" }
setTimeout(function () { this.toaster = { show : false } }.bind(this), 1000)
} else {
this.toaster = { show : true, message : "Password not changed", type : "error" }
setTimeout(function () { this.toaster = { show : false } }.bind(this), 1000)
}
})
.catch(err => (console.log(err)))
}
},
created: function() {
this.get_jwt().then(() => {
this.load_config();
});
}
}
</script>

18
app/backend/src/views/home.vue Executable file
View File

@ -0,0 +1,18 @@
<template>
<div class="backend-content" id="content">
<div class="column col-8 col-xs-12">
<div class="container">
<h3 class="s-title">Getting started</h3>
<br />
<p>SpyGuard is a forked and enhanced version of TinyCheck, an application developed by Kaspersky. SpyGuard's main objective is to detect signs of compromise by monitoring network flows transmitted by a device.</p>
<p>As it uses WiFi, SpyGuard can be used against a wide range of devices, such as smartphones, laptops, IOTs or workstations. To do its job, the analysis engine of SpyGuard is using Indicators of Compromise (IOCs), anomaly detection and is supported by Suricata. </p>
<p>This backend lets you configure your SpyGuard instance. You can push some IOCs for detection and whitelist elements which can be seen during legit communications in order to prevent false positives.</p>
<p>_</p>
</div>
<div class="backend-footer container grid-lg" id="copyright">
<p>For any question, bug report or feedback, please contact the <a href="mailto:spyguard@protonmail.com" target="_blank">SpyGuard's Team</a> or open an issue on the <a href="https://github.com/SpyGuard/spyguard/issues" target="_blank">SpyGuard Github repository</a>.</p>
</div>
</div>
</div>
</template>

View File

@ -0,0 +1,175 @@
<template>
<div class="backend-content" id="content">
<div class="column col-8 col-xs-12">
<h3 class="s-title">Manage MISP instances</h3>
<ul class="tab tab-block">
<li class="tab-item">
<a href="#" v-on:click="switch_tab('addmisp')" v-bind:class="{ active: tabs.addmisp }">Add instance</a>
</li>
<li class="tab-item">
<a href="#" v-on:click="switch_tab('instances')" v-bind:class="{ active: tabs.instances }">Existing instances</a>
</li>
</ul>
<div v-if="tabs.addmisp">
<div class="misp-form">
<label class="misp-label">Instance name</label><span></span>
<input class="form-input" type="text" ref="misp_name" placeholder="CYBERACME MISP" v-model="mispinst.name" required>
<label class="misp-label">Instance URL</label><span></span>
<input class="form-input" type="text" ref="misp_url" placeholder="https://misp.cyberacme.com" v-model="mispinst.url" required>
<label class="misp-label">Authentication key</label><span></span>
<input class="form-input" type="text" ref="misp_key" placeholder="OqHSMyAuth3ntic4t10nK3y0MyAuth3ntic4t10nK3y3iiH" v-model="mispinst.key" required>
<label class="misp-label" v-if="mispinst.url.startsWith('https://')">Verify certificate? </label><span v-if="mispinst.url.startsWith('https://')"></span>
<div style="flex:50%" v-if="mispinst.url.startsWith('https://')"><label class="form-switch">
<input type="checkbox" v-model="mispinst.ssl">
<i class="form-icon"></i>
</label></div>
</div>
<button class="btn-primary btn col-12" v-on:click="add_instance()">Add MISP instance</button>
<div class="form-group" v-if="added">
<div class="toast toast-success">
MISP instance added successfully. Redirecting to instances in 2 seconds.
</div>
</div>
<div class="form-group" v-if="error">
<div class="toast toast-error">
MISP instance not added. {{error}}
</div>
</div>
</div>
<div class="form-group" v-if="tabs.instances">
<div v-if="instances.length">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Name</th>
<th>Server</th>
<th>Authkey</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr v-for="i in instances" v-bind:key="i.id">
<td>{{ i.name }}</td>
<td>{{ i.url.replace('https://', '') .replace('http://', '') }}</td>
<td>{{ i.apikey.slice(0,5) }} [...] {{ i.apikey.slice(35,40) }}</td>
<td>
<span v-if="i.connected" class="instance-online tooltip" :data-tooltip="i.lastsync"> ONLINE</span>
<span v-else class="instance-offline tooltip" :data-tooltip="i.lastsync"> OFFLINE</span>
</td>
<td><button class="btn btn-sm" v-on:click="delete_instance(i)">Delete</button></td>
</tr>
</tbody>
</table>
</div>
<div v-else>
<div class="empty">
<div v-if="loading">
<p class="empty-title h5">
<span class="loading loading-lg"></span>
</p>
<p class="empty-subtitle">Testing and loading your MISP instances.</p>
</div>
<div v-else>
<p class="empty-title h5">No MISP instance found.</p>
<p class="empty-subtitle">Do not hesitate to add a MISP instance.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'managemisp',
data() {
return {
error:false,
loading:false,
added:false,
mispinst:{ name:'', url:'',key:'', ssl:false },
instances:[],
tabs: { "addmisp" : true, "instances" : false },
jwt:""
}
},
props: { },
methods: {
add_instance: function()
{
this.added = false;
this.error = false;
if (this.mispinst.name && this.mispinst.url && this.mispinst.key)
{
axios.post(`/api/misp/add`, { data: { instance: this.mispinst } }, { headers: {'X-Token': this.jwt} }).then(response => {
if(response.data.status){
this.added = true;
setTimeout(function (){
this.switch_tab('instances')
this.mispinst = { name:'', url:'',key:'', ssl:false }
this.added = false
}.bind(this), 2000);
} else {
this.error = response.data.message;
}
})
.catch(err => (console.log(err)))
}
},
delete_instance(elem)
{
axios.get(`/api/misp/delete/${elem.id}`, { timeout: 10000, headers: {'X-Token': this.jwt} })
.then(response => {
if(response.data.status){
this.instances = this.instances.filter(function(el) { return el != elem; });
}
})
.catch(err => (console.log(err)))
},
get_misp_instances()
{
this.loading = true;
this.instances = []
axios.get(`/api/misp/get_all`, { timeout: 10000, headers: {'X-Token': this.jwt} })
.then(response => {
if(response.data.results){
this.instances = response.data.results;
this.instances.forEach(e => {
var lastsync = parseInt((Date.now()/1000 - e.lastsync) / 86400)
e.lastsync = (!lastsync)? "Synchronized today" : `Synchronized ${lastsync} day(s) ago`
} )
}
this.loading = false
})
.catch(err => (console.log(err)))
},
switch_tab: function(tab) {
Object.keys(this.tabs).forEach(key => {
if( key == tab ){
this.tabs[key] = true
if (key == "instances") this.get_misp_instances();
} else {
this.tabs[key] = false
}
});
},
get_jwt(){
axios.get(`/api/get-token`, { timeout: 10000 })
.then(response => {
if(response.data.token){
this.jwt = response.data.token
}
})
.catch(err => (console.log(err)))
}
},
created: function() {
this.get_jwt();
}
}
</script>

View File

@ -0,0 +1,166 @@
<template>
<div class="backend-content" id="content">
<div class="column col-8 col-xs-12">
<h3 class="s-title">Manage watchers instances</h3>
<ul class="tab tab-block">
<li class="tab-item">
<a href="#" v-on:click="switch_tab('addwatcher')" v-bind:class="{ active: tabs.addwatcher }">Add watcher</a>
</li>
<li class="tab-item">
<a href="#" v-on:click="switch_tab('instances')" v-bind:class="{ active: tabs.instances }">Existing watchers</a>
</li>
</ul>
<div v-if="tabs.addwatcher">
<div class="misp-form">
<label class="misp-label">Watcher name</label><span></span>
<input class="form-input" type="text" ref="watcher_name" placeholder="My incredible watcher" v-model="watcher.name" required>
<label class="misp-label">Watcher URL</label><span></span>
<input class="form-input" type="text" ref="watcher_url" placeholder="https://url.of.my.watcher.com/watcher.json" v-model="watcher.url" required>
<label class="misp-label">Watcher Type</label><span></span>
<select class="form-select width-full" placeholder="test" v-model="watcher.type">
<option value="iocs">IOCs</option>
<option value="whitelist">Whitelist</option>
</select>
</div>
<button class="btn-primary btn col-12" v-on:click="add_instance()">Add watcher</button>
<div class="form-group" v-if="added">
<div class="toast toast-success">
Watcher added successfully. Redirecting to watchers in 2 seconds.
</div>
</div>
<div class="form-group" v-if="error">
<div class="toast toast-error">
Watcher not added. {{error}}
</div>
</div>
</div>
<div class="form-group" v-if="tabs.instances">
<div v-if="instances.length">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Type</th>
<th>Name</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr v-for="i in instances" v-bind:key="i.id">
<td>{{ i.type.toUpperCase() }}</td>
<td>{{ i.name }}</td>
<td>
<span v-if="i.status" class="instance-online"> ONLINE</span>
<span v-else class="instance-offline"> OFFLINE</span>
</td>
<td><button class="btn btn-sm" v-on:click="delete_instance(i)">Delete</button></td>
</tr>
</tbody>
</table>
</div>
<div v-else>
<div class="empty">
<div v-if="loading">
<p class="empty-title h5">
<span class="loading loading-lg"></span>
</p>
<p class="empty-subtitle">Testing and loading the watchers.</p>
</div>
<div v-else>
<p class="empty-title h5">No watcher found.</p>
<p class="empty-subtitle">Do not hesitate to add a watcher.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'managewatchers',
data() {
return {
error:false,
loading:false,
added:false,
watcher:{ name:'', url:'', type:"iocs" },
instances:[],
tabs: { "addwatcher" : true, "instances" : false },
jwt:""
}
},
props: { },
methods: {
add_instance: function()
{
this.added = false;
this.error = false;
if (this.watcher.name && this.watcher.url && this.watcher.type)
{
axios.post(`/api/watchers/add`, { data: { instance: this.watcher } }, { headers: {'X-Token': this.jwt} }).then(response => {
if(response.data.status){
this.added = true;
setTimeout(function (){
this.switch_tab('instances')
this.watcher = { name:'', url:'' }
this.added = false
}.bind(this), 2000);
} else {
this.error = response.data.message;
}
})
.catch(err => (console.log(err)))
}
},
delete_instance(elem)
{
axios.get(`/api/watchers/delete/${elem.id}`, { timeout: 10000, headers: {'X-Token': this.jwt} })
.then(response => {
if(response.data.status){
this.instances = this.instances.filter(function(el) { return el != elem; });
}
})
.catch(err => (console.log(err)))
},
get_watchers_instances()
{
this.loading = true;
this.instances = []
axios.get(`/api/watchers/get_all`, { timeout: 10000, headers: {'X-Token': this.jwt} })
.then(response => {
if(response.data.results){
this.instances = response.data.results;
}
this.loading = false
})
.catch(err => (console.log(err)))
},
switch_tab: function(tab) {
Object.keys(this.tabs).forEach(key => {
if( key == tab ){
this.tabs[key] = true
if (key == "instances") this.get_watchers_instances();
} else {
this.tabs[key] = false
}
});
},
get_jwt(){
axios.get(`/api/get-token`, { timeout: 10000 })
.then(response => {
if(response.data.token){
this.jwt = response.data.token
}
})
.catch(err => (console.log(err)))
}
},
created: function() {
this.get_jwt();
}
}
</script>

View File

@ -0,0 +1,254 @@
<template>
<div class="backend-content" id="content">
<div class="column col-8 col-xs-12">
<h3 class="s-title">Manage IOCs</h3>
<ul class="tab tab-block">
<li class="tab-item">
<a href="#" v-on:click="switch_tab('bulk')" v-bind:class="{ active: tabs.bulk }">Bulk import</a>
</li>
<li class="tab-item">
<a href="#" v-on:click="switch_tab('file')" v-bind:class="{ active: tabs.file }">File import</a>
</li>
<li class="tab-item">
<a href="#" v-on:click="switch_tab('export')" v-bind:class="{ active: tabs.export }">Export IOCs</a>
</li>
</ul>
<div v-if="tabs.export">
<iframe :src="export_url" class="frame-export"></iframe>
</div>
<div v-if="tabs.file">
<label class="form-upload empty" for="upload">
<input type="file" class="upload-field" id="upload" @change="import_from_file">
<p class="empty-title h5">Drop or select a file to import.</p>
<p class="empty-subtitle">The file needs to be an export from a SpyGuard instance.</p>
</label>
</div>
<div v-if="tabs.bulk">
<div class="columns">
<div class="column col-4 col-xs-4">
<div class="form-group">
<select class="form-select" v-model="tag">
<option value="">IOC(s) Tag</option>
<option v-for="t in tags" :value="t" :key="t">
{{ t.toUpperCase() }}
</option>
</select>
</div>
</div>
<div class="column col-4 col-xs-4">
<div class="form-group">
<select class="form-select width-full" v-model="type">
<option value="">IOC(s) Type</option>
<option value="unknown">Multiple (regex parsing)</option>
<option v-for="t in types" :value="t.type" :key="t.type">
{{ t.name }}
</option>
</select>
</div>
</div>
<div class="column col-4 col-xs-4">
<div class="form-group">
<select class="form-select width-full" v-model="tlp">
<option value="">IOC(s) TLP</option>
<option value="white">TLP:WHITE</option>
<option value="green">TLP:GREEN</option>
<option value="amber">TLP:AMBER</option>
<option value="red">TLP:RED</option>
</select>
</div>
</div>
</div>
<div class="form-group">
<textarea class="form-input" id="input-example-3" placeholder="Paste your Indicators of Compromise here" rows="15" v-model="iocs"></textarea>
</div>
<div class="form-group">
<button class="btn-primary btn col-12" v-on:click="import_from_bulk()">Import the IOCs</button>
</div>
</div>
<div class="form-group" v-if="imported.length>0">
<div class="toast toast-success">
{{imported.length}} IOC<span v-if="errors.length>1">s</span> imported successfully.
</div>
</div>
<div v-if="errors.length>0">
<div class="form-group">
<div class="toast toast-error">
{{errors.length}} IOC<span v-if="errors.length>1">s</span> not imported, see details below.
</div>
</div>
<div class="form-group">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Indicator</th>
<th>Importation error</th>
</tr>
</thead>
<tbody>
<tr v-for="e in errors" v-bind:key="e.ioc">
<td>{{ e.ioc }}</td>
<td>{{ e.message }}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div v-else-if="type_tag_error==true">
<div class="form-group">
<div class="toast toast-error">
IOC(s) not imported, see details below.
</div>
</div>
<div class="form-group">
<div class="empty">
<p class="empty-title h5">Please select a tag and a type.</p>
<p class="empty-subtitle">If different IOCs types, select "Unknown (regex parsing)".</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'manageiocs',
data() {
return {
type:"",
tag:"",
tlp:"",
iocs:"",
types:[],
tags:[],
errors:[],
imported:[],
type_tag_error: false,
wrong_ioc_file: false,
tabs: { "bulk" : true, "file" : false, "export" : false },
jwt:"",
export_url:"",
config: {},
watcher: ""
}
},
props: { },
methods: {
import_from_bulk: function() {
this.errors = []
this.imported = []
if (this.tag != "" && this.type != "" && this.tlp != ""){
this.iocs.match(/[^\r\n]+/g).forEach(ioc => {
this.import_ioc(this.tag, this.type, this.tlp, ioc);
});
this.iocs = "";
} else {
this.type_tag_error = true
}
},
import_ioc: function(tag, type, tlp, ioc) {
if (ioc != "" && ioc.slice(0,1) != "#"){
if("alert " != ioc.slice(0,6)) {
ioc = ioc.trim()
ioc = ioc.replace(" ", "")
ioc = ioc.replace("[", "")
ioc = ioc.replace("]", "")
ioc = ioc.replace("\\", "")
ioc = ioc.replace("(", "")
ioc = ioc.replace(")", "")
}
axios.get(`/api/ioc/add/${type.trim()}/${tag.trim()}/${tlp.trim()}/${ioc}`, { timeout: 10000, headers: {'X-Token': this.jwt} })
.then(response => {
if(response.data.status){
this.imported.push(response.data);
} else if (response.data.message){
this.errors.push(response.data);
}
})
.catch(err => (console.log(err)))
}
},
delete_watcher: function(watcher) {
var i = this.config.watchers.indexOf(watcher);
this.config.watchers.splice(i, 1);
},
add_watcher: function() {
this.config.watchers.push(this.watcher);
this.watcher = "";
},
enrich_selects: function() {
axios.get(`/api/ioc/get/tags`, { timeout: 10000, headers: {'X-Token': this.jwt} })
.then(response => {
if(response.data.tags) this.tags = response.data.tags
})
.catch(err => (console.log(err)));
axios.get(`/api/ioc/get/types`, { timeout: 10000, headers: {'X-Token': this.jwt} })
.then(response => {
if(response.data.types) this.types = response.data.types
})
.catch(err => (console.log(err)));
},
switch_tab: function(tab) {
this.errors = []
this.imported = []
Object.keys(this.tabs).forEach(key => {
if( key == tab ){
this.tabs[key] = true
} else {
this.tabs[key] = false
}
});
},
import_from_file: function(ev) {
this.errors = []
this.imported = []
const file = ev.target.files[0];
const reader = new FileReader();
reader.onload = e => this.$emit("load", e.target.result);
reader.onload = () => {
try {
JSON.parse(reader.result).iocs.forEach(ioc => {
this.import_ioc(ioc["tag"], ioc["type"], ioc["tlp"], ioc["value"])
})
} catch (error) {
this.wrong_ioc_file = true
}
}
reader.readAsText(file);
},
async get_jwt(){
await axios.get(`/api/get-token`, { timeout: 10000 })
.then(response => {
if(response.data.token){
this.jwt = response.data.token
}
})
.catch(err => (console.log(err)))
},
load_config: function() {
axios.get(`/api/config/list`, {
timeout: 10000,
headers: { 'X-Token': this.jwt }
}).then(response => {
if (response.data) {
this.config = response.data
}
})
.catch(err => (console.log(err)))
}
},
created: function() {
this.get_jwt().then(() => {
this.enrich_selects();
this.load_config();
this.export_url = `/api/ioc/export?token=${this.jwt}`
});
}
}
</script>

View File

@ -0,0 +1,127 @@
<template>
<div class="backend-content" id="content">
<div class="column col-12 col-xs-12">
<h3 class="s-title">Search IOCs</h3>
<div class="form-group">
<textarea class="form-input" id="input-example-3" placeholder="Paste your IOCs here" rows="3" v-model="iocs"></textarea>
</div>
<div class="form-group">
<button class="btn btn-primary col-12" v-on:click="search_iocs()">Search</button>
</div>
<div class="form-group" v-if="results.length>0 ">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Indicator</th>
<th>Tag</th>
<th>TLP</th>
<th>Source</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr v-for="r in results" :key="r.tlp">
<td>{{ r.value }}</td>
<td class="upper">{{ r.tag }}</td>
<td><label :class="['tlp-' + r.tlp]">{{ r.tlp }}</label></td>
<td class="capi">{{ r.source }}</td>
<td><button class="btn btn-sm" v-on:click="remove(r)">Delete</button></td>
</tr>
</tbody>
</table>
</div>
<div v-else-if="first_search==false">
<div v-if="loading">
<div class="empty">
<p class="empty-title h5">
<span class="loading loading-lg"></span>
</p>
<p class="empty-subtitle">Finding your IOC(s)...</p>
</div>
</div>
<div v-else>
<div class="empty">
<p class="empty-title h5">IOC<span v-if="this.iocs.match(/[^\r\n]+/g).length>1">s</span> not found.</p>
<p class="empty-subtitle">Try wildcard search to expend your search.</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'iocs-search',
data() {
return {
results: [],
first_search: true,
jwt:"",
loading:false
}
},
props: { },
methods: {
search_iocs: function() {
this.results = []
this.first_search = false
this.loading = true;
this.iocs.match(/[^\r\n]+/g).forEach(ioc => {
ioc = ioc.trim()
if("alert " != ioc.slice(0,6)) {
ioc = ioc.replace(" ", "")
ioc = ioc.replace("[", "")
ioc = ioc.replace("]", "")
ioc = ioc.replace("\\", "")
ioc = ioc.replace("(", "")
ioc = ioc.replace(")", "")
}
axios.get(`/api/ioc/search/${ioc}`, { timeout: 10000, headers: {'X-Token': this.jwt} })
.then(response => {
if(response.data.results.length>0){
this.results = [].concat(this.results, response.data.results);
}
this.loading = false;
})
.catch(err => (console.log(err)))
});
return true;
},
remove: function(elem){
axios.get(`/api/ioc/delete/${elem.id}`, { timeout: 10000, headers: {'X-Token': this.jwt} })
.then(response => {
if(response.data.status){
this.results = this.results.filter(function(el) { return el != elem; });
}
})
.catch(err => (console.log(err)))
},
load_config: function() {
axios.get(`/api/config/list`, {
timeout: 10000,
headers: { 'X-Token': this.jwt }
}).then(response => {
if (response.data) {
this.config = response.data
}
})
.catch(err => (console.log(err)))
},
async get_jwt(){
await axios.get(`/api/get-token`, { timeout: 10000 })
.then(response => {
if(response.data.token){
this.jwt = response.data.token
}
})
.catch(err => (console.log(err)))
}
},
created: function() {
this.get_jwt()
}
}
</script>

View File

@ -0,0 +1,131 @@
<template>
<div class="backend-content" id="content">
<div v-bind:class="{ 'alert-toaster-visible' : toaster.show, 'alert-toaster-hidden' : !toaster.show }">{{toaster.message}}</div>
<div class="column col-8 col-xs-12">
<h3 class="s-title">Network configuration</h3>
<h5 class="s-subtitle">Interfaces configuration</h5>
<img src="@/assets/network.png" id="network-thumbnail" />
<div class="container interfaces-container">
<div class="columns">
<div class="column col-6">
<span class="interface-label">Wireless AP interface</span>
<select class="form-select width-full" v-model="iface_in" @change="change_interface('in', iface_in)">
<option v-for="iface in config.ifaces_in" :value="iface" :key="iface">
{{ iface.toUpperCase() }}
</option>
</select>
</div>
<div class="column col-6">
<span class="interface-label">Internet link interface</span>
<select class="form-select width-full" v-model="iface_out" @change="change_interface('out', iface_out)">
<option v-for="iface in config.ifaces_out" :value="iface" :key="iface">
{{ iface.toUpperCase() }}
</option>
</select>
</div>
</div>
</div>
<h5 class="s-subtitle">Edit SSIDs names</h5>
<div class="form-group">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Network name</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr v-for="ssid in config.network.ssids" :key="ssid">
<td>{{ ssid }}</td>
<td><button class="btn btn-sm" v-on:click="delete_ssid(ssid)">Delete</button></td>
</tr>
<tr>
<td><input class="form-input" v-model="ssid" type="text" placeholder="SSID name"></td>
<td><button class="btn btn-sm" @click="add_ssid()">Add</button></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'manageinterface',
data() {
return {
config: {},
ssid: "",
iface_in: "",
toaster: { show: false, message : "", type : null }
}
},
props: {},
methods: {
async get_jwt() {
await axios.get(`/api/get-token`, { timeout: 10000 })
.then(response => {
if (response.data.token) {
this.jwt = response.data.token
}
})
.catch(err => (console.log(err)))
},
load_config: function() {
axios.get(`/api/config/list`, {
timeout: 10000,
headers: { 'X-Token': this.jwt }
}).then(response => {
if (response.data) {
this.config = response.data
this.iface_in = this.config.network.in
this.iface_out = this.config.network.out
console.log(this.iface_in);
}
})
.catch(err => (console.log(err)))
},
delete_ssid: function(ssid) {
var i = this.config.network.ssids.indexOf(ssid);
this.config.network.ssids.splice(i, 1);
this.update_ssids();
},
add_ssid: function() {
this.config.network.ssids.push(this.ssid);
this.ssid = "";
this.update_ssids();
},
update_ssids: function() {
axios.get(`/api/config/edit/network/ssids/${this.config.network.ssids.join("|")}`, {
timeout: 10000,
headers: { 'X-Token': this.jwt }
}).then(response => {
if (response.data.status) {
this.toaster = { show : true, message : "Configuration updated", type : "success" }
setTimeout(function () { this.toaster = { show : false } }.bind(this), 1000)
}
})
.catch(err => (console.log(err)))
},
change_interface: function(type, iface) {
axios.get(`/api/config/edit/network/${type}/${iface}`, {
timeout: 10000,
headers: { 'X-Token': this.jwt }
}).then(response => {
this.toaster = { show : true, message : "Configuration updated", type : "success" }
setTimeout(function () { this.toaster = { show : false } }.bind(this), 1000)
if (response.data.status) this.config.network[type] = iface
})
.catch(err => (console.log(err)))
},
},
created: function() {
this.get_jwt().then(() => {
this.load_config();
});
}
}
</script>

View File

@ -0,0 +1,85 @@
<template>
<div class="backend-content" id="content">
<div class="column col-8 col-xs-12">
<br />
<p><strong>A new SpyGuard version is available ({{next_version}}).</strong><br />
<span v-if="!update_launched">Please click on the button below to update your instance.</span>
<span v-if="update_launched&&!update_finished">Updating SpyGuard, please wait. You'll be redirected once updated.</span>
<span v-if="update_launched&&update_finished" class="color-green"> Update finished!</span>
</p>
<button class="btn btn-primary" :class="[ update_launched ? 'loading' : '' ]" v-on:click="launch_update()" v-if="!update_finished">Update Spyguard</button>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'update',
data() {
return {
translation: {},
update_launched: null,
check_interval: null,
next_version: null,
current_version: null,
update_finished: false,
jwt: "",
}
},
methods: {
check_version: function() {
axios.get('/api/update/get-version', { timeout: 60000, headers: { 'X-Token': this.jwt } })
.then(response => {
if(response.data.status) {
if(response.data.current_version == this.next_version){
window.current_version = response.data.current_version
this.update_finished = true
clearInterval(this.check_interval);
setTimeout(function () { window.location.href = "/"; }, 3000)
}
}
})
.catch(error => { console.log(error) });
},
launch_update: function() {
axios.get(`/api/update/process`, { timeout: 60000, headers: { 'X-Token': this.jwt } })
.then(response => {
if(response.data.status) {
if(response.data.message == "Update successfully launched"){
this.update_launched = true
this.check_interval = setInterval(function(){ this.check_version(); }.bind(this), 3000);
}
}
})
.catch(error => { console.log(error) });
},
async get_jwt() {
await axios.get(`/api/get-token`, { timeout: 10000 })
.then(response => {
if (response.data.token) {
this.jwt = response.data.token
}
})
.catch(err => (console.log(err)))
},
get_versions: function() {
axios.get('/api/update/check', { timeout: 60000, headers: { 'X-Token': this.jwt } })
.then(response => {
if(response.data.status){
this.current_version = response.data.current_version
this.next_version = response.data.next_version
if(this.current_version == this.next_version) window.location.href = "/";
}
})
.catch(error => { console.log(error) });
},
},
created: function() {
this.get_jwt().then(() => {
this.get_versions();
});
}
}
</script>

View File

@ -0,0 +1,191 @@
<template>
<div class="backend-content" id="content">
<div class="column col-8 col-xs-12">
<h3 class="s-title">Manage whitelisted elements</h3>
<ul class="tab tab-block">
<li class="tab-item">
<a href="#" v-on:click="switch_tab('bulk')" v-bind:class="{ active: tabs.bulk }">Bulk elements import</a>
</li>
<li class="tab-item">
<a href="#" v-on:click="switch_tab('file')" v-bind:class="{ active: tabs.file }">Import from file</a>
</li>
<li class="tab-item">
<a href="#" v-on:click="switch_tab('export')" v-bind:class="{ active: tabs.export }">Export elements</a>
</li>
</ul>
<div v-if="tabs.export">
<iframe :src="export_url" class="frame-export"></iframe>
</div>
<div v-if="tabs.file">
<label class="form-upload empty" for="upload">
<input type="file" class="upload-field" id="upload" @change="import_from_file">
<p class="empty-title h5">Drop or select a file to import.</p>
<p class="empty-subtitle">The file needs to be an whitelist file export from a SpyGuard instance.</p>
</label>
</div>
<div v-if="tabs.bulk">
<div class="form-group">
<select class="form-select width-full" placeholder="test" v-model="type">
<option value="">Elements Type</option>
<option value="unknown">Multiple (regex parsing)</option>
<option v-for="t in types" :value="t.type" :key="t.type">
{{ t.name }}
</option>
</select>
</div>
<div class="form-group">
<textarea class="form-input" id="input-example-3" placeholder="Paste the elements to be whitelisted here" rows="15" v-model="elements"></textarea>
</div>
<div class="form-group">
<button class="btn-primary btn col-12" v-on:click="import_from_bulk()">Whitelist elements</button>
</div>
</div>
<div class="form-group" v-if="imported.length>0">
<div class="toast toast-success">
{{imported.length}} IOC<span v-if="errors.length>1">s</span> imported successfully.
</div>
</div>
<div v-if="errors.length>0">
<div class="form-group">
<div class="toast toast-error">
{{errors.length}} IOC<span v-if="errors.length>1">s</span> not imported, see details below.
</div>
</div>
<div class="form-group">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Element</th>
<th>Importation error</th>
</tr>
</thead>
<tbody>
<tr v-for="e in errors" :key="e.element">
<td>{{ e.element }}</td>
<td>{{ e.message }}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div v-else-if="type_tag_error==true">
<div class="form-group">
<div class="toast toast-error">
IOC(s) not imported, see details below.
</div>
</div>
<div class="form-group">
<div class="empty">
<p class="empty-title h5">Please select a tag and a type.</p>
<p class="empty-subtitle">If different IOCs types, select "Unknown (regex parsing)".</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'manageiocs',
data() {
return {
type:"",
elements:"",
types:[],
errors:[],
imported:[],
wrong_wh_file: false,
tabs: { "bulk" : true, "file" : false, "export" : false },
jwt:"",
export_url:""
}
},
props: { },
methods: {
import_from_bulk: function() {
this.errors = []
this.imported = []
if (this.type != ""){
this.elements.match(/[^\r\n]+/g).forEach(elem => {
this.import_element(this.type, elem);
});
this.elements = "";
} else {
this.type_tag_error = true
}
},
import_element: function(type, elem) {
if (elem != "" && elem.slice(0,1) != "#"){
axios.get(`/api/whitelist/add/${type.trim()}/${elem.trim()}`, {
timeout: 10000,
headers: { "X-Token" : this.jwt }
}).then(response => {
if(response.data.status){
this.imported.push(response.data);
} else if (response.data.message){
this.errors.push(response.data);
}
})
.catch(err => (console.log(err)))
}
},
enrich_types: function() {
axios.get(`/api/whitelist/get/types`, { timeout: 10000, headers: {'X-Token': this.jwt} })
.then(response => {
if(response.data.types) this.types = response.data.types
})
.catch(err => (console.log(err)));
},
switch_tab: function(tab) {
this.errors = []
this.imported = []
Object.keys(this.tabs).forEach(key => {
if( key == tab ){
this.tabs[key] = true
} else {
this.tabs[key] = false
}
});
},
import_from_file: function(ev) {
this.errors = []
this.imported = []
const file = ev.target.files[0];
const reader = new FileReader();
reader.onload = e => this.$emit("load", e.target.result);
reader.onload = () => {
try {
JSON.parse(reader.result).elements.forEach(elem => {
this.import_element(elem["type"], elem["element"])
})
} catch (error) {
this.wrong_wh_file = true
}
}
reader.readAsText(file);
},
async get_jwt(){
await axios.get(`/api/get-token`, { timeout: 10000 })
.then(response => {
if(response.data.token){
this.jwt = response.data.token
}
})
.catch(err => (console.log(err)))
}
},
created: function() {
this.get_jwt().then(() => {
this.enrich_types();
this.export_url = `/api/whitelist/export?token=${this.jwt}`
});
}
}
</script>

View File

@ -0,0 +1,94 @@
<template>
<div class="backend-content" id="content">
<div class="column col-12 col-xs-12">
<h3 class="s-title">Search whitelisted elements</h3>
<div class="form-group">
<textarea class="form-input" id="input-example-3" placeholder="Paste the elements here" rows="3" v-model="elements"></textarea>
</div>
<div class="form-group">
<button class="btn btn-primary col-12" v-on:click="search_elements()">Search</button>
</div>
<div class="form-group" v-if="results.length>0 ">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Element</th>
<th>Element type</th>
<th> </th>
</tr>
</thead>
<tbody>
<tr v-for="r in results" :key="r.element">
<td>{{ r.element }}</td>
<td>{{ r.type }}</td>
<td><button class="btn btn-sm" v-on:click="remove(r)">Delete</button></td>
</tr>
</tbody>
</table>
</div>
<div v-else-if="first_search==false">
<div class="empty">
<p class="empty-title h5">Element<span v-if="this.elements.match(/[^\r\n]+/g).length>1">s</span> not found.</p>
<p class="empty-subtitle">Try wildcard search to expend your search.</p>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'elements-search',
data() {
return {
results: [],
first_search: true,
jwt:""
}
},
props: { },
methods: {
search_elements: function() {
this.results = []
this.first_search = false
this.elements.match(/[^\r\n]+/g).forEach(elem => {
axios.get(`/api/whitelist/search/${elem.trim()}`, {
timeout: 10000,
headers: {'X-Token': this.jwt}
}).then(response => {
if(response.data.results.length>0){
this.results = [].concat(this.results, response.data.results);
}
})
.catch(err => (console.log(err)))
});
return true;
},
remove: function(elem){
axios.get(`/api/whitelist/delete/${elem.id}`, {
timeout: 10000,
headers: {'X-Token': this.jwt}
}).then(response => {
if(response.data.status){
this.results = this.results.filter(function(el) { return el != elem; });
}
})
.catch(err => (console.log(err)))
},
async get_jwt(){
await axios.get(`/api/get-token`, { timeout: 10000 })
.then(response => {
if(response.data.token){
this.jwt = response.data.token
}
})
.catch(err => (console.log(err)))
}
},
created: function() {
this.get_jwt()
}
}
</script>

11
app/backend/vue.config.js Executable file
View File

@ -0,0 +1,11 @@
module.exports = {
devServer: {
proxy: {
'^/api': {
target: 'https://localhost:5000',
ws: true,
changeOrigin: true
},
}
}
}

1
app/frontend/.npmrc Executable file
View File

@ -0,0 +1 @@
timeout=60000

24
app/frontend/README.md Executable file
View File

@ -0,0 +1,24 @@
# tinycheck-new
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

Some files were not shown because too many files have changed in this diff Show More