[HN Gopher] WordPress security plugin Hide My WP addresses SQL i...
___________________________________________________________________
WordPress security plugin Hide My WP addresses SQL injection,
deactivation flaws
Author : patchstack
Score : 71 points
Date : 2021-11-26 10:17 UTC (12 hours ago)
(HTM) web link (portswigger.net)
(TXT) w3m dump (portswigger.net)
| perrohunter wrote:
| Ironic
| angrygoat wrote:
| SQL injection draws attention to the fact that almost all web
| applications run as root, in regards to the most important asset:
| the data.
|
| It's odd that this hasn't got more attention. It should be easier
| to write backends that tie data access more closely to user
| credentials without the backend trying to enforce that itself. Is
| there anything out there that makes this easy to do?
| Hendrikto wrote:
| > almost all web applications run as root
|
| That's largely a configuration problem. They don't have to run
| as root, most of the time.
| eloff wrote:
| With regards to the database. Not UNIX root.
| eliaspro wrote:
| Should there ever be a web application that needs to run as
| root, it should be rewritten. All logic requiring root
| privileges should be moved into a separate system service
| with a minimal attack surface to which the web application
| delegates those special tasks.
| vntok wrote:
| You misunderstood the grandparent's comment and replied to
| a confused parent. The application does not need to run as
| root, however even when it runs as a normal user, it
| generally has full read/write access to the application
| database. Which is a problem that is not easily solvable.
| raxxorrax wrote:
| I think you need root permissions to start a network service
| on port 80 on Windows. There is a security risk here which
| was addressed in a fairly recent Chrome release that local
| addresses need a respective CORS rule. At least I believe so.
|
| Disadvantage with the Windows behavior is that a webservice
| running on said port has elevated permissions and if you surf
| the web with the same machine, a script inserted into a site
| could launch attacks against it. Of course the site itself
| could be malicious, in that case the CORS rule wouldn't do
| much.
|
| Of course you are correct, running directly on port 80 might
| just be a bad idea, but for development purposes I might do
| that.
| Vogtinator wrote:
| Ports < 1024 are defined as "privileged", so it's not just
| a Windows thing.
|
| What usually happens is that the process only has the
| necessary capability for a brief period to open the port
| and drops it immediately before processing any requests.
| iso1631 wrote:
| It was poorly phrased, but the OP meant that web apps usually
| have full unrestricted access to the database. Clearly that's
| not entirely true (your webapp likely doesn't need truncate,
| or the ability to add/change stored procedures, or the
| schema) but it's broadly there. Your database is effectively
| chmod o+r
| cm2187 wrote:
| I always wondered, how do they exfiltrate the data? The website
| isn't designed to display any schema. Do they save it as file
| from the SQL server? Can't that be locked down? The attacker
| would still be able to delete but at least not extract.
| bflesch wrote:
| If you're able to inject SQL, and the return value of the SQL
| query is not directly displayed to the user, you may use a
| timing-based side channel to exfiltrate data.
|
| E.g. in order to exfiltrate the string "Test123" you would go
| character-by-character, starting with the first character
| "T". For each ASCII character you would wait 10ms, as "T" is
| ASCII #84 [1] you'd sleep() for 84*10=840ms. This sleep() can
| be measured from the attacker side because the SQL query will
| block the HTTP response.
|
| This way, without "seeing" a result, the attacker is able to
| return data.
|
| [1] https://en.m.wikipedia.org/wiki/File:ASCII-Table-wide.svg
| Ginden wrote:
| We're there any actual timings attacks executed like this?
| I'm talking about stack "attacker => internet => reverse-
| proxy => app => database", not extracting data over LAN
| from exposed app.
| bflesch wrote:
| Yes, that's one way to extract data by (ab)using a blind
| sql injection vulnerability.
|
| If you look at sqlmap [1], they offer two techniques for
| blind sql injection: boolean-based and time-based.
| Boolean-based should be used when the app just returns an
| error page (or not) based on your sql injection. The
| time-based approach should be used when no error page
| appears but the SQL is still executed.
|
| But when I look at sqlmap docs for the time-based
| approach [2] I think I got the initial explanation wrong.
| It will do a 5 second delay if a certain condition is
| met, e.g. "Is the first character of the value an 'T'? If
| yes, wait 5 seconds; if not, return immediately". And
| then send hundreds of requests in parallel to iterate
| over all positions & possible characters.
|
| [1]
| https://github.com/sqlmapproject/sqlmap/wiki/Usage#sql-
| injec... [2] https://github.com/sqlmapproject/sqlmap/wiki
| /Usage#seconds-t...
| kenniskrag wrote:
| There is row level security. But that usually means many db
| users or sometimes usergroups are supported.
|
| https://www.postgresql.org/docs/current/ddl-rowsecurity.html
| tremon wrote:
| There isn't, at least not really, since webapps are designed as
| full-service kiosks: all of the data management, user
| management and access control are supposed to be handled from
| the same console. If you want the database to enforce access
| controls, then every user must exist as a separate entity in
| the database, which is good, but then the webapp also needs the
| permissions to manage user accounts in the database, which is
| bad for security, and the webapp can no longer use connection
| pooling, which is bad for performance.
|
| There are tricks you can use, such as implementing row-level
| security and tying it to some concept of end user identity, but
| even ignoring that ORM's don't understand or support RLS and
| developers therefore won't use it: it's still the same problem
| of letting the fox guard the henhouse. The webapp is the single
| control point for both user access and user administration
| (including self-service account creation and password reset),
| so whatever solution you come up with, the webapp will need to
| have super-user access to do that, and therefore if the webapp
| is compromised, your data-level access controls can be
| compromised too.
|
| So, in order to even begin thinking about securing your data,
| the webapp should probably be split into multiple reduced-
| access microservices that handle different aspects of the
| webapp function. As long as we're talking about a single
| monolithic backend, any attempt at scope mitigation can (and
| likely will) be defeated.
| formerly_proven wrote:
| It's not that we don't know how to build things securely,
| it's just that we routinely ignore even basic principles of
| security 'cause it's easier. Virtually every webapp violates
| complete mediation and so it's just unreasonable to expect
| security. Similarly, most developers don't care for security
| and even less about principles and system design. Again, it's
| unreasonable to expect secure outcomes from that.
| pdimitar wrote:
| It's probably more charitable to say "most devs are not
| given time and effort bandwidth to care about security".
| Trust me I'd love to plug more holes before first
| production deployment but management (and my CTO) would
| never approve a time/energy budget for it.
| guiriduro wrote:
| In the current market, I hope it won't sound too
| disingenuous to suggest you look to work with management
| that does. You'll be happier, and the market signal of
| enough people doing it will improve conditions for
| everyone.
| pdimitar wrote:
| I don't disagree in principle but there are many other
| factors that increase my job happiness:
|
| - We have deadlines but they are not strict and very
| rarely somebody is going to even ping you outside work
| hours. People there want some discipline but they don't
| micromanage.
|
| - The atmosphere is 95% of the time super chill.
|
| - There are no egos flying around (not more than usual
| anyway; I scheduled a meeting to explain some coding
| style practices that should be painfully obvious but hey,
| trying not to judge here).
|
| - Technical excellence is appreciated by a very technical
| and careful CTO -- but is indeed often sidelined in favor
| of deadlines and business-enabling work. However, I have
| already successfully fought him and the CEO off on 2-3
| technical excellence tasks by demonstrating they'll
| reduce future slowdowns. Doable but requires some
| brawling in meetings.
|
| - Pay is one of the biggest in EU (although it's like
| 1.5x - 2.0x less the than the US one).
|
| ---
|
| > _and the market signal of enough people doing it will
| improve conditions for everyone._
|
| I keep hearing this and I _want_ it to be true but for 20
| years of career I 've never seen it, not once. Nowadays I
| no longer believe it. Everywhere I worked (I am mostly a
| contractor so it has been a very colorful career) the
| business will stick to their idea of "we can always hire
| somebody else" with persistence that you'd be jealous of
| -- I don't know if it's an illusion or not but trust me,
| it's VERY persistent. That alone weakens the point you
| brought up because employers simply don't believe it and
| often times go out of their way to look for those other
| mythical people -- and I've been told in several
| occasions that the business closed doors before they
| managed to repair their clusterf_ck of an app. That's how
| persistent they are in their thinking process that
| everyone is expendable.
| konha wrote:
| There are some easy wins most applications could use but
| don't most of the time. Like having sensible permissions for
| your app-db-user. Running migrations in a separate process?
| No need to have permission to do schema changes. Events are
| only written to the db and not queried/viewed from the app
| itself? Grant only INSERT rights to the table etc.
| willcipriano wrote:
| I have experimented with a design that only allows the
| application to access a set of stored procedures via it's SQL
| user.
|
| It seems to work, if you write complicated enough stored
| procedures you can enforce things like each entry must be
| created by a logged in user or whatever. Then the application
| is limited to interactions it's supposed to have, so it can't
| drop a audit table or something. I even did login via a
| stored procedure, confirming the hashed password matched and
| generating a bearer token that future stored procedures
| require to function.
| tialaramex wrote:
| My current project is maintenance for a large system built
| of shared procedures.
|
| In principle this feels like a reasonable strategy _but_
| chances are your stored procedures do not enjoy the same
| creature comforts as your "real" software. In my case
| they've got commented out code blocks, procedures with
| names ending V3.bak.tmpMar14.old, randomly different styles
| and formats from one to the next, and inconsistent naming
| (AllGroups allGroups or ag?). All of which would be quickly
| and easily prevented or retrospectively corrected in say C#
| or Java but there's no easy way to do it with the archaic
| T/SQL setup here.
| akersten wrote:
| I'm unfamiliar with T/SQL but of those issues seem like
| fundamental limitations of stored procedures, just
| implementation details that need updating. Why is there
| no way to do it?
| tialaramex wrote:
| Of course, everything is possible, but resources are
| limited and so it matters that it's harder and requires
| ongoing effort to keep this right.
|
| Edited to add: I retrospectively realised the above
| comment had an auto-correct mistake where "easy way" had
| been misscorrected to "way way" and so it wasn't clear I
| meant only that it's needlessly harder
| willcipriano wrote:
| I agree it would require a great deal more discipline to
| implement then the alternatives. I can do it by myself,
| just takes about twice as long to do over the normal way,
| but with a team it would be a nightmare.
| jeroenhd wrote:
| Even in a monolith, scope can be managed. I've worked on an
| application where a specific subset of endpoints used a
| different data source that was configured with different
| credentials, attached to a read-only user. Without code
| execution, these systems were reasonably fool-proof.
|
| A plugin system where an plugin would be exposed to a
| different set of credentials shouldn't be too hard to set up
| with some middleware preparations. Such a system would
| require granting the main account complete database control
| (which is iffy) or would require a lot of manual
| configuration for user permissions (which sucks) but it's
| definitely something you can do in a monolith like WordPress.
|
| Permissions wouldn't be as well-contained as in a proper,
| fragmented, micro-service-oriented permissions model, but it
| would be a good step forward and one that wouldn't
| necessarily break too much when done as a software update.
| friendzis wrote:
| If your database supports session wide environment variables
| you can attach user/group/permissions object to the session and
| have your queries/functions/procedures check that.
|
| If your database supports writable views (e.g. via triggers)
| you can build parametric views.
|
| Both are not plug-and-play modules in your framework and
| requires actual DBA, though.
| ozim wrote:
| SQL injections for me are solved problem.
|
| Frameworks and ORMs are making it easier on back-ends to tie
| data access to user credentials. The same with multi-tenancy if
| you use good framework with ORM you have all the tools to do
| filtering on higher level of abstraction. The same with
| referential consistency on database if it is there - ORM will
| help you to load data that is tied to that account. Making user
| like web app users on database level would make all
| development/ops really costly.
|
| If someone is writing SQL queries directly, he has to have a
| good reason for it. Like if it is plugin for Wordpress it
| probably is not that easy to use ORM.
| Hendrikto wrote:
| > "The function hmwp_get_user_ip tries to retrieve the IP address
| from multiple headers, including IP address headers which can be
| spoofed by the user such as X-Forwarded-For," reads a blog post
| published by Jong yesterday (November 24). "By supplying a
| malicious payload in one of these IP address headers, it will be
| directly inserted into the SQL query which makes SQL injection
| possible."
|
| > wpWave [adressed] both flaws in Hide My WP version 6.2.4,
| released on October 26.
| [deleted]
| zekica wrote:
| WP can't fix this entire class of vulnerabilities properly or it
| won't be Wordpress any more. It is unfortunate that Wordpress is
| one of the worse options for making websites today (not WP
| itself, but any theme or plugin can easily be coded to have
| SQLi), yet it is the most popular.
| Lendal wrote:
| Not surprising to me. I work at a small company, focused on
| industrial automation. It can be very expensive and time-
| consuming to automate things, so our internal processes are
| ironically manual. Customers don't pay us to automate our
| internal processes, so that never gets done.
| cm2187 wrote:
| But it doesn't cost more to use a parametrised query. That's
| dev incompetence not cost pressure.
| virgilp wrote:
| Newrelic synthetic check cannot be used to verify that newrelic
| site is functional(their synthetic checks use Chrome 72, their
| site understandably doesn't support such old browsers)
|
| There's a saying here that the shoemaker's children walk
| barefoot. I think this might not be an isolated phenomenon
| rmbyrro wrote:
| I'm not familiar with WP under the hood. Am I being naive or is
| it feasible to write a routine that scans plug-ins source code
| looking for insecure query argument handling?
| withinboredom wrote:
| There's a couple of excellent static analysis tools (phpstan,
| psalm) that can catch this kind of stuff. I'm 99% sure that
| psalm's security suite would catch this.
| masklinn wrote:
| semgrep has php support, so it should be possible, at least
| with respect to the "basic" APIs. If a plugin wraps the raw sql
| apis I don't think semgrep can "inline" the information, so
| you'd have to reach for the taint tracking but that's way more
| complicated than just check rules.
| mmaunder wrote:
| This plugin has a low install count for WordPress at around 26K.
| It's a commercial plugin as opposed to one of the plugins in the
| WP repo which helps explain the low install count.
|
| Most of the plugins that WP researchers look at are in the
| official repo with higher install counts, so it's nice to see
| stuff like this get some code coverage among researchers.
|
| Envato should really invest in their own automated and human
| vulnerability research. I think there's probably a lot of badness
| out there among the commercial plugins but in many cases
| researchers have to buy the plugin to take a look.
| ChrisMarshallNY wrote:
| This is one of those types of things that shouldn't happen
| anymore, but does.
|
| I'm pretty sure that WordPress now has their own low-level
| version of PDO Prepared Statements. Also, they have a lot of even
| higher-level DB abstractions. I can't think of any reason to
| directly access the DB from a plugin or theme.
| tyingq wrote:
| >I'm pretty sure that WordPress now has their own low-level
| version of PDO Prepared Statements.
|
| I imagine it's well tested, but it's a bunch of PHP escaping
| and regexes inside of wp-db.php. It is not at all real
| placeholders and prepared statements, though the functions are
| named that way. I suppose because there's too much tech debt to
| use normal placeholders.
| ChrisMarshallNY wrote:
| Ah ... well, it's better than nothing.
|
| For me, I always use PDO, and prepared statements and
| transactions. I get a lot of power, for free. I'm not a
| particularly good DB programmer, so I need all the help I can
| get.
| madsohm wrote:
| > I can't think of any reason to directly access the DB from a
| plugin or theme.
|
| Because it's PHP and it's easy.
| ChrisMarshallNY wrote:
| Too true. It's not PHP's fault, though. The same type of
| argument is applied to C++.
|
| We keep developing "nerf-world" languages, designed to
| protect ourselves from ourselves, and most fall down before
| they get a chance to even get going; mostly because they
| constrain, without empowering. I remember moving to Pascal,
| after using Assembly and Machine Code. It was very
| frustrating for me. Pascal was one of the earliest "safe"
| languages.
|
| The problem is that we can't build houses, using PlaySkool
| "Li'l Builder" toolsets.
|
| Also, the WP Codex is _really_ disorganized. It's difficult
| to find anything in it, and that is deadly.
|
| Geeks like to design clever architectures, but we hate to
| document them.
| patchstack wrote:
| Here are full details of that vulnerability:
| https://patchstack.com/hide-my-wp-vulnerabilities-fixed/
| simondotau wrote:
| This is ridiculous. SQLi is a dumb problem and any development
| environment worth using should make it trivial to avoid. All you
| have to do is never allow SQL queries to be formed using string
| concatenation. Or if you do, make sure you're excruciatingly
| strict about it.
|
| I run a large-ish web application written in ColdFusion (more
| precisely, CFML running on the open source _Lucee_ ) which is a
| language where string concatenation is happening all the time.
| This is a very old language which will look embarrassingly janky
| compared to any of the new hotness in vogue on Hacker News. But
| even in CFML I can trivially guarantee zero SQLi by
| parameterising all variables.
|
| Query parameters. They're a thing. If you don't know how your
| favourite programming language has implemented them, learn it.
| Use them.
| [deleted]
| asddubs wrote:
| I agree of course, and in the case of the article you're
| absolutely right, although more generally there are edge cases
| where parameterization doesn't work, like giving choice of
| which row to order by. Naturally in such cases you should be
| operating on a whitelist of options and not pass the user input
| to the query, but the point is that some situations do still
| have to be accounted for.
| Ciantic wrote:
| In WordPress the string concatenation in SQL is normal, even on
| the very first example: $results =
| $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}options WHERE
| option_id = 1", OBJECT );
|
| This is because the database tables aren't static, so one must
| add prefix to each table from a variable. It's horrible, it
| would have been far better if there was magic string like
| %PREFIX% to avoid that.
|
| [1]:
| https://developer.wordpress.org/reference/classes/wpdb/#usin...
___________________________________________________________________
(page generated 2021-11-26 23:02 UTC)