├── .devcontainer ├── .env.sample ├── .htaccess ├── devcontainer.json ├── docker-compose.yml └── docker-uninstall.sh ├── .dockerignore ├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── BUG.yml │ ├── ENHANCEMENT.yml │ ├── EPIC.yml │ ├── FEATURE.yml │ └── config.yml ├── scripts │ └── await-hashtopolis-startup.sh └── workflows │ └── ci.yml ├── .gitignore ├── .vscode ├── launch.json └── settings.json ├── 000-default.conf ├── Dockerfile ├── LICENSE.txt ├── README.md ├── ci ├── HashtopolisTest.class.php ├── HashtopolisTestFramework.class.php ├── apiv2 │ ├── .flake8 │ ├── HACKING.md │ ├── PERMISSIONS_REWORK.md │ ├── create_accessgroup_001.json │ ├── create_accessgroup_002.json │ ├── create_agentbinary_001.json │ ├── create_cracker_001.json │ ├── create_cracker_002.json │ ├── create_crackertype_001.json │ ├── create_crackertype_002.json │ ├── create_file_001.json │ ├── create_hashlist_001.json │ ├── create_hashlist_002.json │ ├── create_hashlist_003.json │ ├── create_hashtype_001.json │ ├── create_healthcheck_001.json │ ├── create_notification_001.json │ ├── create_preprocessor_001.json │ ├── create_pretask_001.json │ ├── create_pretask_003.json │ ├── create_supertask_001.json │ ├── create_task_001.json │ ├── create_task_002.json │ ├── create_task_003.json │ ├── generate_dummy_data.py │ ├── hashtopolis-test-defaults.yaml │ ├── hashtopolis.py │ ├── hashtopolis_agent.py │ ├── htcli.py │ ├── poc_openapi_perm_test.sh │ ├── requirements.txt │ ├── test_accessgroup.py │ ├── test_agent.py │ ├── test_agentassignment.py │ ├── test_agentbinary.py │ ├── test_agentstat.py │ ├── test_attributes.py │ ├── test_chunk.py │ ├── test_config.py │ ├── test_configsection.py │ ├── test_cracker.py │ ├── test_crackertype.py │ ├── test_expand.py │ ├── test_file.py │ ├── test_filter_and_ordering.py │ ├── test_globalpermissiongroup.py │ ├── test_hash.py │ ├── test_hashlist.py │ ├── test_hashtype.py │ ├── test_healthcheck.py │ ├── test_healthcheckagents.py │ ├── test_http_methods.py │ ├── test_logentry.py │ ├── test_notification.py │ ├── test_preprocessor.py │ ├── test_pretask.py │ ├── test_schema.py │ ├── test_speed.py │ ├── test_supertask.py │ ├── test_task.py │ ├── test_taskwrapper.py │ ├── test_user.py │ ├── test_voucher.py │ └── utils.py ├── bundle.sh ├── files │ ├── README.md │ ├── apache.conf │ ├── best64.rule │ ├── db_0.10.0.sql │ ├── db_0.11.0.sql │ ├── db_0.12.0.sql │ ├── db_0.7.0.sql │ ├── db_0.8.0.sql │ ├── db_0.9.0.sql │ ├── example.dict │ ├── example0.hash │ └── prepare.sh ├── run.php ├── server │ └── setup.php └── tests │ ├── AccountTest.class.php │ ├── AgentTest.class.php │ ├── ConfigTest.class.php │ ├── CrackerTest.class.php │ ├── FileTest.class.php │ ├── GroupTest.class.php │ ├── HashlistTest.class.php │ ├── PretaskTest.class.php │ ├── TaskTest.class.php │ ├── TestTest.class.php │ ├── UserTest.class.php │ └── integration │ ├── MaxAgentsTest.class.php │ └── RuleSplitTest.class.php ├── composer.json ├── composer.lock ├── doc ├── .gitignore ├── README.md ├── changelog.md ├── php_style.xml ├── protocol.pdf ├── protocol.tex └── user-api │ ├── sections │ ├── access.tex │ ├── account.tex │ ├── agent.tex │ ├── config.tex │ ├── cracker.tex │ ├── file.tex │ ├── group.tex │ ├── hashlist.tex │ ├── pretask.tex │ ├── superhashlist.tex │ ├── supertask.tex │ ├── task.tex │ ├── test.tex │ └── user.text.tex │ ├── user-api.pdf │ └── user-api.tex ├── docker-compose.yml ├── docker-entrypoint.sh ├── env.example └── src ├── about.php ├── access.php ├── account.php ├── agentStatus.php ├── agents.php ├── ajax └── get_subtasks.php ├── api.php ├── api ├── server.php ├── taskimg.php ├── user.php └── v2 │ ├── .htaccess │ └── index.php ├── apidocs ├── favicon-16x16.png ├── favicon-32x32.png ├── index.css ├── index.html ├── oauth2-redirect.html ├── swagger-initializer.js ├── swagger-ui-bundle.js ├── swagger-ui-bundle.js.map ├── swagger-ui-es-bundle-core.js ├── swagger-ui-es-bundle-core.js.map ├── swagger-ui-es-bundle.js ├── swagger-ui-es-bundle.js.map ├── swagger-ui-standalone-preset.js ├── swagger-ui-standalone-preset.js.map ├── swagger-ui.css ├── swagger-ui.css.map ├── swagger-ui.js └── swagger-ui.js.map ├── bin ├── .htaccess └── hashtopolis.zip ├── binaries.php ├── chunks.php ├── config.php ├── crackers.php ├── cracks.php ├── dba ├── AbstractModel.class.php ├── AbstractModelFactory.class.php ├── ComparisonFilter.class.php ├── ContainFilter.class.php ├── Factory.class.php ├── Filter.class.php ├── Group.class.php ├── GroupFilter.class.php ├── Join.class.php ├── JoinFilter.class.php ├── LikeFilter.class.php ├── LikeFilterInsensitive.class.php ├── MassUpdateSet.class.php ├── Order.class.php ├── OrderFilter.class.php ├── QueryFilter.class.php ├── QueryFilterNoCase.class.php ├── QueryFilterWithNull.class.php ├── UpdateSet.class.php ├── Util.class.php ├── init.php └── models │ ├── AbstractModel.template.txt │ ├── AbstractModelFactory.template.txt │ ├── AccessGroup.class.php │ ├── AccessGroupAgent.class.php │ ├── AccessGroupAgentFactory.class.php │ ├── AccessGroupFactory.class.php │ ├── AccessGroupUser.class.php │ ├── AccessGroupUserFactory.class.php │ ├── Agent.class.php │ ├── AgentBinary.class.php │ ├── AgentBinaryFactory.class.php │ ├── AgentError.class.php │ ├── AgentErrorFactory.class.php │ ├── AgentFactory.class.php │ ├── AgentStat.class.php │ ├── AgentStatFactory.class.php │ ├── AgentZap.class.php │ ├── AgentZapFactory.class.php │ ├── ApiGroup.class.php │ ├── ApiGroupFactory.class.php │ ├── ApiKey.class.php │ ├── ApiKeyFactory.class.php │ ├── Assignment.class.php │ ├── AssignmentFactory.class.php │ ├── Chunk.class.php │ ├── ChunkFactory.class.php │ ├── Config.class.php │ ├── ConfigFactory.class.php │ ├── ConfigSection.class.php │ ├── ConfigSectionFactory.class.php │ ├── CrackerBinary.class.php │ ├── CrackerBinaryFactory.class.php │ ├── CrackerBinaryType.class.php │ ├── CrackerBinaryTypeFactory.class.php │ ├── Factory.template.txt │ ├── File.class.php │ ├── FileDelete.class.php │ ├── FileDeleteFactory.class.php │ ├── FileDownload.class.php │ ├── FileDownloadFactory.class.php │ ├── FileFactory.class.php │ ├── FilePretask.class.php │ ├── FilePretaskFactory.class.php │ ├── FileTask.class.php │ ├── FileTaskFactory.class.php │ ├── Hash.class.php │ ├── HashBinary.class.php │ ├── HashBinaryFactory.class.php │ ├── HashFactory.class.php │ ├── HashType.class.php │ ├── HashTypeFactory.class.php │ ├── Hashlist.class.php │ ├── HashlistFactory.class.php │ ├── HashlistHashlist.class.php │ ├── HashlistHashlistFactory.class.php │ ├── HealthCheck.class.php │ ├── HealthCheckAgent.class.php │ ├── HealthCheckAgentFactory.class.php │ ├── HealthCheckFactory.class.php │ ├── LogEntry.class.php │ ├── LogEntryFactory.class.php │ ├── NotificationSetting.class.php │ ├── NotificationSettingFactory.class.php │ ├── Preprocessor.class.php │ ├── PreprocessorFactory.class.php │ ├── Pretask.class.php │ ├── PretaskFactory.class.php │ ├── RegVoucher.class.php │ ├── RegVoucherFactory.class.php │ ├── RightGroup.class.php │ ├── RightGroupFactory.class.php │ ├── Session.class.php │ ├── SessionFactory.class.php │ ├── Speed.class.php │ ├── SpeedFactory.class.php │ ├── StoredValue.class.php │ ├── StoredValueFactory.class.php │ ├── Supertask.class.php │ ├── SupertaskFactory.class.php │ ├── SupertaskPretask.class.php │ ├── SupertaskPretaskFactory.class.php │ ├── Task.class.php │ ├── TaskDebugOutput.class.php │ ├── TaskDebugOutputFactory.class.php │ ├── TaskFactory.class.php │ ├── TaskWrapper.class.php │ ├── TaskWrapperFactory.class.php │ ├── User.class.php │ ├── UserFactory.class.php │ ├── Zap.class.php │ ├── ZapFactory.class.php │ └── generator.php ├── files.php ├── forgot.php ├── getFile.php ├── getFound.php ├── getHashlist.php ├── groups.php ├── hashes.php ├── hashlists.php ├── hashtypes.php ├── health.php ├── help.php ├── inc ├── .gitignore ├── .htaccess ├── Auth_Yubico.class.php ├── CSRF.class.php ├── Dataset.class.php ├── Encryption.class.php ├── HTException.class.php ├── HTMessages.class.php ├── Lang.class.php ├── Login.class.php ├── Menu.class.php ├── SConfig.class.php ├── UI.class.php ├── Util.class.php ├── api │ ├── APIBasic.class.php │ ├── APICheckClientVersion.class.php │ ├── APIClientError.class.php │ ├── APIDeRegisterAgent.class.php │ ├── APIDownloadBinary.class.php │ ├── APIGetChunk.class.php │ ├── APIGetFile.class.php │ ├── APIGetFileStatus.class.php │ ├── APIGetFound.class.php │ ├── APIGetHashlist.class.php │ ├── APIGetHealthCheck.class.php │ ├── APIGetTask.class.php │ ├── APILogin.class.php │ ├── APIRegisterAgent.class.php │ ├── APISendBenchmark.class.php │ ├── APISendHealthCheck.class.php │ ├── APISendKeyspace.class.php │ ├── APISendProgress.class.php │ ├── APITestConnection.class.php │ └── APIUpdateClientInformation.class.php ├── apiv2 │ ├── auth │ │ └── token.routes.php │ ├── common │ │ ├── AbstractBaseAPI.class.php │ │ ├── AbstractHelperAPI.class.php │ │ ├── AbstractModelAPI.class.php │ │ └── openAPISchema.routes.php │ ├── helper │ │ ├── abortChunk.routes.php │ │ ├── assignAgent.routes.php │ │ ├── createSuperHashlist.routes.php │ │ ├── createSupertask.routes.php │ │ ├── exportCrackedHashes.routes.php │ │ ├── exportLeftHashes.routes.php │ │ ├── exportWordlist.routes.php │ │ ├── importCrackedHashes.routes.php │ │ ├── importFile.routes.php │ │ ├── purgeTask.routes.php │ │ ├── recountFileLines.routes.php │ │ ├── resetChunk.routes.php │ │ ├── setUserPassword.routes.php │ │ └── unassignAgent.routes.php │ └── model │ │ ├── accessgroups.routes.php │ │ ├── agentassignments.routes.php │ │ ├── agentbinaries.routes.php │ │ ├── agents.routes.php │ │ ├── agentstats.routes.php │ │ ├── chunks.routes.php │ │ ├── configs.routes.php │ │ ├── configsections.routes.php │ │ ├── crackers.routes.php │ │ ├── crackertypes.routes.php │ │ ├── files.routes.php │ │ ├── globalpermissiongroups.routes.php │ │ ├── hashes.routes.php │ │ ├── hashlists.routes.php │ │ ├── hashtypes.routes.php │ │ ├── healthcheckagents.routes.php │ │ ├── healthchecks.routes.php │ │ ├── logentries.routes.php │ │ ├── notifications.routes.php │ │ ├── preprocessors.routes.php │ │ ├── pretasks.routes.php │ │ ├── speeds.routes.php │ │ ├── supertasks.routes.php │ │ ├── tasks.routes.php │ │ ├── taskwrappers.routes.php │ │ ├── users.routes.php │ │ └── vouchers.routes.php ├── conf.template.php ├── confv2.php ├── defines │ ├── accessControl.php │ ├── accessGroups.php │ ├── agents.php │ ├── api.php │ ├── config.php │ ├── crackerBinaries.php │ ├── deviceCompress.php │ ├── fileDownload.php │ ├── files.php │ ├── global.php │ ├── hashcat.php │ ├── hashlists.php │ ├── health.php │ ├── log.php │ ├── notifications.php │ ├── preprocessors.php │ ├── tasks.php │ ├── userApi.php │ └── users.php ├── handlers │ ├── AccessControlHandler.class.php │ ├── AccessGroupHandler.class.php │ ├── AccountHandler.class.php │ ├── AgentBinaryHandler.class.php │ ├── AgentHandler.class.php │ ├── ApiHandler.class.php │ ├── ConfigHandler.class.php │ ├── CrackerHandler.class.php │ ├── FileHandler.class.php │ ├── ForgotHandler.class.php │ ├── Handler.class.php │ ├── HashlistHandler.class.php │ ├── HashtypeHandler.class.php │ ├── HealthHandler.class.php │ ├── NotificationHandler.class.php │ ├── PreprocessorHandler.class.php │ ├── PretaskHandler.class.php │ ├── SearchHandler.class.php │ ├── SupertaskHandler.class.php │ ├── TaskHandler.class.php │ └── UsersHandler.class.php ├── info.php ├── load.php ├── mask.php ├── notifications │ ├── Notification.class.php │ ├── NotificationChatBot.class.php │ ├── NotificationDiscord.class.php │ ├── NotificationEmail.class.php │ ├── NotificationExample.class.php │ ├── NotificationSlack.class.php │ └── NotificationTelegram.class.php ├── protocol.php ├── runner │ ├── .gitkeep │ ├── runner.zip │ └── uftp ├── templating │ ├── Statement.class.php │ └── Template.class.php ├── user-api │ ├── UserAPIAccess.class.php │ ├── UserAPIAccount.class.php │ ├── UserAPIAgent.class.php │ ├── UserAPIBasic.class.php │ ├── UserAPIConfig.class.php │ ├── UserAPICracker.class.php │ ├── UserAPIFile.class.php │ ├── UserAPIGroup.class.php │ ├── UserAPIHashlist.class.php │ ├── UserAPIPretask.class.php │ ├── UserAPISuperhashlist.class.php │ ├── UserAPISupertask.class.php │ ├── UserAPITask.class.php │ ├── UserAPITest.class.php │ └── UserAPIUser.class.php └── utils │ ├── AccessControl.class.php │ ├── AccessControlUtils.class.php │ ├── AccessGroupUtils.class.php │ ├── AccessUtils.class.php │ ├── AccountUtils.php │ ├── AgentBinaryUtils.class.php │ ├── AgentUtils.class.php │ ├── ApiUtils.class.php │ ├── ChunkUtils.class.php │ ├── ConfigUtils.class.php │ ├── CrackerBinaryUtils.class.php │ ├── CrackerUtils.class.php │ ├── FileDownloadUtils.class.php │ ├── FileUtils.class.php │ ├── HashlistUtils.class.php │ ├── HashtypeUtils.class.php │ ├── HealthUtils.class.php │ ├── Lock.class.php │ ├── LockUtils.class.php │ ├── NotificationUtils.class.php │ ├── PreprocessorUtils.class.php │ ├── PretaskUtils.class.php │ ├── RunnerUtils.class.php │ ├── SupertaskUtils.class.php │ ├── TaskUtils.class.php │ ├── UserUtils.class.php │ └── locks │ └── .gitkeep ├── index.php ├── install ├── hashtopolis.sql ├── index.php └── updates │ ├── .gitkeep │ ├── reset.php │ ├── update.php │ ├── update_v0.10.x_v0.11.0.php │ ├── update_v0.11.x_v0.12.0.php │ ├── update_v0.12.x_v0.13.0.php │ ├── update_v0.13.x_v0.13.1.php │ ├── update_v0.14.2_v0.14.3.php │ ├── update_v0.14.3_v0.14.4.php │ ├── update_v0.14.x_v0.14.2.php │ ├── update_v0.2.0-beta_v0.2.0.php │ ├── update_v0.2.x_v0.3.0.php │ ├── update_v0.3.0_v0.3.1.php │ ├── update_v0.3.1_v0.3.2.php │ ├── update_v0.3.2_v0.4.0.php │ ├── update_v0.4.0_v0.5.0.php │ ├── update_v0.5.x_v0.6.0.php │ ├── update_v0.6.0_v0.7.0.php │ ├── update_v0.7.x_v0.8.0.php │ ├── update_v0.8.0_v0.9.0.php │ └── update_v0.9.0_v0.10.0.php ├── jscolor ├── arrow.gif ├── cross.gif ├── hs.png ├── hv.png └── jscolor.js ├── lang ├── .htaccess ├── DE-de.php └── EN-en.php ├── log.php ├── login.php ├── logout.php ├── notifications.php ├── preprocessors.php ├── pretasks.php ├── report.php ├── search.php ├── static ├── 7zr.bin ├── 7zr.exe ├── 7zr.osx ├── all.js ├── bootstrap-grid.min.css ├── bootstrap-grid.min.css.map ├── bootstrap-reboot.min.css ├── bootstrap-reboot.min.css.map ├── bootstrap.bundle.min.js ├── bootstrap.bundle.min.js.map ├── bootstrap.dark.custom.css ├── bootstrap.dark.min.css ├── bootstrap.min.css ├── bootstrap.min.css.map ├── bootstrap.min.js ├── bootstrap.min.js.map ├── chartjs.bundle.min.js ├── datatables.min.css ├── datatables.min.js ├── hashtopolis.js ├── jquery.min.js ├── js.cookie.min.js ├── logo.png ├── logo_red.png ├── navbar.css ├── optparse.1.1.1.js ├── optparse.hashtopolis.1.1.1.js ├── popper.min.js ├── popper.min.js.map ├── select2-bootstrap-5.dark.min.css ├── select2-bootstrap-5.min.css ├── select2.min.css ├── select2.min.js └── uftpd.bin ├── superhashlists.php ├── supertasks.php ├── tasks.php ├── templates ├── .htaccess ├── access │ ├── detail.template.html │ ├── index.template.html │ └── new.template.html ├── account.template.html ├── agents │ ├── detail.temperature.template.html │ ├── detail.template.html │ ├── index.template.html │ ├── new.template.html │ └── status.template.html ├── api │ ├── detail.template.html │ ├── index.template.html │ ├── key.template.html │ ├── new.template.html │ └── newkey.template.html ├── binaries.template.html ├── chunks.template.html ├── config.template.html ├── crackers │ ├── detail.template.html │ ├── editVersion.template.html │ ├── index.template.html │ ├── new.template.html │ └── newVersion.template.html ├── cracks.template.html ├── email │ ├── creation.plain.template.html │ ├── creation.template.html │ ├── forgot.plain.template.html │ └── forgot.template.html ├── errors │ ├── error.template.html │ └── restricted.template.html ├── files │ ├── edit.template.html │ └── index.template.html ├── forgot.template.html ├── groups │ ├── detail.template.html │ ├── index.template.html │ └── new.template.html ├── hashes │ └── index.template.html ├── hashlists │ ├── detail.template.html │ ├── detail │ │ ├── pretasks.template.html │ │ ├── superhashlist.template.html │ │ ├── supertasks.template.html │ │ └── tasks.template.html │ ├── index.template.html │ ├── new.template.html │ └── zap.template.html ├── hashtypes.template.html ├── health │ ├── detail.template.html │ └── index.template.html ├── install │ ├── 0.template.html │ ├── 1.template.html │ ├── 2.template.html │ ├── 50.template.html │ ├── 51.template.html │ ├── 52.template.html │ ├── foot.template.html │ └── head.template.html ├── log.template.html ├── notifications.template.html ├── notifications │ ├── chatbot.template.html │ ├── discord.template.html │ ├── email.template.html │ ├── example.template.html │ ├── slack.template.html │ └── telegram.template.html ├── preprocessors │ ├── details.template.html │ ├── edit.template.html │ ├── index.template.html │ └── new.template.html ├── pretasks │ ├── detail.template.html │ ├── index.template.html │ └── new.template.html ├── report │ ├── hashlist-example.template.tex │ └── health-check-example.template.tex ├── search.template.html ├── static │ ├── about.template.html │ ├── help.template.html │ └── index.template.html ├── struct │ ├── foot.template.html │ ├── head.template.html │ ├── menu.template.html │ └── messages.template.html ├── superhashlists │ ├── index.template.html │ └── new.template.html ├── supertasks │ ├── create.template.html │ ├── detail.template.html │ ├── import.template.html │ ├── index.template.html │ └── new.template.html ├── tasks │ ├── autorefresh.template.html │ ├── detail.template.html │ ├── index.template.html │ ├── new.template.html │ ├── normal.template.html │ ├── subtasks.template.html │ └── supertask.template.html └── users │ ├── detail.template.html │ ├── index.template.html │ └── new.template.html ├── users.php └── webfonts ├── fa-brands-400.eot ├── fa-brands-400.svg ├── fa-brands-400.ttf ├── fa-brands-400.woff ├── fa-brands-400.woff2 ├── fa-regular-400.eot ├── fa-regular-400.svg ├── fa-regular-400.ttf ├── fa-regular-400.woff ├── fa-regular-400.woff2 ├── fa-solid-900.eot ├── fa-solid-900.svg ├── fa-solid-900.ttf ├── fa-solid-900.woff └── fa-solid-900.woff2 /.devcontainer/.env.sample: -------------------------------------------------------------------------------- 1 | CONTAINER_USER_CMD_PRE='cat > /usr/local/share/ca-certificates/corporate_ca.crt << EOF 2 | -----BEGIN CERTIFICATE----- 3 | <<< INSERT_PEM_FORMATTED_ROOT_CA_CHAIN_HERE >>> 4 | -----END CERTIFICATE----- 5 | EOF 6 | update-ca-certificates --fresh 7 | echo "openssl.cafile=/etc/ssl/certs/ca-certificates.crt" > /usr/local/etc/php/conf.d/corporate-cert.ini 8 | mkdir -p /usr/etc/ 9 | 10 | # NPM repository cache example 11 | echo "registry=https://nexus.example.com/repository/npm-all/" > /usr/etc/npmrc 12 | ' -------------------------------------------------------------------------------- /.devcontainer/.htaccess: -------------------------------------------------------------------------------- 1 | Order deny,allow 2 | Deny from all -------------------------------------------------------------------------------- /.devcontainer/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | services: 3 | hashtopolis-server-dev: 4 | container_name: hashtopolis-server-dev 5 | build: 6 | context: .. 7 | target: hashtopolis-server-dev 8 | args: 9 | - CONTAINER_USER_CMD_PRE 10 | - CONTAINER_USER_CMD_POST 11 | environment: 12 | HASHTOPOLIS_DB_USER: hashtopolis 13 | HASHTOPOLIS_DB_PASS: hashtopolis 14 | HASHTOPOLIS_DB_HOST: hashtopolis-db-dev 15 | HASHTOPOLIS_DB_DATABASE: hashtopolis 16 | HASHTOPOLIS_APIV2_ENABLE: 1 17 | depends_on: 18 | - hashtopolis-db-dev 19 | ports: 20 | - "8080:80" 21 | volumes: 22 | # This is where VS Code should expect to find your project's source code 23 | # and the value of "workspaceFolder" in .devcontainer/devcontainer.json 24 | - ..:/var/www/html 25 | - hashtopolis-server-dev:/usr/local/share/hashtopolis:Z 26 | networks: 27 | - hashtopolis_dev 28 | hashtopolis-db-dev: 29 | container_name: hashtopolis-db-dev 30 | image: mysql:8.0 31 | restart: always 32 | ports: 33 | - "3306:3306" 34 | volumes: 35 | - hashtopolis-db-dev:/var/lib/mysql 36 | environment: 37 | MYSQL_ROOT_PASSWORD: hashtopolis 38 | MYSQL_DATABASE: hashtopolis 39 | MYSQL_USER: hashtopolis 40 | MYSQL_PASSWORD: hashtopolis 41 | networks: 42 | - hashtopolis_dev 43 | volumes: 44 | hashtopolis-db-dev: 45 | hashtopolis-server-dev: 46 | 47 | networks: 48 | hashtopolis_dev: 49 | # This network will also be used by the python-agent 50 | name: hashtopolis_dev 51 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | /.buildpath 2 | /.project 3 | /.settings/ 4 | query.log 5 | .idea/ 6 | *.iml 7 | src/files/* 8 | !src/files/.htaccess 9 | .vs/ 10 | *.phpproj 11 | *.sln 12 | *.phpproj.user 13 | 14 | # for docker stuff 15 | /db/ 16 | data/conf.php 17 | .env 18 | src/import/* 19 | .gitignore 20 | .dockerignore 21 | src/inc/conf.php 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/BUG.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: File a bug report 3 | title: "[BUG]: " 4 | labels: ["bug"] 5 | assignees: 6 | - octocat 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | Before you submit a bug report please make sure that the same bug was not reported previously. 12 | Further, make sure to include as much information as possible to help identifying it. 13 | - type: input 14 | id: version 15 | attributes: 16 | label: Version Information 17 | description: Which version(s) of the backend, frontend and ui (depending on the bug) are you using. 18 | validations: 19 | required: true 20 | - type: input 21 | id: hashcat 22 | attributes: 23 | label: Hashcat 24 | description: If applicable, which version of Hashcat were you running? 25 | validations: 26 | required: false 27 | - type: textarea 28 | id: description 29 | attributes: 30 | label: Description 31 | description: Describe your issue in as much detail as possible, this may include the exact task command you are trying to run, debug output from the client by running "hashtopolis.exe -d" or with debug flag set on the python client and steps to reproduce. 32 | value: "<> is not a description." 33 | validations: 34 | required: true 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/ENHANCEMENT.yml: -------------------------------------------------------------------------------- 1 | name: Enhancement 2 | description: Enhancement of a feature or functionality 3 | title: "[ENHANCEMENT]: " 4 | labels: ["enhancement"] 5 | assignees: 6 | - octocat 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | Please try to describe the desired enhancement as exactly as possible. 12 | - type: textarea 13 | id: description 14 | attributes: 15 | label: Description 16 | description: "Describe your enhancement proposal as detailed as possible, providing examples helps to understand the desired behavior." 17 | value: "Enhancement Description" 18 | validations: 19 | required: true 20 | 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/EPIC.yml: -------------------------------------------------------------------------------- 1 | name: Epic 2 | description: Feature issue for large additions/changes. Should only be used by Collaborators. 3 | title: "[EPIC]: " 4 | labels: ["epic"] 5 | assignees: 6 | - octocat 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | Please try to describe the desired new addition in detail, i.e. by providing example behaviour, needed actions, handling etc. 12 | - type: textarea 13 | id: description 14 | attributes: 15 | label: Description 16 | description: "Describe your EPIC feature here." 17 | value: "make sure you only propose epic features" 18 | validations: 19 | required: true 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/FEATURE.yml: -------------------------------------------------------------------------------- 1 | name: Feature 2 | description: Request a new feature or functionality 3 | title: "[FEATURE]: " 4 | labels: ["feature"] 5 | assignees: 6 | - octocat 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | Please try to describe the desired new functionality in detail, i.e. by providing example behaviour, needed actions, handling etc. 12 | - type: textarea 13 | id: description 14 | attributes: 15 | label: Description 16 | description: "Describe desired functionality here." 17 | value: "make sure that no feature request exists with the same request already" 18 | validations: 19 | required: true 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/scripts/await-hashtopolis-startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | COUNT=0 4 | while [ $COUNT -lt 16 ] 5 | do 6 | curl localhost:8080/api/server.php -X POST -H 'Content-Type: application/json' -d '{ "action": "testConnection" }' | grep SUCCESS 7 | if [ $? -eq 0 ]; then 8 | exit 0 9 | fi 10 | COUNT=$[$COUNT+1] 11 | sleep 4 12 | done 13 | exit 1 -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Hashtopolis 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - dev 8 | pull_request: 9 | branches: 10 | - master 11 | - dev 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout repository 18 | uses: actions/checkout@v3 19 | - name: Start application containers 20 | working-directory: .devcontainer 21 | run: docker compose up -d 22 | - name: Wait until entrypoint is finished and Hashtopolis is started 23 | run: bash .github/scripts/await-hashtopolis-startup.sh 24 | - name: Give Apache permissions on necessary directories # for the tests, only src/files and src/inc/utils/locks seem necessary 25 | run: docker exec -u root hashtopolis-server-dev bash -c "chown -R www-data:www-data /var/www/html/src && chmod -R g+w /var/www/html/src" 26 | - name: Run test suite 27 | run: docker exec hashtopolis-server-dev php /var/www/html/ci/run.php -vmaster 28 | - name: Install composer dependencies packages 29 | run: docker exec hashtopolis-server-dev composer install --working-dir=/var/www/html/ 30 | - name: Test with pytest 31 | run: docker exec hashtopolis-server-dev pytest /var/www/html/ci/apiv2 32 | - name: Test if pytest is removing all test objects 33 | run: docker exec hashtopolis-server-dev python3 /var/www/html/ci/apiv2/htcli.py run delete-test-data 34 | - name: Show docker log files 35 | if: ${{ always() }} 36 | run: docker logs hashtopolis-server-dev 37 | - name: Show installed files tree in /var/www/html 38 | if: ${{ always() }} 39 | run: docker exec hashtopolis-server-dev find /var/www/html -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.buildpath 2 | /.project 3 | /.settings/ 4 | query.log 5 | .idea/ 6 | *.iml 7 | src/files/* 8 | !src/files/.htaccess 9 | /ci/db-backups/ 10 | .vs/ 11 | *.phpproj 12 | *.sln 13 | *.phpproj.user 14 | *.lock 15 | 16 | # dynamically created by installer 17 | src/install/.htaccess 18 | 19 | # for docker stuff 20 | .env 21 | 22 | # for composer stuff 23 | vendor 24 | 25 | # For python cache files 26 | __pycache__ 27 | .pytest_cache 28 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.testing.unittestArgs": [ 3 | "-v", 4 | "-s", 5 | "./ci", 6 | "-p", 7 | "test_*.py" 8 | ], 9 | "python.testing.pytestEnabled": true, 10 | "python.testing.unittestEnabled": false, 11 | "python.testing.pytestArgs": [ 12 | "ci" 13 | ], 14 | "intelephense.environment.includePaths": [ 15 | "../vendor" 16 | ], 17 | "flake8.args": [ 18 | "--max-line-length=120" 19 | ], 20 | } -------------------------------------------------------------------------------- /000-default.conf: -------------------------------------------------------------------------------- 1 | 2 | DocumentRoot ${HASHTOPOLIS_DOCUMENT_ROOT} 3 | ErrorLog ${APACHE_LOG_DIR}/error.log 4 | CustomLog ${APACHE_LOG_DIR}/access.log combined 5 | 6 | 7 | AllowOverride All 8 | 9 | 10 | Alias /binaries ${HASHTOPOLIS_BINARIES_PATH} 11 | 12 | Require all granted 13 | 14 | 15 | -------------------------------------------------------------------------------- /ci/apiv2/.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 120 3 | -------------------------------------------------------------------------------- /ci/apiv2/create_accessgroup_001.json: -------------------------------------------------------------------------------- 1 | { 2 | "groupName": "Testing Group" 3 | } 4 | -------------------------------------------------------------------------------- /ci/apiv2/create_accessgroup_002.json: -------------------------------------------------------------------------------- 1 | { 2 | "groupName": "Testing Group", 3 | "bogusKey": "This-should-not-be-accepted" 4 | } 5 | -------------------------------------------------------------------------------- /ci/apiv2/create_agentbinary_001.json: -------------------------------------------------------------------------------- 1 | { 2 | "filename": "will-be-autogenerated", 3 | "operatingSystems": "Windows, Linux, OS X", 4 | "type": "python", 5 | "updateTrack": "stable", 6 | "version": "9.9.9" 7 | } 8 | -------------------------------------------------------------------------------- /ci/apiv2/create_cracker_001.json: -------------------------------------------------------------------------------- 1 | { 2 | "crackerBinaryTypeId": 1, 3 | "version": "0.0.1", 4 | "downloadUrl": "https://example.org/files/cracker-0.0.1.7z", 5 | "binaryName": "cracker" 6 | } 7 | 8 | -------------------------------------------------------------------------------- /ci/apiv2/create_cracker_002.json: -------------------------------------------------------------------------------- 1 | { 2 | "crackerBinaryTypeId": 1, 3 | "version": "0.0.1", 4 | "downloadUrl": "https://example.org/files/cracker-0.0.1.7z" 5 | } 6 | 7 | -------------------------------------------------------------------------------- /ci/apiv2/create_crackertype_001.json: -------------------------------------------------------------------------------- 1 | { 2 | "typeName": "generic", 3 | "isChunkingAvailable": true 4 | } 5 | -------------------------------------------------------------------------------- /ci/apiv2/create_crackertype_002.json: -------------------------------------------------------------------------------- 1 | { 2 | "typeName": true, 3 | "isChunkingAvailable": true 4 | } 5 | -------------------------------------------------------------------------------- /ci/apiv2/create_file_001.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceType": "import", 3 | "fileType": 0, 4 | "isSecret": false, 5 | "accessGroupId": 1 6 | } 7 | -------------------------------------------------------------------------------- /ci/apiv2/create_hashlist_001.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Hashlist-md5sum-test123", 3 | "hashTypeId": 0, 4 | "format": 0, 5 | "separator": ";", 6 | "isSalted": false, 7 | "isHexSalt": false, 8 | "accessGroupId": 1, 9 | "useBrain": false, 10 | "brainFeatures": 3, 11 | "notes": "gj", 12 | "sourceType": "paste", 13 | "sourceData": "Y2MwM2U3NDdhNmFmYmJjYmY4YmU3NjY4YWNmZWJlZTUK", 14 | "hashCount": 0, 15 | "isArchived": false, 16 | "isSecret": false 17 | } 18 | -------------------------------------------------------------------------------- /ci/apiv2/create_hashlist_002.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Hashlist-md5sum-002", 3 | "hashTypeId": 0, 4 | "format": 0, 5 | "separator": ";", 6 | "isSalted": false, 7 | "isHexSalt": false, 8 | "accessGroupId": 1, 9 | "useBrain": false, 10 | "brainFeatures": 3, 11 | "notes": "gj", 12 | "sourceType": "paste", 13 | "sourceData": "", 14 | "hashCount": 0, 15 | "isArchived": false, 16 | "isSecret": false 17 | } 18 | -------------------------------------------------------------------------------- /ci/apiv2/create_hashlist_003.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Hashlist-ntlm-003", 3 | "hashTypeId": 1000, 4 | "format": 0, 5 | "separator": ";", 6 | "isSalted": false, 7 | "isHexSalt": false, 8 | "accessGroupId": 1, 9 | "useBrain": false, 10 | "brainFeatures": 3, 11 | "notes": "gj", 12 | "sourceType": "paste", 13 | "sourceData": "Y2MwM2U3NDdhNmFmYmJjYmY4YmU3NjY4YWNmZWJlZTUK", 14 | "hashCount": 0, 15 | "isArchived": false, 16 | "isSecret": false 17 | } 18 | -------------------------------------------------------------------------------- /ci/apiv2/create_hashtype_001.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Dummy HashType", 3 | "hashTypeId": 98765, 4 | "isSalted": false, 5 | "isSlowHash": false 6 | } 7 | -------------------------------------------------------------------------------- /ci/apiv2/create_healthcheck_001.json: -------------------------------------------------------------------------------- 1 | { 2 | "checkType": 0, 3 | "crackerBinaryId": 1, 4 | "hashtypeId": 0 5 | } 6 | -------------------------------------------------------------------------------- /ci/apiv2/create_notification_001.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "agentError", 3 | "actionFilter": "ALL", 4 | "isActive": true, 5 | "notification": "Example", 6 | "receiver": "foobar@example.org" 7 | } 8 | -------------------------------------------------------------------------------- /ci/apiv2/create_preprocessor_001.json: -------------------------------------------------------------------------------- 1 | { 2 | "binaryName": "dummy", 3 | "keyspaceCommand": "--dummy-keyspace", 4 | "limitCommand": "--dummy-limit", 5 | "name": "DummyTest", 6 | "skipCommand": "--dummy-skip", 7 | "url": "https://example.org/dummy-1.2.3.zip" 8 | } 9 | -------------------------------------------------------------------------------- /ci/apiv2/create_pretask_001.json: -------------------------------------------------------------------------------- 1 | { 2 | "taskName": "Example - create_pretasks_001", 3 | "attackCmd": "#HL# -a3 ?l?l?l?l?l", 4 | "chunkTime": 600, 5 | "statusTimer": 700, 6 | "color": "7C6EFF", 7 | "isSmall": true, 8 | "isCpuTask": true, 9 | "useNewBench": true, 10 | "priority": 10, 11 | "maxAgents": 10, 12 | "isMaskImport": false, 13 | "crackerBinaryTypeId": 1, 14 | "files": [] 15 | } -------------------------------------------------------------------------------- /ci/apiv2/create_pretask_003.json: -------------------------------------------------------------------------------- 1 | { 2 | "taskName": "Example - create_pretasks_003", 3 | "attackCmd": "#HL# -a3 ?l?l?l?l?l", 4 | "chunkTime": 600, 5 | "statusTimer": 700, 6 | "color": "7C6EFF", 7 | "isSmall": false, 8 | "isCpuTask": false, 9 | "useNewBench": true, 10 | "priority": 10, 11 | "maxAgents": 10, 12 | "isMaskImport": false, 13 | "crackerBinaryTypeId": 1, 14 | "files": [] 15 | } -------------------------------------------------------------------------------- /ci/apiv2/create_supertask_001.json: -------------------------------------------------------------------------------- 1 | { 2 | "supertaskName": "Dummy Supertask", 3 | "pretasks": ["will", "be", "autogenrated"] 4 | } 5 | 6 | -------------------------------------------------------------------------------- /ci/apiv2/create_task_001.json: -------------------------------------------------------------------------------- 1 | { 2 | "attackCmd": "#HL# -a 0 ad a1", 3 | "chunkSize": 1000, 4 | "chunkTime": 600, 5 | "color": "7C6EFF", 6 | "crackerBinaryId": 1, 7 | "crackerBinaryTypeId": 1, 8 | "forcePipe": true, 9 | "files": [], 10 | "isArchived": false, 11 | "isCpuTask": false, 12 | "isSmall": false, 13 | "maxAgents": 112, 14 | "notes": "example-note", 15 | "preprocessorCommand": "this-is-prepressor", 16 | "priority": 10, 17 | "skipKeyspace": 500, 18 | "staticChunks": 2, 19 | "statusTimer": 5, 20 | "taskName": "Example - Rijmen and Daemen", 21 | "useNewBench": true, 22 | "preprocessorId": 1 23 | } 24 | -------------------------------------------------------------------------------- /ci/apiv2/create_task_002.json: -------------------------------------------------------------------------------- 1 | { 2 | "attackCmd": "#HL# -a 0 ad a1", 3 | "chunkSize": 1000, 4 | "chunkTime": 600, 5 | "color": "7C6EFF", 6 | "crackerBinaryId": 1, 7 | "crackerBinaryTypeId": 1, 8 | "forcePipe": true, 9 | "files": [], 10 | "isArchived": false, 11 | "isCpuTask": false, 12 | "isSmall": false, 13 | "maxAgents": 112, 14 | "notes": "example-note", 15 | "preprocessorCommand": "this-is-prepressor", 16 | "priority": 10, 17 | "skipKeyspace": 500, 18 | "staticChunks": 2, 19 | "statusTimer": 5, 20 | "taskName": "Example - runtime", 21 | "useNewBench": false, 22 | "preprocessorId": 1 23 | } 24 | -------------------------------------------------------------------------------- /ci/apiv2/create_task_003.json: -------------------------------------------------------------------------------- 1 | { 2 | "attackCmd": "#HL# -a 0 ad a1", 3 | "chunkSize": 1000, 4 | "chunkTime": 600, 5 | "color": "7C6EFF", 6 | "crackerBinaryId": 1, 7 | "crackerBinaryTypeId": 1, 8 | "forcePipe": true, 9 | "files": [], 10 | "isArchived": false, 11 | "isCpuTask": false, 12 | "isSmall": false, 13 | "maxAgents": 112, 14 | "notes": "example-note", 15 | "preprocessorCommand": "this-is-prepressor", 16 | "priority": 10, 17 | "skipKeyspace": 500, 18 | "staticChunks": 2, 19 | "statusTimer": 5, 20 | "taskName": "Example - prepressor", 21 | "useNewBench": false, 22 | "preprocessorId": 1 23 | } 24 | -------------------------------------------------------------------------------- /ci/apiv2/generate_dummy_data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Generate dummy data for development/debugging purposes 4 | """ 5 | from utils import do_create_hashlist 6 | 7 | 8 | def generate_dummy_data(): 9 | for _ in range(1000): 10 | # TODO: Generate unique hashlists 11 | do_create_hashlist() 12 | 13 | 14 | # TODO: Generate different objects like users/tasks/crackerbinaries/etc 15 | if __name__ == '__main__': 16 | # TODO: Use seed to generate an predictable 'random' test dataset 17 | generate_dummy_data() 18 | -------------------------------------------------------------------------------- /ci/apiv2/hashtopolis-test-defaults.yaml: -------------------------------------------------------------------------------- 1 | hashtopolis_uri: 'http://localhost:80' 2 | username: 'admin' 3 | password: 'hashtopolis' 4 | -------------------------------------------------------------------------------- /ci/apiv2/poc_openapi_perm_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # PoC to use openapi.json for automated unit testing. This will test of 'GET' permission is available on all API listing endpoints' 4 | # 5 | for ENDPOINT in $(curl -s 'http://localhost:8080/api/v2/openapi.json' | jq -r '.paths | keys[]' | grep -v '}'); do 6 | echo -n "$ENDPOINT..."; 7 | curl --header "Content-Type: application/json" -X GET --header "Authorization: Bearer $TOKEN" "http://localhost:8080$ENDPOINT" -s -d '{}' | grep -q '403' && echo "FAIL" || echo "OK" 8 | done 9 | -------------------------------------------------------------------------------- /ci/apiv2/requirements.txt: -------------------------------------------------------------------------------- 1 | click 2 | click_log 3 | confidence 4 | pytest 5 | tuspy 6 | -------------------------------------------------------------------------------- /ci/apiv2/test_accessgroup.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import AccessGroup 2 | from utils import BaseTest 3 | 4 | 5 | class AccessGroupTest(BaseTest): 6 | model_class = AccessGroup 7 | 8 | def create_test_object(self, *nargs, **kwargs): 9 | return self.create_accessgroup(*nargs, **kwargs) 10 | 11 | def test_create(self): 12 | model_obj = self.create_test_object() 13 | self._test_create(model_obj) 14 | 15 | def test_patch(self): 16 | model_obj = self.create_test_object() 17 | self._test_patch(model_obj, 'groupName') 18 | 19 | def test_delete(self): 20 | model_obj = self.create_test_object(delete=False) 21 | self._test_delete(model_obj) 22 | 23 | def test_exception(self): 24 | self._test_exception(self.create_test_object, file_id='002', delete=False) 25 | 26 | def test_expandables(self): 27 | model_obj = self.create_test_object() 28 | expandables = ['userMembers', 'agentMembers'] 29 | self._test_expandables(model_obj, expandables) 30 | -------------------------------------------------------------------------------- /ci/apiv2/test_agent.py: -------------------------------------------------------------------------------- 1 | from test_task import TaskTest 2 | from hashtopolis import Agent, Helper 3 | from hashtopolis import HashtopolisError 4 | 5 | from utils import BaseTest 6 | 7 | 8 | class AgentTest(BaseTest): 9 | model_class = Agent 10 | 11 | def create_test_object(self, *nargs, **kwargs): 12 | return self.create_agent(*nargs, **kwargs) 13 | 14 | def test_create(self): 15 | model_obj = self.create_test_object() 16 | self._test_create(model_obj) 17 | 18 | def test_patch(self): 19 | model_obj = self.create_test_object() 20 | self._test_patch(model_obj, 'agentName') 21 | 22 | def test_patch_field_ignorerrors_invalid_choice(self): 23 | model_obj = self.create_test_object() 24 | with self.assertRaises(HashtopolisError) as e: 25 | self._test_patch(model_obj, 'ignoreErrors', 5) 26 | self.assertEqual(e.exception.status_code, 500) 27 | 28 | def test_expandables(self): 29 | model_obj = self.create_test_object() 30 | expandables = ['accessGroups', 'agentstats'] 31 | self._test_expandables(model_obj, expandables) 32 | 33 | def test_assign_unassign_agent(self): 34 | agent_obj = self.create_test_object() 35 | 36 | task_test = TaskTest() 37 | task_obj = task_test.create_test_object(delete=True) 38 | 39 | helper = Helper() 40 | 41 | result = helper.assign_agent(agent=agent_obj, task=task_obj) 42 | 43 | self.assertEqual(result['assign'], 'success') 44 | 45 | result = helper.unassign_agent(agent=agent_obj) 46 | 47 | self.assertEqual(result['unassign'], 'success') 48 | 49 | task_test.tearDown() 50 | -------------------------------------------------------------------------------- /ci/apiv2/test_agentassignment.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import HashtopolisResponseError, AgentAssignment 2 | 3 | from utils import BaseTest 4 | 5 | 6 | class AgentStatTest(BaseTest): 7 | model_class = AgentAssignment 8 | 9 | def create_test_object(self, *nargs, **kwargs): 10 | return self.create_agentassignment(*nargs, **kwargs) 11 | 12 | def test_create(self): 13 | model_obj = self.create_test_object() 14 | self._test_create(model_obj) 15 | 16 | def test_patch(self): 17 | model_obj = self.create_test_object() 18 | with self.assertRaises(HashtopolisResponseError) as e: 19 | self._test_patch(model_obj, 'agentId', 1234) 20 | self.assertEqual(e.exception.status_code, 500) 21 | 22 | def test_delete(self): 23 | model_obj = self.create_test_object(delete=False) 24 | self._test_delete(model_obj) 25 | -------------------------------------------------------------------------------- /ci/apiv2/test_agentbinary.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import AgentBinary 2 | from utils import BaseTest 3 | 4 | 5 | class AgentBinaryTest(BaseTest): 6 | model_class = AgentBinary 7 | 8 | # def create_test_object(self, *nargs, **kwargs): 9 | # # TODO: Cannot test create agent binaries with custom filename 10 | # # since we cannot upload files to 'bin' directory 11 | # # file = self.create_file() 12 | # # kwargs['extra_payload'] = dict(filename=file.filename) 13 | # return self.create_agentbinary(*nargs, **kwargs) 14 | 15 | # def test_create(self): 16 | # model_obj = self.create_test_object() 17 | # self._test_create(model_obj) 18 | 19 | # def test_patch(self): 20 | # model_obj = self.create_test_object() 21 | # attr = 'version' 22 | # new_attr_value = '1.2.3' 23 | # self._test_patch(model_obj, attr, new_attr_value) 24 | 25 | # def test_delete(self): 26 | # model_obj = self.create_test_object(delete=False) 27 | # self._test_delete(model_obj) 28 | -------------------------------------------------------------------------------- /ci/apiv2/test_agentstat.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import AgentStat 2 | 3 | from utils import BaseTest 4 | 5 | 6 | class AgentStatTest(BaseTest): 7 | model_class = AgentStat 8 | 9 | def create_test_objects(self, *nargs, **kwargs): 10 | retval = self.create_agent_with_task(*nargs, **kwargs) 11 | return AgentStat.objects.filter(agentId=retval['agent'].id) 12 | 13 | def test_gpu_temperature(self): 14 | gpu_temperatures = [20, 30] 15 | retval = self.create_agent_with_task(gpu_temperatures=gpu_temperatures) 16 | agent = retval['agent'] 17 | objs = AgentStat.objects.filter(agentId=agent.id, statType=1) 18 | self.assertEqual(len(objs), 1) 19 | self.assertListEqual(objs[0].value, gpu_temperatures) 20 | 21 | def test_gpu_utilisation(self): 22 | gpu_utilisations = [40, 50] 23 | retval = self.create_agent_with_task(gpu_utilisations=gpu_utilisations) 24 | agent = retval['agent'] 25 | objs = AgentStat.objects.filter(agentId=agent.id, statType=2) 26 | self.assertEqual(len(objs), 1) 27 | self.assertListEqual(objs[0].value, gpu_utilisations) 28 | 29 | def test_cpu_utilisation(self): 30 | cpu_utilisations = [60, 70] 31 | retval = self.create_agent_with_task(cpu_utilisations=cpu_utilisations) 32 | agent = retval['agent'] 33 | objs = AgentStat.objects.filter(agentId=agent.id, statType=3) 34 | self.assertEqual(len(objs), 1) 35 | self.assertListEqual(objs[0].value, cpu_utilisations) 36 | -------------------------------------------------------------------------------- /ci/apiv2/test_chunk.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import Chunk, Helper 2 | 3 | from utils import BaseTest 4 | 5 | 6 | class ChunkTest(BaseTest): 7 | model_class = Chunk 8 | 9 | def create_test_object(self, *nargs, **kwargs): 10 | retval = self.create_agent_with_task(*nargs, **kwargs) 11 | chunks = Chunk.objects.filter(taskId=retval['task'].id) 12 | self.assertGreaterEqual(len(chunks), 1) 13 | return chunks[0] 14 | 15 | def test_create(self): 16 | model_obj = self.create_test_object() 17 | self._test_create(model_obj) 18 | 19 | def test_expandables(self): 20 | model_obj = self.create_test_object() 21 | expandables = ['task'] 22 | self._test_expandables(model_obj, expandables) 23 | 24 | def test_helper_abort_chunk(self): 25 | chunk = self.create_test_object() 26 | helper = Helper() 27 | helper.abort_chunk(chunk) 28 | 29 | def test_helper_reset_chunk(self): 30 | chunk = self.create_test_object() 31 | helper = Helper() 32 | helper.reset_chunk(chunk) 33 | 34 | def test_helper_purge_task(self): 35 | retval = self.create_agent_with_task() 36 | 37 | helper = Helper() 38 | helper.purge_task(retval['task']) 39 | 40 | chunks = Chunk.objects.filter(taskId=retval['task'].id) 41 | self.assertEqual(len(chunks), 0) 42 | -------------------------------------------------------------------------------- /ci/apiv2/test_config.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import Config 2 | from utils import BaseTest 3 | 4 | 5 | class ConfigTest(BaseTest): 6 | model_class = Config 7 | 8 | def test_patch_config(self): 9 | config = Config.objects.get(item='hashcatBrainEnable') 10 | config.value = "0" 11 | config.save() 12 | 13 | obj = Config.objects.get(item='hashcatBrainEnable') 14 | self.assertEqual(obj.value, "0") 15 | 16 | config.value = "1" 17 | config.save() 18 | 19 | obj = Config.objects.get(item='hashcatBrainEnable') 20 | self.assertEqual(obj.value, "1") 21 | 22 | def test_expandables(self): 23 | model_obj = Config.objects.get(pk=1) 24 | expandables = ['configSection'] 25 | self._test_expandables(model_obj, expandables) 26 | -------------------------------------------------------------------------------- /ci/apiv2/test_configsection.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import ConfigSection 2 | from utils import BaseTest 3 | 4 | 5 | class ConfigSectionTest(BaseTest): 6 | model_class = ConfigSection 7 | 8 | def test_get_one(self): 9 | obj = ConfigSection.objects.get(pk=1) 10 | self.assertIsNotNone(obj) 11 | -------------------------------------------------------------------------------- /ci/apiv2/test_cracker.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import Cracker 2 | from utils import BaseTest 3 | 4 | 5 | class CrackerTest(BaseTest): 6 | model_class = Cracker 7 | 8 | def create_test_object(self, *nargs, **kwargs): 9 | return self.create_cracker(*nargs, **kwargs) 10 | 11 | def test_create(self): 12 | model_obj = self.create_test_object() 13 | self._test_create(model_obj) 14 | 15 | def test_patch(self): 16 | model_obj = self.create_test_object() 17 | self._test_patch(model_obj, 'binaryName') 18 | 19 | def test_delete(self): 20 | model_obj = self.create_test_object(delete=False) 21 | self._test_delete(model_obj) 22 | 23 | def test_exception(self): 24 | self._test_exception(self.create_test_object, file_id='002', delete=False) 25 | 26 | def test_expandables(self): 27 | model_obj = self.create_test_object() 28 | expandables = ['crackerBinaryType'] 29 | self._test_expandables(model_obj, expandables) 30 | -------------------------------------------------------------------------------- /ci/apiv2/test_crackertype.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import CrackerType 2 | from utils import BaseTest 3 | 4 | 5 | class CrackerTypeTest(BaseTest): 6 | model_class = CrackerType 7 | 8 | def create_test_object(self, *nargs, **kwargs): 9 | return self.create_crackertype(*nargs, **kwargs) 10 | 11 | def test_create(self): 12 | model_obj = self.create_test_object() 13 | self._test_create(model_obj) 14 | 15 | def test_patch(self): 16 | model_obj = self.create_test_object() 17 | self._test_patch(model_obj, 'typeName', 'Generic - edited') 18 | 19 | def test_delete(self): 20 | model_obj = self.create_test_object(delete=False) 21 | self._test_delete(model_obj) 22 | 23 | def test_exception(self): 24 | self._test_exception(self.create_test_object, file_id='002', delete=False) 25 | 26 | def test_expandables(self): 27 | model_obj = self.create_test_object() 28 | expandables = ['crackerVersions'] 29 | self._test_expandables(model_obj, expandables) 30 | -------------------------------------------------------------------------------- /ci/apiv2/test_expand.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import AccessGroup, Hashlist, Task 2 | from utils import BaseTest 3 | 4 | 5 | class ExpandTest(BaseTest): 6 | def test_accessgroups_usermembers_m2m(self): 7 | # Many-to-many casting 8 | objs = AccessGroup.objects.all(expand='userMembers') 9 | 10 | # Check the default account 11 | self.assertEqual(objs[0].userMembers_set[0].name, 'admin') 12 | 13 | def test_crackerbinary_o2o(self): 14 | hashlist = self.create_hashlist() 15 | task = self.create_task(hashlist) 16 | 17 | objs = Task.objects.filter(taskId=task.id, expand='crackerBinary') 18 | self.assertEqual(objs[0].crackerBinary.binaryName, 'hashcat') 19 | 20 | def test_individual_object_expanding(self): 21 | hashlist = self.create_hashlist() 22 | 23 | obj = Hashlist.objects.get(pk=hashlist.id, expand='hashes') 24 | self.assertEqual('cc03e747a6afbbcbf8be7668acfebee5', obj.hashes_set[0].hash) 25 | -------------------------------------------------------------------------------- /ci/apiv2/test_file.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import File, Helper 2 | from utils import BaseTest 3 | 4 | 5 | class FileTest(BaseTest): 6 | model_class = File 7 | 8 | def create_test_object(self, *nargs, **kwargs): 9 | return self.create_file(*nargs, **kwargs) 10 | 11 | def test_create(self): 12 | model_obj = self.create_test_object() 13 | self._test_create(model_obj) 14 | 15 | def test_patch(self): 16 | model_obj = self.create_test_object() 17 | self._test_patch(model_obj, 'isSecret', True) 18 | 19 | def test_delete(self): 20 | model_obj = self.create_test_object(delete=False) 21 | self._test_delete(model_obj) 22 | 23 | def test_expandables(self): 24 | model_obj = self.create_test_object() 25 | expandables = ['accessGroup'] 26 | self._test_expandables(model_obj, expandables) 27 | 28 | def test_create_binary(self): 29 | model_obj = self.create_test_object(compress=True) 30 | self._test_create(model_obj) 31 | 32 | def test_recount_wordlist(self): 33 | # Note: After the object creation, the line count is already updated, but afterward it is immutable on the API. 34 | # There the test just check that the API function is callable and returns the file, but the count is 35 | # already the same beforehand. 36 | model_obj = self.create_test_object() 37 | 38 | helper = Helper() 39 | file = helper.recount_file_lines(file=model_obj) 40 | 41 | self.assertEqual(file.lineCount, 3) 42 | -------------------------------------------------------------------------------- /ci/apiv2/test_globalpermissiongroup.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import GlobalPermissionGroup 2 | from utils import BaseTest 3 | 4 | 5 | class GlobalPermissionGroupTest(BaseTest): 6 | model_class = GlobalPermissionGroup 7 | 8 | def create_test_object(self, *nargs, **kwargs): 9 | return self.create_globalpermissiongroup(*nargs, **kwargs) 10 | 11 | def test_create(self): 12 | model_obj = self.create_test_object() 13 | self._test_create(model_obj) 14 | 15 | def test_patch(self): 16 | model_obj = self.create_test_object() 17 | 18 | attr = 'permRightGroupCreate' 19 | model_obj.permissions[attr] = True 20 | model_obj.save() 21 | 22 | # Request object from backend and validate PATCHed permission 23 | obj = self.model_class.objects.get(pk=model_obj.id) 24 | self.assertTrue(obj.permissions[attr]) 25 | 26 | def test_delete(self): 27 | model_obj = self.create_test_object(delete=False) 28 | self._test_delete(model_obj) 29 | 30 | def test_expand(self): 31 | model_obj = self.create_test_object() 32 | expandables = ['user'] 33 | self._test_expandables(model_obj, expandables) 34 | -------------------------------------------------------------------------------- /ci/apiv2/test_hash.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import Hash, HashtopolisResponseError 2 | from utils import BaseTest 3 | 4 | 5 | class HashTest(BaseTest): 6 | model_class = Hash 7 | 8 | def create_test_object(self, *nargs, **kwargs): 9 | hashlist = self.create_hashlist(*nargs, **kwargs) 10 | hash = Hash.objects.filter(hashlistId=hashlist.id)[0] 11 | self.assertIsNotNone(hash) 12 | return hash 13 | 14 | def test_create(self): 15 | model_obj = self.create_test_object() 16 | self._test_create(model_obj) 17 | 18 | def test_patch(self): 19 | # Patching Hashes is not possible via API 20 | model_obj = self.create_test_object() 21 | with self.assertRaises(HashtopolisResponseError) as e: 22 | self._test_patch(model_obj, 'isCracked', True) 23 | self.assertEqual(e.exception.status_code, 500) 24 | 25 | def test_delete(self): 26 | # Deleting Hashes is not possible via API 27 | model_obj = self.create_test_object() 28 | with self.assertRaises(HashtopolisResponseError) as e: 29 | self._test_delete(model_obj) 30 | self.assertEqual(e.exception.status_code, 500) 31 | 32 | def test_expandables(self): 33 | model_obj = self.create_test_object() 34 | expandables = ['hashlist', 'chunk'] 35 | self._test_expandables(model_obj, expandables) 36 | -------------------------------------------------------------------------------- /ci/apiv2/test_hashtype.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import HashType 2 | from utils import BaseTest 3 | 4 | 5 | class HashTypeTest(BaseTest): 6 | model_class = HashType 7 | 8 | def create_test_object(self, *nargs, **kwargs): 9 | return self.create_hashtype(*nargs, **kwargs) 10 | 11 | def test_create(self): 12 | model_obj = self.create_test_object() 13 | self._test_create(model_obj) 14 | 15 | def test_patch(self): 16 | model_obj = self.create_test_object() 17 | self._test_patch(model_obj, 'description') 18 | 19 | def test_delete(self): 20 | model_obj = self.create_test_object(delete=False) 21 | self._test_delete(model_obj) 22 | -------------------------------------------------------------------------------- /ci/apiv2/test_healthcheck.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import HealthCheck 2 | from utils import BaseTest 3 | 4 | 5 | class HealthCheckAgentTest(BaseTest): 6 | model_class = HealthCheck 7 | 8 | def create_test_object(self, *nargs, **kwargs): 9 | return self.create_healthcheck(*nargs, **kwargs) 10 | 11 | def test_create(self): 12 | model_obj = self.create_test_object() 13 | self._test_create(model_obj) 14 | 15 | def test_patch(self): 16 | model_obj = self.create_test_object() 17 | self._test_patch(model_obj, 'crackerBinaryId', 1) 18 | 19 | def test_delete(self): 20 | model_obj = self.create_test_object(delete=False) 21 | self._test_delete(model_obj) 22 | 23 | def test_expandables(self): 24 | model_obj = self.create_test_object() 25 | expandables = ['crackerBinary', 'healthCheckAgents'] 26 | self._test_expandables(model_obj, expandables) 27 | -------------------------------------------------------------------------------- /ci/apiv2/test_healthcheckagents.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import HealthCheckAgent 2 | from utils import BaseTest 3 | 4 | 5 | class HealthCheckAgentTest(BaseTest): 6 | model_class = HealthCheckAgent 7 | 8 | # def create_test_object(self, *nargs, **kwargs): 9 | # # TODO: Create healthcheckagent via Dummy Agent 10 | # self.assertIsNotNone(hash) 11 | # return 12 | 13 | # def test_create(self): 14 | # model_obj = self.create_test_object() 15 | # self._test_create(model_obj) 16 | 17 | # def test_patch(self): 18 | # # Patching HealthCheckAgents is not possible via API 19 | # model_obj = self.create_test_object() 20 | # with self.assertRaises(HashtopolisResponseError) as e: 21 | # attr = 'isCracked' 22 | # new_attr_value = True 23 | # self._test_patch(model_obj, attr, new_attr_value) 24 | # self.assertEqual(e.exception.status_code, 500) 25 | 26 | # def test_delete(self): 27 | # # Deleting HealthCheckAgents is not possible via API 28 | # model_obj = self.create_test_object(delete=False) 29 | # with self.assertRaises(HashtopolisResponseError) as e: 30 | # self._test_delete(model_obj) 31 | # self.assertEqual(e.exception.status_code, 500) 32 | 33 | # def test_expandables(self): 34 | # model_obj = self.create_test_object() 35 | # expandables = ['agent', 'healthcheck'] 36 | # self._test_expandables(model_obj, expandables) 37 | -------------------------------------------------------------------------------- /ci/apiv2/test_http_methods.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | from hashtopolis import HashtopolisConnector, HashtopolisConfig 4 | from utils import BaseTest 5 | 6 | 7 | class HttpMethodsTest(BaseTest): 8 | def test_empty_body(self): 9 | config = HashtopolisConfig() 10 | conn = HashtopolisConnector('/ui/users', config) 11 | conn.authenticate() 12 | 13 | headers = conn._headers 14 | del headers['Content-Type'] 15 | 16 | uri = conn._api_endpoint + conn._model_uri 17 | 18 | r = requests.get(uri, headers=headers) 19 | values = r.json().get('values') 20 | 21 | self.assertGreaterEqual(len(values), 1) 22 | -------------------------------------------------------------------------------- /ci/apiv2/test_logentry.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import LogEntry 2 | from utils import BaseTest 3 | 4 | 5 | class LogEntryTest(BaseTest): 6 | model_class = LogEntry 7 | 8 | def test_get_one(self): 9 | obj = LogEntry.objects.get(pk=1) 10 | self.assertIsNotNone(obj) 11 | 12 | # TODO: Create event which generate logenties and check if logentry is created 13 | -------------------------------------------------------------------------------- /ci/apiv2/test_notification.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import Notification 2 | from utils import BaseTest 3 | 4 | 5 | class NotificationTest(BaseTest): 6 | model_class = Notification 7 | 8 | def create_test_object(self, *nargs, **kwargs): 9 | return self.create_notification(*nargs, **kwargs) 10 | 11 | def test_create(self): 12 | model_obj = self.create_test_object() 13 | self._test_create(model_obj) 14 | 15 | def test_patch(self): 16 | model_obj = self.create_test_object() 17 | self._test_patch(model_obj, 'receiver', 'dummy-user@example.com') 18 | 19 | def test_delete(self): 20 | model_obj = self.create_test_object(delete=False) 21 | self._test_delete(model_obj) 22 | 23 | def test_expandables(self): 24 | model_obj = self.create_test_object() 25 | expandables = ['user'] 26 | self._test_expandables(model_obj, expandables) 27 | -------------------------------------------------------------------------------- /ci/apiv2/test_preprocessor.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import Preprocessor 2 | from utils import BaseTest 3 | 4 | 5 | class PreprocessorTest(BaseTest): 6 | model_class = Preprocessor 7 | 8 | def create_test_object(self, *nargs, **kwargs): 9 | return self.create_preprocessor(*nargs, **kwargs) 10 | 11 | def test_create(self): 12 | model_obj = self.create_test_object() 13 | self._test_create(model_obj) 14 | 15 | def test_patch(self): 16 | model_obj = self.create_test_object() 17 | self._test_patch(model_obj, 'name') 18 | 19 | def test_delete(self): 20 | model_obj = self.create_test_object(delete=False) 21 | self._test_delete(model_obj) 22 | -------------------------------------------------------------------------------- /ci/apiv2/test_pretask.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import Pretask 2 | from utils import BaseTest 3 | 4 | 5 | class PretaskTest(BaseTest): 6 | model_class = Pretask 7 | 8 | def create_test_object(self, *nargs, **kwargs): 9 | return self.create_pretask(*nargs, **kwargs) 10 | 11 | def test_create(self): 12 | model_obj = self.create_test_object() 13 | self._test_create(model_obj) 14 | 15 | def test_patch(self): 16 | model_obj = self.create_test_object() 17 | self._test_patch(model_obj, 'taskName') 18 | 19 | def test_delete(self): 20 | model_obj = self.create_test_object(delete=False) 21 | self._test_delete(model_obj) 22 | 23 | def test_expandables(self): 24 | model_obj = self.create_test_object() 25 | expandables = ['pretaskFiles'] 26 | self._test_expandables(model_obj, expandables) 27 | 28 | def test_create_pretask_alt(self): 29 | model_obj = self.create_test_object(file_id='003') 30 | self._test_create(model_obj) 31 | -------------------------------------------------------------------------------- /ci/apiv2/test_schema.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import Meta 2 | from utils import BaseTest 3 | 4 | 5 | class AttributeTypeTest(BaseTest): 6 | def test_get_meta(self): 7 | meta = Meta() 8 | meta.get_meta() 9 | -------------------------------------------------------------------------------- /ci/apiv2/test_speed.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import HashtopolisResponseError, Speed 2 | from utils import BaseTest 3 | 4 | 5 | class SpeedTest(BaseTest): 6 | model_class = Speed 7 | 8 | def create_test_object(self, *nargs, **kwargs): 9 | retval = self.create_agent_with_task(*nargs, **kwargs) 10 | return Speed.objects.filter(taskId=retval['task'].id)[0] 11 | 12 | def test_create(self): 13 | model_obj = self.create_test_object() 14 | self._test_create(model_obj) 15 | 16 | def test_patch(self): 17 | # Patching should not be possible via API 18 | model_obj = self.create_test_object() 19 | with self.assertRaises(HashtopolisResponseError) as e: 20 | self._test_patch(model_obj, 'speed', 1234) 21 | self.assertEqual(e.exception.status_code, 500) 22 | 23 | def test_delete(self): 24 | # Delete should not be possible via API 25 | model_obj = self.create_test_object() 26 | with self.assertRaises(HashtopolisResponseError) as e: 27 | self._test_delete(model_obj) 28 | self.assertEqual(e.exception.status_code, 500) 29 | 30 | def test_expandables(self): 31 | model_obj = self.create_test_object() 32 | expandables = ['agent', 'task'] 33 | self._test_expandables(model_obj, expandables) 34 | -------------------------------------------------------------------------------- /ci/apiv2/test_supertask.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import Supertask 2 | from utils import BaseTest 3 | 4 | 5 | class SupertaskTest(BaseTest): 6 | model_class = Supertask 7 | 8 | def create_test_object(self, *nargs, **kwargs): 9 | pretasks = [self.create_pretask() for i in range(2)] 10 | return self.create_supertask(pretasks=pretasks, *nargs, **kwargs) 11 | 12 | def test_create(self): 13 | model_obj = self.create_test_object() 14 | self._test_create(model_obj) 15 | 16 | def test_patch(self): 17 | model_obj = self.create_test_object() 18 | self._test_patch(model_obj, 'supertaskName') 19 | 20 | def test_delete(self): 21 | model_obj = self.create_test_object(delete=False) 22 | self._test_delete(model_obj) 23 | 24 | def test_expandables(self): 25 | model_obj = self.create_test_object() 26 | expandables = ['pretasks'] 27 | self._test_expandables(model_obj, expandables) 28 | 29 | def test_new_pretasks(self): 30 | model_obj = self.create_test_object() 31 | 32 | # Quirk for expanding object to allow update to take place 33 | work_obj = Supertask.objects.get(pk=model_obj.id, expand='pretasks') 34 | new_pretasks = [self.create_pretask() for i in range(2)] 35 | selected_pretasks = [work_obj.pretasks_set[0], new_pretasks[1]] 36 | work_obj.pretasks_set = selected_pretasks 37 | work_obj.save() 38 | 39 | obj = Supertask.objects.get(pk=model_obj.id, expand='pretasks') 40 | self.assertListEqual(selected_pretasks, obj.pretasks_set) 41 | -------------------------------------------------------------------------------- /ci/apiv2/test_user.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import User, Helper 2 | from utils import BaseTest 3 | 4 | 5 | class UserTest(BaseTest): 6 | model_class = User 7 | 8 | def create_test_object(self, *nargs, **kwargs): 9 | return self.create_user(*nargs, **kwargs) 10 | 11 | def test_create(self): 12 | model_obj = self.create_test_object() 13 | self._test_create(model_obj) 14 | 15 | def test_patch(self): 16 | gp_group = self.create_globalpermissiongroup() 17 | user = self.create_user() 18 | 19 | user.globalPermissionGroupId = gp_group.id 20 | user.save() 21 | 22 | obj = user.objects.get(id=user.id) 23 | self.assertEqual(obj.globalPermissionGroupId, gp_group.id) 24 | 25 | def test_delete(self): 26 | model_obj = self.create_test_object(delete=False) 27 | self._test_delete(model_obj) 28 | 29 | def test_expand(self): 30 | model_obj = self.create_test_object() 31 | expandables = ['accessGroups', 'globalPermissionGroup'] 32 | self._test_expandables(model_obj, expandables) 33 | 34 | def test_disable_enable_user(self): 35 | user = self.create_test_object() 36 | 37 | # Disable User 38 | user.isValid = False 39 | user.save() 40 | 41 | obj = User.objects.get(id=user.id) 42 | self.assertFalse(obj.isValid) 43 | 44 | # Enable user 45 | user.isValid = True 46 | user.save() 47 | 48 | obj = User.objects.get(id=user.id) 49 | self.assertTrue(obj.isValid) 50 | 51 | def test_helper_set_user_password(self): 52 | user = self.create_test_object() 53 | newPassword = "testing123" 54 | helper = Helper() 55 | helper.set_user_password(user, newPassword) 56 | helper._test_authentication(user.name, newPassword) 57 | -------------------------------------------------------------------------------- /ci/apiv2/test_voucher.py: -------------------------------------------------------------------------------- 1 | from hashtopolis import Voucher 2 | from utils import BaseTest 3 | 4 | 5 | class VoucherTest(BaseTest): 6 | model_class = Voucher 7 | 8 | def create_test_object(self, *nargs, **kwargs): 9 | return self.create_voucher(*nargs, **kwargs) 10 | 11 | def test_create(self): 12 | model_obj = self.create_test_object() 13 | self._test_create(model_obj) 14 | 15 | def test_patch(self): 16 | model_obj = self.create_test_object() 17 | self._test_patch(model_obj, 'voucher') 18 | 19 | def test_delete(self): 20 | model_obj = self.create_test_object(delete=False) 21 | self._test_delete(model_obj) 22 | -------------------------------------------------------------------------------- /ci/bundle.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -f server.zip ]; then 4 | rm server.zip 5 | fi 6 | 7 | count=$(git log $(git describe --tags --abbrev=0)..HEAD --oneline | wc -l | tr -d ' ') 8 | sed -i -E 's/BUILD = "repository"/BUILD = "'"$count"'"/g' ../src/inc/info.php 9 | cd ../src/ 10 | zip -r ../ci/server.zip * -x "*.gitignore" -x "*.txt" -x "*README.md" -x "*generator.php" 11 | cd ../ci/ 12 | sed -i -E 's/BUILD = "'"$count"'"/BUILD = "repository"/g' ../src/inc/info.php -------------------------------------------------------------------------------- /ci/files/README.md: -------------------------------------------------------------------------------- 1 | Notice: Following files were taken from the Hashcat repository to be used as examples 2 | 3 | - best64.rule 4 | - example.dict 5 | - example0.hash -------------------------------------------------------------------------------- /ci/files/apache.conf: -------------------------------------------------------------------------------- 1 | 2 | DocumentRoot /var/www/html/hashtopolis/src 3 | 4 | 5 | 6 | Options -Indexes 7 | AllowOverride All 8 | Order allow,deny 9 | Allow from all 10 | Require all granted 11 | -------------------------------------------------------------------------------- /ci/files/best64.rule: -------------------------------------------------------------------------------- 1 | ## nothing, reverse, case... base stuff 2 | : 3 | r 4 | u 5 | T0 6 | 7 | ## simple number append 8 | $0 9 | $1 10 | $2 11 | $3 12 | $4 13 | $5 14 | $6 15 | $7 16 | $8 17 | $9 18 | 19 | ## special number append 20 | $0 $0 21 | $0 $1 22 | $0 $2 23 | $1 $1 24 | $1 $2 25 | $1 $3 26 | $2 $1 27 | $2 $2 28 | $2 $3 29 | $6 $9 30 | $7 $7 31 | $8 $8 32 | $9 $9 33 | $1 $2 $3 34 | 35 | ## high frequency append 36 | $e 37 | $s 38 | 39 | ## high frequency overwrite at end 40 | ] $a 41 | ] ] $s 42 | ] ] $a 43 | ] ] $e $r 44 | ] ] $i $e 45 | ] ] ] $o 46 | ] ] ] $y 47 | ] ] ] $1 $2 $3 48 | ] ] ] $m $a $n 49 | ] ] ] $d $o $g 50 | 51 | ## high frequency prepend 52 | ^1 53 | ^e ^h ^t 54 | 55 | ## high frequency overwrite at start 56 | o0d 57 | o0m o1a 58 | 59 | ## leetify 60 | so0 61 | si1 62 | se3 63 | 64 | ## simple extracts 65 | D2 66 | D2 D2 67 | D3 68 | D4 69 | 70 | ## undouble word 71 | '5 D3 72 | '5 $1 73 | 74 | ## removes suffixes from 'strongified' passwords in dict 75 | ] 76 | ] ] 77 | ] ] ] 78 | ] ] ] d 79 | ] ] D1 ] 80 | 81 | ## rotates 82 | +5 ] } } } } '4 83 | O02 { { { { { { 84 | } ] ] { 85 | } } -0 O12 86 | } } } 87 | } } } } '4 88 | } } } } } '5 89 | } } } } } } Y4 '4 d 90 | 91 | ## unknown 92 | *04 +0 '4 93 | *05 O03 d '3 p1 94 | +0 +0 +0 +0 +0 +0 +0 +0 95 | +0 +0 +0 O12 96 | Z4 '8 O42 97 | Z5 '6 O31 ] p1 98 | Z5 *75 '5 { O02 99 | d O28 Y4 '4 d 100 | f *A5 '8 O14 101 | p2 '7 p1 O58 102 | O14 d p2 '6 103 | -------------------------------------------------------------------------------- /ci/files/prepare.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd /var/www/html/hashtopolis 4 | git checkout $1 5 | chown -R www-data /var/www/html/hashtopolis 6 | chmod -R 0777 /var/www/html/hashtopolis/src/inc/ -------------------------------------------------------------------------------- /ci/server/setup.php: -------------------------------------------------------------------------------- 1 | \n"); 10 | } 11 | $version = $argv[1]; 12 | $envPath = "/var/www/html/hashtopolis/"; 13 | 14 | // simulate installation with creating conf.php (we just put in some peppers) 15 | $CONFIG = "setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 30 | try { 31 | $db->query("CREATE DATABASE IF NOT EXISTS hashtopolis;"); 32 | $db->query("USE hashtopolis;"); 33 | $db->query(file_get_contents($envPath . "src/install/hashtopolis.sql")); 34 | } 35 | catch (PDOException $e) { 36 | fwrite(STDERR, "Failed to initialize database: " . $e->getMessage()); 37 | exit(-1); 38 | } 39 | 40 | $load = file_get_contents($envPath . "src/inc/load.php"); 41 | $load = str_replace('ini_set("display_errors", "0");', 'ini_set("display_errors", "1");', $load); 42 | file_put_contents($envPath . "src/inc/load.php", $load); 43 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hashtopolis/hashtopolis-skeleton", 3 | "description": "A Hashtopolis API skeleton application", 4 | "keywords": [ 5 | "microframework", 6 | "rest", 7 | "router", 8 | "psr7" 9 | ], 10 | "homepage": "http://github.com/hashtopolis/server", 11 | "license": "MIT", 12 | "authors": [ 13 | { 14 | "name": "Various Authors", 15 | "email": "noreply@example.org", 16 | "homepage": "http://example.org" 17 | } 18 | ], 19 | "require": { 20 | "php": "^7.4 || ^8.0", 21 | "ext-json": "*", 22 | "crell/api-problem": "^3.6", 23 | "middlewares/negotiation": "^2.1", 24 | "monolog/monolog": "^2.8", 25 | "php-di/php-di": "7.0.7", 26 | "slim/psr7": "^1.5", 27 | "slim/slim": "^4.10", 28 | "tuupola/slim-basic-auth": "^3.3", 29 | "tuupola/slim-jwt-auth": "^3.6", 30 | "ext-pdo" : "*" 31 | }, 32 | "require-dev": { 33 | "jangregor/phpstan-prophecy": "^1.0.0", 34 | "phpspec/prophecy-phpunit": "^2.0", 35 | "phpstan/extension-installer": "^1.1.0", 36 | "phpstan/phpstan": "^1.8", 37 | "phpunit/phpunit": "^9.5.25", 38 | "squizlabs/php_codesniffer": "^3.7" 39 | }, 40 | "config": { 41 | "allow-plugins": { 42 | "phpstan/extension-installer": true 43 | }, 44 | "process-timeout": 0, 45 | "sort-packages": true 46 | }, 47 | "autoload": { 48 | "psr-4": { 49 | "App\\": "src/" 50 | } 51 | }, 52 | "autoload-dev": { 53 | "psr-4": { 54 | "Tests\\": "tests/" 55 | } 56 | }, 57 | "scripts": { 58 | "start": "php -S localhost:8080 -t src", 59 | "test": "phpunit" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | *.aux 2 | *.log 3 | *.synctex.gz 4 | 5 | -------------------------------------------------------------------------------- /doc/protocol.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/doc/protocol.pdf -------------------------------------------------------------------------------- /doc/user-api/sections/test.tex: -------------------------------------------------------------------------------- 1 | \section*{Test (\textit{test})} 2 | This section is used to do testing queries, e.g. to test connectivity or availability of this API. The test section is the only one which allows to make requests without an access key. 3 | \subsection*{\textit{connection}} 4 | Used to test if the URL is a valid API endpoint. 5 | { 6 | \color{blue} 7 | \begin{verbatim} 8 | { 9 | "section":"test", 10 | "request":"connection" 11 | } 12 | \end{verbatim} 13 | } 14 | 15 | { 16 | \color{OliveGreen} 17 | \begin{verbatim} 18 | { 19 | "section": "test", 20 | "request": "connection", 21 | "response": "SUCCESS" 22 | } 23 | \end{verbatim} 24 | } 25 | \subsection*{\textit{access}} 26 | Used to check if a given API key is still valid and can be used. 27 | { 28 | \color{blue} 29 | \begin{verbatim} 30 | { 31 | "section": "test", 32 | "request": "access", 33 | "accessKey": "mykey" 34 | } 35 | \end{verbatim} 36 | } 37 | { 38 | \color{OliveGreen} 39 | \begin{verbatim} 40 | { 41 | "section": "test", 42 | "request": "access", 43 | "response": "OK" 44 | } 45 | \end{verbatim} 46 | } 47 | { 48 | \color{BrickRed} 49 | \begin{verbatim} 50 | { 51 | "section": "test", 52 | "request": "access", 53 | "response": "ERROR", 54 | "message": "API key was not found!" 55 | } 56 | \end{verbatim} 57 | } -------------------------------------------------------------------------------- /doc/user-api/user-api.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/doc/user-api/user-api.pdf -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | services: 3 | hashtopolis-backend: 4 | container_name: hashtopolis-backend 5 | image: hashtopolis/backend:latest 6 | restart: always 7 | volumes: 8 | - hashtopolis:/usr/local/share/hashtopolis:Z 9 | environment: 10 | HASHTOPOLIS_DB_USER: $MYSQL_USER 11 | HASHTOPOLIS_DB_PASS: $MYSQL_PASSWORD 12 | HASHTOPOLIS_DB_HOST: $HASHTOPOLIS_DB_HOST 13 | HASHTOPOLIS_DB_DATABASE: $MYSQL_DATABASE 14 | HASHTOPOLIS_ADMIN_USER: $HASHTOPOLIS_ADMIN_USER 15 | HASHTOPOLIS_ADMIN_PASSWORD: $HASHTOPOLIS_ADMIN_PASSWORD 16 | HASHTOPOLIS_APIV2_ENABLE: $HASHTOPOLIS_APIV2_ENABLE 17 | depends_on: 18 | - db 19 | ports: 20 | - 8080:80 21 | db: 22 | container_name: db 23 | image: mysql:8.0 24 | restart: always 25 | volumes: 26 | - db:/var/lib/mysql 27 | environment: 28 | MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASS 29 | MYSQL_DATABASE: $MYSQL_DATABASE 30 | MYSQL_USER: $MYSQL_USER 31 | MYSQL_PASSWORD: $MYSQL_PASSWORD 32 | hashtopolis-frontend: 33 | container_name: hashtopolis-frontend 34 | image: hashtopolis/frontend:latest 35 | environment: 36 | HASHTOPOLIS_BACKEND_URL: $HASHTOPOLIS_BACKEND_URL 37 | restart: always 38 | depends_on: 39 | - hashtopolis-backend 40 | ports: 41 | - 4200:80 42 | volumes: 43 | db: 44 | hashtopolis: 45 | -------------------------------------------------------------------------------- /env.example: -------------------------------------------------------------------------------- 1 | MYSQL_ROOT_PASS=hashtopolis 2 | MYSQL_DATABASE=hashtopolis 3 | MYSQL_USER=hashtopolis 4 | MYSQL_PASSWORD=hashtopolis 5 | 6 | HASHTOPOLIS_ADMIN_USER=admin 7 | HASHTOPOLIS_ADMIN_PASSWORD=hashtopolis 8 | HASHTOPOLIS_DB_HOST=db 9 | 10 | HASHTOPOLIS_APIV2_ENABLE=0 11 | HASHTOPOLIS_BACKEND_URL=http://localhost:8080/api/v2 12 | -------------------------------------------------------------------------------- /src/about.php: -------------------------------------------------------------------------------- 1 | checkPermission(DViewControl::ABOUT_VIEW_PERM); 6 | 7 | UI::add('pageTitle', "About"); 8 | Template::loadInstance("static/about"); 9 | echo Template::getInstance()->render(UI::getObjects()); 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/account.php: -------------------------------------------------------------------------------- 1 | isLoggedin()) { 11 | header("Location: index.php?err=4" . time() . "&fw=" . urlencode($_SERVER['PHP_SELF'] . "?" . $_SERVER['QUERY_STRING'])); 12 | die(); 13 | } 14 | 15 | AccessControl::getInstance()->checkPermission(DViewControl::ACCOUNT_VIEW_PERM); 16 | 17 | Template::loadInstance("account"); 18 | Menu::get()->setActive("account_settings"); 19 | UI::add('pageTitle', "Account Settings"); 20 | 21 | //catch actions here... 22 | if (isset($_POST['action']) && CSRF::check($_POST['csrf'])) { 23 | $accountHandler = new AccountHandler(Login::getInstance()->getUserID()); 24 | $accountHandler->handle($_POST['action']); 25 | if (UI::getNumMessages() == 0) { 26 | Util::refresh(); 27 | } 28 | } 29 | 30 | $group = Factory::getRightGroupFactory()->get(Login::getInstance()->getUser()->getRightGroupId()); 31 | UI::add('group', $group); 32 | 33 | $qF = new QueryFilter(ApiKey::USER_ID, Login::getInstance()->getUserID(), "="); 34 | $apiKeys = Factory::getApiKeyFactory()->filter([Factory::FILTER => $qF]); 35 | UI::add('keys', $apiKeys); 36 | 37 | echo Template::getInstance()->render(UI::getObjects()); 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/api/v2/.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | # rewrite empty (without host/port/query) to index.php 5 | # re-appending the query string and ignoring any further rules 6 | RewriteRule ^$ index.php [QSA,L] 7 | # don't rewrite for files or directories which exist on the filesystem... 8 | RewriteCond %{REQUEST_FILENAME} !-f 9 | RewriteCond %{REQUEST_FILENAME} !-d 10 | # ...and rewrite the remaining 11 | RewriteRule ^(.*)$ index.php [QSA,L] 12 | -------------------------------------------------------------------------------- /src/apidocs/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/apidocs/favicon-16x16.png -------------------------------------------------------------------------------- /src/apidocs/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/apidocs/favicon-32x32.png -------------------------------------------------------------------------------- /src/apidocs/index.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | overflow: -moz-scrollbars-vertical; 4 | overflow-y: scroll; 5 | } 6 | 7 | *, 8 | *:before, 9 | *:after { 10 | box-sizing: inherit; 11 | } 12 | 13 | body { 14 | margin: 0; 15 | background: #fafafa; 16 | } 17 | -------------------------------------------------------------------------------- /src/apidocs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Swagger UI 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/apidocs/swagger-initializer.js: -------------------------------------------------------------------------------- 1 | window.onload = function() { 2 | // 3 | 4 | // the following lines will be replaced by docker/configurator, when it runs in a docker-container 5 | window.ui = SwaggerUIBundle({ 6 | url: "/api/v2/openapi.json", 7 | dom_id: '#swagger-ui', 8 | deepLinking: true, 9 | presets: [ 10 | SwaggerUIBundle.presets.apis, 11 | SwaggerUIStandalonePreset 12 | ], 13 | plugins: [ 14 | SwaggerUIBundle.plugins.DownloadUrl 15 | ], 16 | layout: "StandaloneLayout" 17 | }); 18 | 19 | // 20 | }; 21 | -------------------------------------------------------------------------------- /src/bin/.htaccess: -------------------------------------------------------------------------------- 1 | Order deny,allow 2 | Deny from all -------------------------------------------------------------------------------- /src/bin/hashtopolis.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/bin/hashtopolis.zip -------------------------------------------------------------------------------- /src/binaries.php: -------------------------------------------------------------------------------- 1 | isLoggedin()) { 8 | header("Location: index.php?err=4" . time() . "&fw=" . urlencode($_SERVER['PHP_SELF'] . "?" . $_SERVER['QUERY_STRING'])); 9 | die(); 10 | } 11 | 12 | AccessControl::getInstance()->checkPermission(DViewControl::BINARIES_VIEW_PERM); 13 | 14 | UI::add('newBinary', false); 15 | UI::add('editBinary', false); 16 | 17 | Template::loadInstance("binaries"); 18 | Menu::get()->setActive("config_binaries"); 19 | 20 | //catch actions here... 21 | if (isset($_POST['action']) && CSRF::check($_POST['csrf'])) { 22 | $binaryHandler = new AgentBinaryHandler(); 23 | $binaryHandler->handle($_POST['action']); 24 | if (UI::getNumMessages() == 0) { 25 | Util::refresh(); 26 | } 27 | } 28 | UI::add('pageTitle', "Agent Binaries"); 29 | 30 | if (isset($_GET['new'])) { 31 | UI::add('newBinary', true); 32 | UI::add('pageTitle', "New Agent Binary"); 33 | } 34 | else if (isset($_GET['edit'])) { 35 | $bin = Factory::getAgentBinaryFactory()->get($_GET['edit']); 36 | if ($bin == null) { 37 | UI::printError("ERROR", "Invalid agent binary ID!"); 38 | } 39 | UI::add('pageTitle', "Edit Agent Binary of type " . $bin->getType()); 40 | UI::add('editBinary', true); 41 | UI::add('bin', $bin); 42 | } 43 | UI::add('binaries', Factory::getAgentBinaryFactory()->filter([])); 44 | 45 | echo Template::getInstance()->render(UI::getObjects()); 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/config.php: -------------------------------------------------------------------------------- 1 | isLoggedin()) { 10 | header("Location: index.php?err=4" . time() . "&fw=" . urlencode($_SERVER['PHP_SELF'] . "?" . $_SERVER['QUERY_STRING'])); 11 | die(); 12 | } 13 | 14 | AccessControl::getInstance()->checkPermission(DViewControl::CONFIG_VIEW_PERM); 15 | 16 | Template::loadInstance("config"); 17 | Menu::get()->setActive("config_server"); 18 | 19 | //catch actions here... 20 | if (isset($_POST['action']) && CSRF::check($_POST['csrf'])) { 21 | $configHandler = new ConfigHandler(); 22 | $configHandler->handle($_POST['action']); 23 | if (UI::getNumMessages() == 0) { 24 | Util::refresh(); 25 | } 26 | } 27 | 28 | $configuration = array(); 29 | $configSectionId = (isset($_GET['view'])) ? $_GET['view'] : 1; 30 | $qF = new QueryFilter(Config::CONFIG_SECTION_ID, $configSectionId, "="); 31 | $entries = Factory::getConfigFactory()->filter([Factory::FILTER => $qF]); 32 | UI::add('configSectionId', 0); 33 | foreach ($entries as $entry) { 34 | $set = new DataSet(); 35 | $set->addValue('item', $entry->getItem()); 36 | $set->addValue('value', $entry->getValue()); 37 | $configuration[] = $set; 38 | UI::add('configSectionId', $configSectionId); 39 | } 40 | 41 | UI::add('pageTitle', "Configuration"); 42 | UI::add('configuration', $configuration); 43 | 44 | echo Template::getInstance()->render(UI::getObjects()); 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/dba/AbstractModel.class.php: -------------------------------------------------------------------------------- 1 | key1 = $key1; 17 | $this->key2 = $key2; 18 | $this->operator = $operator; 19 | $this->overrideFactory = $overrideFactory; 20 | } 21 | 22 | function getQueryString($table = "") { 23 | if ($table != "") { 24 | $table = $table . "."; 25 | } 26 | if ($this->overrideFactory != null) { 27 | $table = $this->overrideFactory->getModelTable() . "."; 28 | } 29 | 30 | return $table . $this->key1 . $this->operator . $table . $this->key2; 31 | } 32 | 33 | function getValue() { 34 | return null; 35 | } 36 | 37 | function getHasValue() { 38 | return false; 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /src/dba/ContainFilter.class.php: -------------------------------------------------------------------------------- 1 | key = $key; 16 | $this->values = $values; 17 | $this->factory = $factory; 18 | $this->inverse = $inverse; 19 | } 20 | 21 | function getQueryString($table = "") { 22 | if ($table != "") { 23 | $table = $table . "."; 24 | } 25 | if ($this->factory != null) { 26 | $table = $this->factory->getModelTable() . "."; 27 | } 28 | 29 | $app = array(); 30 | for ($x = 0; $x < sizeof($this->values); $x++) { 31 | $app[] = "?"; 32 | } 33 | if (sizeof($app) == 0) { 34 | if ($this->inverse) { 35 | return "TRUE"; 36 | } 37 | return "FALSE"; 38 | } 39 | return $table . $this->key . (($this->inverse) ? " NOT" : "") . " IN (" . implode(",", $app) . ")"; 40 | } 41 | 42 | function getValue() { 43 | return $this->values; 44 | } 45 | 46 | function getHasValue() { 47 | return true; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/dba/Filter.class.php: -------------------------------------------------------------------------------- 1 | by = $by; 14 | $this->factory = $factory; 15 | } 16 | 17 | function getQueryString($table = "") { 18 | if ($table != "") { 19 | $table = $table . "."; 20 | } 21 | if ($this->factory != null) { 22 | $table = $this->factory->getModelTable() . "."; 23 | } 24 | 25 | return $table . $this->by . " "; 26 | } 27 | } 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/dba/Join.class.php: -------------------------------------------------------------------------------- 1 | otherFactory = $otherFactory; 40 | $this->match1 = $matching1; 41 | $this->match2 = $matching2; 42 | 43 | $this->otherTableName = $this->otherFactory->getModelTable(); 44 | $this->overrideOwnFactory = $overrideOwnFactory; 45 | } 46 | 47 | /** 48 | * @return AbstractModelFactory 49 | */ 50 | function getOtherFactory() { 51 | return $this->otherFactory; 52 | } 53 | 54 | function getMatch1() { 55 | return $this->match1; 56 | } 57 | 58 | function getMatch2() { 59 | return $this->match2; 60 | } 61 | 62 | function getOtherTableName() { 63 | return $this->otherTableName; 64 | } 65 | 66 | /** 67 | * @return AbstractModelFactory 68 | */ 69 | function getOverrideOwnFactory() { 70 | return $this->overrideOwnFactory; 71 | } 72 | } 73 | 74 | 75 | -------------------------------------------------------------------------------- /src/dba/LikeFilter.class.php: -------------------------------------------------------------------------------- 1 | key = $key; 16 | $this->value = $value; 17 | $this->factory = $factory; 18 | $this->match = true; 19 | } 20 | 21 | function setMatch($status) { 22 | $this->match = $status; 23 | } 24 | 25 | function getQueryString($table = "") { 26 | if ($table != "") { 27 | $table = $table . "."; 28 | } 29 | if ($this->factory != null) { 30 | $table = $this->factory->getModelTable() . "."; 31 | } 32 | 33 | $inv = ""; 34 | if ($this->match === false) { 35 | $inv = " NOT"; 36 | } 37 | 38 | return $table . $this->key . $inv . " LIKE BINARY ?"; 39 | } 40 | 41 | function getValue() { 42 | return $this->value; 43 | } 44 | 45 | function getHasValue() { 46 | return true; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/dba/LikeFilterInsensitive.class.php: -------------------------------------------------------------------------------- 1 | key = $key; 15 | $this->value = $value; 16 | $this->factory = $factory; 17 | } 18 | 19 | function getQueryString($table = "") { 20 | if ($table != "") { 21 | $table = $table . "."; 22 | } 23 | if ($this->factory != null) { 24 | $table = $this->factory->getModelTable() . "."; 25 | } 26 | 27 | return "LOWER(" . $table . $this->key . ") LIKE LOWER(?)"; 28 | } 29 | 30 | function getValue() { 31 | return $this->value; 32 | } 33 | 34 | function getHasValue() { 35 | return true; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/dba/MassUpdateSet.class.php: -------------------------------------------------------------------------------- 1 | matchValue = $matchValue; 9 | $this->updateValue = $updateValue; 10 | } 11 | 12 | function getMatchValue() { 13 | return $this->matchValue; 14 | } 15 | 16 | function getUpdateValue() { 17 | return $this->updateValue; 18 | } 19 | 20 | function getMassQuery($key) { 21 | return "WHEN " . $key . " = ? THEN ? "; 22 | } 23 | } -------------------------------------------------------------------------------- /src/dba/Order.class.php: -------------------------------------------------------------------------------- 1 | by = $by; 15 | $this->type = $type; 16 | $this->factory = $factory; 17 | } 18 | 19 | function getQueryString($table = "") { 20 | if ($table != "") { 21 | $table = $table . "."; 22 | } 23 | if ($this->factory != null) { 24 | $table = $this->factory->getModelTable() . "."; 25 | } 26 | 27 | return $table . $this->by . " " . $this->type; 28 | } 29 | } 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/dba/QueryFilter.class.php: -------------------------------------------------------------------------------- 1 | key = $key; 16 | $this->value = $value; 17 | $this->operator = $operator; 18 | $this->factory = $factory; 19 | } 20 | 21 | function getQueryString($table = "") { 22 | if ($table != "") { 23 | $table = $table . "."; 24 | } 25 | if ($this->factory != null) { 26 | $table = $this->factory->getModelTable() . "."; 27 | } 28 | 29 | if ($this->value === null) { 30 | if ($this->operator == '<>') { 31 | return $table . $this->key . " IS NOT NULL "; 32 | } 33 | return $table . $this->key . " IS NULL "; 34 | } 35 | return $table . $this->key . $this->operator . "?"; 36 | } 37 | 38 | function getValue() { 39 | if ($this->value === null) { 40 | return null; 41 | } 42 | return $this->value; 43 | } 44 | 45 | function getHasValue() { 46 | if ($this->value === null) { 47 | return false; 48 | } 49 | return true; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/dba/QueryFilterNoCase.class.php: -------------------------------------------------------------------------------- 1 | key = $key; 16 | $this->value = $value; 17 | $this->operator = $operator; 18 | $this->factory = $factory; 19 | } 20 | 21 | function getQueryString($table = "") { 22 | if ($table != "") { 23 | $table = $table . "."; 24 | } 25 | if ($this->factory != null) { 26 | $table = $this->factory->getModelTable() . "."; 27 | } 28 | 29 | if ($this->value === null) { 30 | if ($this->operator == '<>') { 31 | return $table . $this->key . " IS NOT NULL "; 32 | } 33 | return $table . $this->key . " IS NULL "; 34 | } 35 | return "(LOWER(" . $table . $this->key . ") " . $this->operator . "? OR " . $table . $this->key . $this->operator . "?)"; 36 | } 37 | 38 | function getValue() { 39 | if ($this->value === null) { 40 | return null; 41 | } 42 | return array($this->value, $this->value); 43 | } 44 | 45 | function getHasValue() { 46 | if ($this->value === null) { 47 | return false; 48 | } 49 | return true; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/dba/QueryFilterWithNull.class.php: -------------------------------------------------------------------------------- 1 | key = $key; 17 | $this->value = $value; 18 | $this->operator = $operator; 19 | $this->factory = $factory; 20 | $this->matchNull = $matchNull; 21 | } 22 | 23 | function getQueryString($table = "") { 24 | if ($table != "") { 25 | $table = $table . "."; 26 | } 27 | if ($this->factory != null) { 28 | $table = $this->factory->getModelTable() . "."; 29 | } 30 | 31 | if ($this->value === null) { 32 | if ($this->operator == '<>') { 33 | return $table . $this->key . " IS NOT NULL "; 34 | } 35 | return $table . $this->key . " IS NULL "; 36 | } 37 | if ($this->matchNull) { 38 | return "(" . $table . $this->key . $this->operator . "? OR " . $table . $this->key . " IS NULL)"; 39 | } 40 | return "(" . $table . $this->key . $this->operator . "? OR " . $table . $this->key . " IS NOT NULL)"; 41 | } 42 | 43 | function getValue() { 44 | if ($this->value === null) { 45 | return null; 46 | } 47 | return $this->value; 48 | } 49 | 50 | function getHasValue() { 51 | if ($this->value === null) { 52 | return false; 53 | } 54 | return true; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/dba/UpdateSet.class.php: -------------------------------------------------------------------------------- 1 | key = $key; 9 | $this->value = $value; 10 | } 11 | 12 | function getQuery($table = "") { 13 | return $table . $this->key . "=?"; 14 | } 15 | 16 | function getValue() { 17 | return $this->value; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/dba/Util.class.php: -------------------------------------------------------------------------------- 1 | $val) { 40 | $arr[] = "`$table`.`$key` AS `$table.$key`"; 41 | } 42 | return implode(", ", $arr); 43 | } 44 | 45 | /** 46 | * Checks if $search starts with $pattern. Shortcut for strpos==0 47 | * @param $search string 48 | * @param $pattern string 49 | * @return bool 50 | */ 51 | public static function startsWith($search, $pattern) { 52 | if (strpos($search, $pattern) === 0) { 53 | return true; 54 | } 55 | return false; 56 | } 57 | } -------------------------------------------------------------------------------- /src/dba/models/AbstractModel.template.txt: -------------------------------------------------------------------------------- 1 | __MODEL_PK__; 32 | } 33 | 34 | function getId() { 35 | return $this->__MODEL_PK__; 36 | } 37 | 38 | function setId($id) { 39 | $this->__MODEL_PK__ = $id; 40 | } 41 | 42 | /** 43 | * Used to serialize the data contained in the model 44 | * @return array 45 | */ 46 | public function expose() { 47 | return get_object_vars($this); 48 | } 49 | 50 | __MODEL_GETTER_SETTER__ 51 | 52 | __MODEL_VARIABLE_NAMES__ 53 | 54 | __MODEL_PERMISSION_DEFINES__ 55 | } 56 | -------------------------------------------------------------------------------- /src/dba/models/Factory.template.txt: -------------------------------------------------------------------------------- 1 | checkPermission(DViewControl::FORGOT_VIEW_PERM); 6 | 7 | Template::loadInstance("forgot"); 8 | 9 | if (isset($_POST['action']) && CSRF::check($_POST['csrf'])) { 10 | $forgotHandler = new ForgotHandler(); 11 | $forgotHandler->handle($_POST['action']); 12 | if (UI::getNumMessages() == 0) { 13 | Util::refresh(); 14 | } 15 | } 16 | 17 | UI::add('pageTitle', "Forgot Password"); 18 | 19 | echo Template::getInstance()->render(UI::getObjects()); 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/hashtypes.php: -------------------------------------------------------------------------------- 1 | isLoggedin()) { 8 | header("Location: index.php?err=4" . time() . "&fw=" . urlencode($_SERVER['PHP_SELF'] . "?" . $_SERVER['QUERY_STRING'])); 9 | die(); 10 | } 11 | 12 | AccessControl::getInstance()->checkPermission(DViewControl::HASHTYPES_VIEW_PERM); 13 | 14 | Template::loadInstance("hashtypes"); 15 | Menu::get()->setActive("config_hashtypes"); 16 | 17 | //catch actions here... 18 | if (isset($_POST['action']) && CSRF::check($_POST['csrf'])) { 19 | $hashtypeHandler = new HashtypeHandler(); 20 | $hashtypeHandler->handle($_POST['action']); 21 | if (UI::getNumMessages() == 0) { 22 | Util::refresh(); 23 | } 24 | } 25 | 26 | $hashtypes = Factory::getHashTypeFactory()->filter([]); 27 | 28 | UI::add('hashtypes', $hashtypes); 29 | UI::add('pageTitle', "Hashtypes"); 30 | 31 | echo Template::getInstance()->render(UI::getObjects()); 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/help.php: -------------------------------------------------------------------------------- 1 | checkPermission(DViewControl::HELP_VIEW_PERM); 6 | 7 | Template::loadInstance("static/help"); 8 | UI::add('pageTitle', "Help"); 9 | echo Template::getInstance()->render(UI::getObjects()); 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/inc/.gitignore: -------------------------------------------------------------------------------- 1 | /stat.php 2 | /conf.php 3 | -------------------------------------------------------------------------------- /src/inc/.htaccess: -------------------------------------------------------------------------------- 1 | Order deny,allow 2 | Deny from all -------------------------------------------------------------------------------- /src/inc/CSRF.class.php: -------------------------------------------------------------------------------- 1 | values = $arr; 8 | } 9 | 10 | public function setValues($arr) { 11 | $this->values = $arr; 12 | } 13 | 14 | public function addValue($key, $val) { 15 | $this->values[$key] = $val; 16 | } 17 | 18 | public function getVal($key) { 19 | if (isset($this->values[$key])) { 20 | return $this->values[$key]; 21 | } 22 | return false; 23 | } 24 | 25 | public function getKeys() { 26 | $keys = []; 27 | foreach ($this->values as $key => $val) { 28 | $keys[] = $key; 29 | } 30 | return $keys; 31 | } 32 | 33 | public function getAllValues() { 34 | return $this->values; 35 | } 36 | } -------------------------------------------------------------------------------- /src/inc/HTException.class.php: -------------------------------------------------------------------------------- 1 | arr = $message; 8 | $this->message = implode("\n", $this->arr); 9 | } 10 | 11 | public function getHTMLMessage() { 12 | return implode("
", $this->arr); 13 | } 14 | } -------------------------------------------------------------------------------- /src/inc/Menu.class.php: -------------------------------------------------------------------------------- 1 | active = $name; 26 | } 27 | 28 | /** 29 | * Set which menu point should be active 30 | * 31 | * @param string $name identifier used on checking for active 32 | */ 33 | public function setActive($name) { 34 | $this->active = $name; 35 | } 36 | 37 | /** 38 | * Request for a identifier if it is active or no. 39 | * 40 | * @param string $name identifier to check 41 | * @param string $classonly when it's used in a dropdown provide the name of the dropdown object here 42 | * @return string with " class='active'" if is active or "" if not 43 | */ 44 | public function isActive($name, $classonly = "") { 45 | if ($classonly == 'classonly') { 46 | $split = explode("_", $this->active); 47 | if ($split[0] == $name) { 48 | return " active"; 49 | } 50 | return ""; 51 | } 52 | if ($name == $this->active) { 53 | return " active"; 54 | } 55 | return ""; 56 | } 57 | } 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/inc/SConfig.class.php: -------------------------------------------------------------------------------- 1 | filter([]); 15 | self::$instance = new DataSet(); 16 | foreach ($res as $entry) { 17 | self::$instance->addValue($entry->getItem(), $entry->getValue()); 18 | } 19 | } 20 | return self::$instance; 21 | } 22 | 23 | /** 24 | * Force reloading the config from the database 25 | */ 26 | public static function reload() { 27 | SConfig::getInstance(true); 28 | } 29 | } -------------------------------------------------------------------------------- /src/inc/api/APIBasic.class.php: -------------------------------------------------------------------------------- 1 | mset($this->agent, [Agent::LAST_IP => Util::getIP(), Agent::LAST_ACT => $action, Agent::LAST_TIME => time()]); 25 | } 26 | 27 | public function sendErrorResponse($action, $msg) { 28 | $ANS = array(); 29 | $ANS[PResponseErrorMessage::ACTION] = $action; 30 | $ANS[PResponseErrorMessage::RESPONSE] = PValues::ERROR; 31 | $ANS[PResponseErrorMessage::MESSAGE] = $msg; 32 | header("Content-Type: application/json"); 33 | echo json_encode($ANS); 34 | die(); 35 | } 36 | 37 | public function checkToken($action, $QUERY) { 38 | $qF = new QueryFilter(Agent::TOKEN, $QUERY[PQuery::TOKEN], "="); 39 | $agent = Factory::getAgentFactory()->filter([Factory::FILTER => array($qF)], true); 40 | if ($agent == null) { 41 | DServerLog::log(DServerLog::WARNING, "Agent from " . Util::getIP() . " sent invalid token!"); 42 | $this->sendErrorResponse($action, "Invalid token!"); 43 | } 44 | $this->agent = $agent; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/inc/api/APIDeRegisterAgent.class.php: -------------------------------------------------------------------------------- 1 | sendErrorResponse(PActions::DEREGISTER, "Invalid de-registering query!"); 8 | } 9 | $this->checkToken(PActions::DEREGISTER, $QUERY); 10 | 11 | if (!SConfig::getInstance()->getVal(DConfig::ALLOW_DEREGISTER)) { 12 | $this->sendErrorResponse(PActions::DEREGISTER, "De-registration is not allowed on this server!"); 13 | } 14 | try { 15 | AgentUtils::delete($this->agent->getId(), null); 16 | } 17 | catch (HTException $e) { 18 | $this->sendErrorResponse(PActions::DEREGISTER, "Error occured during de-registration: " . $e->getMessage()); 19 | } 20 | $this->sendResponse(array( 21 | PQueryDeRegister::ACTION => PActions::DEREGISTER, 22 | PResponseDeRegister::RESPONSE => PValues::SUCCESS 23 | ) 24 | ); 25 | } 26 | } -------------------------------------------------------------------------------- /src/inc/api/APIGetFileStatus.class.php: -------------------------------------------------------------------------------- 1 | filter([]); 8 | $files = []; 9 | foreach ($deleteRequests as $deleteRequest) { 10 | $files[] = $deleteRequest->getFilename(); 11 | } 12 | 13 | $this->sendResponse(array( 14 | PResponseGetFileStatus::ACTION => PActions::GET_FILE_STATUS, 15 | PResponseGetFileStatus::RESPONSE => PValues::SUCCESS, 16 | PResponseGetFileStatus::FILENAMES => $files 17 | ) 18 | ); 19 | } 20 | } -------------------------------------------------------------------------------- /src/inc/api/APIGetHealthCheck.class.php: -------------------------------------------------------------------------------- 1 | sendErrorResponse(PActions::GET_HEALTH_CHECK, "Invalid get health check query!"); 9 | } 10 | $this->checkToken(PActions::GET_HEALTH_CHECK, $QUERY); 11 | $this->updateAgent(PActions::GET_HEALTH_CHECK); 12 | 13 | $healthCheckAgent = HealthUtils::checkNeeded($this->agent); 14 | if ($healthCheckAgent == null) { 15 | // for whatever reason there is no check available anymore 16 | $this->sendErrorResponse(PActions::GET_HEALTH_CHECK, "No health check available for this agent!"); 17 | } 18 | $healthCheck = Factory::getHealthCheckFactory()->get($healthCheckAgent->getHealthCheckId()); 19 | 20 | DServerLog::log(DServerLog::INFO, "Received health check task", [$this->agent, $healthCheck]); 21 | 22 | $hashes = file_get_contents("/tmp/health-check-" . $healthCheck->getId() . ".txt"); 23 | $hashes = explode("\n", $hashes); 24 | 25 | $this->sendResponse([ 26 | PResponseGetHealthCheck::ACTION => PActions::GET_HEALTH_CHECK, 27 | PResponseGetHealthCheck::RESPONSE => PValues::SUCCESS, 28 | PResponseGetHealthCheck::ATTACK => " --hash-type=" . $healthCheck->getHashtypeId() . " " . $healthCheck->getAttackCmd() . " " . $this->agent->getCmdPars(), 29 | PResponseGetHealthCheck::CRACKER_BINARY_ID => (int)$healthCheck->getCrackerBinaryId(), 30 | PResponseGetHealthCheck::HASHES => $hashes, 31 | PResponseGetHealthCheck::CHECK_ID => (int)$healthCheck->getId(), 32 | PResponseGetHealthCheck::HASHLIST_ALIAS => SConfig::getInstance()->getVal(DConfig::HASHLIST_ALIAS) 33 | ] 34 | ); 35 | } 36 | } -------------------------------------------------------------------------------- /src/inc/api/APILogin.class.php: -------------------------------------------------------------------------------- 1 | sendErrorResponse(PActions::LOGIN, "Invalid login query!"); 12 | } 13 | $this->checkToken(PActions::LOGIN, $QUERY); 14 | Factory::getAgentFactory()->set($this->agent, Agent::CLIENT_SIGNATURE, htmlentities($QUERY[PQueryLogin::CLIENT_SIGNATURE], ENT_QUOTES, "UTF-8")); 15 | $this->updateAgent(PActions::LOGIN); 16 | 17 | DServerLog::log(DServerLog::DEBUG, "Agent logged in", [$this->agent]); 18 | 19 | $this->sendResponse(array( 20 | PResponseLogin::ACTION => PActions::LOGIN, 21 | PResponseLogin::RESPONSE => PValues::SUCCESS, 22 | PResponseLogin::MULTICAST => (SConfig::getInstance()->getVal(DConfig::MULTICAST_ENABLE)) ? true : false, 23 | PResponseLogin::TIMEOUT => (int)SConfig::getInstance()->getVal(DConfig::AGENT_TIMEOUT), 24 | PResponseLogin::VERSION => $VERSION . " (" . Util::getGitCommit() . ")" 25 | ) 26 | ); 27 | } 28 | } -------------------------------------------------------------------------------- /src/inc/api/APITestConnection.class.php: -------------------------------------------------------------------------------- 1 | sendResponse(array( 6 | PResponse::ACTION => PActions::TEST_CONNECTION, 7 | PResponse::RESPONSE => PValues::SUCCESS 8 | ) 9 | ); 10 | } 11 | } -------------------------------------------------------------------------------- /src/inc/apiv2/helper/abortChunk.routes.php: -------------------------------------------------------------------------------- 1 | ['type' => 'int'] 24 | ]; 25 | } 26 | 27 | public function actionPost(array $data): array|null { 28 | $chunk = self::getChunk($data[Chunk::CHUNK_ID]); 29 | 30 | TaskUtils::abortChunk($chunk->getId(), $this->getCurrentUser()); 31 | return null; 32 | } 33 | } 34 | 35 | ChunkAbortHelperAPI::register($app); -------------------------------------------------------------------------------- /src/inc/apiv2/helper/assignAgent.routes.php: -------------------------------------------------------------------------------- 1 | ["type" => "int"], 24 | Task::TASK_ID => ["type" => "int"], 25 | ]; 26 | } 27 | 28 | public function actionPost($data): array|null { 29 | AgentUtils::assign($data[Agent::AGENT_ID], $data[Task::TASK_ID], $this->getCurrentUser()); 30 | 31 | # TODO: Check how to handle custom return messages that are not object, probably we want that to be in some kind of standardized form. 32 | return ["assign" => "success"]; 33 | } 34 | } 35 | 36 | AssignAgentHelperAPI::register($app); -------------------------------------------------------------------------------- /src/inc/apiv2/helper/exportCrackedHashes.routes.php: -------------------------------------------------------------------------------- 1 | ["type" => "int"], 26 | ]; 27 | } 28 | 29 | public function actionPost($data): array|null { 30 | $hashlist = self::getHashlist($data[Hashlist::HASHLIST_ID]); 31 | 32 | $file = HashlistUtils::export($hashlist->getId(), $this->getCurrentUser()); 33 | return $this->object2Array($file); 34 | } 35 | } 36 | 37 | ExportCrackedHashesHelperAPI::register($app); -------------------------------------------------------------------------------- /src/inc/apiv2/helper/exportLeftHashes.routes.php: -------------------------------------------------------------------------------- 1 | ["type" => "int"], 26 | ]; 27 | } 28 | 29 | public function actionPost($data): array|null { 30 | $hashlist = self::getHashlist($data[Hashlist::HASHLIST_ID]); 31 | 32 | $file = HashlistUtils::leftlist($hashlist->getId(), $this->getCurrentUser()); 33 | 34 | return $this->object2Array($file); 35 | } 36 | } 37 | 38 | ExportLeftHashesHelperAPI::register($app); -------------------------------------------------------------------------------- /src/inc/apiv2/helper/exportWordlist.routes.php: -------------------------------------------------------------------------------- 1 | ["type" => "int"], 26 | ]; 27 | } 28 | 29 | public function actionPost($data): array|null { 30 | $hashlist = self::getHashlist($data[Hashlist::HASHLIST_ID]); 31 | 32 | $arr = HashlistUtils::createWordlists($hashlist->getId(), $this->getCurrentUser()); 33 | 34 | return $this->object2Array($arr[2]); 35 | } 36 | } 37 | 38 | ExportWordlistHelperAPI::register($app); -------------------------------------------------------------------------------- /src/inc/apiv2/helper/importCrackedHashes.routes.php: -------------------------------------------------------------------------------- 1 | ["type" => "int"], 24 | "sourceData" => ['type' => 'str'], 25 | "separator" => ['type' => 'str'], 26 | ]; 27 | } 28 | 29 | public function actionPost($data): array|null { 30 | $hashlist = self::getHashlist($data[Hashlist::HASHLIST_ID]); 31 | 32 | $result = HashlistUtils::processZap($hashlist->getId(), $data["separator"], "paste", ["hashfield" => $data["sourceData"]], [], $this->getCurrentUser()); 33 | 34 | # TODO: Check how to handle custom return messages that are not object, probably we want that to be in some kind of standardized form. 35 | return [ 36 | "totalLines" => $result[0], 37 | "newCracked" => $result[1], 38 | "alreadyCracked" => $result[2], 39 | "invalid" => $result[3], 40 | "notFound" => $result[4], 41 | "processTime" => $result[5], 42 | "tooLongPlaintexts" => $result[6], 43 | ]; 44 | } 45 | } 46 | 47 | ImportCrackedHashesHelperAPI::register($app); -------------------------------------------------------------------------------- /src/inc/apiv2/helper/purgeTask.routes.php: -------------------------------------------------------------------------------- 1 | ["type" => "int"], 25 | ]; 26 | } 27 | 28 | public function actionPost($data): array|null { 29 | $task = self::getTask($data[Task::TASK_ID]); 30 | 31 | TaskUtils::purgeTask($task->getId(), $this->getCurrentUser()); 32 | return null; 33 | } 34 | } 35 | 36 | PurgeTaskHelperAPI::register($app); -------------------------------------------------------------------------------- /src/inc/apiv2/helper/recountFileLines.routes.php: -------------------------------------------------------------------------------- 1 | ["type" => "int"], 24 | ]; 25 | } 26 | 27 | public function actionPost($data): array|null { 28 | // first retrieve the file, as fileCountLines does not check any permissions, therfore to be sure call getFile() first, even if it is not required technically 29 | FileUtils::getFile($data[File::FILE_ID], $this->getCurrentUser()); 30 | 31 | FileUtils::fileCountLines($data[File::FILE_ID]); 32 | 33 | return $this->object2Array(FileUtils::getFile($data[File::FILE_ID], $this->getCurrentUser())); 34 | } 35 | } 36 | 37 | RecountFileFilesHelperAPI::register($app); -------------------------------------------------------------------------------- /src/inc/apiv2/helper/resetChunk.routes.php: -------------------------------------------------------------------------------- 1 | ['type' => 'int'] 24 | ]; 25 | } 26 | 27 | public function actionPost(array $data): array|null { 28 | $chunk = self::getChunk($data[Chunk::CHUNK_ID]); 29 | TaskUtils::resetChunk($chunk->getId(), $this->getCurrentUser()); 30 | return null; 31 | } 32 | } 33 | 34 | ChunkResetHelperAPI::register($app); -------------------------------------------------------------------------------- /src/inc/apiv2/helper/setUserPassword.routes.php: -------------------------------------------------------------------------------- 1 | ["type" => "int"], 27 | "password" => ["type" => "str"] 28 | ]; 29 | } 30 | 31 | public function actionPost($data): array|null { 32 | $user = self::getUser($data[User::USER_ID]); 33 | 34 | /* Set user password if provided */ 35 | UserUtils::setPassword( 36 | $user->getId(), 37 | $data["password"], 38 | $this->getCurrentUser() 39 | ); 40 | return null; 41 | } 42 | } 43 | 44 | SetUserPasswordHelperAPI::register($app); -------------------------------------------------------------------------------- /src/inc/apiv2/helper/unassignAgent.routes.php: -------------------------------------------------------------------------------- 1 | ["type" => "int"], 24 | ]; 25 | } 26 | 27 | public function actionPost($data): array|null { 28 | AgentUtils::assign($data[Agent::AGENT_ID], 0, $this->getCurrentUser()); 29 | 30 | # TODO: Check how to handle custom return messages that are not object, probably we want that to be in some kind of standardized form. 31 | return ["unassign" => "success"]; 32 | } 33 | } 34 | 35 | UnassignAgentHelperAPI::register($app); -------------------------------------------------------------------------------- /src/inc/apiv2/model/agentbinaries.routes.php: -------------------------------------------------------------------------------- 1 | getCurrentUser() 28 | ); 29 | 30 | /* On succesfully insert, return ID */ 31 | $qFs = [ 32 | new QueryFilter(AgentBinary::FILENAME, $data[AgentBinary::FILENAME], '='), 33 | new QueryFilter(AgentBinary::VERSION, $data[AgentBinary::VERSION], '='), 34 | ]; 35 | 36 | /* Hackish way to retreive object since Id is not returned on creation */ 37 | $oF = new OrderFilter(AgentBinary::AGENT_BINARY_ID, "DESC"); 38 | $objects = $this->getFactory()->filter([Factory::FILTER => $qFs, Factory::ORDER => $oF]); 39 | /* No unique properties set on columns, thus multiple entries could exists, pick the latest (DESC ordering used) */ 40 | assert(count($objects) >= 1); 41 | 42 | return $objects[0]->getId(); 43 | } 44 | 45 | protected function deleteObject(object $object): void { 46 | AgentBinaryUtils::deleteBinary($object->getId()); 47 | } 48 | } 49 | 50 | AgentBinaryAPI::register($app); -------------------------------------------------------------------------------- /src/inc/apiv2/model/agentstats.routes.php: -------------------------------------------------------------------------------- 1 | delete($object); 33 | } 34 | } 35 | 36 | AgentStatsAPI::register($app); -------------------------------------------------------------------------------- /src/inc/apiv2/model/configsections.routes.php: -------------------------------------------------------------------------------- 1 | getCurrentUser() 23 | ); 24 | 25 | return $data[HashType::HASH_TYPE_ID]; 26 | } 27 | 28 | protected function deleteObject(object $object): void { 29 | HashtypeUtils::deleteHashtype($object->getId()); 30 | } 31 | } 32 | 33 | HashTypeAPI::register($app); -------------------------------------------------------------------------------- /src/inc/apiv2/model/logentries.routes.php: -------------------------------------------------------------------------------- 1 | getFactory()->filter([Factory::FILTER => $qFs, Factory::ORDER => $oF]); 39 | assert(count($objects) == 1); 40 | 41 | return $objects[0]->getId(); 42 | } 43 | 44 | protected function deleteObject(object $object): void { 45 | Factory::getLogEntryFactory()->delete($object); 46 | } 47 | } 48 | 49 | LogEntryAPI::register($app); -------------------------------------------------------------------------------- /src/inc/apiv2/model/preprocessors.routes.php: -------------------------------------------------------------------------------- 1 | getFactory()->filter([Factory::FILTER => $qFs, Factory::ORDER => $oF]); 39 | assert(count($objects) == 1); 40 | 41 | return $objects[0]->getId(); 42 | } 43 | 44 | protected function deleteObject(object $object): void { 45 | PreprocessorUtils::delete($object->getId()); 46 | } 47 | } 48 | 49 | PreprocessorAPI::register($app); -------------------------------------------------------------------------------- /src/inc/apiv2/model/vouchers.routes.php: -------------------------------------------------------------------------------- 1 | getFactory()->filter([Factory::FILTER => $qFs, Factory::ORDER => $oF]); 31 | assert(count($objects) == 1); 32 | 33 | return $objects[0]->getId(); 34 | } 35 | 36 | protected function deleteObject(object $object): void { 37 | AgentUtils::deleteVoucher($object->getId()); 38 | } 39 | } 40 | 41 | VoucherAPI::register($app); -------------------------------------------------------------------------------- /src/inc/conf.template.php: -------------------------------------------------------------------------------- 1 | "/var/www/hashtopolis/files/", 12 | "import" => "/var/www/hashtopolis/import/", 13 | "log" => "/var/www/hashtopolis/log/", 14 | "config" => "/var/www/hashtopolis/config/", 15 | ]; 16 | 17 | //END CONFIG 18 | -------------------------------------------------------------------------------- /src/inc/defines/accessGroups.php: -------------------------------------------------------------------------------- 1 | "AMD", 6 | "CPU @" => "", 7 | "Intel Corporation" => "Intel", 8 | "Intel(R) Core(TM)" => "Core", 9 | "Intel(R) Pentium(R) CPU" => "Pentium", 10 | "NVIDIA Corporation Device" => "NVIDIA", 11 | "NVIDIA GeForce" => "NVIDIA" 12 | ); 13 | } -------------------------------------------------------------------------------- /src/inc/defines/fileDownload.php: -------------------------------------------------------------------------------- 1 | checkPermission(DAccessControlAction::CREATE_GROUP_PERM); 13 | $group = AccessControlUtils::createGroup($_POST['groupName']); 14 | header("Location: access.php?id=" . $group->getId()); 15 | die(); 16 | case DAccessControlAction::DELETE_GROUP: 17 | AccessControl::getInstance()->checkPermission(DAccessControlAction::DELETE_GROUP_PERM); 18 | AccessControlUtils::deleteGroup($_POST['groupId']); 19 | break; 20 | case DAccessControlAction::EDIT: 21 | AccessControl::getInstance()->checkPermission(DAccessControlAction::EDIT_PERM); 22 | $changes = AccessControlUtils::updateGroupPermissions($_POST['groupId'], $_POST['perm']); 23 | if ($changes) { 24 | UI::addMessage(UI::WARN, "NOTE: Some permissions were additionally allowed because of dependencies!"); 25 | } 26 | break; 27 | default: 28 | UI::addMessage(UI::ERROR, "Invalid action!"); 29 | break; 30 | } 31 | } 32 | catch (HTException $e) { 33 | UI::addMessage(UI::ERROR, $e->getMessage()); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/inc/handlers/ApiHandler.class.php: -------------------------------------------------------------------------------- 1 | getMessage()); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/inc/handlers/ConfigHandler.class.php: -------------------------------------------------------------------------------- 1 | checkPermission(DConfigAction::UPDATE_CONFIG_PERM); 13 | ConfigUtils::updateConfig($_POST); 14 | UI::addMessage(UI::SUCCESS, "Config was updated!"); 15 | break; 16 | case DConfigAction::REBUILD_CACHE: 17 | AccessControl::getInstance()->checkPermission(DConfigAction::REBUILD_CACHE_PERM); 18 | $ret = ConfigUtils::rebuildCache(); 19 | UI::addMessage(UI::SUCCESS, "Updated all chunks and hashlists. Corrected " . $ret[0] . " chunks and " . $ret[1] . " hashlists."); 20 | break; 21 | case DConfigAction::RESCAN_FILES: 22 | AccessControl::getInstance()->checkPermission(DConfigAction::RESCAN_FILES_PERM); 23 | ConfigUtils::scanFiles(); 24 | UI::addMessage(UI::SUCCESS, "File scan was successfull, no actions required!"); 25 | break; 26 | case DConfigAction::CLEAR_ALL: 27 | AccessControl::getInstance()->checkPermission(DConfigAction::CLEAR_ALL_PERM); 28 | ConfigUtils::clearAll(Login::getInstance()->getUser()); 29 | break; 30 | default: 31 | UI::addMessage(UI::ERROR, "Invalid action!"); 32 | break; 33 | } 34 | } 35 | catch (HTException $e) { 36 | UI::addMessage(UI::ERROR, $e->getMessage()); 37 | } 38 | catch (HTMessages $m) { 39 | UI::addMessage(UI::ERROR, $m->getHTMLMessage()); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/inc/handlers/Handler.class.php: -------------------------------------------------------------------------------- 1 | getUser()); 17 | UI::addMessage(UI::SUCCESS, "New hashtype created successfully!"); 18 | break; 19 | default: 20 | UI::addMessage(UI::ERROR, "Invalid action!"); 21 | break; 22 | } 23 | } 24 | catch (HTException $e) { 25 | UI::addMessage(UI::ERROR, $e->getMessage()); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/inc/handlers/HealthHandler.class.php: -------------------------------------------------------------------------------- 1 | checkPermission(DHealthCheckAction::CREATE_PERM); 13 | HealthUtils::createHealthCheck(intval($_POST['hashtypeId']), intval($_POST['type']), intval($_POST['crackerBinaryVersionId'])); 14 | break; 15 | case DHealthCheckAction::RESET_AGENT: 16 | AccessControl::getInstance()->checkPermission(DHealthCheckAction::RESET_AGENT_PERM); 17 | HealthUtils::resetAgentCheck(intval($_POST['healthCheckAgentId'])); 18 | break; 19 | case DHealthCheckAction::DELETE_HEALTH_CHECK: 20 | AccessControl::getInstance()->checkPermission(DHealthCheckAction::DELETE_HEALTH_CHECK_PERM); 21 | HealthUtils::deleteHealthCheck(intval($_POST['healthCheckId'])); 22 | break; 23 | default: 24 | throw new HTException("Invalid action!"); 25 | } 26 | } 27 | catch (HTException $e) { 28 | UI::addMessage(UI::ERROR, $e->getMessage()); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/inc/handlers/PreprocessorHandler.class.php: -------------------------------------------------------------------------------- 1 | checkPermission(DPreprocessorAction::ADD_PREPROCESSOR_PERM); 13 | PreprocessorUtils::addPreprocessor($_POST['name'], $_POST['binaryName'], $_POST['url'], $_POST['keyspaceCommand'], $_POST['skipCommand'], $_POST['limitCommand']); 14 | UI::addMessage(UI::SUCCESS, "Added new preprocessor!"); 15 | break; 16 | case DPreprocessorAction::DELETE_PREPROCESSOR: 17 | AccessControl::getInstance()->checkPermission(DPreprocessorAction::DELETE_PREPROCESSOR_PERM); 18 | PreprocessorUtils::delete($_POST['preprocessorId']); 19 | UI::addMessage(UI::SUCCESS, "Deleted preprocessor successfully!"); 20 | break; 21 | case DPreprocessorAction::EDIT_PREPROCESSOR: 22 | AccessControl::getInstance()->checkPermission(DPreprocessorAction::EDIT_PREPROCESSOR_PERM); 23 | PreprocessorUtils::editPreprocessor($_POST['preprocessorId'], $_POST['name'], $_POST['binaryName'], $_POST['url'], $_POST['keyspaceCommand'], $_POST['skipCommand'], $_POST['limitCommand']); 24 | UI::addMessage(UI::SUCCESS, "Saved changes successfully!"); 25 | break; 26 | default: 27 | UI::addMessage(UI::ERROR, "Invalid action!"); 28 | break; 29 | } 30 | } 31 | catch (HTException $e) { 32 | UI::addMessage(UI::ERROR, $e->getMessage()); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/inc/info.php: -------------------------------------------------------------------------------- 1 | notification->getUserId()); 14 | return $obj; 15 | } 16 | 17 | function sendMessage($message, $subject) { 18 | $message = explode("##########", $message); 19 | Util::sendMail($this->receiver, $subject, $message[0], $message[1]); 20 | } 21 | } 22 | 23 | HashtopolisNotification::add('Email', new HashtopolisNotificationEmail()); 24 | -------------------------------------------------------------------------------- /src/inc/notifications/NotificationExample.class.php: -------------------------------------------------------------------------------- 1 | receiver . ": " . $message . "\n", FILE_APPEND); 17 | } 18 | } 19 | 20 | HashtopolisNotification::add('Example', new HashtopolisNotificationExample()); 21 | 22 | -------------------------------------------------------------------------------- /src/inc/notifications/NotificationSlack.class.php: -------------------------------------------------------------------------------- 1 | $message)); 17 | 18 | $ch = curl_init($this->receiver); 19 | 20 | if (SConfig::getInstance()->getVal(DConfig::NOTIFICATIONS_PROXY_ENABLE) == 1) { 21 | curl_setopt($ch, CURLOPT_PROXY, SConfig::getInstance()->getVal(DConfig::NOTIFICATIONS_PROXY_SERVER)); 22 | curl_setopt($ch, CURLOPT_PROXYPORT, SConfig::getInstance()->getVal(DConfig::NOTIFICATIONS_PROXY_PORT)); 23 | $type = CURLPROXY_HTTP; 24 | switch (SConfig::getInstance()->getVal(DConfig::NOTIFICATIONS_PROXY_TYPE)) { 25 | case DProxyTypes::HTTPS: 26 | $type = CURLPROXY_HTTPS; 27 | break; 28 | case DProxyTypes::SOCKS4: 29 | $type = CURLPROXY_SOCKS4; 30 | break; 31 | case DProxyTypes::SOCKS5: 32 | $type = CURLPROXY_SOCKS5; 33 | break; 34 | } 35 | curl_setopt($ch, CURLOPT_PROXYTYPE, $type); 36 | curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, "true"); 37 | } 38 | 39 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); 40 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 41 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 42 | $result = curl_exec($ch); 43 | curl_close($ch); 44 | 45 | return $result; 46 | } 47 | } 48 | 49 | HashtopolisNotification::add('Slack', new HashtopolisNotificationSlack()); 50 | 51 | -------------------------------------------------------------------------------- /src/inc/runner/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/inc/runner/.gitkeep -------------------------------------------------------------------------------- /src/inc/runner/runner.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/inc/runner/runner.zip -------------------------------------------------------------------------------- /src/inc/runner/uftp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/inc/runner/uftp -------------------------------------------------------------------------------- /src/inc/utils/CrackerBinaryUtils.class.php: -------------------------------------------------------------------------------- 1 | filter([Factory::FILTER => $qF]); 16 | /** @var $newest CrackerBinary */ 17 | $newest = null; 18 | foreach ($binaries as $binary) { 19 | if ($newest == null || Util::versionComparison($binary->getVersion(), $newest->getVersion()) < 0) { 20 | $newest = $binary; 21 | } 22 | } 23 | if ($newest == null) { 24 | throw new HTException("No binary versions available, cannot create tasks!"); 25 | } 26 | return $newest; 27 | } 28 | } -------------------------------------------------------------------------------- /src/inc/utils/FileDownloadUtils.class.php: -------------------------------------------------------------------------------- 1 | filter([Factory::FILTER => [$qF1, $qF2]]); 18 | if ($check != null) { 19 | return; // file is already in pending list 20 | } 21 | $fileDownload = new FileDownload(null, time(), $fileId, DFileDownloadStatus::PENDING); 22 | Factory::getFileDownloadFactory()->save($fileDownload); 23 | } 24 | 25 | /** 26 | * Removes a file from the download list 27 | * @param int $fileId 28 | */ 29 | public static function removeFile($fileId) { 30 | $qF = new QueryFilter(FileDownload::FILE_ID, $fileId, "="); 31 | Factory::getFileDownloadFactory()->massDeletion([Factory::FILTER => $qF]); 32 | } 33 | } -------------------------------------------------------------------------------- /src/inc/utils/Lock.class.php: -------------------------------------------------------------------------------- 1 | lockFile = $lockFile; 22 | $this->lock = $lock; 23 | } 24 | 25 | /** 26 | * @throws Exception 27 | */ 28 | public function getLock() { 29 | // Get exclusive lock (blocking) 30 | $ret = flock($this->lock, LOCK_EX); 31 | if ($ret === false) { 32 | throw new Exception("Could not get lock on lockfile '" . $this->lockFile . "'!"); 33 | } 34 | } 35 | 36 | /** 37 | * @throws Exception 38 | */ 39 | public function release() { 40 | /* Release the lock */ 41 | $ret = flock($this->lock, LOCK_UN); 42 | if ($ret === false) { 43 | throw new Exception("Could not release lock on lockfile '" . $this->lockFile . "'."); 44 | } 45 | // not closing as otherwise we cannot reuse this object for locking 46 | // fclose($this->lock); 47 | } 48 | } -------------------------------------------------------------------------------- /src/inc/utils/LockUtils.class.php: -------------------------------------------------------------------------------- 1 | getLock(); 24 | } 25 | catch (Exception $e) { 26 | die("Locking: " . $e->getMessage()); 27 | } 28 | } 29 | 30 | /** 31 | * @param string $lockFile 32 | */ 33 | public static function release($lockFile) { 34 | if (isset(self::$locks[$lockFile])) { 35 | $lock = self::$locks[$lockFile]; 36 | try { 37 | $lock->release(); 38 | } 39 | catch (Exception $e) { 40 | die("Locking: " . $e->getMessage()); 41 | } 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/inc/utils/locks/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/inc/utils/locks/.gitkeep -------------------------------------------------------------------------------- /src/index.php: -------------------------------------------------------------------------------- 1 | checkPermission(DViewControl::INDEX_VIEW_PERM); 6 | 7 | Template::loadInstance("static/index"); 8 | UI::add('pageTitle', "Welcome"); 9 | 10 | if (isset($_GET['err'])) { 11 | $err = $_GET['err']; 12 | $time = substr($err, 1); 13 | if (time() - $time < 10) { 14 | switch ($err[0]) { 15 | case '1': 16 | UI::addMessage(UI::ERROR, "Invalid form submission!"); 17 | break; 18 | case '2': 19 | UI::addMessage(UI::ERROR, "You need to fill in both fields!"); 20 | break; 21 | case '3': 22 | UI::addMessage(UI::ERROR, "Wrong username/password/OTP!"); 23 | break; 24 | case '4': 25 | UI::addMessage(UI::ERROR, "You need to be logged in to view this! Please log in again."); 26 | break; 27 | } 28 | } 29 | } 30 | else if (isset($_GET['logout'])) { 31 | $logout = $_GET['logout']; 32 | $time = substr($logout, 1); 33 | if (time() - $time < 10) { 34 | UI::addMessage(UI::SUCCESS, "You logged out successfully!"); 35 | } 36 | } 37 | 38 | $fw = ""; 39 | if (isset($_GET['fw'])) { 40 | $fw = $_GET['fw']; 41 | } 42 | UI::add('fw', htmlentities($fw, ENT_QUOTES, "UTF-8")); 43 | 44 | echo Template::getInstance()->render(UI::getObjects()); 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/install/updates/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/install/updates/.gitkeep -------------------------------------------------------------------------------- /src/install/updates/reset.php: -------------------------------------------------------------------------------- 1 | get($userId); 21 | if ($user == null) { 22 | die("User not found!\n"); 23 | } 24 | 25 | $newSalt = Util::randomString(20); 26 | $newHash = Encryption::passwordHash($newPassword, $newSalt); 27 | $user->setPasswordHash($newHash); 28 | $user->setPasswordSalt($newSalt); 29 | $user->setIsComputedPassword(0); 30 | Factory::getUserFactory()->update($user); 31 | echo "User " . $user->getUsername() . " has a new password now\n!"; 32 | break; 33 | case "pepper": // use this if you have overwritten the Encryption class and the pepper values should be generated again. 34 | $pepper = array(Util::randomString(50), Util::randomString(50), Util::randomString(50)); 35 | $crypt = file_get_contents(dirname(__FILE__) . "/../../inc/Encryption.class.php"); 36 | $crypt = str_replace("__PEPPER1__", $pepper[0], str_replace("__PEPPER2__", $pepper[1], str_replace("__PEPPER3__", $pepper[2], $crypt))); 37 | file_put_contents(dirname(__FILE__) . "/../../inc/Encryption.class.php", $crypt); 38 | echo "Peppers are generated new!\n"; 39 | break; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /src/install/updates/update_v0.14.2_v0.14.3.php: -------------------------------------------------------------------------------- 1 | getDB()->query("ALTER TABLE `Task` MODIFY `attackCmd` TEXT NOT NULL;"); 7 | Factory::getAgentFactory()->getDB()->query("ALTER TABLE `Pretask` MODIFY `attackCmd` TEXT NOT NULL;"); 8 | Factory::getAgentFactory()->getDB()->query("ALTER TABLE `HealthCheck` MODIFY `attackCmd` TEXT NOT NULL;"); 9 | Factory::getAgentFactory()->getDB()->query("ALTER TABLE `Agent` MODIFY `cmdPars` TEXT NOT NULL;"); 10 | $EXECUTED["v0.14.x_attackCmd"] = true; 11 | } 12 | -------------------------------------------------------------------------------- /src/install/updates/update_v0.14.3_v0.14.4.php: -------------------------------------------------------------------------------- 1 | getDB()->query("ALTER TABLE `TaskWrapper` ADD `maxAgents` INT(11) NOT NULL;"); 9 | } 10 | $EXECUTED["v0.14.x_maxAgents_taskwrapper"] = true; 11 | } 12 | 13 | if (!isset($PRESENT["v0.14.x_agentBinaries"])) { 14 | Util::checkAgentVersion("python", "0.7.2", true); 15 | $EXECUTED["v0.14.x_agentBinaries"] = true; 16 | } 17 | -------------------------------------------------------------------------------- /src/install/updates/update_v0.2.0-beta_v0.2.0.php: -------------------------------------------------------------------------------- 1 | getDB()->query("ALTER TABLE `LogEntry` CHANGE `level` `level` VARCHAR(20) NOT NULL"); 13 | echo "OK\n"; 14 | 15 | echo "Change plaintext error on BinaryHash... "; 16 | Factory::getAgentFactory()->getDB()->query("ALTER TABLE `HashBinary` CHANGE `plaintext` `plaintext` VARCHAR(200) NULL DEFAULT NULL;"); 17 | echo "OK\n"; 18 | 19 | echo "Check csharp binary... "; 20 | $qF = new QueryFilter(AgentBinary::TYPE, "csharp", "="); 21 | $binary = Factory::getAgentBinaryFactory()->filter([Factory::FILTER => $qF], true); 22 | if ($binary != null) { 23 | if (Util::versionComparison($binary->getVersion(), "0.40") == 1) { 24 | echo "update version... "; 25 | $binary->setVersion("0.40"); 26 | Factory::getAgentBinaryFactory()->update($binary); 27 | echo "OK"; 28 | } 29 | } 30 | echo "\n"; 31 | 32 | echo "Update complete!\n"; 33 | -------------------------------------------------------------------------------- /src/install/updates/update_v0.3.0_v0.3.1.php: -------------------------------------------------------------------------------- 1 | getDB()->query("ALTER TABLE `Zap` CHANGE `agentId` `agentId` INT(11) NULL"); 11 | echo "OK\n"; 12 | 13 | echo "Update complete!\n"; 14 | -------------------------------------------------------------------------------- /src/install/updates/update_v0.3.1_v0.3.2.php: -------------------------------------------------------------------------------- 1 | getDB()->query("ALTER TABLE `Zap` CHANGE `agentId` `agentId` INT(11) NULL"); 13 | echo "OK\n"; 14 | 15 | echo "Check csharp binary... "; 16 | $qF = new QueryFilter(AgentBinary::TYPE, "csharp", "="); 17 | $binary = Factory::getAgentBinaryFactory()->filter([Factory::FILTER => $qF], true); 18 | if ($binary != null) { 19 | if (Util::versionComparison($binary->getVersion(), "0.43.13") == 1) { 20 | echo "update version... "; 21 | $binary->setVersion("0.43.13"); 22 | Factory::getAgentBinaryFactory()->update($binary); 23 | echo "OK"; 24 | } 25 | } 26 | echo "\n"; 27 | 28 | echo "Update complete!\n"; 29 | -------------------------------------------------------------------------------- /src/jscolor/arrow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/jscolor/arrow.gif -------------------------------------------------------------------------------- /src/jscolor/cross.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/jscolor/cross.gif -------------------------------------------------------------------------------- /src/jscolor/hs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/jscolor/hs.png -------------------------------------------------------------------------------- /src/jscolor/hv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/jscolor/hv.png -------------------------------------------------------------------------------- /src/lang/.htaccess: -------------------------------------------------------------------------------- 1 | Order deny,allow 2 | Deny from all -------------------------------------------------------------------------------- /src/lang/DE-de.php: -------------------------------------------------------------------------------- 1 | isLoggedin()) { 11 | header("Location: index.php?err=4" . time() . "&fw=" . urlencode($_SERVER['PHP_SELF'] . "?" . $_SERVER['QUERY_STRING'])); 12 | die(); 13 | } 14 | 15 | AccessControl::getInstance()->checkPermission(DViewControl::LOG_VIEW_PERM); 16 | 17 | Template::loadInstance("log"); 18 | UI::add('pageTitle', "Log"); 19 | Menu::get()->setActive("config_log"); 20 | 21 | $level = "0"; 22 | if (isset($_POST['show'])) { 23 | $level = $_POST['level']; 24 | } 25 | UI::add('level', $level); 26 | 27 | $qF = new QueryFilter(LogEntry::LEVEL, $level, "="); 28 | $oF = new OrderFilter(LogEntry::TIME, "DESC LIMIT 100"); 29 | 30 | $filter = array(Factory::ORDER => $oF); 31 | if ($level !== "0") { 32 | $filter[Factory::FILTER] = $qF; 33 | } 34 | 35 | $entries = Factory::getLogEntryFactory()->filter($filter); 36 | UI::add('entries', $entries); 37 | 38 | echo Template::getInstance()->render(UI::getObjects()); 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/login.php: -------------------------------------------------------------------------------- 1 | checkPermission(DViewControl::LOGIN_VIEW_PERM); 6 | 7 | if (!isset($_POST['username']) || !isset($_POST['password'])) { 8 | header("Location: index.php?err=1" . time()); 9 | die(); 10 | } 11 | 12 | $username = $_POST['username']; 13 | $password = $_POST['password']; 14 | 15 | // isYubikeyEnabled() ? 16 | $otp = (isset($_POST['otp'])) ? $_POST['otp'] : ""; 17 | $fw = (isset($_POST['fw'])) ? $_POST['fw'] : ""; 18 | 19 | if (strlen($username) == 0 || strlen($password) == 0) { 20 | header("Location: index.php?err=2" . time()); 21 | die(); 22 | } 23 | 24 | Login::getInstance()->login($username, $password, $otp); 25 | 26 | if (Login::getInstance()->isLoggedin()) { 27 | if (strlen($fw) > 0) { 28 | $fw = urldecode($fw); 29 | $url = Util::buildServerUrl() . ((Util::startsWith($fw, '/')) ? "" : "/") . $fw; 30 | header("Location: " . $url); 31 | die(); 32 | } 33 | header("Location: index.php"); 34 | die(); 35 | } 36 | 37 | header("Location: index.php?err=3" . time()); 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/logout.php: -------------------------------------------------------------------------------- 1 | checkPermission(DViewControl::LOGOUT_VIEW_PERM); 6 | 7 | if (!Login::getInstance()->isLoggedin()) { 8 | header("Location: index.php"); 9 | die(); 10 | } 11 | 12 | Login::getInstance()->logout(); 13 | 14 | header("Location: index.php?logout=1" . time()); 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/search.php: -------------------------------------------------------------------------------- 1 | isLoggedin()) { 6 | header("Location: index.php?err=4" . time() . "&fw=" . urlencode($_SERVER['PHP_SELF'] . "?" . $_SERVER['QUERY_STRING'])); 7 | die(); 8 | } 9 | 10 | AccessControl::getInstance()->checkPermission(DViewControl::SEARCH_VIEW_PERM); 11 | 12 | Template::loadInstance("search"); 13 | UI::add('pageTitle', "Search Hashes"); 14 | Menu::get()->setActive("lists_search"); 15 | 16 | UI::add('result', false); 17 | 18 | //catch actions here... 19 | if (isset($_POST['action']) && CSRF::check($_POST['csrf'])) { 20 | $searchHandler = new SearchHandler(); 21 | $searchHandler->handle($_POST['action']); 22 | if (UI::getNumMessages() == 0) { 23 | Util::refresh(); 24 | } 25 | } 26 | 27 | echo Template::getInstance()->render(UI::getObjects()); 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/static/7zr.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/static/7zr.bin -------------------------------------------------------------------------------- /src/static/7zr.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/static/7zr.exe -------------------------------------------------------------------------------- /src/static/7zr.osx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/static/7zr.osx -------------------------------------------------------------------------------- /src/static/bootstrap.dark.custom.css: -------------------------------------------------------------------------------- 1 | .table-bordered th, .table-bordered td { 2 | border: 1px solid #3e464a !important; 3 | } 4 | 5 | .table thead th { 6 | vertical-align: bottom; 7 | border-bottom: 2px solid #3e464a !important; 8 | } 9 | 10 | .table-bordered { 11 | border: 1px solid #3e464a !important; 12 | } 13 | 14 | .alert-success { 15 | background-color: #397b39; 16 | } 17 | 18 | .alert-warning { 19 | background-color: #b16a06; 20 | } 21 | 22 | .alert-danger { 23 | background-color: #bf4d4a; 24 | } 25 | 26 | .btn-success { 27 | background-image: linear-gradient(#4a984a, #337533 60%, #347134); 28 | background-color: #3a773a; 29 | } 30 | 31 | .btn-danger { 32 | background-image: linear-gradient(#d9534f, #8e3533 60%, #963331); 33 | background-color: #d9534f; 34 | } 35 | 36 | .btn-warning { 37 | background-image: linear-gradient(#b16a06, #bf7205 60%, #bf7205); 38 | background-color: #b16a06; 39 | } 40 | -------------------------------------------------------------------------------- /src/static/hashtopolis.js: -------------------------------------------------------------------------------- 1 | function expansionCheck(elementId) { 2 | var isHidden = $(elementId).is(":hidden"); 3 | if (isHidden === true) { 4 | window.localStorage.setItem(elementId, "yes"); 5 | } 6 | else { 7 | window.localStorage.setItem(elementId, "no"); 8 | } 9 | } 10 | 11 | function checkOnLoading(elementId) { 12 | isExpanded = window.localStorage.getItem(elementId); 13 | if (isExpanded === "yes") { 14 | $(elementId).collapse("show"); 15 | } 16 | } 17 | 18 | $(function () { 19 | $('[data-toggle="tooltip"]').tooltip() 20 | }) -------------------------------------------------------------------------------- /src/static/js.cookie.min.js: -------------------------------------------------------------------------------- 1 | /*! js-cookie v2.2.1 | MIT */ 2 | 3 | !function(a){var b;if("function"==typeof define&&define.amd&&(define(a),b=!0),"object"==typeof exports&&(module.exports=a(),b=!0),!b){var c=window.Cookies,d=window.Cookies=a();d.noConflict=function(){return window.Cookies=c,d}}}(function(){function a(){for(var a=0,b={};astruct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |

