Jump to content

Jacques1

Members
  • Posts

    4,207
  • Joined

  • Last visited

  • Days Won

    209

Everything posted by Jacques1

  1. Are you sure this is your code? The query to select the file isn't even syntactically valid (there's no FROM clause). Besides that, why is there a limit when you select a row by its ID? Shouldn't the ID be unique anyway? And why do you call fetch() in a loop when you've just double-checked that you never get more than one row? Why not just fetch this row? Passing any content type that happens to reside in the database right to the client also isn't a good idea. In fact, it's a serious vulnerability. Anybody who can set the type has the power to change the meaning of the file. For example, a harmless image may be turned into a malicious HTML document to attack your users. You need a whitelist of acceptable types. I'm sure (or at least I hope) you already have that for the upload, so just reuse it here.
  2. 16 bytes is just fine. Note that you have to encode the bytes to turn them into sensible characters. If you use simple hexadecimal encoding, you get 32 characters: $new_filename = bin2hex(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)); What do you mean?
  3. w3schools is infamous for wrong and inaccurate information. Note that they are not associated with the W3C. It's a private company in Norway which appearently uses the name to sell certificates. Nevertheless, it's OK to accept the “image/x-png” MIME type (since the type is irrelevant anyway), but you shouldn't allow an “x-png” extension. The problem of the file_exists() method is that there's a gap between the check and the action. If two users try to upload the same new file at the same time, file_exists() returns false in both cases, because the file indeed doesn't exist at that point in time. However, the situation changes when the files are actually written. Now one upload will overwrite the other. Instead of a weak random number and a weak backup, it's better to have a strong random number which doesn't need a backup. Yeah, well, as long as you make sure the ID is indeed a number, it's OK. But I'd rather backup my database regularly. What I mean is that you should have a separate domain for the uploads. Let's say your main domain is www.millertime.com, and the document root of this site is /var/www/millertime/www. Then you should have a separate domain like uploads.millertime.io with a separate document root like /var/www/millertime/uploads. That's where the uploaded images go. The point is that even if you do have malicious JavaScript code on uploads.millertime.io, it cannot access the main domain www.millertime.com. All browsers prevent that. Of course an extra domain is expensive, so it might not be an option. Maybe you can at least get a subdomain like uploads.millertime.com. This isn't quite as secure, because some data like cookies is shared between the domains. But it's better than nothing.
  4. But don't forget the exit; afterwards.
  5. Neither getimagesize() nor finfo_file() have any relevance for security, because even a perfectly valid image can contain arbitrary code. The only thing that matters is how the file is interpreted. Note that you have to worry both about your server and your users. Enforcing a whitelist of file extensions is a good start, but it's by no means sufficient. If see the following problems: The code is damn complex for such a simple task, and it's very difficult to read due to the structure, the formatting and a lot of duplicate checks. This greatly increases the risk of bugs. There's no backup plan. Either this code, the webserver and the clients all behave exactly like they should, or you're screwed. That's not a good idea. Internet Explorer in particular will actively work against you, so it's very important to have a second line of defense. What's with all those strange MIME types and extensions? Why do you want to allow the “x-png” extension? When do you expect to get the nonexistent “image/jpg” type? Do you really need people to upload progressive JPEGs? The problem is that the more exotic the data, the bigger the risk that somebody misunderstands it. This md5(uniqid()) stuff is a bit silly. It may be “good enough” for a low-traffic, low-value website, but why fumble with workarounds when every serious operating system is capable of generating proper random numbers? The file_exists() check doesn't work, but if you use proper random numbers, you don't need it anyway. What is Session::get(Config::get('session/session_name'))? Are you sure you can safely insert it into the file path? Why do you need the subfolder in the first place? I'd suggest the following: Throw away all duplicate checks. You don't really need any type checks at all: This is, at best, a usability feature for the odd case that the client accidentally takes a non-image and gives it an image extension. Refactor the code: Use proper indentation, make the structure clearer (e. g., put the standard case before the error case). Use Content Security Policy to tell the browser that no scripts should ever be executed. A good policy would be: default-src 'none'; sandbox. Note, however, that only modern browsers respect this header. Serve the images from a separate domain, preferable not a subdomain. Due to the Same-Origin Policy, malicious scripts will at least be isolated on this domain and cannot access the main site. This is actually the only way to deal with Internet Explorer. Allow only the types and extensions you actually need. Use the random number generator of your operating system. You can access it through several PHP interfaces, depending on which extensions you have installed: Mcrypt has mcrypt_create_iv(), OpenSSL has openssl_random_pseudo_bytes(). Otherwise, you can read directly from the system device (e. g. /dev/urandom).
  6. Do you realize that all of your scripts are wide open to SQL injection attacks? That you're printing all MySQL errors with all sensitive information directly on the screen? That you don't have any checks to make sure that the scripts can indeed only be executed by your servers? Besides that, the whole setup with those raw PHP scripts waiting to be executed by somebody is ... not good. When you want two servers to communicate, you need an API: a well-defined interface with specific functionalities, specific responses, authentication and proper(!) error handling. It's much easier than it may sound. For example: Use JSON-RPC to call remote functions and exchange data in a proper way. There are several PHP libraries which make it very easy to set up a client and a server (they also handle the cURL stuff for you). Generate a random password (e. g. 16 bytes read from /dev/urandom) and have the client send it with each request. Then store a hash of the password (SHA-256 is enough) on the server and use it to authenticate the client. You should use HTTPS between the servers.
  7. First of all: Guys, please, please stop copying and pasting crap code you found somewhere on the Internet. I understand that you're new to cURL. But the answer to this problem is to learn, not adopt the first piece of code you've stumbled upon. After 4 years, you should know that most code is plain crap and pretty much the last thing you want on your server. This line silently breaks the security of all HTTPS connections by turning off certificate verification: That's obviously a very, very bad idea, because the whole reason for using HTTPS is security. Even worse, this “feature” isn't documented anywhere in the code you've posted. It just sits there waiting to take effect when you least expect it. Actually, the only reason why this option is used at all is because people don't know how to set up HTTPS, run into an error and decide to “solve” this problem by effectively deactivating HTTPS. How intelligent. So don't use the code. Take some time to learn cURL and then write your own code. Get which values?
  8. parse_url() http_build_query()
  9. ginerjm's solution is much, much cleaner than messing with opening and closing tags based on the current state. In his code, one iteration assembles one row. You can actually see the markup in front of you. In your code, a row is assembled across multiple iterations, and you have to follow the control flow to figure out the resulting markup.
  10. Jacques1

    multi query

    What is the purpose of the second table when it has the exact same structure of the first one?
  11. Ch0cu3r, when you hand out security-related code, please make sure that it's actually secure. You know that this exact code will be copied and pasted around for the next 10 years. The session part is completely messed up, and you've been doing this long enough to understand the importance of HTML-escaping. tomasantunes, the main problem is that you're using some very, very bad information source. Whatever book or website or YouTube “tutorial” you got this from: Keep away from them in the future. They're teaching you garbage PHP from the 90s, and you're the one who will suffer the consequences. First of all, you have no security whatsoever. You just drop the raw user input into the query strings, allowing anybody to manipulate the queries and fetch any data they want. Then you somehow thought it's a good idea to store the passwords as plaintext or hash them with MD5. Those two major vulnerabilities already allow an attacker to download all user passwords and see if they work on other websites as well (maybe they've been reused on Facebook, Gmail etc.). So if you go on like that, you'll hurt yourself and, what's even worse, your users. My first suggestion is that you don't manage user passwords until you have a solid understanding of security. It's too early for this right now. Simply make a website which is open to everybody, doesn't store private data and doesn't make any promises with regard to security. That's how I started, and I think it was a very good idea. It allowed me to screw up without putting other people at risk. You definitely need a better information source, and you need to start thinking about security. I don't mean details like “What is the best way to hash a password?”. I'm talking about awareness. There's an excellent online book about security basics which explains the common risks and how to deal with them. Unfortunately, there's no central website for good information about PHP. The only way to separate the wheat from the chaff is to compare many different sources, be critical and think for yourself. Personally, I follow some basic rules: A lot of PHP “programmers” handing out advice are absolutely clueless, so question everything and think for yourself. Don't just adopt techniques you saw somewhere or copy code you found on the Internet. Keep away from fishy “code for free” websites with no credibility whatsoever. Keep away from “w3schools” in particular. Big professional communities like Stackoverflow are helpful, because there's a certain extend of peer review: If somebody talks bullshit, there's hopefully somebody else who points out the error. However, that doesn't always work, so you still need to be critical. Check the date. PHP and web programming in general change, so a “tutorial” from 2004 probably doesn't cover the state of the art. Check the reputation of the author (if possible). In the area of security, for example, Pádraic Brady and Anthony Ferrara actually know what they're talking about. Close, but no cigar. This is one of the better attempts, but the author still screws up (session management, escaping etc.). I stick to my previous recommendation: It's too early for this. Learn PHP, learn security. When you actually know what you're doing, you can either write your own code or choose good code from somebody else.
  12. Yes, I mean those two lines. They are not only completely irrelevant for the client, they actually help attackers by giving away internal information about your webserver. Which version of Apache and PHP you're running is none of your users' business.
  13. TLS (or the older SSL) has nothing to do with PHP. This protocol is handled by your webserver before your PHP script is even executed. So this is a system administration task. There are basically 5 steps to do: Learn the basics: How does asymmetric cryptography work? What is a certificate? How does the client connect to the server? etc. Generate an RSA key pair as well as a self-signed certificate for testing. Configure your webserver to offer TLS. Test your configuration with https://www.ssllabs.com/ssltest/. If everything is running properly, generate a new RSA keypair to be used in production. You now need a certificate from a recognized certification authority (GlobalSign, Symtantec, Comodo etc.) so that browser will accept it. Be careful not to waste your money, though. A simple certificate protecting a single domain shouldn't cost more than, say, $25 per year. There's also StartCom which claims to offer certificates for free. However, this should be taken with a grain of salt. When people had to renew their certificates in the course of the “Heartbleed” bug, StartCom wanted them to pay for it. There are tons of tutorials out there covering the basic webserver configuration. Just search for it. If you're using Apache, for example, the first tutorial that looked reasonable was this one. Tutorials about what?
  14. Ch0cu3r's assumption is wrong. First of all, relying on the default algorithm is a bad idea, because you lose one of the key features of modern password hash algorithms: the ability to tweak the computational cost for the specific server hardware and the specific use case. A good dedicated server has much more power than some cheap shared host, so it would be silly to use the same weak settings in both cases and make life easier for attackers. An admin account is much more important than a regular user account, so again it would be silly the use some standard setting. And of course hardware generally becomes better over time. There simply is no one-size-fits-all configuration. Pick a specific algorithm and a specific cost factor. The only algorithm available at this time is bcrypt, and the right cost factor can be determined by choosing the desired duration of the hash calculation and increasing the cost factor until you get this duration on your current server. Revise the settings when the hardware changes. Now that you understand the importance of adjusting the algorithm, it's should also be obvious why rehashing is needed. Whenever you change the cost factor, you should upgrade existing hashes. This happens in the log-in procedure after(!) you've checked the password: <?php // Those settings should be in some external configuration file define('PASSWORD_HASH_ALGORITHM', PASSWORD_BCRYPT); define('PASSWORD_HASH_COST', 14); // log-in ... if (password_verify($_POST['password'], $stored_password_hash)) { // does the current hash need an update? if (password_needs_rehash($stored_password_hash, PASSWORD_HASH_ALGORITHM, array('cost' => PASSWORD_HASH_COST))) { $updated_password_hash = password_hash($_POST['password'], PASSWORD_HASH_ALGORITHM, array('cost' => PASSWORD_HASH_COST)); // replace the current hash with $updated_password_hash } ... }
  15. What is wrong with you? We've already told you how to do it. We've explained the exact steps. Yet you keep repeating the same sentences like a madman. Did you see our replies? Did you understand them? If not, then ask, but don't just skip the answers and repeat your question. That doesn't get you anywhere. Yes, I understand that you want to run a PHP script at user-defined points of time. I'm not stupid. To implement this, you tell the Windows Task Scheduler to run a certain PHP script every minute (or whatever time interval you find appropriate). This script checks if there are any user-defined actions to do at this point in time and executes them. Let's say user A wants to send an SMS at 16:00 today (UTC), and user B wants to send an SMS at 18:30. Your server would do this: ... 11:11: call PHP script -> nothing to do 11:12: call PHP script -> nothing to do 11:13: call PHP script -> nothing to do ... 15:59: call PHP script -> nothing to do 16:00: call PHP script -> user A wants to send an SMS, do it ... 18:29: call PHP script -> nothing to do 18:30: call PHP script -> user B wants to send an SMS, do it ... You get the idea?
  16. API for what? I have no idea what you're talking about.
  17. I think you're missing the point, ginerjm. cyllo wants to use PHP as a template engine, that is, he wants an HTML document with embedded control structures (loops, if statements etc.) for the dynamic parts. This is perfectly valid. PHP is a rather lousy template language compared to Twig or Smarty, but the concept is just fine and very common. In fact, I wonder what you do you instead. You're talking about chunks of HTML with PHP values, but some pages are more complex than that and need actual control structures. How do you generate markup with a loop, for example? The verbose PHP syntax is not “rarely seen” or “rarely used”. You use it in exactly this scenario: In a template, curly braces don't work very well, because you just can't see which one belongs to which statement. This doesn't happen with an explicit “endfor” or “endif”.
  18. The main problem is that you don't seem to understand when PHP code and JavaScript code is actually executed. PHP scripts run on the server. They are invoked by your webserver to produce the HTML document (or any other content). This document is sent to the client. And then the browser runs the JavaScript code which is embedded into the HTML document. So PHP and JavaScript are executed at two entirely different points of time by two entirely different agents. They are not even aware of each other. That means trying to invoke the PHP interpreter within JavaScript is not only impossible, it doesn't even make sense. You're confusing two different layers. The problem is that your programming style actually fosters this: You just throw all PHPSQLHTMLCSSJavaScript into one big file with no structure whatsoever. No wonder you've lost track of which code runs when. You should avoid this so-called spaghetti code and cleanly separate the different languages: JavaScript code belongs into external scripts, do not stuff it into inline scripts or attributes within the HTML document. The same goes for CSS. PHP code also doesn't belong into HTML markup except when its only purpose is to generate the HTML. A good rule for beginners is: Put all PHP code on top and all HTML markup to the bottom of the script. Going back to your question, there are two options: You send the form to the user. When they try to submit it, they are stopped by a JavaScript function which asks them for confirmation. If they confirm their action, the JavaScript function adds some additional form field and lets the browser submit the form. Otherwise, the form is not submitted. The target PHP script then checks the presence of the extra field: If it's there, you can add the data. Otherwise, the user doesn't have JavaScript running and needs to do a confirmation with plain HTML (another form, a checkbox or whatever). You use Ajax to trigger the target PHP script with your JavaScript function. I don't recommend this, because it's much more complex and requires advanced knowledge. ginerjm's suggestion is not a good idea, because if the user has turned off JavaScript (like me), the browser just submits the form without asking for confirmation first.
  19. You should store the ID of the user, not their name. But apart from that, yes, you fetch the user ID from the session and then use it to look up any data you need in the database. I don't know where you've read that and where you've got the code from, but you need to stay away from that place. This is complete and utter nonsense. You should have read our replies instead. First of all, you do not encrypt passwords. You hash them. Maybe you're just confusing the terms, but it's very important that you understand the difference between those two concepts. Encryption is by definition reversible: Given the key, one can turn the ciphertext back into the plaintext. Hashing is not reversible, it merely produces a “checksum” of the input. You can check if a particular string matches the original input by comparing the hashes, but you cannot convert a hash back into the input. The only way to find the original data is to try out different strings until the hashes match (which is called brute-force attack). How hard that is depends on the data and the hash algorithm. Encrypting passwords is an awful idea, because it would allow an attacker to get all plaintext passwords once they've obtained the key. This is an unacceptable and completely unnecessary risk. We do not want to retrieve the passwords, we just want to be able to check them. And this is what a hash is for. However, that doesn't mean you can simply pick any hash algorithm you found somewhere on the Internet. Like I already said above, hashes can be attacked by trying out many different inputs. This is a very real threat in today's world, because anybody with a bit of money has access to massive computing power. For example, even an old graphics card like the GTX 580 can calculate around 100 million Whirlpool hashes per second. It's easy to see that finding an average password is now only a matter of time and money. So forget about Whirlpool and any home-made stuff. You need an actual password hash algorithm which was designed by actual cryptographers. The most important requirement is that it's computationally expensive to make brute-force attacks harder. We also need to be able to tweak the algorithm, because the hardware of tomorrow will be better than the hardware we're currently dealing with. Currently, there are not many options to choose from: There's bcrypt. It's fairly strong, well-tested and well-integrated into PHP (see our links above). This is what you should use. scrypt is a newer design which is meant to replace bcrypt in the long run. It's rather young at this point, which means there's a bigger risk of undiscovered weaknesses. It's also rather complex and doesn't have a native PHP implementation. Right now, I wouldn't recommend scrypt. PBKDF2 is weaker than bcrypt and scrypt. But since it's NIST-approved, people sometimes bring it up (it's not approved for password hashing, though!). There's actually a big competition for a new password hash algorithm going on right now, so we may see new and better algorithms in the future. But if we assume that it takes 15 years until an algorithm has been tested properly and made its way into all mainstream programming languages, that won't be before the year 2030.
  20. When was this ever the way? I don't even know what you're doing there. You store the session ID in the database? Why would you do that? Or are you saying you store the entire session in the database with a custom session handler? By default, a PHP session is a file holding data. PHP automatically sets a cookie with a session ID and resumes the session whenever the user presents the cookie. So all you have to do is store the user ID in the session. If you depart from this scheme, what's your reason? In any case, when it comes to sessions, the devil is in the details. There are many mistakes you can make, so if you want to make sure you're doing it correctly, you should post the exact code and preferably also your session configuration (the session.* directives from the php.ini). Storing critical data like the access level is definitely a bad idea. The problem is that the session doesn't get updated when you change the underlying data in your database. For example, if you reduce the access level of a user, they may still run around with the original access level in their session. That's obviously a problem. In the worst case, they can actively prevent your changes from taking effect. So be very careful what you put into the session. In general, you shouldn't abuse the session for caching at all. If you already store the data in your database, simply look it up there. You do not encrypt them at all. You hash them with the bcrypt algorithm. If you already have PHP 5.5, you can use the new Password Hashing API. If you have at least PHP 5.3.7, you can use a compatibility library which offers the same functions. PHP versions before to 5.3.7 have a defect in the low-level hash algorithm and cannot be used.
  21. Why on earth do you tell your users the exact version of the webserver and PHP? What are they supposed to do with this information? Actually, it does help some people: Attackers can now skip the step of fingerprinting your software, because you've already told them everything they need to know. How kind of you.
  22. I think there's a deeper problem: You've started to implement your own template system which appearently isn't up to the job and may never be. Why not use an existing template engine which actually works? There's Twig, there's Smarty, and there are many others. I'm sure you'll find one that you like.
  23. Please don't use backticks. We've discussed this multiple times, and the bottom line is: Backticks are harmful. In addition to that, you'd have to add them every single time you access the column, and if you ever forget it, you'll again wonder what the hell is wrong. The solution is to not use reserved words as identifiers.
  24. A little bitchy, are we? By all means, I didn't want to hamper the hardcore comp-sci nerd discussion you appearently were about to unleash. Let's dive into the fascinating world of ASTs. I'm listening (seriously). Until now, all you had to say about PHP 7 is that people argued about the name. That doesn't exactly qualify as a deep scientific insight, does it?
  25. What is $_SERVER['user_id']? I'm fairly sure you mean $_SESSION['user_id'].
×
×
  • 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.