Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented request #64810 (impossible to load extension via pdo_sqlite) #3368

Closed
wants to merge 5 commits into from

Conversation

cwt137
Copy link

@cwt137 cwt137 commented Jul 5, 2018

Hello. This is an attempt to fix https://bugs.php.net/bug.php?id=64810 . This allows PDO to load extensions just like the native Sqlite3 API can do. This means there is more feature parity between the two APIs.

A couple of tests are failing. Could I please have some help resolving it?

@cwt137
Copy link
Author

cwt137 commented Jul 6, 2018

Test and stuff finally pass.

@nikic nikic added the Feature label Jul 7, 2018
@cwt137 cwt137 changed the base branch from PHP-7.2 to master July 9, 2018 20:23
@cwt137 cwt137 changed the title Implement PDO::sqliteLoadExtension() Implemented request #64810 (impossible to load extension via pdo_sqlite) Jul 9, 2018
@cwt137
Copy link
Author

cwt137 commented Jul 10, 2018

I changed branch to master so that this can be included in PHP 7.3. I also updated the title so it is hopefully more appropriate. I hear the feature freeze is on the 17th. What can I do to make sure this makes the deadline?

@BenMorel
Copy link
Contributor

Would love to see this in PHP 7.3. Ping @cmb69 and @smalyshev !

@cmb69
Copy link
Contributor

cmb69 commented Jul 10, 2018

This PR is similar to #2698, and as such should at least be discussed on internals@.

@smalyshev
Copy link
Contributor

Loading binaries at runtime creates all kinds of tricky situations IMHO, even in single-threaded servers. Does it really needs to be happen at runtime? Maybe have INI value that pre-loads all needed extensions would be better?

@BenMorel
Copy link
Contributor

How is that different from SQLite3::loadExtension()?

@smalyshev
Copy link
Contributor

indeed, not very different. So I guess if PDO maintainers are fine with it, then ok, but since it's in PDO probably needs to be discussed.

@cwt137
Copy link
Author

cwt137 commented Jul 11, 2018

@cmb69 This is totally different than that PR. That PR is about getting blob data from a result as a stream? This PR is basically to add functionality to SQLite via its extensions system. The only thing similar is that both PRs add a sqlite instance method onto the PDO class.

@BenMorel This PR implements the same functionality as SQLite3::loadExtension(), just for PDO. You can't use PDO and that method together since you didn't open the database using the SQLite3 API. I am trying to make sure that I can use the same features in PDO as I could with SQLite3, so I coded this PR to have the same behaviour. Its a pain to use Laravel and have all the DB setup and then you have to use the SQLite3 API. Makes no sense

@smalyshev It shouldn't be an ini setting because on every request that uses pdo_sqlite would load the extension. Also, you might want to load a different extension, depending on what the request is. This is why I think the people who created the original method for the SQLite3 API implemented it this way. I am trying to make sure PDO has the same functionality as SQLite3.

@BenMorel
Copy link
Contributor

@cwt137 I know, I was reacting to @smalyshev's comment.

However, I just realized that your PR adds a sqliteLoadExtension() method to PDO, which makes it similar in this matter to #2698 indeed (this is what @cmb69 meant), and IMHO is not a good thing to do: PDO should stay as generic as possible.

Is there any reason why you couldn't just add support for SELECT LOAD_EXTENSION(), which is what the original PHP bug is about, and which wouldn't require a new PDO method?

@cwt137
Copy link
Author

cwt137 commented Jul 11, 2018 via email

@cmb69
Copy link
Contributor

cmb69 commented Jul 11, 2018

SELECT LOAD_EXTENSION() doesn't work, because extension loading is disabled by default. The PR (as well as the respective code in ext/sqlite3) enables it only temporary. See also https://www.sqlite.org/c3ref/enable_load_extension.html.

@BenMorel
Copy link
Contributor

What about creating an ini option to enable SQLite LOAD EXTENSION in PDO then? Something like:

pdo_sqlite.enable_load_extension = 1

This would be off by default to keep the current behaviour.