New Permission Group

4 | {%TEMPLATE->struct/messages%} 5 |
6 | 7 | 8 |
9 |
10 | 11 | 12 | 13 | 16 | 17 | 18 | 21 | 22 |
Group Name 14 | 15 |
19 | 20 |
23 |
24 |
25 |
26 | {%TEMPLATE->struct/foot%} 27 | -------------------------------------------------------------------------------- /src/templates/api/new.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->struct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |

New Api Access Group

4 | {%TEMPLATE->struct/messages%} 5 |
6 | 7 | 8 |
9 |
10 | 11 | 12 | 13 | 16 | 17 | 18 | 21 | 22 |
Group Name 14 | 15 |
19 | 20 |
23 |
24 |
25 |
26 | {%TEMPLATE->struct/foot%} 27 | -------------------------------------------------------------------------------- /src/templates/api/newkey.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->struct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |

New API Key

4 | {%TEMPLATE->struct/messages%} 5 |
6 | 7 | 8 |
9 |
10 | 11 | 12 | 13 | 21 | 22 | 23 | 24 | 32 | 33 | 34 | 37 | 38 |
User 14 | 20 |
API Access Group 25 | 31 |
35 | 36 |
39 |
40 |
41 |
42 | {%TEMPLATE->struct/foot%} 43 | -------------------------------------------------------------------------------- /src/templates/crackers/editVersion.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->struct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |

Edit binary version of [[htmlentities([[binaryType.getTypeName()]], ENT_QUOTES, "UTF-8")]]

4 | {%TEMPLATE->struct/messages%} 5 |
6 | 7 | 8 | 9 |
10 |
11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 34 | 35 |
Binary Version: 15 | 16 |
Binary Base Name (which needs to be called on the client without os-dependent extension): 21 | 22 |
Download URL (where the client can download a 7zip with the binary): 27 | 28 |
32 | 33 |
36 |
37 |
38 |
39 | {%TEMPLATE->struct/foot%} 40 | -------------------------------------------------------------------------------- /src/templates/crackers/new.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->struct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |

Create new binary type

4 | {%TEMPLATE->struct/messages%} 5 |
6 | 7 | 8 |
9 |
10 | 11 | 12 | 13 | 19 | 20 | 21 | 24 | 25 |
Binary Type Name: 14 | 18 |
22 | 23 |
26 |
27 |
28 |
29 | {%TEMPLATE->struct/foot%} 30 | -------------------------------------------------------------------------------- /src/templates/crackers/newVersion.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->struct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |

Create new binary version of [[htmlentities([[binaryType.getTypeName()]], ENT_QUOTES, "UTF-8")]]

4 | {%TEMPLATE->struct/messages%} 5 |
6 | 7 | 8 | 9 |
10 |
11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 34 | 35 |
Binary Version: 15 | 16 |
Binary Base Name (which needs to be called on the client without os-dependent extension): 21 | 22 |
Download URL (where the client can download a 7zip with the binary): 27 | 28 |
32 | 33 |
36 |
37 |
38 |
39 | {%TEMPLATE->struct/foot%} 40 | -------------------------------------------------------------------------------- /src/templates/email/creation.plain.template.html: -------------------------------------------------------------------------------- 1 | Hi [[username]], 2 | 3 | Your account on [[$APP_NAME]] was created. You can now log in with the following credentials: 4 | Username: [[username]] 5 | Password: [[password]] 6 | Go to [[$APP_NAME]]: [[url]] -------------------------------------------------------------------------------- /src/templates/email/creation.template.html: -------------------------------------------------------------------------------- 1 | Hi [[username]],

2 |

3 | Your account on [[$APP_NAME]] was created. You can now log in with the following credentials:
4 | Username: [[username]]
5 | Password: [[password]]

6 | Go to [[$APP_NAME]]: [[url]] 7 |

-------------------------------------------------------------------------------- /src/templates/email/forgot.plain.template.html: -------------------------------------------------------------------------------- 1 | Hi [[username]], 2 | 3 | You requested to reset your password for [[$APP_NAME]] 4 | New Password: [[password]] 5 | -------------------------------------------------------------------------------- /src/templates/email/forgot.template.html: -------------------------------------------------------------------------------- 1 | Hi [[username]],

2 |

3 | You requested to reset your password for [[$APP_NAME]]
4 | New Password: [[password]] 5 |

-------------------------------------------------------------------------------- /src/templates/errors/error.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->struct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |

Error

4 |
5 | [[message]] 6 |
7 | {%TEMPLATE->struct/foot%} 8 | -------------------------------------------------------------------------------- /src/templates/errors/restricted.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->struct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |
4 | You have no access to this page! 5 |
6 | {%TEMPLATE->struct/foot%} 7 | -------------------------------------------------------------------------------- /src/templates/forgot.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->struct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |

Forgot password

4 | {%TEMPLATE->struct/messages%} 5 |
6 |
7 |
8 |
9 |
10 |
11 | 12 | 13 |
14 | 15 |
16 | 17 |
18 |
19 |
20 | 21 |
22 | 23 |
24 |
25 |
26 |
27 | 28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | {%TEMPLATE->struct/foot%} 36 | -------------------------------------------------------------------------------- /src/templates/groups/new.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->struct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |

New Access Group

4 | {%TEMPLATE->struct/messages%} 5 |
6 | 7 | 8 |
9 |
10 | 11 | 12 | 13 | 16 | 17 | 18 | 21 | 22 |
Group Name 14 | 15 |
19 | 20 |
23 |
24 |
25 |
26 | {%TEMPLATE->struct/foot%} 27 | -------------------------------------------------------------------------------- /src/templates/hashlists/detail/pretasks.template.html: -------------------------------------------------------------------------------- 1 | {{IF [[accessControl.hasPermission([[$DAccessControl::RUN_TASK_ACCESS]])]]}} 2 |

Create pre-configured tasks:

3 |
4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | {{FOREACH task;[[preTasks]]}} 15 | 16 | 19 | 0}} style="background-color: #[[task.getColor()]]""{{ENDIF}}> 20 |   21 | 22 | 26 | 27 | {{ENDFOREACH}} 28 | 29 | 33 | 34 |
IDColorName
17 | [[task.getId()]] 18 | 23 | 24 | [[task.getTaskName()]] 25 |
30 | 31 | Select All 32 |
35 |
36 |
37 | {{ENDIF}} -------------------------------------------------------------------------------- /src/templates/hashlists/detail/superhashlist.template.html: -------------------------------------------------------------------------------- 1 |

Hashlists included in this superhashlist:

2 |
3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | {{FOREACH sublist;[[sublists]]}} 11 | 12 | 15 | 22 | 27 | 28 | {{ENDFOREACH}} 29 |
IDNameCracked
13 | [[sublist.getVal('hashlist')->getId()]] 14 | 16 | [[sublist.getVal('hashlist')->getHashlistName()]] 17 | {{IF [[sublist.getVal('hashlist')->getIsSecret()]] == 1}} 18 | 19 | {{ENDIF}} 20 | [[Util::tickdone([[sublist.getVal('hashlist')->getCracked()]], [[sublist.getVal('hashlist')->getHashCount()]])]] 21 | 23 | [[Util::showperc([[sublist.getVal('hashlist')->getCracked()]], [[sublist.getVal('hashlist')->getHashCount()]])]]%
24 | ([[sublist.getVal('hashlist')->getCracked()]] 25 | / [[sublist.getVal('hashlist')->getHashCount()]]) 26 |
30 |
31 |
32 | 33 | -------------------------------------------------------------------------------- /src/templates/install/0.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->install/head%} 2 |

3 | Welcome to the Hashtopolis Installation Procedure! 4 |

5 |

6 | To run Hashtopolis you need a running MySQL server. You will be prompted for details during installation, 7 | keep informations ready to enter. 8 |

