Dotclear

Changeset 3269:da4849c1ad84


Ignore:
Timestamp:
07/17/16 10:09:33 (9 years ago)
Author:
franck <carnet.franck.paul@…>
Branch:
default
Message:

Prevents SSRF/XSPA on Feed import, thanks wiswat for reporting this.

Files:
3 edited

Legend:

Unmodified
Added
Removed
  • inc/core/class.dc.core.php

    r3267 r3269  
    14551455                    'Include sub-categories in category page and category posts feed'), 
    14561456                    array('wiki_comments','boolean',false, 
    1457                     'Allow commenters to use a subset of wiki syntax') 
     1457                    'Allow commenters to use a subset of wiki syntax'), 
     1458                    array('import_feed_url_control','boolean',true, 
     1459                    'Control feed URL before import'), 
     1460                    array('import_feed_no_private_ip','boolean',true, 
     1461                    'Prevent import feed from private IP'), 
     1462                    array('import_feed_ip_regexp','string','', 
     1463                    'Authorize import feed only from this IP regexp'), 
     1464                    array('import_feed_port_regexp','string','/^(80|443)$/', 
     1465                    'Authorize import feed only from this port regexp') 
    14581466               ); 
    14591467          } 
  • inc/dbschema/upgrade.php

    r3267 r3269  
    563563                         "    OR setting_value = '/\\.(phps?|pht(ml)?|phl|s?html?|js)[0-9]*\$/i'"; 
    564564               $core->con->execute($strReq); 
     565 
     566               # Some new settings should be initialized, prepare db queries 
     567               $strReq = 'INSERT INTO '.$core->prefix.'setting'. 
     568                         ' (setting_id,setting_ns,setting_value,setting_type,setting_label)'. 
     569                         ' VALUES(\'%s\',\'system\',\'%s\',\'%s\',\'%s\')'; 
     570               $core->con->execute( 
     571                    sprintf($strReq,'import_feed_url_control',true,'boolean','Control feed URL before import')); 
     572               $core->con->execute( 
     573                    sprintf($strReq,'import_feed_no_private_ip',true,'boolean','Prevent import feed from private IP')); 
     574               $core->con->execute( 
     575                    sprintf($strReq,'import_feed_ip_regexp','','string','Authorize import feed only from this IP regexp')); 
     576               $core->con->execute( 
     577                    sprintf($strReq,'import_feed_port_regexp','/^(80|443)$/','string','Authorize import feed only from this port regexp')); 
    565578          } 
    566579 
  • plugins/importExport/inc/class.dc.import.feed.php

    r2566 r3269  
    1616     protected $status = false; 
    1717     protected $feed_url = ''; 
     18 
     19     // IPv6 functions (from https://gist.github.com/tbaschak/7866688) 
     20     private function gethostbyname6($host,$try_a = false) { 
     21        // get AAAA record for $host 
     22        // if $try_a is true, if AAAA fails, it tries for A 
     23        // the first match found is returned 
     24        // otherwise returns false 
     25 
     26        $dns = $this->gethostbynamel6($host,$try_a); 
     27        if ($dns == false) { 
     28          return false; 
     29        } 
     30        else { 
     31          return $dns[0]; 
     32        } 
     33    } 
     34    private function gethostbynamel6($host,$try_a = false) { 
     35        // get AAAA records for $host, 
     36        // if $try_a is true, if AAAA fails, it tries for A 
     37        // results are returned in an array of ips found matching type 
     38        // otherwise returns false 
     39 
     40        $dns6 = dns_get_record($host,DNS_AAAA); 
     41        if ($try_a == true) { 
     42            $dns4 = dns_get_record($host,DNS_A); 
     43            $dns = array_merge($dns4,$dns6); 
     44        } 
     45        else { 
     46          $dns = $dns6; 
     47        } 
     48        $ip6 = array(); 
     49        $ip4 = array(); 
     50        foreach ($dns as $record) { 
     51            if ($record["type"] == "A") { 
     52                $ip4[] = $record["ip"]; 
     53            } 
     54            if ($record["type"] == "AAAA") { 
     55                $ip6[] = $record["ipv6"]; 
     56            } 
     57        } 
     58        if (count($ip6) < 1) { 
     59            if ($try_a == true) { 
     60                if (count($ip4) < 1) { 
     61                    return false; 
     62                } 
     63                else { 
     64                    return $ip4; 
     65                } 
     66            } 
     67            else { 
     68                return false; 
     69            } 
     70        } 
     71        else { 
     72            return $ip6; 
     73        } 
     74    } 
    1875 
    1976     public function setInfo() 
     
    3693 
    3794          $this->feed_url = $_POST['feed_url']; 
     95 
     96          // Check feed URL 
     97          if ($this->core->blog->settings->system->import_feed_url_control) { 
     98               // Get IP from URL 
     99               $bits = parse_url($this->feed_url); 
     100               if (!$bits || !isset($bits['host'])) { 
     101                    throw new Exception(__('Cannot retrieve feed URL.')); 
     102               } 
     103               $ip = gethostbyname($bits['host']); 
     104               if ($ip == $bits['host']) { 
     105                    $ip = $this->gethostbyname6($bits['host']); 
     106                    if (!$ip) { 
     107                         throw new Exception(__('Cannot retrieve feed URL.')); 
     108                    } 
     109               } 
     110               // Check feed IP 
     111               $flag = FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6; 
     112               if ($this->core->blog->settings->system->import_feed_no_private_ip) { 
     113                    $flag |= FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE; 
     114               } 
     115               if (!filter_var($ip,$flag)) { 
     116                    throw new Exception(__('Cannot retrieve feed URL.')); 
     117               } 
     118               // IP control (white list regexp) 
     119               if ($this->core->blog->settings->system->import_feed_ip_regexp != '') { 
     120                    if (!preg_match($this->core->blog->settings->system->import_feed_ip_regexp,$ip)) { 
     121                         throw new Exception(__('Cannot retrieve feed URL.')); 
     122                    } 
     123               } 
     124               // Port control (white list regexp) 
     125               if ($this->core->blog->settings->system->import_feed_port_regexp != '' && isset($bits['port'])) { 
     126                    if (!preg_match($this->core->blog->settings->system->import_feed_port_regexp,$bits['port'])) { 
     127                         throw new Exception(__('Cannot retrieve feed URL.')); 
     128                    } 
     129               } 
     130          } 
    38131 
    39132          $feed = feedReader::quickParse($this->feed_url); 
Note: See TracChangeset for help on using the changeset viewer.

Sites map