main
Robert 4 months ago
parent 4f941ea83d
commit 9b60d01456
  1. 22
      docs/TODO.md
  2. 4
      src/bootstrap/safer_io.php
  3. 2
      src/classes/apis/api.php
  4. 8
      src/classes/app.php
  5. 8
      src/classes/assets.php
  6. 4
      src/classes/exceptions/DB_Exception.php
  7. 7
      src/classes/php_file_cache.php
  8. 2
      src/classes/random_engine.php
  9. 465
      src/classes/safer_sql.php
  10. 23
      src/classes/security.php
  11. 30
      src/classes/services/paragon_crypto/crypto.php
  12. 4
      src/classes/services/paragon_crypto/password_storage.php
  13. 4
      src/classes/services/paragon_crypto/sodium_storage.php
  14. 4
      src/classes/services/sessions/cookie_session_handler.php

@ -7,6 +7,10 @@
[x] → Encrypted/Compressed Sessions
[ ] → Ensure JS error reporting works
[ ] → Force Database methods to try Cache First and Save Cache Data
[ ] → Kernels
[ ] → HTTP → Requests, Responce
@ -41,11 +45,17 @@
[x] → End/Open Tag Matching
[x] → UUIDv7 for APIs, etc...
[ ] → Rate Limiting
[?] → PHP Mailer / Access Token
[x] → PHP Mailer
[ ] → Access Tokens (like for emails)
[x] → UUIDv7 (like Database IDs)
[x] → CSRF Tokens in security.php...
[x] → Password Hashing/Verify in security.php
[x] → Twilio Support
@ -53,10 +63,6 @@
[x] → Error Handler
[x] → CSRF Tokens
[x] → Password Hashing/Verify
[ ] → Sane Config/Service file defaults
[ ] → Sane Folder Structure and Documentation
@ -69,5 +75,3 @@
[ ] → Tests
[x] → RSS Feed
[x] → Private API for Sensitive Transactions:

@ -521,9 +521,9 @@ final class safer_io {
$safer_db_data = $safer_data;
} else {
if (isset($a->use_db_filter) && $a->use_db_filter == DB_FILTER::ON) {
$safe_for_db = \tts\extras\safer_sql::get_safer_sql_text($safer_data);
$safe_for_db = \CodeHydrater\safer_sql::get_safer_sql_text($safer_data);
$text = $safe_for_db["text"];
$meta[$input_field_name]['db_filter_status'] = $safe_for_db["status"] ?? \tts\SQL_SAFETY_FLAG::filtered;
$meta[$input_field_name]['db_filter_status'] = $safe_for_db["status"] ?? \CodeHydrater\SQL_SAFETY_FLAG::filtered;
} else {
$text = $safer_data;
}

@ -231,7 +231,7 @@ class api {
$data['code'] = $long_code;
$memory_check = bootstrap\common::get_bool(\tts\misc::request_var('debug'));
$memory_check = bootstrap\common::get_bool(\CodeHydrater\misc::request_var('debug'));
if ($memory_check) {
$echo = false;
$data['memory_used'] = memory_usage::get_memory_stats($echo);

@ -12,14 +12,6 @@ namespace CodeHydrater;
use Exception;
/**
*
* @todo Ensure JS error reporting works
* @todo Finish Session MGT, Encrypted Sessions
* @todo Make Cached Sessions
* @todo Force Database methods to try Cache First and Save Cache Data
*/
class app {
private $file;
private $class;

@ -112,13 +112,13 @@ final class assets {
}
if ($scope === 'project' || $scope === 'app') {
$path = PROJECT_ASSETS_DIR . "/";
$tts = self::is_minified($path, $file);
return ($tts !== false) ? PROJECT_ASSETS_BASE_REF . "/" . $tts : false;
$ism = self::is_minified($path, $file);
return ($ism !== false) ? PROJECT_ASSETS_BASE_REF . "/" . $ism : false;
}
if ($scope === 'assets') {
$path = ASSETS_DIR . "/";
$tts = self::is_minified($path, $file);
return ($tts !== false) ? ASSETS_BASE_REF . "/" . $tts : false;
$ism = self::is_minified($path, $file);
return ($ism !== false) ? ASSETS_BASE_REF . "/" . $ism : false;
}
return $file;
}

@ -53,8 +53,8 @@ class DB_Exception extends \Exception {
if (empty($message)) {
$message = self::$error_message;
}
$live = (\main_tts\is_live());
if ($live === false || \tts\session_management::has_user_right('debugger')) {
$live = (\CodeHydrater\bootstrap\is_live());
if ($live === false || \CodeHydrater\session_management::has_user_right('debugger')) {
$msg = ($debug == DEBUGGER::basic ||
(self::$debug === DEBUGGER::basic &&
$debug === DEBUGGER::static)

@ -18,7 +18,12 @@ class php_file_cache {
protected $cache_path;
public function __construct($path) {
$this->cache_path = rtrim($path, '/') . '/';
$is_safe_path = bootstrap\requires::is_dangerous($path);
if ($is_safe_path === false) {
throw new \Exception("Bad cache path");
}
$safer_path = bootstrap\requires::filter_dir_path($path);
$this->cache_path = rtrim($safer_path, '/') . '/';
if (!is_dir($this->cache_path)) {
mkdir($this->cache_path, 0775, true);
}

@ -61,7 +61,7 @@ class random_engine {
}
private function select_from_array(array $a, int $num ): array {
$array_count = \bs_tts\common::get_count($a) - 1;
$array_count = \CodeHydrater\bootstrap\common::get_count($a) - 1;
if ($array_count < 1) {
return [];
}

@ -0,0 +1,465 @@
<?php
declare(strict_types=1);
/**
* @author Robert Strutts <Robert@TryingToScale.com>
* @copyright Copyright (c) 2022, Robert Strutts.
* @license MIT
*/
/**
* @todo This is just for PLAY for now!!!!
* Too many FALSE positives and too many FALSE Negatives!!!
*/
namespace CodeHydrater;
enum SQL_SAFETY_FLAG {
case good; // All Okey
case filtered; // Found isseues but tried to filter them out
case dangerious; // May still be bad
}
class safer_sql {
/**
* List of SQL attacks:
* @link https://github.com/payloadbox/sql-injection-payload-list
* @link https://www.neuralegion.com/blog/sql-injection-payloads/
* @link https://ismailtasdelen.medium.com/sql-injection-payload-list-b97656cfd66b
*/
// NoSQL attacks and now SQL attacks as JSON is used EveryWhere
private static function found_bad_json(string $string): bool {
if (function_exists("str_contains")) {
if (str_contains($string, '[]') === true) return true; // GET Array
}
if (preg_match('/.match/', $string) === 1) return true;
if (preg_match('/&&/', $string) === 1) return true;
if (preg_match('/\|\|/', $string) === 1) return true;
if (preg_match('/\$where/', $string) === 1) return true;
if (preg_match("/mapReduce/", $string) === 1) return true;
if (preg_match('/\$group/', $string) === 1) return true;
if (preg_match('/\$regex/', $string) === 1) return true;
if (preg_match('/\$exists/', $string) === 1) return true;
if (preg_match('/\$ne/', $string) === 1) return true;
if (preg_match('/\$gt/', $string) === 1) return true;
if (preg_match('/\$lt/', $string) === 1) return true;
if (preg_match('/\$eq/', $string) === 1) return true;
if (preg_match('/\$nin/', $string) === 1) return true;
if (preg_match('/\$where/', $string) === 1) return true;
if (preg_match('/\$or/', $string) === 1) return true;
if (preg_match('/\$and/', $string) === 1) return true;
if (preg_match('/\$in/', $string) === 1) return true;
if (preg_match('/\$accumulator/', $string) === 1) return true;
if (preg_match('/\$function/', $string) === 1) return true;
if (preg_match("/:/", $string) === 1 &&
preg_match("/{/", $string) === 1) return true;
return false;
}
// Stacked queries can be used to execute multiple queries in succession.
private static function found_sql_stacker(string $string): bool {
if (preg_match("/;/", $string) === 1) return true;
return false;
}
private static function found_sql_compair(string $string): bool {
if (preg_match("/=/", $string) === 1) return true;
return false;
}
private static function found_quotes_in(string $string): bool {
if (preg_match("/'/", $string) === 1) return true;
if (preg_match("/\"/", $string) === 1) return true;
return false;
}
private static function found_sql_comment(string $string): bool {
if (preg_match("/\#/", $string) === 1) return true; // Hash
if (preg_match("/\/\*/", $string) === 1) return true; // C-style comment
if (preg_match("/--/", $string) === 1) return true; // SQL comment
if (preg_match("/\`/", $string) === 1) return true; // Backtick
//if (preg_match("/\x00/", $string) === 1) return true; // NULL Byte, !errors out!
return false;
}
private static function found_string_cat(string $string): bool {
if (preg_match("/\+/i", $string) === 1) return true; // addition, concatenate (or space in url)
if (preg_match("/\|\|/i", $string) === 1) return true; // (double pipe) concatenate
if (preg_match("/\%/", $string) === 1) return true; // wildcard attribute indicator
return false;
}
private static function found_sql_time_based_attack(string $string): bool {
if (preg_match("/union/i", $string) === 1) {
if (preg_match("/all/i", $string) === 1) {
return true;
}
if (preg_match("/select/i", $string) === 1) {
return true;
}
if (preg_match("/null/i", $string) === 1) {
return true;
}
}
if (preg_match("/sleep\s*\(/i", $string) === 1) return true;
if (preg_match("/waitfor delay/i", $string) === 1) return true;
if (preg_match("/benchmark\s*\(/i", $string) === 1) return true;
if (preg_match("/pg_sleep\s*\(/i", $string) === 1) return true;
if (preg_match("/randomblob/i", $string) === 1) return true;
if (preg_match("/convert/i", $string) === 1) {
if (preg_match("/int/i", $string) === 1) {
return true;
}
}
return false;
}
private static function found_sql_suspicious(string $string): bool {
if (self::found_sql_compair($string) === true) return true;
if (self::found_sql_stacker($string) === true) return true;
if (self::found_sql_comment($string) === true) return true;
if (self::found_quotes_in($string) === true) return true;
if (self::found_string_cat($string) === true) return true;
return false;
}
private static function found_sql_admin_attack(string $string): bool {
if (preg_match("/admin/i", $string) === 1) {
if (preg_match("/ or /i", $string) === 1) {
if (preg_match("/1/", $string) === 1) {
return true;
}
if (preg_match("/0/", $string) === 1) {
return true;
}
}
if (self::found_sql_suspicious($string) === true) return true;
}
return false;
}
private static function found_sql_statement(string $string): bool {
if (preg_match("/or/i", $string) === 1 || preg_match("/and/i", $string) === 1) {
if (self::found_sql_suspicious($string) === true) return true;
}
if (preg_match("/drop database/i", $string) === 1) return true;
if (preg_match("/drop table/i", $string) === 1) return true;
if (preg_match("/drop user/i", $string) === 1) return true;
if (preg_match("/drop view/i", $string) === 1) return true;
if (preg_match("/drop column/i", $string) === 1) return true;
if (preg_match("/drop procedure/i", $string) === 1) return true;
if (preg_match("/drop/i", $string) === 1) {
if (self::found_sql_suspicious($string) === true) return true;
}
if (preg_match("/where/i", $string) === 1) {
if (self::found_sql_suspicious($string) === true) return true;
}
if (preg_match("/select/i", $string) === 1) {
if (self::found_sql_suspicious($string) === true) return true;
}
if (preg_match("/having/i", $string) === 1) {
if (self::found_sql_suspicious($string) === true) return true;
}
if (preg_match("/distinct/i", $string) === 1) {
if (self::found_sql_suspicious($string) === true) return true;
}
// NOTE: \s* is for no-space or spaces!!! /i is to ignore Case!
if (preg_match("/\'\s*or/i", $string) === 1) return true;
if (preg_match("/\'\)\s*or/i", $string) === 1) return true;
if (preg_match("/\'\s*and/i", $string) === 1) return true;
if (preg_match("/\'\)\s*and/i", $string) === 1) return true;
if (preg_match("/or\s*true\-\-/", $string) === 1) return true;
if (preg_match("/if\s*\(/i", $string) === 1) return true;
if (preg_match("/\@\@version/i", $string) === 1) return true; // Get DB Ver
if (preg_match("/\@\@hostname/i", $string) === 1) return true;
if (preg_match("/\@\@datadir/i", $string) === 1) return true;
if (preg_match("/connection_id/i", $string) === 1) return true; // MySQL DB ID
if (preg_match("/crc32\s*\(/i", $string) === 1) return true; // MySQL DB ID
if (preg_match("/conv\s*\(/i", $string) === 1) return true; // MySQL DB ID
if (preg_match("/\@\@connections/i", $string) === 1) return true; // MSSQL DB ID
if (preg_match("/\@\@cpu_busy/i", $string) === 1) return true; // MSSQL DB ID
if (preg_match("/user_id\s*\(/i", $string) === 1) return true; // MSSQL DB ID
if (preg_match("/rownum/i", $string) === 1) return true; // Oracle DB ID
if (preg_match("/rawtohex\s*\(/i", $string) === 1) return true; // Oracle DB ID
if (preg_match("/lnnvl\s*\(/i", $string) === 1) return true; // Oracle DB ID
if (preg_match("/::int/i", $string) === 1) return true; // PostgreSQL DB ID
if (preg_match("/pg_client_encoding\s*\(/i", $string) === 1) return true; // PostgreSQL DB ID
if (preg_match("/get_current_ts_config\s*\(/i", $string) === 1) return true; // PostgreSQL DB ID
if (preg_match("/quote_literal\s*\(/i", $string) === 1) return true; // PostgreSQL DB ID
if (preg_match("/current_database\s*\(/i", $string) === 1) return true; // PostgreSQL DB ID
if (preg_match("/sqlite_version\s*\(/i", $string) === 1) return true; // SQLite DB ID
if (preg_match("/last_insert_rowid\s*\(/i", $string) === 1) return true; // SQLite DB ID
if (preg_match("/last_insert_rowid\s*\(/i", $string) === 1) return true; // SQLite DB ID
if (preg_match("/val\s*\(/i", $string) === 1) return true; // MSAccess DB ID
if (preg_match("/cvar\s*\(/i", $string) === 1) return true; // MSAccess DB ID
if (preg_match("/iif\s*\(/i", $string) === 1) return true; // MSAccess DB ID
if (preg_match("/atn\s*\(/i", $string) === 1) return true; // MSAccess DB ID
if (preg_match("/cdbl\s*\(/i", $string) === 1) return true; // MSAccess DB ID
if (preg_match("/grant\s*all/i", $string) === 1) return true;
if (preg_match("/into\s*dumpfile/i", $string) === 1) return true;
if (preg_match("/load\s*data\s*infile/i", $string) === 1) return true;
if (preg_match("/into\s*outfile/i", $string) === 1) return true;
if (preg_match("/load_file/i", $string) === 1) return true;
if (preg_match("/delete\s*from/i", $string) === 1) return true;
if (preg_match("/group_concat/i", $string) === 1) return true;
if (preg_match("/order by/i", $string) === 1) return true;
if (preg_match("/case when/i", $string) === 1) return true;
if (preg_match("/extractvalue/i", $string) === 1) return true;
if (preg_match("/\/etc\/passwd/i", $string) === 1) return true;
if (preg_match("/\/var\/log/i", $string) === 1) return true;
if (preg_match("/binary_checksum\s*\(/i", $string) === 1) return true; // ID MSSQL DB Engine
if (preg_match("/user\s*\(\)/i", $string) === 1) return true; // Get current user
if (preg_match("/system_user[\s]+\(\)/i", $string) === 1) return true; // Get current user
if (preg_match("/mysql.user/i", $string) === 1) return true; // List Users
if (preg_match("/mysql.db/i", $string) === 1) return true; // List Databases
if (preg_match("/database\s*\(/i", $string) === 1) return true;
if (preg_match("/information_schema/i", $string) === 1) return true; // List Columns
if (preg_match("/table_schema/i", $string) === 1) return true;
if (preg_match("/table_name/i", $string) === 1) return true;
if (preg_match("/\.columns/i", $string) === 1) return true;
if (preg_match("/\.tables/i", $string) === 1) return true;
// https://www.w3schools.com/mysql/mysql_ref_functions.asp
$fns = [
// String FNs
'ascii', 'char_length', 'character_length', 'concat', 'concat_ws',
'field', 'find_in_set', 'format', 'insert', 'instr', 'lcase', 'left',
'length', 'locate', 'lower', 'lpad', 'ltrim', 'mid', 'position',
'repeat', 'replace', 'reverse', 'right', 'rpad', 'rtrim', 'space',
'strcmp', 'substr', 'substring', 'substring_index', 'trim', 'ucase',
'upper',
// Numeric FNs
'abs','acos', 'asin', 'atan', 'atan2', 'avg', 'ceil', 'ceiling', 'cos',
'cot', 'count', 'degrees', 'div', 'exp', 'floor', 'greatest', 'least',
'ln', 'log', 'log10', 'log2', 'max', 'min', 'mod', 'pi', 'pow', 'power',
'radians', 'rand', 'round', 'sign', 'sin', 'sqrt', 'sum', 'tan', 'truncate',
// ADV FNs
'bin', 'binary', 'case', 'cast', 'coalesce', 'connection_id', 'conv',
'convert', 'current_user', 'database', 'if', 'ifnull', 'isnull',
'last_insert_id', 'nullif', 'session_user', 'system_user', 'user',
'version',
// OP FNs
'and', 'between', 'cast', 'char', 'count', 'div', 'in', 'is', 'is_not',
'is_not_null', 'is_null', 'like', 'member_of', 'not', 'not_between',
'not_in', 'not_like', 'not_regexp', 'or', 'regexp', 'sounds_like',
'floor', 'md5', 'rand', 'rlike', 'row', 'xor',
// https://dev.mysql.com/doc/refman/8.0/en/string-functions.html
'bit_length', 'let', 'export_set', 'from_base64', 'hex', 'load_file',
'make_set', 'match', 'oct', 'octet_length', 'ord', 'quote', 'regexp',
'regexp_instr', 'regexp_like', 'regexp_replace', 'regexp_substr',
'select', 'soundex', 'to_base64', 'unhex', 'weight_string'
];
foreach($fns as $fn_keyword) {
if (preg_match("/{$fn_keyword}\s*\(/i", $string) === 1) return true;
}
return false;
}
private static function found_sql_evil_symbols(string $string): bool {
if (preg_match("/\-/", $string) === 1) return true;
if (preg_match("/\&/", $string) === 1) return true;
if (preg_match("/\*/", $string) === 1) return true;
if (preg_match("/\^/", $string) === 1) return true;
if (preg_match("/\'\s*\'/", $string) === 1) return true;
if (preg_match("/\"\s*\"/", $string) === 1) return true;
if (preg_match("/\)\)/", $string) === 1) return true;
if (preg_match("/\//", $string) === 1) return true;
if (function_exists("str_contains")) {
if (str_contains($string, '\')') === true) return true;
if (str_contains($string, '\")') === true) return true;
if (str_contains($string, '\`)') === true) return true;
if (str_contains($string, '\\') === true) return true;
if (str_contains($string, '%00') === true) return true;
if (str_contains($string, '\' or 1=1-- -') === true) return true; // Normal SQL
if (str_contains($string, '\' || 1==1//') === true) return true; // Mongo SQL
if (str_contains($string, '\' || 1==1%00') === true) return true; // Mongo SQL
}
return false;
}
private static function found_sql_bad_symbols(string $string): bool {
$ltc = ltrim($string);
$ltc_len = strlen($ltc);
$left_most = ($ltc_len < 6) ? $ltc_len : 6;
$first_chars = substr($ltc, 0, $left_most);
if ($first_chars !== false) {
if (function_exists("str_contains")) {
if (str_contains($first_chars, 'or') === true) return true;
if (str_contains($first_chars, 'and') === true) return true;
}
if (self::found_sql_suspicious($first_chars) === true) return true;
if (self::found_sql_evil_symbols($first_chars) === true) return true;
}
if (self::found_sql_suspicious($string) === false) return false;
if (function_exists("str_contains")) {
if (str_contains($first_chars, '1') === true) return true;
if (str_contains($first_chars, '0') === true) return true;
if (str_contains($first_chars, '1337') === true) return true;
}
if (self::found_sql_evil_symbols($string) === true) return true;
return false;
}
public static function found_sql_injection_cmds(string $string): bool {
/*
* There are a number of ways to prevent Poison Null Byte injections
* within PHP. These include escaping the NULL byte with a backslash,
* however, the most recommended way to do so is to completely remove
* the byte by using code similar to the following:
*/
$string = str_replace(chr(0), '', $string);
if (self::found_sql_time_based_attack($string) === true) return true;
if (self::found_sql_admin_attack($string) === true) return true;
if (self::found_sql_bad_symbols($string) === true) return true;
if (self::found_sql_statement($string) === true) return true;
if (self::found_bad_json($string) === true) return true;
if (self::found_sql_comment($string) === true &&
self::found_quotes_in($string) === true) {
return true;
}
return false;
}
private static function found_sql_keyword(string $string): bool {
$words = [
'ACCESSIBLE','ACCOUNT','ACTION','ACTIVE','ADD','ADMIN','AFTER','AGAINST','AGGREGATE',
'ALGORITHM','ALL','ALTER','ALWAYS','ANALYSE','ANALYZE','AND','ANY','ARRAY','AS',
'ASC','ASCII','ASENSITIVE','AT','AUTOEXTEND_SIZE','AUTO_INCREMENT','AVG','AVG_ROW_LENGTH',
'BACKUP','BEFORE','BEGIN','BETWEEN','BIGINT','BINARY','BINLOG','BIT','BLOB','BLOCK',
'BOOL','BOOLEAN','BOTH','BTREE','BUCKETS','BY','BYTE','CACHE','CALL','CASCADE','CASCADED',
'CASE','CATALOG_NAME','CHAIN','CHANGE','CHANGED','CHANNEL','CHAR','CHARACTER','CHARSET',
'CHECK','CHECKSUM','CIPHER','CLASS_ORIGIN','CLIENT','CLONE','CLOSE','COALESCE','CODE',
'COLLATE','COLLATION','COLUMN','COLUMNS','COLUMN_FORMAT','COLUMN_NAME','COMMENT','COMMIT',
'COMMITTED','COMPACT','COMPLETION','COMPONENT','COMPRESSED','COMPRESSION','CONCURRENT',
'CONDITION','CONNECTION','CONSISTENT','CONSTRAINT','CONSTRAINT_CATALOG','CONSTRAINT_NAME',
'CONSTRAINT_SCHEMA','CONTAINS','CONTEXT','CONTINUE','CONVERT','CPU','CREATE','CROSS',
'CUBE','CUME_DIST','CURRENT','CURRENT_DATE','CURRENT_TIME','CURRENT_TIMESTAMP','CURRENT_USER',
'CURSOR','CURSOR_NAME','DATA','DATABASE','DATABASES','DATAFILE','DATE','DATETIME','DAY',
'DAY_HOUR','DAY_MICROSECOND','DAY_MINUTE','DAY_SECOND','DEALLOCATE','DEC','DECIMAL',
'DECLARE','DEFAULT','DEFAULT_AUTH','DEFINER','DEFINITION','DELAYED','DELAY_KEY_WRITE',
'DELETE','DENSE_RANK','DESC','DESCRIBE','DESCRIPTION','DES_KEY_FILE','DETERMINISTIC',
'DIAGNOSTICS','DIRECTORY','DISABLE','DISCARD','DISK','DISTINCT','DISTINCTROW','DIV',
'DO','DOUBLE','DROP','DUAL','DUMPFILE','DUPLICATE','DYNAMIC','EACH','ELSE','ELSEIF',
'EMPTY','ENABLE','ENCLOSED','ENCRYPTION','END','ENDS','ENFORCED','ENGINE','ENGINES',
'ENUM','ERROR','ERRORS','ESCAPE','ESCAPED','EVENT','EVENTS','EVERY','EXCEPT',
'EXCHANGE','EXCLUDE','EXECUTE','EXISTS','EXIT','EXPANSION','EXPIRE','EXPLAIN',
'EXPORT','EXTENDED','EXTENT_SIZE','FAILED_LOGIN_ATTEMPTS','FALSE','FAST','FAULTS',
'FETCH','FIELDS','FILE','FILE_BLOCK_SIZE','FILTER','FIRST','FIRST_VALUE','FIXED',
'FLOAT','FLOAT4','FLOAT8','FLUSH','FOLLOWING','FOLLOWS','FOR','FORCE','FOREIGN',
'FORMAT','FOUND','FROM','FULL','FULLTEXT','FUNCTION','GENERAL','GENERATED',
'GEOMCOLLECTION','GEOMETRY','GEOMETRYCOLLECTION','GET','GET_FORMAT','GET_MASTER_PUBLIC_KEY',
'GLOBAL','GRANT','GRANTS','GROUP','GROUPING','GROUPS','GROUP_REPLICATION','HANDLER',
'HASH','HAVING','HELP','HIGH_PRIORITY','HISTOGRAM','HISTORY','HOST','HOSTS','HOUR',
'HOUR_MICROSECOND','HOUR_MINUTE','HOUR_SECOND','IDENTIFIED','IF','IGNORE',
'IGNORE_SERVER_IDS','IMPORT','IN','INACTIVE','INDEX','INDEXES','INFILE','INITIAL_SIZE',
'INNER','INOUT','INSENSITIVE','INSERT','INSERT_METHOD','INSTALL','INSTANCE','INT','INT1',
'INT2','INT3','INT4','INT8','INTEGER','INTERVAL','INTO','INVISIBLE','INVOKER','IO',
'IO_AFTER_GTIDS','IO_BEFORE_GTIDS','IO_THREAD','IPC','IS','ISOLATION','ISSUER','ITERATE',
'JOIN','JSON','JSON_TABLE','JSON_VALUE','KEY','KEYS','KEY_BLOCK_SIZE','KILL','LAG',
'LANGUAGE','LAST','LAST_VALUE','LATERAL','LEAD','LEADING','LEAVE','LEAVES','LEFT',
'LESS','LEVEL','LIKE','LIMIT','LINEAR','LINES','LINESTRING','LIST','LOAD','LOCAL',
'LOCALTIME','LOCALTIMESTAMP','LOCK','LOCKED','LOCKS','LOGFILE','LOGS','LONG',
'LONGBLOB','LONGTEXT','LOOP','LOW_PRIORITY','MASTER','MASTER_AUTO_POSITION',
'MASTER_BIND','MASTER_COMPRESSION_ALGORITHMS','MASTER_CONNECT_RETRY','MASTER_DELAY',
'MASTER_HEARTBEAT_PERIOD','MASTER_HOST','MASTER_LOG_FILE',
'MASTER_LOG_POS','MASTER_PASSWORD','MASTER_PORT','MASTER_PUBLIC_KEY_PATH',
'MASTER_RETRY_COUNT','MASTER_SERVER_ID','MASTER_SSL','MASTER_SSL_CA',
'MASTER_SSL_CAPATH','MASTER_SSL_CERT','MASTER_SSL_CIPHER','MASTER_SSL_CRL',
'MASTER_SSL_CRLPATH','MASTER_SSL_KEY','MASTER_SSL_VERIFY_SERVER_CERT',
'MASTER_TLS_CIPHERSUITES','MASTER_TLS_VERSION','MASTER_USER',
'MASTER_ZSTD_COMPRESSION_LEVEL','MATCH','MAXVALUE','MAX_CONNECTIONS_PER_HOUR',
'MAX_QUERIES_PER_HOUR','MAX_ROWS','MAX_SIZE','MAX_UPDATES_PER_HOUR','MAX_USER_CONNECTIONS',
'MEDIUM','MEDIUMBLOB','MEDIUMINT','MEDIUMTEXT','MEMBER','MEMORY','MERGE','MESSAGE_TEXT',
'MICROSECOND','MIDDLEINT','MIGRATE','MINUTE','MINUTE_MICROSECOND','MINUTE_SECOND',
'MIN_ROWS','MOD','MODE','MODIFIES','MODIFY','MONTH','MULTILINESTRING','MULTIPOINT',
'MULTIPOLYGON','MUTEX','MYSQL_ERRNO','NAME','NAMES','NATIONAL','NATURAL','NCHAR',
'NDB','NDBCLUSTER','NESTED','NETWORK_NAMESPACE','NEVER','NEW','NEXT','NO','NODEGROUP',
'NONE','NOT','NOWAIT','NO_WAIT','NO_WRITE_TO_BINLOG','NTH_VALUE','NTILE','NULL','NULLS',
'NUMBER','NUMERIC','NVARCHAR','OF','OFF','OFFSET','OJ','OLD','ON','ONE','ONLY','OPEN',
'OPTIMIZE','OPTIMIZER_COSTS','OPTION','OPTIONAL','OPTIONALLY','OPTIONS','OR','ORDER',
'ORDINALITY','ORGANIZATION','OTHERS','OUT','OUTER','OUTFILE','OVER','OWNER','PACK_KEYS',
'PAGE','PARSER','PARTIAL','PARTITION','PARTITIONING','PARTITIONS','PASSWORD',
'PASSWORD_LOCK_TIME','PATH','PERCENT_RANK','PERSIST','PERSIST_ONLY','PHASE','PLUGIN',
'PLUGINS','PLUGIN_DIR','POINT','POLYGON','PORT','PRECEDES','PRECEDING','PRECISION',
'PREPARE','PRESERVE','PREV','PRIMARY','PRIVILEGES','PRIVILEGE_CHECKS_USER','PROCEDURE',
'PROCESS','PROCESSLIST','PROFILE','PROFILES','PROXY','PURGE','QUARTER','QUERY','QUICK',
'RANDOM','RANGE','RANK','READ','READS','READ_ONLY','READ_WRITE','REAL','REBUILD',
'RECOVER','RECURSIVE','REDOFILE','REDO_BUFFER_SIZE','REDUNDANT','REFERENCE','REFERENCES',
'REGEXP','RELAY','RELAYLOG','RELAY_LOG_FILE','RELAY_LOG_POS','RELAY_THREAD','RELEASE',
'RELOAD','REMOTE','REMOVE','RENAME','REORGANIZE','REPAIR','REPEAT','REPEATABLE','REPLACE',
'REPLICATE_DO_DB','REPLICATE_DO_TABLE','REPLICATE_IGNORE_DB','REPLICATE_IGNORE_TABLE',
'REPLICATE_REWRITE_DB','REPLICATE_WILD_DO_TABLE','REPLICATE_WILD_IGNORE_TABLE',
'REPLICATION','REQUIRE','REQUIRE_ROW_FORMAT','RESET','RESIGNAL','RESOURCE','RESPECT',
'RESTART','RESTORE','RESTRICT','RESUME','RETAIN','RETURN','RETURNED_SQLSTATE','RETURNING',
'RETURNS','REUSE','REVERSE','REVOKE','RIGHT','RLIKE','ROLE','ROLLBACK','ROLLUP','ROTATE',
'ROUTINE','ROW','ROWS','ROW_COUNT','ROW_FORMAT','ROW_NUMBER','RTREE','SAVEPOINT','SCHEDULE',
'SCHEMA','SCHEMAS','SCHEMA_NAME','SECOND','SECONDARY','SECONDARY_ENGINE','SECONDARY_LOAD',
'SECONDARY_UNLOAD','SECOND_MICROSECOND','SECURITY','SELECT','SENSITIVE','SEPARATOR','SERIAL',
'SERIALIZABLE','SERVER','SESSION','SET','SHARE','SHOW','SHUTDOWN','SIGNAL','SIGNED','SIMPLE',
'SKIP','SLAVE','SLOW','SMALLINT','SNAPSHOT','SOCKET','SOME','SONAME','SOUNDS','SOURCE',
'SPATIAL','SPECIFIC','SQL','SQLEXCEPTION','SQLSTATE','SQLWARNING','SQL_AFTER_GTIDS',
'SQL_AFTER_MTS_GAPS','SQL_BEFORE_GTIDS','SQL_BIG_RESULT','SQL_BUFFER_RESULT','SQL_CACHE',
'SQL_CALC_FOUND_ROWS','SQL_NO_CACHE','SQL_SMALL_RESULT','SQL_THREAD','SQL_TSI_DAY',
'SQL_TSI_HOUR','SQL_TSI_MINUTE','SQL_TSI_MONTH','SQL_TSI_QUARTER','SQL_TSI_SECOND',
'SQL_TSI_WEEK','SQL_TSI_YEAR','SRID','SSL','STACKED','START','STARTING','STARTS',
'STATS_AUTO_RECALC','STATS_PERSISTENT','STATS_SAMPLE_PAGES','STATUS','STOP','STORAGE',
'STORED','STRAIGHT_JOIN','STREAM','STRING','SUBCLASS_ORIGIN','SUBJECT','SUBPARTITION',
'SUBPARTITIONS','SUPER','SUSPEND','SWAPS','SWITCHES','SYSTEM','TABLE','TABLES','TABLESPACE',
'TABLE_CHECKSUM','TABLE_NAME','TEMPORARY','TEMPTABLE','TERMINATED','TEXT','THAN','THEN',
'THREAD_PRIORITY','TIES','TIME','TIMESTAMP','TIMESTAMPADD','TIMESTAMPDIFF','TINYBLOB',
'TINYINT','TINYTEXT','TLS','TO','TRAILING','TRANSACTION','TRIGGER','TRIGGERS','TRUE',
'TRUNCATE','TYPE','TYPES','UNBOUNDED','UNCOMMITTED','UNDEFINED','UNDO','UNDOFILE',
'UNDO_BUFFER_SIZE','UNICODE','UNINSTALL','UNION','UNIQUE','UNKNOWN','UNLOCK','UNSIGNED',
'UNTIL','UPDATE','UPGRADE','USAGE','USE','USER','USER_RESOURCES','USE_FRM','USING',
'UTC_DATE','UTC_TIME','UTC_TIMESTAMP','VALIDATION','VALUE','VALUES','VARBINARY',
'VARCHAR','VARCHARACTER','VARIABLES','VARYING','VCPU','VIEW','VIRTUAL','VISIBLE','WAIT',
'WARNINGS','WEEK','WEIGHT_STRING','WHEN','WHERE','WHILE','WINDOW','WITH','WITHOUT',
'WORK','WRAPPER','WRITE','X509','XA','XID','XML','XOR','YEAR','YEAR_MONTH','ZEROFILL'
];
$parts = preg_split('/\s+/', $string);
foreach($parts as $part) {
$lc = mb_strtoupper($part);
if (in_array($lc, $words)) return true;
}
return false;
}
private static function try_to_clean_sql(string $string): string {
$bad_items = [
'.user', '.db','.columns', '.tables', 'load_file', 'table_',
'_schema', 'connection_id', 'binary_checksum', 'cpu_busy',
'user_id', 'rownum', 'rawtohex', 'lnnvl', 'pg_client_encoding',
'get_current_ts_config', 'quote_literal', 'current_database',
'sqlite_version', 'last_insert_rowid', 'last_insert_rowid',
'group_concat', 'system_user'
];
return str_replace($bad_items, "", $string);
}
public static function get_safer_sql_text(string $string): array {
$string = str_replace(chr(0), '', $string); // Remove NULL Bytes
if (self::found_sql_injection_cmds($string)) {
/*
* At this Point: Never allow Quotes, @$*=()%`
* Limit allowed chars now, to safe ones!
*/
$cleaner = self::try_to_clean_sql($string);
$safer = preg_replace('/[^a-zA-Z0-9.\s]/', "", $cleaner);
if (self::found_sql_keyword($safer)) {
return ["text"=>$safer, "status"=>SQL_SAFETY_FLAG::dangerious];
}
return ["text"=>$safer, "status"=>SQL_SAFETY_FLAG::filtered];
}
return ["text"=>$string, "status"=>SQL_SAFETY_FLAG::good];
}
}

@ -76,26 +76,33 @@ final class security {
return false;
}
private static function is_valid_hash_algo($algo): bool {
return (in_array($algo, password_algos()));
}
/*
* The password_hash() function not only uses a secure
* one-way hashing algorithm, but it automatically handles
* salt and prevents time based side-channel attacks.
*/
public static function do_password_hash(string $password): bool | string {
public static function do_password_hash(#[\SensitiveParameter] string $password): bool | string {
$pwd_peppered = self::make_hash($password);
$hash_algo = \main_tts\configure::get(
$hash_algo = bootstrap\configure::get(
"security",
"hash_algo"
);
if (! empty($hash_algo)) {
return password_hash($pwd_peppered, $hash_algo);
) ?? false;
if ($hash_algo === false) {
throw new \Exception("Security Hash Algo not set!");
}
if (! self::is_valid_hash_algo($hash_algo)) {
throw new \Exception("Invalid Security Hash Alogo set");
}
return password_hash($pwd_peppered, self::find_default_hash_algo());
return password_hash($pwd_peppered, $hash_algo);
}
public static function do_password_verify(
string $input_pwd, $db_password
#[\SensitiveParameter] string $input_pwd, #[\SensitiveParameter] $db_password
): bool {
$pwd_peppered = self::make_hash($input_pwd);
return password_verify($pwd_peppered, $db_password);
@ -107,7 +114,7 @@ final class security {
* @param string $level (weak, low, high, max)
* @return string new Hashed
*/
public static function make_hash(string $text): string {
public static function make_hash(#[\SensitiveParameter] string $text): string {
$level = bootstrap\configure::get('security', 'hash_level');
if (empty($level)) {
$level = "normal";

@ -18,7 +18,7 @@ class crypto {
public function __construct(#[\SensitiveParameter] private string $key) {
$this->rnd = new \tts\random_engine();
$this->rnd = new \CodeHydrater\random_engine();
}
/*
* Secret key encryption (or symmetric encryption as it’s also
@ -167,7 +167,7 @@ class crypto {
}
public static function a_single_key_maker(): string {
$rnd = new \tts\random_engine();
$rnd = new \CodeHydrater\random_engine();
return base64_encode($rnd->get_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES));
}
/*
@ -213,26 +213,26 @@ class crypto {
/*
* Usage:
*
$key = tts\services\paragon_crypto\crypto::a_single_key_maker();
$enc = tts\services\paragon_crypto\crypto::safe_encrypt('Encrypt This String...', $key, \tts\services\paragon_crypto\crypto::single_key);
$key = CodeHydrater\services\paragon_crypto\crypto::a_single_key_maker();
$enc = CodeHydrater\services\paragon_crypto\crypto::safe_encrypt('Encrypt This String...', $key, \CodeHydrater\services\paragon_crypto\crypto::single_key);
echo $enc . "<br/>";
$dec = \tts\services\paragon_crypto\crypto::safe_decrypt($enc, $key, \tts\services\paragon_crypto\crypto::single_key);
$dec = \CodeHydrater\services\paragon_crypto\crypto::safe_decrypt($enc, $key, \CodeHydrater\services\paragon_crypto\crypto::single_key);
echo $dec . "<br/>";;
// --------------------
$key_pair_Alice = \tts\services\paragon_crypto\crypto::make_user_box_kp();
$secret_Alice = \tts\services\paragon_crypto\crypto::get_user_box_secret_key($key_pair_Alice);
$public_Alice = \tts\services\paragon_crypto\crypto::get_user_box_public_key($key_pair_Alice);
$key_pair_Alice = \CodeHydrater\services\paragon_crypto\crypto::make_user_box_kp();
$secret_Alice = \CodeHydrater\services\paragon_crypto\crypto::get_user_box_secret_key($key_pair_Alice);
$public_Alice = \CodeHydrater\services\paragon_crypto\crypto::get_user_box_public_key($key_pair_Alice);
$key_pair_Bob = \tts\services\paragon_crypto\crypto::make_user_box_kp();
$secret_Bob = \tts\services\paragon_crypto\crypto::get_user_box_secret_key($key_pair_Bob);
$public_Bob = \tts\services\paragon_crypto\crypto::get_user_box_public_key($key_pair_Bob);
$key_pair_Bob = \CodeHydrater\services\paragon_crypto\crypto::make_user_box_kp();
$secret_Bob = \CodeHydrater\services\paragon_crypto\crypto::get_user_box_secret_key($key_pair_Bob);
$public_Bob = \CodeHydrater\services\paragon_crypto\crypto::get_user_box_public_key($key_pair_Bob);
$kA = \tts\services\paragon_crypto\crypto::box_reassemble_keypair($secret_Alice, $public_Bob);
$enc = \tts\services\paragon_crypto\crypto::safe_encrypt('Encrypt This String2...', $kA, \tts\services\paragon_crypto\crypto::multiple_keys);
$kA = \CodeHydrater\services\paragon_crypto\crypto::box_reassemble_keypair($secret_Alice, $public_Bob);
$enc = \CodeHydrater\services\paragon_crypto\crypto::safe_encrypt('Encrypt This String2...', $kA, \CodeHydrater\services\paragon_crypto\crypto::multiple_keys);
echo $enc . "<br/>";
$kB = \tts\services\paragon_crypto\crypto::box_reassemble_keypair($secret_Bob, $public_Alice);
$dec = \tts\services\paragon_crypto\crypto::safe_decrypt($enc, $kB, \tts\services\paragon_crypto\crypto::multiple_keys);
$kB = \CodeHydrater\services\paragon_crypto\crypto::box_reassemble_keypair($secret_Bob, $public_Alice);
$dec = \CodeHydrater\services\paragon_crypto\crypto::safe_decrypt($enc, $kB, \CodeHydrater\services\paragon_crypto\crypto::multiple_keys);
echo $dec;
*/

@ -16,7 +16,7 @@ class password_storage {
private $random_engine;
public function __construct() {
$this->random_engine = new \tts\random_engine();
$this->random_engine = new \CodeHydrater\random_engine();
}
public function generate_a_key(): string {
@ -120,7 +120,7 @@ class password_storage {
}
/*
$c = new \tts\services\paragon_crypto\password_storage();
$c = new \CodeHydrater\services\paragon_crypto\password_storage();
$k = $c->generate_a_key();
$h = $c->hash("HelpMe", $k);
var_dump( $c->verify("HelpMe", $h, $k) );

@ -29,7 +29,7 @@ class sodium_storage {
* Sets the encryption key
*/
public function __construct(#[\SensitiveParameter] private string $key) {
$this->random_engine = new \tts\random_engine();
$this->random_engine = new \CodeHydrater\random_engine();
}
public function encrypt(#[\SensitiveParameter] string $plain_text, string $item_name = ""): string {
@ -113,7 +113,7 @@ class sodium_storage {
$secretkey = "78a5011b9997cd03a28a3412c66565b7c32715b35e055d7abfc228236308d3b2";
$plain_text = "Hello World!";
$sc = new \tts\services\paragon_crypto\sodium_storage($secretkey);
$sc = new \CodeHydrater\services\paragon_crypto\sodium_storage($secretkey);
$index = "sensitive";
$encoded = $sc->encode($index, $plain_text);
setcookie($index, $encoded);

@ -110,7 +110,7 @@ class cookie_session_handler implements \SessionHandlerInterface {
public function write($id, $data): bool {
if (headers_sent($file, $line)) {
throw new \CodeHydrater\services\sessions\cookie_sessions_handler_exception("Error headers were already sent by $file on line # $line ");
throw new cookie_sessions_handler_exception("Error headers were already sent by $file on line # $line ");
}
$data = $this->write_helper($data);
/*
@ -119,7 +119,7 @@ class cookie_session_handler implements \SessionHandlerInterface {
* as web browsers only support up to 4K of Cookie Data!
*/
if (strlen($data) > 4000) {
throw new \tts\services\sessions\cookie_sessions_handler_exception("Session data too big (over 4KB)");
throw new cookie_sessions_handler_exception("Session data too big (over 4KB)");
}
$cookie_lifetime = (int) ini_get('session.cookie_lifetime');

Loading…
Cancel
Save