9 | {{IF [[32bit]]}} 10 |

11 | WARNING: It appears that you are running on a 32bit OS only or the PHP installation is 32bit only. This can often 12 | cause problems with larger keyspaces on tasks. 13 |

14 | {{ENDIF}} 15 |

16 | 17 |

18 | {%TEMPLATE->install/foot%} -------------------------------------------------------------------------------- /src/templates/install/1.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->install/head%} 2 |

3 | DB Connection is ready now, Hashtopolis will now fill the database with the initial data and structure. 4 | Click on 'Continue' when you're ready. If there happens any error there must be a problem. Please note that this might 5 | take some time. 6 |

7 |

8 | 9 |

10 | {%TEMPLATE->install/foot%} -------------------------------------------------------------------------------- /src/templates/install/2.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->install/head%} 2 |

3 | User should be created successfully now.
4 | Your installation should be complete now. Please make sure that you protect or delete the 'install' folder. If you use apache2, make sure 5 | you have the 'AllowOverride All' set for the Hashtopolis directory, if you use nginx make sure to protect these folders: files, import, inc, lang, templates. 6 |

7 |

8 | 9 |

10 | {%TEMPLATE->install/foot%} -------------------------------------------------------------------------------- /src/templates/install/50.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->install/head%} 2 |

3 | Make sure the www user can write the Hashtopolis directory, and click 'Recheck' when you're done. 4 |

