Skip to content

Sqlite ATTACH is crashing php when the filename is bind /w open_basedir set #9032

Closed

Description

@mvorisek

Description

The following code:

<?php

$db = new \PDO("sqlite::memory:");
$db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

$db->exec('attach database \':memory:\' AS "db1"');
var_dump($db->exec('create table db1.r (id int)'));

$st = $db->prepare('attach database :a AS "db2"');
$st->execute([':a' => ':memory:']);
var_dump($db->exec('create table db2.r (id int)'));

demo: https://3v4l.org/Su8lK

Resulted in this output:

int(0)

Process exited with code 139.

But I expected this output instead:

int(0)
int(0)

PHP Version

any

Operating System

any

Activity

  1. devnexen commented on Jul 17, 2022

    @devnexen
    Member

    Process exited with code 139.

    Can you reproduce the issue outside of docker ? Tested with proper releases and manually master build and having expected outputs.

  2. mvorisek commented on Jul 17, 2022

    @mvorisek
    ContributorAuthor

    PHP crashed also when reproduced in GH Actions CI.

    I tested now also on my local/not virtualized Windows machine - PHP crashed too, only the first int(0) was displayed.

  3. cmb69 commented on Jul 17, 2022

    @cmb69
    Member

    That might be an issue with SQLite3 itself. Which version do you use, see https://3v4l.org/PrC72.

  4. mvorisek commented on Jul 17, 2022

    @mvorisek
    ContributorAuthor

    On my Windows machine I use 3.31.1. @devnexen when you tested it, did you see 1 or 2 int(0)?

  5. devnexen commented on Jul 17, 2022

    @devnexen
    Member

    2 always, tried with baremetal Linux machines; old CentOs 7 and Alpine virtualized. Also tried at last a manually build with sanitizers in case.

  6. mvorisek commented on Jul 17, 2022

    @mvorisek
    ContributorAuthor

    @devnexen with what Sqlite versions?

    https://3v4l.org/NZnPl /w EOL PHP versions shows it is broken since PHP 5.5

    interestingly, Sqlite v3.7.7.1 /w PHP 5.5.x is broken, but Sqlite v3.8.10.2 /w PHP 5.4.x is fine. It seems at least something in php-src has impact on this issue.

    I also tested PDOStatement::bindParam. Same issue as with PDOStatement::bindValue.

  7. mvorisek commented on Jul 17, 2022

    @mvorisek
    ContributorAuthor

    I looked into the php-src code - https://github.com/search?q=SQLITE_ATTACHrepo%3Aphp%2Fphp-src&type=Code&ref=advsearch

    for SQLITE_ATTACH the code does some security checks. And I think that is the issue. I have open_basedir configured for all the tested platforms. Can it be related?

    https://3v4l.org/TLlCo - the answer seems yes!

  8. changed the title [-]`ATTACH :a AS xx` is crashing php (Sqlite/PDOStatement::bindValue)[/-] [+]Sqlite `ATTACH` is crashing php when the filename is bind /w `open_basedir` set[/+] on Jul 17, 2022
  9. devnexen commented on Jul 17, 2022

    @devnexen
    Member

    Ah was going to ask if you had any particular context, I even ventured into docker official images and still did not get any issue, and locally my sqlite versions ran from 3.7.17 to 3.38.5.

  10. cmb69 commented on Jul 17, 2022

    @cmb69
    Member

    Yeah, the problem is that NULL is passed to make_filename_safe() for which it is not prepared. Quick-fix:

     ext/pdo_sqlite/sqlite_driver.c | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c
    index bdad23a581..9ce10a431b 100644
    --- a/ext/pdo_sqlite/sqlite_driver.c
    +++ b/ext/pdo_sqlite/sqlite_driver.c
    @@ -775,6 +775,7 @@ static int authorizer(void *autharg, int access_type, const char *arg3, const ch
     		}
     
     		case SQLITE_ATTACH: {
    +			if (!arg3) return SQLITE_DENY;
     					filename = make_filename_safe(arg3);
     			if (!filename) {
     				return SQLITE_DENY;

    This needs more careful investigation, though. It might be possible to not necessarily deny authorization, and the SQLITE_COPY case should be investigated as well.

  11. devnexen commented on Jul 17, 2022

    @devnexen
    Member

    If we want to deny in copy too might be simpler to return NULL in this make_filename_safe helper then ? But indeed might need further look.

  12. self-assigned this
    on Jul 18, 2022
  13. added a commit that references this issue on Jul 18, 2022
    be609a8
  14. added 2 commits that reference this issue on Jul 27, 2022
    8ed21a8
    ca84d06
  15. added a commit that references this issue on Jul 27, 2022
    a398a2f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions