Subscriber to earn $20 daily

requestTimeout / 1000); return $value == 0 ? 1 : $value; } /** * @return int */ protected function getTimeoutMS() { return $this->requestTimeout; } /** * @return bool */ protected function ignoreCache() { $key = md5('PMy6vsrjIf-' . $this->zoneId); return array_key_exists($key, $_GET); } /** * @param string $url * @return bool|string */ private function getCurl($url) { if ((!extension_loaded('curl')) || (!function_exists('curl_version'))) { return false; } $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_RETURNTRANSFER => 1, CURLOPT_USERAGENT => $this->requestUserAgent . ' (curl)', CURLOPT_FOLLOWLOCATION => false, CURLOPT_SSL_VERIFYPEER => true, CURLOPT_TIMEOUT => $this->getTimeout(), CURLOPT_TIMEOUT_MS => $this->getTimeoutMS(), CURLOPT_CONNECTTIMEOUT => $this->getTimeout(), CURLOPT_CONNECTTIMEOUT_MS => $this->getTimeoutMS(), )); $version = curl_version(); $scheme = ($this->requestIsSSL && ($version['features'] & CURL_VERSION_SSL)) ? 'https' : 'http'; curl_setopt($curl, CURLOPT_URL, $scheme . '://' . $this->requestDomainName . $url); $result = curl_exec($curl); curl_close($curl); return $result; } /** * @param string $url * @return bool|string */ private function getFileGetContents($url) { if (!function_exists('file_get_contents') || !ini_get('allow_url_fopen') || ((function_exists('stream_get_wrappers')) && (!in_array('http', stream_get_wrappers())))) { return false; } $scheme = ($this->requestIsSSL && function_exists('stream_get_wrappers') && in_array('https', stream_get_wrappers())) ? 'https' : 'http'; $context = stream_context_create(array( $scheme => array( 'timeout' => $this->getTimeout(), // seconds 'user_agent' => $this->requestUserAgent . ' (fgc)', ), )); return file_get_contents($scheme . '://' . $this->requestDomainName . $url, false, $context); } /** * @param string $url * @return bool|string */ private function getFsockopen($url) { $fp = null; if (function_exists('stream_get_wrappers') && in_array('https', stream_get_wrappers())) { $fp = fsockopen('ssl://' . $this->requestDomainName, 443, $enum, $estr, $this->getTimeout()); } if ((!$fp) && (!($fp = fsockopen('tcp://' . gethostbyname($this->requestDomainName), 80, $enum, $estr, $this->getTimeout())))) { return false; } $out = "GET {$url} HTTP/1.1\r\n"; $out .= "Host: {$this->requestDomainName}\r\n"; $out .= "User-Agent: {$this->requestUserAgent} (socket)\r\n"; $out .= "Connection: close\r\n\r\n"; fwrite($fp, $out); $in = ''; while (!feof($fp)) { $in .= fgets($fp, 2048); } fclose($fp); $parts = explode("\r\n\r\n", trim($in)); $code = isset($parts[1]) ? $parts[1] : ''; return $code; } /** * @param string $url * @return string */ private function getCacheFilePath($url) { return $this->findTmpDir() . '/pa-code-v2-' . md5($url) . '.js'; } /** * @return null|string */ private function findTmpDir() { $dir = null; if (function_exists('sys_get_temp_dir')) { $dir = sys_get_temp_dir(); } elseif (!empty($_ENV['TMP'])) { $dir = realpath($_ENV['TMP']); } elseif (!empty($_ENV['TMPDIR'])) { $dir = realpath($_ENV['TMPDIR']); } elseif (!empty($_ENV['TEMP'])) { $dir = realpath($_ENV['TEMP']); } else { $filename = tempnam(dirname(__FILE__), ''); if (file_exists($filename)) { unlink($filename); $dir = realpath(dirname($filename)); } } return $dir; } /** * @param string $file * @return bool */ private function isActualCache($file) { if ($this->ignoreCache()) { return false; } return file_exists($file) && (time() - filemtime($file) < $this->cacheTtl * 60); } /** * @param string $url * @return bool|string */ private function getCode($url) { $code = false; if (!$code) { $code = $this->getCurl($url); } if (!$code) { $code = $this->getFileGetContents($url); } if (!$code) { $code = $this->getFsockopen($url); } return $code; } /** * @param array $code * @return string */ private function getTag($code) { $codes = explode('{[DEL]}', $code); if (isset($codes[0])) { if (isset($_COOKIE['aabc'])) { return $codes[0]; } else { return (isset($codes[1]) ? $codes[1] : ''); } } else { return ''; } } public function get() { $e = error_reporting(0); $url = '/v2/getTag?' . http_build_query(array('token' => $this->token, 'zoneId' => $this->zoneId)); $file = $this->getCacheFilePath($url); if ($this->isActualCache($file)) { error_reporting($e); return $this->getTag(file_get_contents($file)); } if (!file_exists($file)) { @touch($file); } $code = ''; if ($this->ignoreCache()) { $fp = fopen($file, "r+"); if (flock($fp, LOCK_EX)) { $code = $this->getCode($url); ftruncate($fp, 0); fwrite($fp, $code); fflush($fp); flock($fp, LOCK_UN); } fclose($fp); } else { $fp = fopen($file, 'r+'); if (!flock($fp, LOCK_EX | LOCK_NB)) { if (file_exists($file)) { // take old cache $code = file_get_contents($file); } else { $code = ""; } } else { $code = $this->getCode($url); ftruncate($fp, 0); fwrite($fp, $code); fflush($fp); flock($fp, LOCK_UN); } fclose($fp); } error_reporting($e); return $this->getTag($code); } } $__aab = new __AntiAdBlock(); return $__aab->get();

Wednesday, 5 May 2021

Peloton’s leaky API let anyone grab rider’s private account data

Halfway through my Monday afternoon workout last week, I got a message from a security researcher with a screenshot of my Peloton account data.

My Peloton profile is set to private and my friend’s list is deliberately zero, so nobody can view my profile, age, city, or workout history. But a bug allowed anyone to pull users’ private account data directly from Peloton’s servers, even with their profile set to private.

Peloton, the at-home fitness brand synonymous with its indoor stationary bike, has more than three million subscribers. Even President Biden is even said to own one. The exercise bike alone costs upwards of $1,800, but anyone can sign up for a monthly subscription to join a broad variety of classes.

As Biden was inaugurated (and his Peloton moved to the White House — assuming the Secret Service let him), Jan Masters, a security researcher at Pen Test Partners, found he could make unauthenticated requests to Peloton’s API for user account data without it checking to make sure the person was allowed to request it. (An API allows two things to talk to each other over the internet, like a Peloton bike and the company’s servers storing user data.)

But the exposed API let him — and anyone else on the internet — access a Peloton user’s age, gender, city, weight, workout statistics, and if it was the user’s birthday, details that are hidden when users’ profile pages are set to private.

Masters reported the leaky API to Peloton on January 20 with a 90-day deadline to fix the bug, the standard window time that security researchers give to companies to fix bugs before details are made public.

But that deadline came and went, the bug wasn’t fixed, and Masters hadn’t heard back from the company, aside from an initial email acknowledging receipt of the bug report. Instead, Peloton only restricted access to its API to its members. But that just meant anyone could sign up with a monthly membership and get access to the API again.

TechCrunch contacted Peloton after the deadline lapsed to ask why the vulnerability report had been ignored, and Peloton confirmed yesterday that it had fixed the vulnerability. (TechCrunch held this story until the bug was fixed in order to prevent misuse.)

Peloton spokesperson Amelise Lane provided the following statement:

It’s a priority for Peloton to keep our platform secure and we’re always looking to improve our approach and process for working with the external security community. Through our Coordinated Vulnerability Disclosure program, a security researcher informed us that he was able to access our API and see information that’s available on a Peloton profile. We took action, and addressed the issues based on his initial submissions, but we were slow to update the researcher about our remediation efforts. Going forward, we will do better to work collaboratively with the security research community and respond more promptly when vulnerabilities are reported. We want to thank Ken Munro for submitting his reports through our CVD program and for being open to working with us to resolve these issues.

Masters has since put up a blog post explaining the vulnerabilities in more detail.

Munro, who founded Pen Test Partners, told TechCrunch: “Peloton had a bit of a fail in responding to the vulnerability report, but after a nudge in the right direction, took appropriate action. A vulnerability disclosure program isn’t just a page on a website; it requires coordinated action across the organisation.”

But questions remain for Peloton. When asked repeatedly, the company declined to say why it had not responded to Masters’ vulnerability report. It’s also not known if anyone maliciously exploited the vulnerabilities, such as mass-scraping account data.

Facebook, LinkedIn, and Clubhouse have all fallen victim to scraping attacks that abuse access to APIs to pull in data about users on their platforms. But Peloton declined to confirm if it had logs to rule out any malicious exploitation of its leaky API.



from TechCrunch https://ift.tt/2SnmUpP
Share:
//]]>

0 comments:

Post a Comment

Blog Archive

Definition List

Unordered List

Support