I could go on (all night) but I trust you all get the point. I have two questions.
First, at what point can we say “Emre, you’re really bad at writing code. There are lots of other jobs. Find another.”
Second and more importantly for the future of the web, how can we as an industry protect innocent users from projects like this?? This monstrosity has over 1 million active installs and the chuckle head doesn’t have a fucking clue how to write SQL.
> The authors were initially reluctant to acknowledge the CSRF issue, but after obtaining a second opinion from the WordPress plugin team, they fixed it in version 0.9.5.
In what world do you get notified there's a possibility for SQL injection in your code, and then not immediately fix it? This statement shows such arrogance, and little regard for the security of users.
Yeah…the poor researcher had to make a video to show off the CSRF attack. First off, that researcher really should never pay for another beverage again. Second, the arrogance, holy shit the arrogance. Dude here managed to consistently write SQLi vulnerabilities over multiple releases - he’s really not in the place to argue.
The fundamental problem here is people and companies have got used to the idea they can get huge amounts of software for free, and expect it to be high quality and well maintained.
If Fastest Cache was only a free plugin, I’d give the dude a bit of credit. But it’s not free - his commercial versions are dramatically overpriced considering that he seems to write a new SQLi every odd numbered release. This is overpriced, garbage software and dude can go fuck himself. At this point, I’d happily call this level of negligence criminal.
I've only seen the free versions, so I agree if you are charging it should be better quality.
Personally, I wish programming was treated as "proper engineering", in the same way as bridge building -- there are standards, and you get in serious trouble if you build a bridge, it falls down, and it was clearly your fault.
Of course, people should still be allowed to "build a bridge in their backyard", they just have to put clear warning signs on it, and if a company uses an "illegal bridge", it's their fault when it falls down.
We might still get there, we are still in the early days, similar to when there were no building standards and they fell down / burnt down regularly. After there were enough major disasters, people started demanding better.
Physics is a rule set that never changes, hence engineering standards can be built around it.
Qualitative systems like programming languages have an immeasurable amount of variation and complexity and are extremely difficult to monitor and enforce standards around.
What’s required is a better stack that is less error prone. If programmers can’t make the mistakes in the first place, they won’t happen.
The basic rules of logic which CPUs use and much easier than physics, and have been fixed liner (see quantum mechanics and relativity). I am ignoring CPU bugs here, but then again I wouldn't expect a law to blame programmers for those, same way a builder wouldn't be blamed for defect concrete they couldn't have known about.
Also, new building materials are created all the time, tested, then allowed if they meet fixed safety standards.
This isn't a smartphone. It is a server that other people (that you specifically get to target) have to use.
It is your responsibility to verify your supply chain. If you can't do that, maybe you shouldn't operate a website that collects user information.
At least before cloud you would have to set up bare metal services which gave people an idea of what they were actually assembling. The fancy control panels and one click installs have created a group of overly entitled administrators who can't admin and won't take any responsibility for running shit, misconfigured, off the shelf services from companies they didn't even vet.
You are missing the point. This is a freemium plugin listed in the WordPress plugin directory. They (WordPress) are being negligent by exposing users to that kind of code without any warning, enabling users to install this directly from they WP Admin area.
One should expect at least a red flag, but as always they just care about numbers.
I completely get the point. We are looking at both sides of the same coin. Read my comment again. We are both describing the same problem from different angles.
You claim that WordPress has a responsibility to vet the submissions on their plugin repo in the same way that Apple vets apps on the app store.
I think this level of abstraction has made web operators lazy. I think WordPress.org has a responsibility to host everybody's code and that it is your responsibility as a website operator to vet that code before you let your server run it. Just because you pay for Github or financially contribute to an app on Github doesn't shield you from bad code that another Github user has submitted.
Nevermind WordPress and all of the plugins they host are GPLv2, which means.....(verbatim) "BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW."
But the author did try to prevent SQL injections, and misuse of functions happens sometime ¯\_(ツ)_/¯. It's not that trivial when reading the code. A Stored XSS Via CSRF is also far from trivial.
In conclusion, we all write bugs. Some are tricky. Don't be so angry !
Why on earth are people using string concatenation? Surely $wpdb->get_results should be deprecated in favour of something that accepts parameterised queries?
Why in the hell are people still injecting strings into queries? In 2021??!
There is no excuse to concatenate the id into the query string, but the first parameter, the table prefix is not something you can do with parametrized queries. There are probably better ways to abstract this, but in the end if you need to dynamically determine the tables or columns you have to concatenate that stuff into your SQL query string.
You're supposed to build the string with $wpdb::prepare[1] before running it through get_results. This will prevent SQLi. It's been available and recommended for like a decade, and any WP code linter will yell at you if you're just building queries out of random concatenated strings.
My first recommendation would be to question whether you even need a caching plugin. I'd recommend a benchmark. PHP today is much faster than it used to be, and in many cases caching plugins have been written with old, slow PHP in mind.
Pro tip: If you have trouble measuring the effect of your caching plugin, it probably means its effect is neglegible.
If you really feel you need a caching plugin, WP Super Cache is written by the company that also writes Wordpress. I'd consider that the most trustworthy.
Yeah, if you're on cheap shared hosting (which many, many WordPress sites are), then you're going to hit various limits and have your site disabled the day Ahrefs and Majestic 12 both decide to crawl your site the same day.
A properly set up caching plugin basically saves the pages as plain HTML and serve them with mod_rewrite instead of invoking PHP every time. The speed difference for an individual page load might not be that much for a properly optimized site, but the overall resource usage will be much lower.
> The speed difference for an individual page load might not be that much for a properly optimized site, but the overall resource usage will be much lower.
Is that what you believe or do you have benchmark results?
I work helping people set up things like caching. On the three sites I looked at today, caching plugins had an immediate and positive effect.
That serving static files use less resources than firing up PHP should hardly be surprising.
Sure, mod_lsapi and FastCGI are fast, and opcache is a godsend, but static files are still going to be faster than doing multiple MySQL queries, triggering plugins, rendering the HTML, doing whatever post-processing the plugins do, and then serving the result.
Caching is a must on WordPress. The first distributed password bruteforce (of which there will be many) will drive the load on your server into 3 digits in short notice otherwise.
The bottleneck is MySQL. At some point you'll need a caching plugin, even a simple one. One of the problems, in general, with the WordPress ecosystem is the bloat.
You can also write a minimal cache system in just ~2/300 lines of PHP that is still very efficient. So efficient you can even survive a hug of death from HN on a tiny VPS without a blink. I did it.
Yet, people seems so attracted to those bloated "fastest" plugins...
For logged out users, sure (I did). If your users are logged in or you need to process their visit server side, it's a bit harder. AFAIK you can't do fragmented caching with vanilla Varnish.
> My first recommendation would be to question whether you even need a caching plugin.
My first question to you would be "Why wouldn't you bypass PHP and MySQL if you can?".
For some really basic site sure, you can go without caching, but for any reasonable degree of complexity not using caching is a foolish waste of hardware and end-user patience since we can be talking TTFB of 100-200 ms vs up to seconds.
The closest thing you'll get to serverless wordpress in one click. There is no wordpress caching plug-in I am aware of that will get you anywhere near.
Configurablity and ease of use. Many people run Wordpress on cheap, shared hosting and would only have the option of a cache plugin. A lot of WP admins likewise have no command-line experience and couldn’t install nginx without resorting to Google.
Personally I always go with Cache Enabler (by KeyCDN) with nginx. Simple and rock solid. Creates static HTML. For optimum performance (bypassing PHP altogether) configure nginx to try_files (or equivalent in Apache) in the wp-content/cache directory.
Edit: I've also used WP Super Cache and W3 Total Cache quite extensively, both both of these have on some sites had a tendency to randomly clear the cache and I've never managed to figure out why. Cache Enabler has never done this.
That's a very obvious SQL injection, and a completely unnecessary one. I don't actually know how PHP handles this, but usually it's really not any more work to pass parameters as parameters and not concatenate them into the SQL string. And SQL injections are not an obscure or difficult to understand subject, it's probably the most obvious common security issue.
There are cases where it's more annoying to do stuff in plain SQL and where you'd have to concatenate strings. But this is not one of them, is a simple parameter that needs to be passed to the query.
In WordPress there is the `$wpdb` class, that abstracts database access away. It is advised to use `$wpdb->prepare()` with prepared statements. Then you have an array with placeholders and an array with values, which the `$wpdb` class should handle correctly.
But looking at this code, simply casting to an int with `(int) $id` in the `set_id()` method would have been enough.
The problem isn't so much concatenation, as it is, concatenation based on dynamic (e.g user-submitted) input. In some (admittedly rare cases), it's hard to avoid concatenation since not every part of an SQL query can be parameterized, such as table names.
(Fun "fact", I vaguely remember that, once upon a time, even things like parameters in limit/offsets weren't universally supported. Also, and correct me if I'm wrong, first class support for arrays (e.g., via any($1)) is relatively new).
It's worse...the call doesn't even support bind params. There is a "$wpdb->prepare()", but it's not real bind params, but rather a bunch of php quoting, escaping, and stripping. And in this case, they didn't even do that.
So basically, by lowering the barrier to entry and making it easy, they've actually made it difficult/impossible to write even slightly secure code whilst simulataneously encouraging the level of developer who has no idea what they are doing.
Legacy. Plus the ODBC layer is sort of 'broken' then add on nearly 25 years of examples on the internet.
We have 2 modes of using ODBC/SQL.
Almost tightly bound. Basically you have a bit of query string with question marks in it and you bind out your data points. Either for sending/receiving. Even passing in prepared strings could be an attack vector if you know what you are doing. As it breaks one of the 'rules' of secure programing trusting the client to tell you the correct thing. This however is the currently the only best way to do it, unless you go full on with the stored procedure pattern (which can still have injection attacks).
Loosely bound. Here is a totally composed string ready to go just run it. Also a good way to make easy SQL injection attacks.
Both involve string manipulation.
Then a requirement of that interface is it has to sort of kind of work with at least 4 different SQL systems. Anyone who has had to port stored procs between some of these different SQL systems, can attest to, that they are not the same, except in some very basic ways.
On top of that there are a lot of bad examples out there. But also once someone finally kind of gets something to work they may cut and paste that method. Which may or may not be good. Plus SQL has this stigma for many years of 'being hard'. I know I ended up as the 'SQL guy' for awhile because many in some of my orgs would not touch it.
That is what the runtime environments have to deal with. Some paper over it with an API abstraction, some are better than others.
WordPress.org is just a vector to sell Jetpack and WordPress.com at this point.
In the past decade they could have easily fixed a lot of key pains in WordPress, but on one side there are a bunch of amateurs WP users who just don't care and on the other, if they fix obvious security and performance issues, they can't sell "managed WordPress" that easily.
How hard is it to add a "staticize WordPress" toggle? Log in, WP is dynamic; log out, PHP stuff is rendered unexecutable. If WP had a native "static" mode, plugin authors would have to figure out a way to support it well in most cases.
WP has built in cache (an API for it, which hundreds of caching plugins take advantage of).
Built-in CDN doesn't make any sense for the self-hosted version. But you can install a plethora of third party plugins for CDN, like Jetpack.
Multilingual support I can agree with. There are discussions ongoing about it and I do think it's going to drop some time in 2022, but for now you're relegated to solutions like Polylang. Polylang actually works really well out of the box, but it does not have 100% compatibility with every plugin.
There are multiple plugins that do each of those things. There's no need to build it into the core product.
I'm not a big fan of wordpress but am running it anyway for our corporate website (I'm the CTO) because it hits the good enough mark and it is just not worth my time trying to come up with something better.
The big advantage of the current setup: I don't have to micromanage it beyond making sure we have backups and the site stays up and running. Our sales and marketing people manage the content and I don't have to babysit them. Win, win for me because I have more interesting things to do then maintaining a website.
The downside: it's PHP and security vulnerabilities are a constant risk and worry with that. I just checked we are up to date and don't have this caching plugin installed. However, we have a constant stream of opportunistic bot traffic trying to exploit pretty much every vulnerability ever for wordpress, php, and php related tooling that we aren't even running. So, I'm more than a bit paranoid about any hypothetical way in.
I'm a little surprised there isn't a general purpose option inside Apache. I'd like to go into my .htaccess and say "Any GET request that matches this regex, please cache and serve future requests from the cache for x seconds."
(I'd set it to an hour normally and 6 hours if I'm on HN.)
That sort of thing would be perfect for WordPress and similar CMSs.
The best WP cache plugins generate static copies of pages then put rewriterules in the .htaccess to serve them, which is functionally pretty close to what you describe.
This way the request doesn’t touch php at all which is a big advantage.
WordPress already has its own htaccess file for rewriting URLs into query string parameters. I wonder why it doesn't include a cache command as normal. The number of times I've gone to a page only to be faced with a MySQL error for too many connections.
Many plugins add dynamic pages to WordPress - e-commerce carts, membership plugins etc. If WP would just add a cache to everything they would not work. You might say that there could be an API for these plugin to register their uncached routes, but not everyone runs Apache - Nginx is also commonly used and would also need to somehow be supported.
As someone who has written their own WP caching plugin, it's actually very convenient to perform the caching in PHP, because you can check for cookies and regex expressions for URLs, and there are many plugins that handle it well. For most sites I use a free one called Cache Enabler.
The people who use wordpress cache plugin are not really technical. They use 5$/month shared hosting crap where you can't configure anything more than mod_rewrite in .htaccess.
And that is why I have forbidden third party WP plugins at the company I work for - no exception.
There is only 1 plugin and it is the one we write our self which take care of caching and all custom needs. Each line of code in that plugin is double checked and properly tested before going in production.
Another solution is to pay a penetration tester or an offensive security expert to audit your website. They’ll probably load up Kali and run SQLMAP and Nikto against it and do some custom penetration testing.
Here’s a report on 0.8.4.8:
https://www.acunetix.com/vulnerabilities/web/wordpress-plugi...
Here’s a report on 0.8.7.4:
https://www.acunetix.com/vulnerabilities/web/wordpress-plugi...
I could go on (all night) but I trust you all get the point. I have two questions.
First, at what point can we say “Emre, you’re really bad at writing code. There are lots of other jobs. Find another.”
Second and more importantly for the future of the web, how can we as an industry protect innocent users from projects like this?? This monstrosity has over 1 million active installs and the chuckle head doesn’t have a fucking clue how to write SQL.