mirror of
https://github.com/typecho/typecho.git
synced 2025-04-21 02:01:52 +02:00
fix pingback's security issue
ref: https://joychou.org/web/typecho-ssrf-analysis-and-exploit.html
This commit is contained in:
parent
0e7b399ba8
commit
eeedef972a
@ -22,7 +22,7 @@ define('__TYPECHO_MB_SUPPORTED__', function_exists('mb_get_info') && function_ex
|
||||
class Typecho_Common
|
||||
{
|
||||
/** 程序版本 */
|
||||
const VERSION = '1.1/17.8.17';
|
||||
const VERSION = '1.1/17.10.13';
|
||||
|
||||
/**
|
||||
* 允许的属性
|
||||
@ -1105,6 +1105,67 @@ EOF;
|
||||
return array($type, $header, $body);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否是一个安全的主机名
|
||||
*
|
||||
* @param $host
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkSafeHost($host)
|
||||
{
|
||||
if ('localhost' == $host) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$address = gethostbyname($host);
|
||||
$inet = inet_pton($address);
|
||||
|
||||
if ($inet === false) {
|
||||
// 有可能是ipv6的地址
|
||||
$records = dns_get_record($host, DNS_AAAA);
|
||||
|
||||
if (empty($records)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$address = $records[0]['ipv6'];
|
||||
$inet = inet_pton($address);
|
||||
}
|
||||
|
||||
if (strpos($address, '.')) {
|
||||
// ipv4
|
||||
// 非公网地址
|
||||
$privateNetworks = array(
|
||||
'10.0.0.0|10.255.255.255',
|
||||
'172.16.0.0|172.31.255.255',
|
||||
'192.168.0.0|192.168.255.255',
|
||||
'169.254.0.0|169.254.255.255',
|
||||
'127.0.0.0|127.255.255.255'
|
||||
);
|
||||
|
||||
$long = ip2long($address);
|
||||
|
||||
foreach ($privateNetworks as $network) {
|
||||
list ($from, $to) = explode('|', $network);
|
||||
|
||||
if ($long >= ip2long($from) && $long <= ip2long($to)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// ipv6
|
||||
// https://en.wikipedia.org/wiki/Private_network
|
||||
$from = inet_pton('fd00::');
|
||||
$to = inet_pton('fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff');
|
||||
|
||||
if ($inet >= $from && $inet <= $to) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图片
|
||||
*
|
||||
|
@ -294,8 +294,8 @@ abstract class Typecho_Http_Client_Adapter
|
||||
*
|
||||
* @access public
|
||||
* @param string $url 请求地址
|
||||
* @param string $rfc 请求协议
|
||||
* @return string
|
||||
* @throws Typecho_Http_Client_Exception
|
||||
*/
|
||||
public function send($url)
|
||||
{
|
||||
@ -307,6 +307,10 @@ abstract class Typecho_Http_Client_Adapter
|
||||
throw new Typecho_Http_Client_Exception('Unknown Host', 500);
|
||||
}
|
||||
|
||||
if (!in_array($params['scheme'], array('http', 'https'))) {
|
||||
throw new Typecho_Http_Client_Exception('Unknown Scheme', 500);
|
||||
}
|
||||
|
||||
if (!empty($params['path'])) {
|
||||
$this->path = $params['path'];
|
||||
}
|
||||
|
@ -140,7 +140,6 @@ class Widget_Service extends Widget_Abstract_Options implements Widget_Interface
|
||||
->setHeader('User-Agent', $this->options->generator)
|
||||
->setTimeout(3)
|
||||
->setData($input)
|
||||
->setIp('127.0.0.1')
|
||||
->send(Typecho_Common::url('/action/service', $this->options->index));
|
||||
|
||||
} catch (Typecho_Http_Client_Exception $e) {
|
||||
|
@ -2057,6 +2057,16 @@ class Widget_XmlRpc extends Widget_Abstract_Contents implements Widget_Interface
|
||||
$pathInfo = Typecho_Common::url(substr($target, strlen($this->options->index)), '/');
|
||||
$post = Typecho_Router::match($pathInfo);
|
||||
|
||||
/** 检查源地址是否合法 */
|
||||
$params = parse_url($source);
|
||||
if (false === $params || !in_array($params['scheme'], array('http', 'https'))) {
|
||||
return new IXR_Error(16, _t('源地址服务器错误'));
|
||||
}
|
||||
|
||||
if (!Typecho_Common::checkSafeHost($params['host'])) {
|
||||
return new IXR_Error(16, _t('源地址服务器错误'));
|
||||
}
|
||||
|
||||
/** 这样可以得到cid或者slug*/
|
||||
if (!($post instanceof Widget_Archive) || !$post->have() || !$post->is('single')) {
|
||||
return new IXR_Error(33, _t('这个目标地址不存在'));
|
||||
|
Loading…
x
Reference in New Issue
Block a user