5 |

6 | 7 |

8 | {%TEMPLATE->install/foot%} -------------------------------------------------------------------------------- /src/templates/install/51.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->install/head%} 2 |

3 | DB Connection
4 | Please fill in the form below for the database connection for Hashtopolis. 5 |

6 | {{IF [[failed]]}} 7 |

8 | Test connection failed, please try again! 9 |

10 | {{ENDIF}} 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
Server hostname
Server port
MySQL user
MySQL password
Database name
 
38 |
39 | {%TEMPLATE->install/foot%} -------------------------------------------------------------------------------- /src/templates/install/52.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->install/head%} 2 |

3 | Create Admin User
4 | Please fill in the form below to create an admin user. 5 |

6 | [[message]] 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
Username
Email Address
Password
Repeat password
 
30 |
31 | {%TEMPLATE->install/foot%} -------------------------------------------------------------------------------- /src/templates/install/foot.template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/templates/install/head.template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hashtopolis Installation 6 | 7 | 8 |
9 |

Hashtopolis Installation

-------------------------------------------------------------------------------- /src/templates/notifications/chatbot.template.html: -------------------------------------------------------------------------------- 1 | [[simplified]] -------------------------------------------------------------------------------- /src/templates/notifications/discord.template.html: -------------------------------------------------------------------------------- 1 | [[message]] 2 | -------------------------------------------------------------------------------- /src/templates/notifications/email.template.html: -------------------------------------------------------------------------------- 1 | Hi [[username]]

2 | 3 | [[html]] 4 | 5 | ##########Hi [[username]] 6 | 7 | [[message]] -------------------------------------------------------------------------------- /src/templates/notifications/example.template.html: -------------------------------------------------------------------------------- 1 | [[message]] -------------------------------------------------------------------------------- /src/templates/notifications/slack.template.html: -------------------------------------------------------------------------------- 1 | [[simplified]] -------------------------------------------------------------------------------- /src/templates/notifications/telegram.template.html: -------------------------------------------------------------------------------- 1 | [[message]] 2 | -------------------------------------------------------------------------------- /src/templates/preprocessors/details.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->struct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |

Preprocessor details for '[[htmlentities([[preprocessor.getName()]], ENT_QUOTES, "UTF-8")]]'

4 | {%TEMPLATE->struct/messages%} 5 |
6 |
7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 32 | 33 |
10 | Edit 11 |
Name[[htmlentities([[preprocessor.getName()]], ENT_QUOTES, "UTF-8")]]
Binary Basename[[htmlentities([[preprocessor.getBinaryName()]], ENT_QUOTES, "UTF-8")]]
URL[[htmlentities([[preprocessor.getUrl()]], ENT_QUOTES, "UTF-8")]]
Commands 28 | [[htmlentities([[preprocessor.getKeyspaceCommand()]], ENT_QUOTES, "UTF-8")]] / 29 | [[htmlentities([[preprocessor.getSkipCommand()]], ENT_QUOTES, "UTF-8")]] / 30 | [[htmlentities([[preprocessor.getLimitCommand()]], ENT_QUOTES, "UTF-8")]] 31 |
34 |
35 |
36 | {%TEMPLATE->struct/foot%} -------------------------------------------------------------------------------- /src/templates/preprocessors/index.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->struct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |

Preprocessors

4 | {%TEMPLATE->struct/messages%} 5 |
6 |
7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {{FOREACH preprocessor;[[preprocessors]]}} 19 | 20 | 21 | 22 | 32 | 33 | {{ENDFOREACH}} 34 |
10 | Add 11 |
Preprocessor IDNameAction
[[preprocessor.getId()]][[htmlentities([[preprocessor.getName()]], ENT_QUOTES, "UTF-8")]] 23 | {{IF [[accessControl.hasPermission([[$DAccessControl::SERVER_CONFIG_ACCESS]])]]}} 24 |
25 | 26 | 27 | 28 | 29 |
30 | {{ENDIF}} 31 |
35 |
36 |
37 | {%TEMPLATE->struct/foot%} -------------------------------------------------------------------------------- /src/templates/preprocessors/new.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->struct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |

Add new Preprocessor

4 | {%TEMPLATE->struct/messages%} 5 |
6 | 7 | 8 |
9 |
10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | 25 | 28 | 29 | 30 | 31 | 34 | 35 | 36 | 39 | 40 | 41 | 44 | 45 | 46 | 49 | 50 |
Name: 14 | 15 |
Binary Basename: 20 | 21 |
Download URL: 26 | 27 |
Commands (set to empty if not available) 32 | 33 |
37 | 38 |
42 | 43 |
47 | 48 |
51 |
52 |
53 |
54 | {%TEMPLATE->struct/foot%} 55 | -------------------------------------------------------------------------------- /src/templates/report/hashlist-example.template.tex: -------------------------------------------------------------------------------- 1 | \documentclass[12pt]{article} 2 | \begin{document} 3 | 4 | \section*{Hashlist '[[hashlist.getHashlistName()]]'} 5 | 6 | Hash type: [[Util::texEscape([[hashtype.getDescription()]])]]\\ 7 | Total hashes: [[hashlist.getHashCount()]]\\ 8 | Cracked hashes: [[hashlist.getCracked()]]\\ 9 | 10 | \subsection*{Tasks} 11 | 12 | {{FOREACH task;[[tasks]]}} 13 | \subsubsection*{Task '[[Util::texEscape([[task.getTaskName()]])]]' ([[task.getId()]])} 14 | Command: \texttt{[[Util::texEscape([[task.getAttackCmd()]])]]}\\ 15 | Notes: [[Util::texEscape([[task.getNotes()]])]] 16 | {{ENDFOREACH}} 17 | 18 | \end{document} -------------------------------------------------------------------------------- /src/templates/report/health-check-example.template.tex: -------------------------------------------------------------------------------- 1 | \documentclass[12pt]{article} 2 | \begin{document} 3 | 4 | \section*{Health Check '[[check.getId()]]'} 5 | 6 | Checked agents: [[sizeof([[agentChecks]])]]\\ 7 | 8 | \subsection*{Agents} 9 | 10 | {{FOREACH agentCheck;[[agentChecks]]}} 11 | \subsubsection*{Agent '[[agents.getVal([[agentCheck.getAgentId()]])->getAgentName()]]'} 12 | TODO: result here 13 | {{ENDFOREACH}} 14 | 15 | \end{document} -------------------------------------------------------------------------------- /src/templates/static/help.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->struct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |

[[$APP_NAME]] Help

4 |

Video Tutorials

5 | 9 |

Wiki help

10 | 15 | {%TEMPLATE->struct/foot%} 16 | -------------------------------------------------------------------------------- /src/templates/struct/foot.template.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 6 | [[$APP_NAME]]: [[version]]{{IF [[build]]}}+[[build]]{{ENDIF}} [[gitcommit]] - About - Help 7 | {{IF strlen([[config.getVal([[$DConfig::CONTACT_EMAIL]])]]) > 0}} 8 | - Contact Admin 9 | {{ENDIF}} 10 | 11 |

12 | ©2016-[[date("Y")]] s3in!c - [[$APP_NAME]] 13 |

14 |
15 | 16 | 17 |
18 | 19 | -------------------------------------------------------------------------------- /src/templates/struct/messages.template.html: -------------------------------------------------------------------------------- 1 | {{FOREACH message;[[messages]]}} 2 |
3 | [[message.getVal('message')]] 4 |
5 | {{ENDFOREACH}} -------------------------------------------------------------------------------- /src/templates/superhashlists/new.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->struct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |

New superhashlist

4 | {%TEMPLATE->struct/messages%} 5 |
6 | 7 | 8 |
9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | {{FOREACH list;[[lists]]}} 17 | 18 | 21 | 22 | 23 | 24 | {{ENDFOREACH}} 25 | 26 | 27 | 30 | 31 | 32 | 36 | 37 |
IDNameHash type
19 | [[list.getId()]] 20 | [[list.getHashlistName()]][[hashtypes.getVal([[list.getHashtypeId()]])]]
Name: 28 | 29 |
33 | 34 | Select All 35 |
38 |
39 |
40 |
41 | {%TEMPLATE->struct/foot%} 42 | -------------------------------------------------------------------------------- /src/templates/supertasks/create.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->struct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |

Create Supertask

4 | {%TEMPLATE->struct/messages%} 5 |
6 | 7 | 8 |
9 |
10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | {{FOREACH task;[[preTasks]]}} 21 | 22 | 23 | 31 | 32 | {{ENDFOREACH}} 33 | {{IF [[sizeof([[preTasks]])]] == 0}} 34 | 35 | {{ENDIF}} 36 | 37 | 40 | 41 |
Name: 14 | 15 |
Select tasks assigned to this supertask:
  24 | 25 | {{IF [[accessControl.hasPermission([[$DAccessControl::VIEW_PRETASK_ACCESS]])]]}} 26 | [[task.getTaskName()]] 27 | {{ELSE}} 28 | [[task.getTaskName()]] 29 | {{ENDIF}} 30 |
Currently there are no preconfigured tasks which can be used for creating supertasks!
38 | 39 |
42 |
43 |
44 |
45 | {%TEMPLATE->struct/foot%} -------------------------------------------------------------------------------- /src/templates/tasks/autorefresh.template.html: -------------------------------------------------------------------------------- 1 |
2 | {{IF [[autorefresh]] > 0}} 3 |
4 | 5 | 6 | 7 |
8 |
9 | {{ELSE}} 10 |
11 | 12 | 13 | 14 |
15 |
16 | {{ENDIF}} 17 |
-------------------------------------------------------------------------------- /src/templates/users/index.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->struct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |

All users ([[numUsers]])

4 | {%TEMPLATE->struct/messages%} 5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | {{FOREACH entry;[[allUsers]]}} 20 | 21 | 22 | 23 | 24 | 25 | 26 | 33 | 34 | 35 | 38 | 39 | {{ENDFOREACH}} 40 |
IDUsernameCreation dateLast loginEmailValiditySession lifetimeRight groupAction
[[entry.getVal('user').getId()]][[htmlentities([[entry.getVal('user').getUsername()]], ENT_QUOTES, "UTF-8")]][[date([[config.getVal(DConfig::TIME_FORMAT)]], [[entry.getVal('user').getRegisteredSince()]])]][[date([[config.getVal(DConfig::TIME_FORMAT)]], [[entry.getVal('user').getLastLoginDate()]])]][[entry.getVal('user').getEmail()]] 27 | {{IF [[entry.getVal('user').getIsValid()]] == 1}} 28 | Valid 29 | {{ELSE}} 30 | Invalid/Not activated 31 | {{ENDIF}} 32 | [[entry.getVal('user').getSessionLifetime()]][[entry.getVal('group').getGroupName()]] 36 | 37 |
41 |
42 |
43 | {%TEMPLATE->struct/foot%} 44 | -------------------------------------------------------------------------------- /src/templates/users/new.template.html: -------------------------------------------------------------------------------- 1 | {%TEMPLATE->struct/head%} 2 | {%TEMPLATE->struct/menu%} 3 |

New user

4 | {%TEMPLATE->struct/messages%} 5 |
6 | 7 | 8 |
9 |
10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | 25 | 33 | 34 | 35 | 38 | 39 |
Username 14 | 15 |
Email address 20 | 21 |
User group 26 | 32 |
36 | 37 |
40 |
41 |
42 |
43 | {%TEMPLATE->struct/foot%} 44 | -------------------------------------------------------------------------------- /src/webfonts/fa-brands-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/webfonts/fa-brands-400.eot -------------------------------------------------------------------------------- /src/webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /src/webfonts/fa-brands-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/webfonts/fa-brands-400.woff -------------------------------------------------------------------------------- /src/webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /src/webfonts/fa-regular-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/webfonts/fa-regular-400.eot -------------------------------------------------------------------------------- /src/webfonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/webfonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /src/webfonts/fa-regular-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/webfonts/fa-regular-400.woff -------------------------------------------------------------------------------- /src/webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /src/webfonts/fa-solid-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/webfonts/fa-solid-900.eot -------------------------------------------------------------------------------- /src/webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /src/webfonts/fa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/webfonts/fa-solid-900.woff -------------------------------------------------------------------------------- /src/webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashtopolis/server/aadb30798299cc1b4b0ad2d7ef20c7ca307094c0/src/webfonts/fa-solid-900.woff2 --------------------------------------------------------------------------------