diff --git a/.gitignore b/.gitignore index f9ba930a..6fbd82bb 100644 --- a/.gitignore +++ b/.gitignore @@ -31,10 +31,10 @@ www.pid *.swo # Attachments directory -src/data/attachments/* -!src/data/attachments/index.php -src/data/attachments/deleted/* -!src/data/attachments/deleted/index.php +attachments/* +!attachments/index.php +attachments/deleted/* +!attachments/deleted/index.php # Custom logos directory src/data/customlogos/* diff --git a/.travis.yml b/.travis.yml index cc8b03a5..23616c75 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,13 @@ -# We use language generic because that's the only thing that's supported for the -# trusty distro -language: generic +# We are now using Docker to test builds with Travis - this removes our dependency on Ubuntu 14.04 sudo: required -dist: trusty +language: generic -group: deprecated-2017Q2 +services: + - docker -install: ./extra/provision.sh -m dev -s $TRAVIS_BUILD_DIR -d $TRAVIS_BUILD_DIR +install: + - docker build --build-arg MODE=dev -t="fbctf_in_travis" . -script: ./extra/run_tests.sh $TRAVIS_BUILD_DIR +script: + - docker run -d -p 80:80 -p 443:443 --name="fbctf_in_travis" fbctf_in_travis + - docker exec fbctf_in_travis /var/www/fbctf/extra/run_tests.sh /var/www/fbctf/ diff --git a/Dockerfile b/Dockerfile index d97cd8cf..fe22c4db 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,4 @@ -FROM ubuntu:trusty -LABEL maintainer="Boik Su " +FROM ubuntu:xenial ENV HOME /root @@ -10,9 +9,11 @@ ARG TYPE=self ARG KEY ARG CRT +ENV HHVM_DISABLE_NUMA true + WORKDIR $HOME COPY . $HOME -RUN chown www-data:www-data $HOME +RUN apt-get update && apt-get -y install sudo apt-utils RUN ./extra/provision.sh -m $MODE -c $TYPE -k $KEY -C $CRT -D $DOMAIN -e $EMAIL -s `pwd` --docker CMD ["./extra/service_startup.sh"] \ No newline at end of file diff --git a/Vagrantfile b/Vagrantfile index 2078262c..6e0dc3dd 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -4,7 +4,7 @@ VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| - config.vm.box = "ubuntu/trusty64" + config.vm.box = "ubuntu/xenial64" config.vm.network "private_network", ip: "10.10.10.5" config.vm.hostname = "FacebookCTF-Dev" config.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'" diff --git a/Vagrantfile-multi b/Vagrantfile-multi index 158d4923..b7aa0a73 100644 --- a/Vagrantfile-multi +++ b/Vagrantfile-multi @@ -4,7 +4,7 @@ VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| - config.vm.box = "ubuntu/trusty64" + config.vm.box = "ubuntu/xenial64" config.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'" # MySQL Server diff --git a/Vagrantfile-single b/Vagrantfile-single index ac168729..712420d6 100644 --- a/Vagrantfile-single +++ b/Vagrantfile-single @@ -4,7 +4,7 @@ VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| - config.vm.box = "ubuntu/trusty64" + config.vm.box = "ubuntu/xenial64" config.vm.network "private_network", ip: "10.10.10.5" config.vm.hostname = "facebookCTF-Dev" config.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'" diff --git a/composer.json b/composer.json index 0dc4d333..70eb026d 100644 --- a/composer.json +++ b/composer.json @@ -4,6 +4,7 @@ "license": "CC-BY-NC-4.0", "require": { "facebook/xhp-lib": "2.x", + "facebook/graph-sdk": "5.x", "google/apiclient": "^2.0" }, "require-dev": { diff --git a/composer.lock b/composer.lock index ce54b8ed..64d2fa25 100644 --- a/composer.lock +++ b/composer.lock @@ -4,9 +4,67 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "7fa4023de48d9c453ad8eaa93913ae96", - "content-hash": "a8b3ade722987ad56f29a0fc697a5c70", + "hash": "98f4d4750954ef68e0ab70174023f199", + "content-hash": "d462af7ff5694e2192b54e1ffd67c264", "packages": [ + { + "name": "facebook/graph-sdk", + "version": "5.6.1", + "source": { + "type": "git", + "url": "https://github.com/facebook/php-graph-sdk.git", + "reference": "2f9639c15ae043911f40ffe44080b32bac2c5280" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/facebook/php-graph-sdk/zipball/2f9639c15ae043911f40ffe44080b32bac2c5280", + "reference": "2f9639c15ae043911f40ffe44080b32bac2c5280", + "shasum": "" + }, + "require": { + "php": "^5.4|^7.0" + }, + "require-dev": { + "guzzlehttp/guzzle": "~5.0", + "mockery/mockery": "~0.8", + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "guzzlehttp/guzzle": "Allows for implementation of the Guzzle HTTP client", + "paragonie/random_compat": "Provides a better CSPRNG option in PHP 5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "Facebook\\": "src/Facebook/" + }, + "files": [ + "src/Facebook/polyfills.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Facebook Platform" + ], + "authors": [ + { + "name": "Facebook", + "homepage": "https://github.com/facebook/php-graph-sdk/contributors" + } + ], + "description": "Facebook SDK for PHP", + "homepage": "https://github.com/facebook/php-graph-sdk", + "keywords": [ + "facebook", + "sdk" + ], + "time": "2017-08-16 17:28:07" + }, { "name": "facebook/xhp-lib", "version": "v2.3.2", @@ -133,6 +191,7 @@ "TypeAssert", "hack" ], + "abandoned": "hhvm/type-assert", "time": "2017-02-15 02:26:23" }, { diff --git a/database/countries.sql b/database/countries.sql index 8bf03ef4..4dba1bba 100644 --- a/database/countries.sql +++ b/database/countries.sql @@ -12,7 +12,9 @@ CREATE TABLE `countries` ( `enabled` tinyint(1) DEFAULT 0, `d` text DEFAULT NULL, `transform` text DEFAULT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `iso_code` (`iso_code`), + KEY `enabled` (`enabled`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -298,4 +300,4 @@ UPDATE `countries` SET enabled = 1 WHERE iso_code = "ZA"; UPDATE `countries` SET enabled = 1 WHERE iso_code = "ZM"; UPDATE `countries` SET enabled = 1 WHERE iso_code = "ZW"; /*!40000 ALTER TABLE `countries` ENABLE KEYS */; -UNLOCK TABLES; +UNLOCK TABLES; \ No newline at end of file diff --git a/database/schema.sql b/database/schema.sql index 82a2966b..3c80338e 100644 --- a/database/schema.sql +++ b/database/schema.sql @@ -36,7 +36,7 @@ CREATE TABLE `levels` ( `id` int(11) NOT NULL AUTO_INCREMENT, `active` tinyint(1) NOT NULL, `type` varchar(4) NOT NULL, - `title` text NOT NULL, + `title` varchar(255) NOT NULL, `description` text NOT NULL, `entity_id` int(11) NOT NULL, `category_id` int(11) NOT NULL, @@ -48,7 +48,9 @@ CREATE TABLE `levels` ( `hint` text NOT NULL, `penalty` int(11) NOT NULL, `created_ts` timestamp NOT NULL DEFAULT 0, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `entity_id` (`entity_id`), + KEY `active` (`active`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -61,7 +63,7 @@ DROP TABLE IF EXISTS `categories`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `categories` ( `id` int(11) NOT NULL AUTO_INCREMENT, - `category` text NOT NULL, + `category` varchar(255) NOT NULL, `protected` tinyint(1) NOT NULL, `created_ts` timestamp NOT NULL DEFAULT 0, PRIMARY KEY (`id`) @@ -116,8 +118,8 @@ DROP TABLE IF EXISTS `teams`; CREATE TABLE `teams` ( `id` int(11) NOT NULL AUTO_INCREMENT, `active` tinyint(1) NOT NULL DEFAULT 1, - `name` text NOT NULL, - `password_hash` text NOT NULL, + `name` varchar(255) NOT NULL, + `password_hash` varchar(255) NOT NULL, `points` int(11) NOT NULL DEFAULT 0, `last_score` timestamp NOT NULL, `logo` text NOT NULL, @@ -125,7 +127,9 @@ CREATE TABLE `teams` ( `protected` tinyint(1) NOT NULL DEFAULT 0, `visible` tinyint(1) NOT NULL DEFAULT 1, `created_ts` timestamp NOT NULL DEFAULT 0, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `visible` (`visible`), + KEY `active` (`active`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -146,6 +150,22 @@ CREATE TABLE `livesync` ( ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `teams_oauth` +-- + +DROP TABLE IF EXISTS `teams_oauth`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `teams_oauth` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `type` text NOT NULL, + `team_id` int(11) NOT NULL, + `token` text NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `teams_data` -- @@ -156,10 +176,11 @@ DROP TABLE IF EXISTS `teams_data`; CREATE TABLE `teams_data` ( `id` int(11) NOT NULL AUTO_INCREMENT, `team_id` int(11) NOT NULL, - `name` text NOT NULL, - `email` text NOT NULL, + `name` varchar(255) NOT NULL, + `email` varchar(255) NOT NULL, `created_ts` timestamp NOT NULL DEFAULT 0, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `team_id` (`team_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -172,13 +193,14 @@ DROP TABLE IF EXISTS `sessions`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `sessions` ( `id` int(11) NOT NULL AUTO_INCREMENT, - `cookie` text NOT NULL, + `cookie` varchar(200) NOT NULL, `data` text NOT NULL, `team_id` int(11) NOT NULL, `created_ts` timestamp NOT NULL DEFAULT 0, `last_access_ts` timestamp NOT NULL, - `last_page_access` text NOT NULL, - PRIMARY KEY (`id`) + `last_page_access` varchar(200) NOT NULL, + PRIMARY KEY (`id`), + KEY `cookie` (`cookie`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -215,10 +237,16 @@ INSERT INTO `configuration` (field, value, description) VALUES("auto_announce", INSERT INTO `configuration` (field, value, description) VALUES("progressive_cycle", "300", "(Integer) Frequency to take progressive scoreboard in seconds"); INSERT INTO `configuration` (field, value, description) VALUES("bases_cycle", "5", "(Integer) Frequency to score base levels in seconds"); INSERT INTO `configuration` (field, value, description) VALUES("autorun_cycle", "30", "(Integer) Frequency to cycle autorun in seconds"); +INSERT INTO `configuration` (field, value, description) VALUES("gameboard_cycle", "5", "(Integer) Frequency to cycle gameboard in seconds"); +INSERT INTO `configuration` (field, value, description) VALUES("conf_cycle", "10", "(Integer) Frequency to cycle configuration and commandline in seconds"); +INSERT INTO `configuration` (field, value, description) VALUES("leaderboard_limit", "50", "(Integer) Maximum number of teams to show on the leaderboard"); INSERT INTO `configuration` (field, value, description) VALUES("registration", "0", "(Boolean) Ability to register teams"); INSERT INTO `configuration` (field, value, description) VALUES("registration_names", "0", "(Boolean) Registration will ask for names"); INSERT INTO `configuration` (field, value, description) VALUES("registration_type", "1", "(Integer) Type of registration: 1 - Open; 2 - Tokenized;"); INSERT INTO `configuration` (field, value, description) VALUES("registration_players", "3", "(Integer) Number of players per team"); +INSERT INTO `configuration` (field, value, description) VALUES("registration_facebook", "0", "(Boolean) Allow Facebook Registration"); +INSERT INTO `configuration` (field, value, description) VALUES("registration_google", "0", "(Boolean) Allow Google Registration"); +INSERT INTO `configuration` (field, value, description) VALUES("registration_prefix", "Hacker", "(String) Automated Team Registation Name Prefix"); INSERT INTO `configuration` (field, value, description) VALUES("ldap", "0", "(Boolean) Ability to use LDAP to login"); INSERT INTO `configuration` (field, value, description) VALUES("ldap_server", "ldap://localhost", "(String) LDAP Server"); INSERT INTO `configuration` (field, value, description) VALUES("ldap_port", "389", "(Integer) LDAP Port"); @@ -226,6 +254,8 @@ INSERT INTO `configuration` (field, value, description) VALUES("ldap_domain_suff INSERT INTO `configuration` (field, value, description) VALUES("login", "1", "(Boolean) Ability to login"); INSERT INTO `configuration` (field, value, description) VALUES("login_select", "0", "(Boolean) Login selecting the team"); INSERT INTO `configuration` (field, value, description) VALUES("login_strongpasswords", "0", "(Boolean) Enforce using strong passwords"); +INSERT INTO `configuration` (field, value, description) VALUES("login_facebook", "0", "(Boolean) Allow Facebook Login"); +INSERT INTO `configuration` (field, value, description) VALUES("login_google", "0", "(Boolean) Allow Google Login"); INSERT INTO `configuration` (field, value, description) VALUES("password_type", "1", "(Integer) Type of passwords: See table password_types"); INSERT INTO `configuration` (field, value, description) VALUES("default_bonus", "30", "(Integer) Default value for bonus in levels"); INSERT INTO `configuration` (field, value, description) VALUES("default_bonusdec", "10", "(Integer) Default bonus decrement in levels"); @@ -291,12 +321,13 @@ DROP TABLE IF EXISTS `registration_tokens`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `registration_tokens` ( `id` int(11) NOT NULL AUTO_INCREMENT, - `token` text NOT NULL, + `token` varchar(250) NOT NULL, `used` tinyint(1) NOT NULL, `team_id` int(11) NOT NULL, `created_ts` timestamp NOT NULL DEFAULT 0, `use_ts` timestamp NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `token` (`token`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -314,7 +345,9 @@ CREATE TABLE `scores_log` ( `points` int(11) NOT NULL, `level_id` int(11) NOT NULL, `type` varchar(4) NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `level_id` (`level_id`), + KEY `team_id` (`team_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -331,7 +364,8 @@ CREATE TABLE `bases_log` ( `code` int(11) NOT NULL, `response` text NOT NULL, `level_id` int(11) NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `level_id` (`level_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -344,12 +378,16 @@ DROP TABLE IF EXISTS `scripts`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `scripts` ( `id` int(11) NOT NULL AUTO_INCREMENT, + `host` varchar(1024) NOT NULL, `ts` timestamp NULL, `pid` int(11) NOT NULL, - `name` text NOT NULL, + `name` varchar(255) NOT NULL, `cmd` text NOT NULL, `status` tinyint(1) NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `host` (`host`), + KEY `status` (`status`), + KEY `name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -366,7 +404,9 @@ CREATE TABLE `failures_log` ( `team_id` int(11) NOT NULL, `level_id` int(11) NOT NULL, `flag` text NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `team_id` (`team_id`), + KEY `level_id` (`level_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -383,7 +423,9 @@ CREATE TABLE `hints_log` ( `level_id` int(11) NOT NULL, `team_id` int(11) NOT NULL, `penalty` int(11) NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `level_id` (`level_id`), + KEY `team_id` (`team_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; diff --git a/database/test_schema.sql b/database/test_schema.sql index 5beadecb..e91e2057 100644 --- a/database/test_schema.sql +++ b/database/test_schema.sql @@ -36,7 +36,7 @@ CREATE TABLE `levels` ( `id` int(11) NOT NULL AUTO_INCREMENT, `active` tinyint(1) NOT NULL, `type` varchar(4) NOT NULL, - `title` text NOT NULL, + `title` varchar(255) NOT NULL DEFAULT '', `description` text NOT NULL, `entity_id` int(11) NOT NULL, `category_id` int(11) NOT NULL, @@ -47,9 +47,11 @@ CREATE TABLE `levels` ( `flag` text NOT NULL, `hint` text NOT NULL, `penalty` int(11) NOT NULL, - `created_ts` timestamp NOT NULL DEFAULT 0, - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; + `created_ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + KEY `entity_id` (`entity_id`), + KEY `active` (`active`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -61,7 +63,7 @@ DROP TABLE IF EXISTS `categories`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `categories` ( `id` int(11) NOT NULL AUTO_INCREMENT, - `category` text NOT NULL, + `category` varchar(255) NOT NULL, `protected` tinyint(1) NOT NULL, `created_ts` timestamp NOT NULL DEFAULT 0, PRIMARY KEY (`id`) @@ -116,8 +118,8 @@ DROP TABLE IF EXISTS `teams`; CREATE TABLE `teams` ( `id` int(11) NOT NULL AUTO_INCREMENT, `active` tinyint(1) NOT NULL DEFAULT 1, - `name` text NOT NULL, - `password_hash` text NOT NULL, + `name` varchar(255) NOT NULL, + `password_hash` varchar(255) NOT NULL, `points` int(11) NOT NULL DEFAULT 0, `last_score` timestamp NOT NULL, `logo` text NOT NULL, @@ -125,7 +127,9 @@ CREATE TABLE `teams` ( `protected` tinyint(1) NOT NULL DEFAULT 0, `visible` tinyint(1) NOT NULL DEFAULT 1, `created_ts` timestamp NOT NULL DEFAULT 0, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `visible` (`visible`), + KEY `active` (`active`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -146,6 +150,22 @@ CREATE TABLE `livesync` ( ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `teams_oauth` +-- + +DROP TABLE IF EXISTS `teams_oauth`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `teams_oauth` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `type` text NOT NULL, + `team_id` int(11) NOT NULL, + `token` text NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `teams_data` -- @@ -156,10 +176,11 @@ DROP TABLE IF EXISTS `teams_data`; CREATE TABLE `teams_data` ( `id` int(11) NOT NULL AUTO_INCREMENT, `team_id` int(11) NOT NULL, - `name` text NOT NULL, - `email` text NOT NULL, + `name` varchar(255) NOT NULL, + `email` varchar(255) NOT NULL, `created_ts` timestamp NOT NULL DEFAULT 0, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `team_id` (`team_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -172,14 +193,15 @@ DROP TABLE IF EXISTS `sessions`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `sessions` ( `id` int(11) NOT NULL AUTO_INCREMENT, - `cookie` text NOT NULL, + `cookie` varchar(200) NOT NULL, `data` text NOT NULL, `team_id` int(11) NOT NULL, `created_ts` timestamp NOT NULL DEFAULT 0, `last_access_ts` timestamp NOT NULL, - `last_page_access` text NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; + `last_page_access` varchar(200) NOT NULL, + PRIMARY KEY (`id`), + KEY `cookie` (`cookie`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -215,10 +237,16 @@ INSERT INTO `configuration` (field, value, description) VALUES("auto_announce", INSERT INTO `configuration` (field, value, description) VALUES("progressive_cycle", "300", "(Integer) Frequency to take progressive scoreboard in seconds"); INSERT INTO `configuration` (field, value, description) VALUES("bases_cycle", "5", "(Integer) Frequency to score base levels in seconds"); INSERT INTO `configuration` (field, value, description) VALUES("autorun_cycle", "30", "(Integer) Frequency to cycle autorun in seconds"); +INSERT INTO `configuration` (field, value, description) VALUES("gameboard_cycle", "5", "(Integer) Frequency to cycle gameboard in seconds"); +INSERT INTO `configuration` (field, value, description) VALUES("conf_cycle", "10", "(Integer) Frequency to cycle configuration and commandline in seconds"); +INSERT INTO `configuration` (field, value, description) VALUES("leaderboard_limit", "50", "(Integer) Maximum number of teams to show on the leaderboard"); INSERT INTO `configuration` (field, value, description) VALUES("registration", "0", "(Boolean) Ability to register teams"); INSERT INTO `configuration` (field, value, description) VALUES("registration_names", "0", "(Boolean) Registration will ask for names"); INSERT INTO `configuration` (field, value, description) VALUES("registration_type", "1", "(Integer) Type of registration: 1 - Open; 2 - Tokenized;"); INSERT INTO `configuration` (field, value, description) VALUES("registration_players", "3", "(Integer) Number of players per team"); +INSERT INTO `configuration` (field, value, description) VALUES("registration_facebook", "0", "(Boolean) Allow Facebook Registration"); +INSERT INTO `configuration` (field, value, description) VALUES("registration_google", "0", "(Boolean) Allow Google Registration"); +INSERT INTO `configuration` (field, value, description) VALUES("registration_prefix", "Hacker", "(String) Automated Team Registation Name Prefix"); INSERT INTO `configuration` (field, value, description) VALUES("ldap", "0", "(Boolean) Ability to use LDAP to login"); INSERT INTO `configuration` (field, value, description) VALUES("ldap_server", "ldap://localhost", "(String) LDAP Server"); INSERT INTO `configuration` (field, value, description) VALUES("ldap_port", "389", "(Integer) LDAP Port"); @@ -226,6 +254,8 @@ INSERT INTO `configuration` (field, value, description) VALUES("ldap_domain_suff INSERT INTO `configuration` (field, value, description) VALUES("login", "1", "(Boolean) Ability to login"); INSERT INTO `configuration` (field, value, description) VALUES("login_select", "0", "(Boolean) Login selecting the team"); INSERT INTO `configuration` (field, value, description) VALUES("login_strongpasswords", "0", "(Boolean) Enforce using strong passwords"); +INSERT INTO `configuration` (field, value, description) VALUES("login_facebook", "0", "(Boolean) Allow Facebook Login"); +INSERT INTO `configuration` (field, value, description) VALUES("login_google", "0", "(Boolean) Allow Google Login"); INSERT INTO `configuration` (field, value, description) VALUES("password_type", "1", "(Integer) Type of passwords: See table password_types"); INSERT INTO `configuration` (field, value, description) VALUES("default_bonus", "30", "(Integer) Default value for bonus in levels"); INSERT INTO `configuration` (field, value, description) VALUES("default_bonusdec", "10", "(Integer) Default bonus decrement in levels"); @@ -291,12 +321,13 @@ DROP TABLE IF EXISTS `registration_tokens`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `registration_tokens` ( `id` int(11) NOT NULL AUTO_INCREMENT, - `token` text NOT NULL, + `token` varchar(250) NOT NULL, `used` tinyint(1) NOT NULL, `team_id` int(11) NOT NULL, `created_ts` timestamp NOT NULL DEFAULT 0, `use_ts` timestamp NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `token` (`token`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -314,7 +345,9 @@ CREATE TABLE `scores_log` ( `points` int(11) NOT NULL, `level_id` int(11) NOT NULL, `type` varchar(4) NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `level_id` (`level_id`), + KEY `team_id` (`team_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -331,7 +364,8 @@ CREATE TABLE `bases_log` ( `code` int(11) NOT NULL, `response` text NOT NULL, `level_id` int(11) NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `level_id` (`level_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -344,12 +378,16 @@ DROP TABLE IF EXISTS `scripts`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `scripts` ( `id` int(11) NOT NULL AUTO_INCREMENT, + `host` varchar(1024) NOT NULL, `ts` timestamp NULL, `pid` int(11) NOT NULL, - `name` text NOT NULL, + `name` varchar(255) NOT NULL, `cmd` text NOT NULL, `status` tinyint(1) NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `host` (`host`), + KEY `status` (`status`), + KEY `name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -366,7 +404,9 @@ CREATE TABLE `failures_log` ( `team_id` int(11) NOT NULL, `level_id` int(11) NOT NULL, `flag` text NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `team_id` (`team_id`), + KEY `level_id` (`level_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -383,7 +423,9 @@ CREATE TABLE `hints_log` ( `level_id` int(11) NOT NULL, `team_id` int(11) NOT NULL, `penalty` int(11) NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + KEY `level_id` (`level_id`), + KEY `team_id` (`team_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; diff --git a/extra/cache/Dockerfile b/extra/cache/Dockerfile index 288b9d18..d4d2b5fd 100644 --- a/extra/cache/Dockerfile +++ b/extra/cache/Dockerfile @@ -1,5 +1,4 @@ -FROM ubuntu:trusty -LABEL maintainer="Boik Su " +FROM ubuntu:xenial ENV HOME /root @@ -13,5 +12,6 @@ ARG CRT WORKDIR $HOME COPY . $HOME +RUN apt-get update && apt-get -y install sudo apt-utils RUN ./extra/provision.sh -m $MODE -c $TYPE -k $KEY -C $CRT -D $DOMAIN -e $EMAIL -s `pwd` --docker --multiple-servers --server-type cache CMD ["./extra/cache/cache_startup.sh"] diff --git a/extra/hhvm/Dockerfile b/extra/hhvm/Dockerfile index 534f1181..ae044f24 100644 --- a/extra/hhvm/Dockerfile +++ b/extra/hhvm/Dockerfile @@ -1,5 +1,4 @@ -FROM ubuntu:trusty -LABEL maintainer="Boik Su " +FROM ubuntu:xenial ENV HOME /root @@ -10,8 +9,11 @@ ARG TYPE=self ARG KEY ARG CRT +ENV HHVM_DISABLE_NUMA true + WORKDIR $HOME COPY . $HOME +RUN apt-get update && apt-get -y install sudo apt-utils RUN ./extra/provision.sh -m $MODE -c $TYPE -k $KEY -C $CRT -D $DOMAIN -e $EMAIL -s `pwd` --docker --multiple-servers --server-type hhvm --mysql-server mysql --cache-server cache CMD ["./extra/hhvm/hhvm_startup.sh"] diff --git a/extra/hhvm/hhvm_startup.sh b/extra/hhvm/hhvm_startup.sh index a3671250..82dd7817 100755 --- a/extra/hhvm/hhvm_startup.sh +++ b/extra/hhvm/hhvm_startup.sh @@ -2,7 +2,8 @@ set -e -service hhvm restart +chown -R www-data:www-data /var/www/fbctf +sudo -u www-data service hhvm restart while true; do if [[ -e /var/run/hhvm/sock ]]; then diff --git a/extra/lib.sh b/extra/lib.sh index 6f397e08..9dbeddca 100755 --- a/extra/lib.sh +++ b/extra/lib.sh @@ -59,7 +59,7 @@ function install_unison() { function repo_osquery() { log "Adding osquery repository keys" sudo DEBIAN_FRONTEND=noninteractive apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1484120AC4E9F8A1A577AEEE97A80C63C9D8B80B - sudo DEBIAN_FRONTEND=noninteractive add-apt-repository "deb [arch=amd64] https://osquery-packages.s3.amazonaws.com/trusty trusty main" + sudo DEBIAN_FRONTEND=noninteractive add-apt-repository "deb [arch=amd64] https://pkg.osquery.io/deb deb main" } function install_mysql() { @@ -128,6 +128,7 @@ function letsencrypt_cert() { fi if [[ "$__docker" = true ]]; then + mkdir -p /root/tmp cat <<- EOF > /root/tmp/certbot.sh #!/bin/bash if [[ ! ( -d /etc/letsencrypt && "\$(ls -A /etc/letsencrypt)" ) ]]; then @@ -228,16 +229,14 @@ function install_hhvm() { package software-properties-common - log "Adding HHVM key" + log "Adding HHVM keys" sudo DEBIAN_FRONTEND=noninteractive apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0x5a16e7281be7a449 + sudo DEBIAN_FRONTEND=noninteractive apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xB4112585D386EB94 log "Adding HHVM repo" - sudo DEBIAN_FRONTEND=noninteractive add-apt-repository "deb http://dl.hhvm.com/ubuntu $(lsb_release -sc) main" + sudo DEBIAN_FRONTEND=noninteractive add-apt-repository "deb http://dl.hhvm.com/ubuntu xenial-lts-3.21 main" package_repo_update - - log "Installing HHVM" - # Installing the package so the dependencies are installed too package hhvm log "Enabling HHVM to start by default" @@ -273,7 +272,7 @@ function hhvm_performance() { cat "$__config" | sed "s|$__oldrepo|$__repofile|g" | sudo tee "$__config" sudo hhvm-repo-mode enable "$__path" sudo chown www-data:www-data "$__repofile" - sudo service hhvm start + sudo service hhvm restart } function install_composer() { @@ -287,9 +286,6 @@ function install_composer() { } function install_nodejs() { - log "Removing node.js legacy version" - sudo DEBIAN_FRONTEND=noninteractive apt-get remove --purge nodejs -y - log "Downloading and setting node.js version 6.x repo information" dl_pipe "https://deb.nodesource.com/setup_6.x" | sudo -E bash - diff --git a/extra/mysql/Dockerfile b/extra/mysql/Dockerfile index 6f23ff8b..606d5de7 100644 --- a/extra/mysql/Dockerfile +++ b/extra/mysql/Dockerfile @@ -1,5 +1,4 @@ -FROM ubuntu:trusty -LABEL maintainer="Boik Su " +FROM ubuntu:xenial ENV HOME /root @@ -13,5 +12,6 @@ ARG CRT WORKDIR $HOME COPY . $HOME +RUN apt-get update && apt-get -y install sudo apt-utils RUN ./extra/provision.sh -m $MODE -c $TYPE -k $KEY -C $CRT -D $DOMAIN -e $EMAIL -s `pwd` --docker --multiple-servers --server-type mysql CMD ["./extra/mysql/mysql_startup.sh"] diff --git a/extra/mysql/mysql_startup.sh b/extra/mysql/mysql_startup.sh index f72893c4..c0581cf9 100755 --- a/extra/mysql/mysql_startup.sh +++ b/extra/mysql/mysql_startup.sh @@ -2,6 +2,10 @@ set -e +chown -R mysql:mysql /var/lib/mysql +chown -R mysql:mysql /var/run/mysqld +chown -R mysql:mysql /var/log/mysql + service mysql restart while true; do diff --git a/extra/nginx.conf b/extra/nginx.conf index cc305a47..c2a8b55a 100644 --- a/extra/nginx.conf +++ b/extra/nginx.conf @@ -40,6 +40,7 @@ server { location ~ \.php$ { try_files $uri =404; fastcgi_pass unix:/var/run/hhvm/sock; + fastcgi_intercept_errors on; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; diff --git a/extra/nginx/Dockerfile b/extra/nginx/Dockerfile index 4fa27f92..af55c347 100644 --- a/extra/nginx/Dockerfile +++ b/extra/nginx/Dockerfile @@ -1,5 +1,4 @@ -FROM ubuntu:trusty -LABEL maintainer="Boik Su " +FROM ubuntu:xenial ENV HOME /root @@ -12,7 +11,7 @@ ARG CRT WORKDIR $HOME COPY . $HOME -RUN chown www-data:www-data $HOME +RUN apt-get update && apt-get -y install sudo apt-utils RUN ./extra/provision.sh -m $MODE -c $TYPE -k $KEY -C $CRT -D $DOMAIN -e $EMAIL -s `pwd` --docker --multiple-servers --server-type nginx --hhvm-server hhvm CMD ["./extra/nginx/nginx_startup.sh"] diff --git a/extra/nginx/nginx.conf b/extra/nginx/nginx.conf index 350ba270..c5edb099 100644 --- a/extra/nginx/nginx.conf +++ b/extra/nginx/nginx.conf @@ -38,13 +38,8 @@ server { root CTFPATH; index index.php; - location /data/attachments/ { - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - include fastcgi_params; - fastcgi_pass HHVMSERVER:9000; - } - location /data/customlogos/ { + fastcgi_intercept_errors on; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; fastcgi_pass HHVMSERVER:9000; @@ -53,6 +48,7 @@ server { location ~ \.php$ { try_files $uri =404; fastcgi_pass HHVMSERVER:9000; + fastcgi_intercept_errors on; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; diff --git a/extra/nginx/nginx_startup.sh b/extra/nginx/nginx_startup.sh index 98c95b1c..45da1fdc 100755 --- a/extra/nginx/nginx_startup.sh +++ b/extra/nginx/nginx_startup.sh @@ -6,6 +6,7 @@ if [[ -e /root/tmp/certbot.sh ]]; then /bin/bash /root/tmp/certbot.sh fi +chown -R www-data:www-data /var/www/fbctf service nginx restart while true; do diff --git a/extra/provision.sh b/extra/provision.sh index 4ea22b98..00b15291 100755 --- a/extra/provision.sh +++ b/extra/provision.sh @@ -244,7 +244,6 @@ fi # If multiple servers are being utilized, ensure provision was called from the "nginx" or "hhvm" servers if [[ "$MULTIPLE_SERVERS" == false || "$SERVER_TYPE" = "nginx" || $SERVER_TYPE = "hhvm" ]]; then - package language-pack-en if [[ "$UPDATE" == true ]] ; then log "Updating repo" @@ -265,7 +264,6 @@ fi log "Installing HHVM" install_hhvm "$CTF_PATH" "$HHVM_CONFIG_PATH" "$MULTIPLE_SERVERS" - # Install Composer log "Installing Composer" install_composer "$CTF_PATH" log "Installing Composer in /usr/bin" @@ -326,10 +324,10 @@ fi fi log "Creating attachments folder, and setting ownership to www-data" - sudo sudo mkdir -p "$CTF_PATH/src/data/attachments" - sudo sudo mkdir -p "$CTF_PATH/src/data/attachments/deleted" - sudo chown -R www-data:www-data "$CTF_PATH/src/data/attachments" - sudo chown -R www-data:www-data "$CTF_PATH/src/data/attachments/deleted" + sudo sudo mkdir -p "$CTF_PATH/attachments" + sudo sudo mkdir -p "$CTF_PATH/attachments/deleted" + sudo chown -R www-data:www-data "$CTF_PATH/attachments" + sudo chown -R www-data:www-data "$CTF_PATH/attachments/deleted" log "Creating custom logos folder, and setting ownership to www-data" sudo mkdir -p "$CTF_PATH/src/data/customlogos" @@ -359,10 +357,10 @@ if [[ "$MULTIPLE_SERVERS" == false || "$SERVER_TYPE" = "mysql" ]]; then # Configuration for MySQL if [[ "$MULTIPLE_SERVERS" == true ]] && [[ "$SERVER_TYPE" = "mysql" ]]; then # This is required in order to generate password hash (since HHVM is not being installed) - package php5-cli + package php7.0-cli - sudo sed -e '/^bind-address/ s/^#*/#/' -i /etc/mysql/my.cnf - sudo sed -e '/^skip-external-locking/ s/^#*/#/' -i /etc/mysql/my.cnf + sudo sed -e '/^bind-address/ s/^#*/#/' -i /etc/mysql/mysql.conf.d/mysqld.cnf + sudo sed -e '/^skip-external-locking/ s/^#*/#/' -i /etc/mysql/mysql.conf.d/mysqld.cnf fi # Database creation diff --git a/extra/run_tests.sh b/extra/run_tests.sh index 862fbe4f..e0763a86 100755 --- a/extra/run_tests.sh +++ b/extra/run_tests.sh @@ -12,6 +12,34 @@ CODE_PATH=${1:-/vagrant} DB_USER=${2:-root} DB_PWD=${3:-root} +echo "[+] Verifying service status" +READY=0 +for i in {1..10}; do + HHVM_STATUS=$(service hhvm status | grep -P "start|running|Uptime" | wc -l) + NGINX_STATUS=$(service nginx status | grep -P "start|running|Uptime" | wc -l) + MYSQL_STATUS=$(service mysql status | grep -P "start|running|Uptime" | wc -l) + MC_STATUS=$(service memcached status | grep -P "start|running|Uptime" | wc -l) + if [ $HHVM_STATUS == 0 ] || [ $NGINX_STATUS == 0 ] || [ $MYSQL_STATUS == 0 ] || [ $MC_STATUS == 0 ]; then + echo "[+] Services not ready, waiting 10 seconds..." + sleep 10 + continue + else + READY=1 + break + fi +done + +if [ $READY = 0 ]; then + echo "[!] Services are not running, tests cannot be completed." + exit 1 +else + echo "[+] Services are running" +fi + + +echo "[+] Changing directory to $CODE_PATH" +cd "$CODE_PATH" + echo "[+] Starting tests setup in $CODE_PATH" mysql -u "$DB_USER" --password="$DB_PWD" -e "CREATE DATABASE $DB;" diff --git a/extra/service_startup.sh b/extra/service_startup.sh index 14df5340..b16b4ca7 100755 --- a/extra/service_startup.sh +++ b/extra/service_startup.sh @@ -10,7 +10,12 @@ if [[ -e /var/run/hhvm/sock ]]; then rm -f /var/run/hhvm/sock fi -service hhvm restart +chown -R mysql:mysql /var/lib/mysql +chown -R mysql:mysql /var/run/mysqld +chown -R mysql:mysql /var/log/mysql +chown -R www-data:www-data /var/www/fbctf + +sudo -u www-data service hhvm restart service nginx restart service mysql restart service memcached restart diff --git a/extra/settings.ini.example b/extra/settings.ini.example index 5b0cb752..3b65cd38 100644 --- a/extra/settings.ini.example +++ b/extra/settings.ini.example @@ -6,7 +6,9 @@ DB_NAME = 'DATABASE' DB_USERNAME = 'MYUSER' DB_PASSWORD = 'MYPWD' -MC_HOST = 'MCHOST' +MC_HOST[] = 'MCHOST' MC_PORT = '11211' +FACEBOOK_OAUTH_APP_ID = '' +FACEBOOK_OAUTH_APP_SECRET = '' GOOGLE_OAUTH_FILE = '' diff --git a/src/Db.php b/src/Db.php index c1a3bf28..7e101906 100644 --- a/src/Db.php +++ b/src/Db.php @@ -25,6 +25,11 @@ private function __construct() { private function __clone(): void {} + public static function getDatabaseStats(): array { + $db = self::getInstance(); + return $db->pool->getPoolStats(); + } + public function getBackupCmd(): string { $usr = must_have_idx($this->config, 'DB_USERNAME'); $pwd = must_have_idx($this->config, 'DB_PASSWORD'); diff --git a/src/Router.php b/src/Router.php index 22fad642..bffaf9a9 100644 --- a/src/Router.php +++ b/src/Router.php @@ -106,6 +106,6 @@ public static function isRequestModal(): bool { // Check to see if the request is going through the router public static function isRequestRouter(): bool { - return self::getRequestedPage() != "index"; + return self::getRequestedPage() !== "index"; } } diff --git a/src/SessionUtils.php b/src/SessionUtils.php index 0cadfa10..fe0d0301 100644 --- a/src/SessionUtils.php +++ b/src/SessionUtils.php @@ -110,14 +110,14 @@ public static function sessionActive(): bool { public static function enforceLogin(): void { /* HH_IGNORE_ERROR[2050] */ if (!self::sessionActive()) { - throw new IndexRedirectException(); + throw new LoginRedirectException(); } } public static function enforceAdmin(): void { /* HH_IGNORE_ERROR[2050] */ if (!array_key_exists('admin', $_SESSION)) { - throw new IndexRedirectException(); + throw new LoginRedirectException(); } } diff --git a/src/controllers/AdminController.php b/src/controllers/AdminController.php index a7eb52e8..d8c002be 100644 --- a/src/controllers/AdminController.php +++ b/src/controllers/AdminController.php @@ -4,7 +4,7 @@ class AdminController extends Controller { <<__Override>> protected function getTitle(): string { $custom_org = \HH\Asio\join(Configuration::gen('custom_org')); - return tr($custom_org->getValue()). ' '. tr('CTF'). ' | '. tr('Admin'); + return tr($custom_org->getValue()).' '.tr('CTF').' | '.tr('Admin'); } <<__Override>> @@ -152,13 +152,15 @@ class="fb--conf--registration_type" // TODO: Translate password types private async function genStrongPasswordsSelect(): Awaitable<:xhp> { - $types = await Configuration::genAllPasswordTypes(); - $config = await Configuration::genCurrentPasswordType(); + list($types, $config) = await \HH\Asio\va( + Configuration::genAllPasswordTypes(), + Configuration::genCurrentPasswordType(), + ); $select = ; foreach ($types as $type) { $select->appendChild( -