Jump to content

Jacques1

Members
  • Posts

    4,207
  • Joined

  • Last visited

  • Days Won

    209

Everything posted by Jacques1

  1. I gave you a link in my reply regarding MySQL replication. Read it. Sockets are yet another option, but then you do need extra code on each server to open a socket, periodically query the database for changes and send those changes to the client. You seemed to have a major problem with that idea.
  2. You're not understanding the answer. My point is that servers can send out notifications on data changes, so instead of the client(s) constantly polling the server(s) for new data, the server(s) can notify the client(s) exactly when there actually is new data. This has nothing to do with adding new scripts to the remote servers. All your fetch logic can remain on the client. The difference is that you can get rid of the polling. For example, you can hook into the MySQL replication mechanism to get change events. This actually doesn't require any modifications on the servers at all.
  3. So what exactly "isn't working"? <?php $secret = 'se:cr:et:co:de'; $success = '1'; $sess_timeout = '60'; $idle_timeout = '30'; $session_data = $success.$sess_timeout.$idle_timeout.$secret; $nonsense_hash = sha1($session_data); echo $nonsense_hash;
  4. Use the same connection parameters you used for mysqli (which you said worked fine). Double-check the IP address and the port, and make sure the MySQL server is running.
  5. Is there any reason why you can't register the clients at the remote server and make it notify the clients of changes? This would let you get rid of polling altogether.
  6. There's a controller for every page, not for every GUI component. The purpose of a controller is to process a request to a particular URL. GUI components are handled by the template engine (i. e. on the view layer).
  7. Definitely use a static(!) whitelist. PHP has a long history of fudging up even basic functions, so I wouldn't trust hacks like the basename() approach. For example, some file operations used to be vulnerable to null byte injections where the user could hide part of the path behind a \0. Trying to fix user input (which is what your basename() ultimately does) is generally a bad idea, because it's error-prone and can cause a lot of confusion. Either accept the input as is, or reject it altogether.
  8. The Python code is fairly awful and shows a misunderstanding of security basics, so instead of trying to translate it, I'd rather solve the underlying problem. That is, unless you're somehow obliged to implement this wrong technique. What is it you're trying to do? First off, mixing a secret into a plain SHA-1 hash is a bad idea. There are specialized constructs for this purpose like HMACs (hash-based authentication codes), and there are better hash algorithms like SHA-256. SHA-1 is pretty much obsolete by now. You also need to decide exactly which data you store and how to store them in an unambiguous manner. Hashing timeout durations doesn't make much sense (you'd hash absolute times), and plain concatenation leads to ambiguities. For example, both data pairs (12, 6) and (1, 26) yield the exact same string when concatenated, but they're completely different. A more sane approach: <?php const HMAC_ALGO = 'sha256'; const HMAC_KEY = 'f57a1c9756f056b74839ecfd036f273f99578babc704463043856fe1466b383a'; const SESSION_TIMEOUT_MINUTES = 60; const SESSION_IDLE_TIMEOUT_MINUTES = 30; // note absolute times $sessionTimeoutTime = strtotime('+'.SESSION_TIMEOUT_MINUTES.' minutes'); $sessionIdleTimeoutTime = strtotime('+'.SESSION_IDLE_TIMEOUT_MINUTES.' minutes'); $sessionData = $sessionTimeoutTime.':'.$sessionIdleTimeoutTime; // note the use of a colon as a separator $hmac = hash_hmac(HMAC_ALGO, $sessionData, HMAC_KEY); var_dump($hmac); Note that I'm speculating here, because I don't know the exact requirements.
  9. 1: My point is that you should stop generating dynamic HTML markup with PHP altogether. There are specialized languages like the already mentioned Twig which are much better for that (see the Twig homepage for a detailed comparison in terms of conciseness, security and ease of use). So PHP should only be used for the application logic and delegate all HTML-related tasks to a separate component. You'll immediately see that your core application becomes much simpler. 3: Yes. In professional applications, this is called a front controller: It receives all requests and then delegates the processing to individual objects for the various pages.
  10. First off: Kudos for creating this nice project as a beginner. It's rare to see such decent code and HTML markup on the first attempt. And it's even on GitHub! Give that man a medal. There's nothing particulary wrong at this early stage. However, given your obvious talent and/or experience, I recommend you skip a few learning steps: Right now, you're creating your dynamic HTML markup with PHP. That's possible, but it has several disadvantages: PHP is very verbose when used for this task, it forces you to put the HTML fragments together yourself (which can become very complex when you have arbitrarily nested components), it encourages you to mix application logic with visuals, and it's insecure in the sense that a “page” is a full-blown PHP application which can do anything from rendering HTML to formatting your HDD (when it should really just render HTML). Consider using a dedicated template engine like Twig or Smarty. It's much more compact, secure and takes care of many tedious template management tasks. Rework your directory structure. All client-side resources (JavaScript files, CSS, images etc.) should be put into an extra folder like resources. The pages (or Twig templates) should be separated from the application core (which contains classes, libraries etc.) and again be put into an extra folder. The index.php script should delegate the entire request to a special class which is associated with the URL and takes care of the processing. For example, a request to /index.php?page=invoice would be handled by an Invoice class, and the index script merely acts as a kind of router without generating any HTML markup on its own.
  11. First off, make sure you have the PDO connection parameters right. For example, there's no manual error handling in your code, which means you must make PDO throw an exception in case of an error (otherwise you'd just keep going). A good starting point is this: <?php const DB_HOST = 'localhost'; const DB_USER = '...'; const DB_PASSWORD = '...'; const DB_NAME = '...'; const DB_CHARSET = 'UTF8'; $dsn = 'mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset='.DB_CHARSET; $databaseConnection = new PDO($dsn, DB_USER, DB_PASSWORD, [ PDO::ATTR_EMULATE_PREPARES => false, // use actual prepared statements, don't emulate them PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // make PDO throw an exception in case of an error PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // fetch associative arrays by default ]); The password check itself can be simplified to $userStmt = $databaseConnection->prepare(' SELECT user_id, -- I am guessing here password -- password_hash would be a better name -- add additional columns if needed FROM apna_users WHERE username = :username -- use named parameters for the sake of readability '); $userStmt->execute([ 'username' => $username, ]); $user = $userStmt->fetch(); if ($user && password_verify($password, $user['password'])) { echo 'Credentials correct.'; } else { echo 'Username or password incorrect.'; }
  12. So what's the actual goal here? To get rid of the strange looking characters in the original string? The problem is that your character encoding is messed up. The original string is encoded with UTF-8 (a multibyte Unicode encoding) and contains several Unicode dashes. But your application misinterprets the string as ISO 8859-1 data (a single byte encoding) and displays each multibyte character as a sequence of multiple nonsense characters. To fix the problem, you need to make your application use UTF-8 all the way, including the database, the database connection, the HTML document and possibly other components.
  13. Turn your error reporting on and all the way up. Some mysqli methods you're calling don't even exist, and even those which do exist work completely different. It seems you're somehow trying to mix the mysqli library with the unrelated PDO extension, which of course makes no sense. I gave you a link to the PHP manual which explains in great detail how prepared statements in mysqli work. Read it. Programming is an exact science, so you need to use the actual mysqli API rather than what you think the API should look like. By the way, mysqli sucks compared to PDO, so if there's a chance to switch, I recommend you do that. Clearly you already prefer PDO.
  14. Your code is wide open to SQL injection attacks, and you're misunderstanding password hashing. Use prepared statements for dynamic query input. And fix the password check: password_hash() is only used to create a new hash during registration or a password reset. To verify a password, you fetch the user's hash and call password_verify() with the submitted password and the stored hash. You cannot do a database search with password_hash(), because the same password will always have a different hash due to the random salt.
  15. Read the documentation of preg_replace_callback() in the PHP manual. It explains exactly how the function works and shows several examples. What you need is a callback function which receives the matches array as an argument and returns the replacement string: function ($matches) { return ...; // the replacement for the matching substring }
  16. What kind of school is this? The code you've shown is plain wrong and shows a deep misunderstanding of programming basics. This isn't even amateur level. It's a collection of security vulnerabilities and terrible practices from the 90s (table layouts, style attributes etc.). So either you've spent all lessons in a coma, or your teacher needs to get fired. In any case: If you actually want to learn how to program, throw your Dreamweaver away, go to the Mozilla Developer Network and let them teach you how HTML looks like in the 21st century.
  17. A sufficiently big random number from a device like /dev/urandom will provide uniqueness, so this is perfectly valid. PHP has a large variety of randomness APIs depending on the version: If you have PHP 7, there are random_bytes() and random_int(). This is the recommended approach. The same functions are available in PHP 5 through a library. If you neither have PHP 7 nor want to use a library, there are mcrypt_create_iv() from the Mcrypt extension and openssl_random_pseudo_bytes() from the OpenSSL extension. To ensure global uniquess, you should generate 128 bits (16 bytes). You can then use hex-encoding or Base64-encoding to make the bytes human-readable. If you want a standardized format, there's UUID. <?php // Include the random_compat library if the PHP version is below 7 $random = random_bytes(16); // hex encoding $id = bin2hex($random); echo $id, '<br>'; // a shorter alternative: Base64 encoding (uses characters a-z, A-Z, 0-9, +, /) $id = rtrim(base64_encode($random), '='); echo $id, '<br>';
  18. It's sometimes useful for one-liners as shown in the examples in the manual.
  19. Why exactly do you want three(!) sets of permissions? You have user-specific permissions, then role-specific permissions and finally employee-specific permissions. It would make a lot more sense to bind permissions to roles and allow a user to have multiple roles. A role can represent all three cases: a single user, a group and an employee. You can even reuse the employee-specific permissions (e. g. all employees of X should be able to do Y).
  20. No nervous breakdown this time? I'm disappointed.
  21. How about: everything. Stop copypasting garbage code from the Internet and expecting others to repair it. The idea of programming is that you write code. Yes, your own code with your own hands. I know this must sound crazy to you, but that's how it works.
  22. Get a proper IDE which can analyze your queries, and you'll immediately know the type of any column just by pointing to it. No need for any prefixes. The Hungarian notation may be useful for special cases, but it's still an oddity, hard to read and has been actively rejected by many projects – including PHP. I've never seen it in a database. So you might want to adopt more common naming conventions, especially if there's a chance that somebody else might work on the project.
  23. A SHA-2 hash is not a SHA-2 HMAC. As I already said above, you simply create an extra column for the HMAC of the e-mail address and make it UNIQUE. Whenever you want to add a new address, you calculate the HMAC with PHP and try to insert the address together with the HMAC. If the address already exists, the HMAC will be identitical to an existing value and violate the UNIQUE constraint. Otherwise the query will succeed, and you know that the address is indeed unique. It's really very simple once you understand the idea. <?php class HMAC { /** * @var the underlying algorithm for the HMAC */ const ALGO = 'sha256'; /** * @var the length of the HMAC key in bytes */ const KEY_LENGTH = 32; /** * @var string the HMAC key */ protected $key; /** * HMAC constructor. * * @param string $key the HMAC key */ public function __construct($key) { if (!is_string($key)) { throw new InvalidArgumentException('Invalid key type. Expected a string.'); } if (strlen($key) != static::KEY_LENGTH) { throw new InvalidArgumentException('Invalid key length. Expected '.static::KEY_LENGTH.' bytes.'); } $this->key = $key; } /** * Calculates the HMAC of a message * * @param string $message the message * * @return string the resulting HMAC */ public function calculate($message) { if (!is_string($message)) { throw new InvalidArgumentException('Invalid message type. Expected a string.'); } return hash_hmac(static::ALGO, $message, $this->key); } /** * Verifies the integrity of a message with a known HMAC. * * @param string $message the message to be verified * @param string $hmac the known HMAC * * @return bool whether the HMAC of the message matches the known HMAC */ public function verify($message, $hmac) { if (!is_string($message)) { throw new InvalidArgumentException('Invalid message type. Expected a string.'); } if (!is_string($hmac)) { throw new InvalidArgumentException('Invalid HMAC type. Expected a string.'); } return hash_equals($this->calculate($message), $hmac); } } <?php $key = hex2bin('8311f033e7235286f5d9b17f2e83366989c3f12b414dc15348dbed2aaa102b2d'); // note binary key $hMAC = new HMAC($key); $email = 'foo@example.com'; $emailHMAC = $hMAC->calculate($email); // insert $email with $emailHMAC
  24. Just don't include the message in the output. Only return the HMAC. Storing a “public key” together with the HMAC makes no sense either; I'm not even sure what you mean by that, because HMACs have nothing to do with public-key cryptography. HMAC validation must not use the standard string comparison algorithm; when you use the == or === operator, PHP stops at the first non-matching byte and allows an attacker to figure out the expected HMAC through time differences. You need a special comparison function which is immune to timing attacks like hash_equals(). The expected key length is hard-coded to 256 bits, but it should be equal the output length of the hash algorithm (RFC 2104). In the case of SHA-512, that's 512 bits. So either create a lookup table for the output sizes of all supported hash algorithms, or use a hard-coded algorithm together with its specific length (SHA-256 is perfectly fine, no need for anything else). Use binary keys as arguments; expecting pre-encoded strings is a bit weird and makes validation more difficult. Currently, you double-encode the computed HMAC by letting PHP hex-encode the result and then adding your own Base64 encoding. This makes no sense and wastes space. If you want your own encoding, apply it to binary data (set the fourth parameter of hash_hmac() to true).
  25. The point of the HMAC is to act as an independent “checksum” so that you can keep your e-mail addresses encrypted in any way you want and perform the UNIQUE check on the HMAC instead of the (unknown) address. This completely solves the problem.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.