This would avoid having to add a SQLite-specific method to PDO (which again, IMO is not a good idea), and we could use SELECT LOAD_EXTENSION() in client code instead.

@BenMorel
Copy link
Contributor

Just noficed that the pdo_sqlite extension already adds 3 methods to PDO; I didn't know that. These methods are explicitly marked as EXPERIMENTAL though, and can be modified (and removed, perhaps?) at any time, without notice.

So I stand with my suggestion above, ini option pdo_sqlite.enable_load_extension, which I feel is more likely to be accepted by the community, and more likely to stay in future releases.

@cwt137
Copy link
Author

cwt137 commented Jul 12, 2018

I forgot about this function. Like you said, the ability to load a SQLite extention is turned on temporarily. This is for security reasons. Turning on the loading of extensions could be done on initializing pdo_sqlite, but a hacker could load an extension using the select statement if they used SQL injection.

@BenMorel
Copy link
Contributor

To me, SQL injection is a thing of the past. If you're using prepared statements, you should never ever have to build a query string from a user-originated variable, so this is a non-issue.

This is just my opinion, of course.

# Conflicts:
#	ext/pdo_sqlite/config.m4
#	ext/pdo_sqlite/config.w32
@cwt137
Copy link
Author

cwt137 commented Oct 29, 2018

@BenNorel I agree with you 100%! Everybody should be parameterizing their SQL. But unfortunately it is not the case and it is the #1 security hole/threat/whatever according to OWASP. Also, I do not think it is a good idea removing the current 3 PDO methods for SQLite. They provide a valuable purpose and because of the unique nature of SQLite, there is no equivalent in other SQL databases. For example, in SQLite, you create your own user defined function (UDF) in PHP and have the database use it. But, the UDF does not run on the database, but runs in the programming language that created the UDF. Here is one big usecase; because the default build of SQLite does not have any trigonometric functions, you must use PHP to create a UDF to use inside of PHP. This is accomplished by using one of the 3 extra PDO methods. Here is an example.

@BenMorel
Copy link
Contributor

You have a point regarding the necessity of keeping the current PDO methods for SQLite!

Now, I honestly don't mind which solution is retained, as long as LOAD_EXTENSION() is possible in some way.

I'm just standing up by my comment above, that SQL injection should not be a reason not to add useful functionality in a library. Anyone not using prepared statements and blindly injecting user input into their SQL queries is asking for trouble anyway. When you can already fiddle with, or drop their database, I don't care if you can, also, execute abitrary extensions on their server.

@teresko
Copy link

teresko commented Apr 8, 2019

So, has there been any progress regarding this feature?
Or is everyone waiting for branch to get stale enough :)

@beberlei
Copy link
Contributor

beberlei commented Apr 8, 2019

@BenMorel i strongly disagree on a global INI option to enable loading extensions, potentially everywhere in every PDO::query call. Stating "sql injection is a thing of the past" is also quite dangerous, given that it is still in the top 10 of OWASP list, it is very much a thing of the present.

PDOs API is weird and different drivers add different things to the class. This is not restricted to sqlite driver and I don't think taking a stand now on preventing further changes to this weird API makes sense.

@beberlei
Copy link
Contributor

beberlei commented Apr 8, 2019

The PR needs a rebase onto 7.4 or master, since the ZTS threadsafe handling in sqlite extensions is not present anymore.

Copy link
Member

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be okay in this form for 7.4. As has been pointed out, there are already multiple similar methods provided by PDO SQLite and the API closely matches what the sqlite3 extension does. I agree with @beberlei that having this contained API is better than a global ini setting, especially in light of the recent introduction of the defensive setting for sqlite3.

@@ -66,6 +66,10 @@ if test "$PHP_PDO_SQLITE" != "no"; then
PHP_CHECK_LIBRARY(sqlite3,sqlite3_key,[
AC_DEFINE(HAVE_SQLITE3_KEY,1, [have commercial sqlite3 with crypto support])
])
PHP_CHECK_LIBRARY(sqlite3,sqlite3_load_extension,
[],
[AC_DEFINE(SQLITE_OMIT_LOAD_EXTENSION, 1, [have sqlite3 with extension support])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit odd, we'd usually go for a positive define instead. HAVE_SQLITE3_LOAD_EXTENSION would be typical.

@@ -4,6 +4,7 @@ ARG_WITH("pdo-sqlite", "for pdo_sqlite support", "no");

if (PHP_PDO_SQLITE != "no") {
if (SETUP_SQLITE3("pdo_sqlite", PHP_PDO_SQLITE, PHP_PDO_SQLITE_SHARED)) {
ADD_FLAG('CFLAGS_PDO_SQLITE', "/D SQLITE_THREADSAFE=" + (PHP_ZTS == "yes" ? "1" : "0") + " ");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand the purpose of this change. As we no longer bundle libsqlite3 nowadays, does this even have an effect?

@BenMorel
Copy link
Contributor

BenMorel commented Apr 8, 2019

@BenMorel i strongly disagree on a global INI option to enable loading extensions, potentially everywhere in every PDO::query call. Stating "sql injection is a thing of the past" is also quite dangerous, given that it is still in the top 10 of OWASP list, it is very much a thing of the present.

That's a crazy state of things in 2019, probably due to a lot of legacy code, and poor developer training.

PDOs API is weird and different drivers add different things to the class. This is not restricted to sqlite driver and I don't think taking a stand now on preventing further changes to this weird API makes sense.

I guess you're right. Either way to implement it will be good for me anyway! 👍

@RollingHog
Copy link

Once again, what was the solution? Feature still seems to be non-existent, at least in PHP documentation.

@cmb69
Copy link
Contributor

cmb69 commented May 8, 2020

This PR is still unresolved. The problem is that adding driver specific methods to PDO via the currently existing mechanism (basicall __call like), has faced some strong oposition, so this should be discussed on internals. It probably would make sense to start some general discussion about this issue, and to hopefully come to a solution, so driver specific functionality could be added to PDO in the future.

@RollingHog
Copy link

RollingHog commented May 12, 2020

Uh-oh. From one point, I do understand concern about "polluting the function space". From another, I kinda really need it (and some other people from SO too, I guess). Maybe they would agree on something like callDriverSpecific('functionName', arguments...)? It looks awful, but at least it can work.

@aboks
Copy link
Contributor

aboks commented May 28, 2020

I found a workaround for this functionality not being present yet, but it involves a fair amount of spooky black magic and I definitely wouldn't recommend it for production.

@pbowyer pbowyer mentioned this pull request Jun 24, 2020
10 tasks
@krakjoe
Copy link
Member

krakjoe commented May 10, 2021

This appears to have gone stale, and there appears to be more recent work going on in this area, so closing now.

@krakjoe krakjoe closed this May 10, 2021
@BenMorel
Copy link
Contributor

@krakjoe This is still not solved as far as I can tell, though. Could you please point me to another issue / PR that would deal with this?

@cmb69
Copy link
Contributor

cmb69 commented May 10, 2021

I'm afraid there is no recent work going on in this area. This needs a general solution regarding driver specific functionality; otherwise such feature additions are blocked indefinitely. :(

@cmb69
Copy link
Contributor

cmb69 commented May 10, 2021

@BenMorel, please raise this as general issue on the internals ML – we really need a general solution (do it like it has done before; driver specific subclasses; helper classes; whatever).

@krakjoe
Copy link
Member

krakjoe commented May 10, 2021

My apologies, at a glance, it looks like 5765 is related and more recent, but I see it's not really going anywhere either ...

@cmb69
Copy link
Contributor

cmb69 commented May 11, 2021

Oh, indeed, PR #5765 tries to adress this isseu in a general way. Driver objects might be the way to go to reduce BC issues.

@pbowyer
Copy link

pbowyer commented Jul 7, 2021

@krakjoe I'd like #5765 to address this issue but concluded my C/PHP internals skills are not up to the task.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet