Browse Source

DHT/twisterd interaction security fix

main
ghost 3 years ago
parent
commit
c130741678
  1. 2
      src/application/controller/api/follow/add.php
  2. 2
      src/application/controller/api/follow/total.php
  3. 3
      src/application/controller/api/post/add.php
  4. 30
      src/application/controller/api/post/get.php
  5. 12
      src/application/controller/api/user/avatar.php
  6. 36
      src/application/controller/api/user/profile.php
  7. 8
      src/application/controller/register.php
  8. 57
      src/application/controller/settings/profile.php
  9. 19
      src/system/helper/filter.php
  10. 5
      tool/crawler/blockchain.php

2
src/application/controller/api/follow/add.php

@ -7,7 +7,7 @@ $response = [
if (isset($_SESSION['userName']) && isset($_POST['userName'])) { if (isset($_SESSION['userName']) && isset($_POST['userName'])) {
$result = $_twister->follow($_SESSION['userName'], [$_POST['userName']]); $result = $_twister->follow($_SESSION['userName'], [Filter::userName($_POST['userName'])]);
$response = [ $response = [
'success' => true, 'success' => true,

2
src/application/controller/api/follow/total.php

@ -8,7 +8,7 @@ $response = [
if (isset($_SESSION['userName'])) { if (isset($_SESSION['userName'])) {
$userName = isset($_POST['userName']) ? $_POST['userName'] : $_SESSION['userName']; $userName = isset($_POST['userName']) ? Filter::userName($_POST['userName']) : $_SESSION['userName'];
$followingUsersTotal = 0; $followingUsersTotal = 0;

3
src/application/controller/api/post/add.php

@ -21,7 +21,8 @@ if (isset($_SESSION['userName'])) {
'message' => _('Could not receive user post') 'message' => _('Could not receive user post')
]; ];
} else if (isset($userPosts[0]['userpost']['k']) && $result = $_twister->newPostMessage($_SESSION['userName'], $userPosts[0]['userpost']['k'] + 1, $_POST['message'])) { } else if (isset($userPosts[0]['userpost']['k']) &&
$result = $_twister->newPostMessage($_SESSION['userName'], Filter::int($userPosts[0]['userpost']['k']) + 1, $_POST['message'])) {
$response = [ $response = [
'success' => true, 'success' => true,

30
src/application/controller/api/post/get.php

@ -8,7 +8,19 @@ $response = [
if (isset($_SESSION['userName'])) { if (isset($_SESSION['userName'])) {
$userNames = isset($_GET['userName']) && $_GET['userName'] ? [Filter::userName($_GET['userName'])] : $_twister->getFollowing($_SESSION['userName']); $userNames = [];
if (isset($_GET['userName']) && !empty($_GET['userName'])) {
$userNames[] = Filter::userName($_GET['userName']);
} else {
foreach ((array) $_twister->getFollowing($_SESSION['userName']) as $followingUserName) {
$userNames[] = Filter::userName($followingUserName);
}
}
if ($result = $_twister->getPosts($userNames, APPLICATION_MAX_POST_FEED)) { if ($result = $_twister->getPosts($userNames, APPLICATION_MAX_POST_FEED)) {
@ -16,14 +28,14 @@ if (isset($_SESSION['userName'])) {
foreach ($result as $post) { foreach ($result as $post) {
// Split message parts // Split message parts
$messages = [$post['userpost']['msg']]; $messages = [Filter::string($post['userpost']['msg'])];
for ($i = 0; $i <= APPLICATION_MAX_POST_SPLIT; $i++) { for ($i = 0; $i <= APPLICATION_MAX_POST_SPLIT; $i++) {
$n = sprintf('msg%s', $i); $n = sprintf('msg%s', $i);
if (isset($post['userpost'][$n])) { if (isset($post['userpost'][$n])) {
$messages[] = $post['userpost'][$n]; $messages[] = Filter::string($post['userpost'][$n]);
} }
} }
@ -32,29 +44,29 @@ if (isset($_SESSION['userName'])) {
if (isset($post['userpost']['rt'])) { if (isset($post['userpost']['rt'])) {
// Split reTwists parts // Split reTwists parts
$reTwists = [$post['userpost']['rt']['msg']]; $reTwists = [Filter::string($post['userpost']['rt']['msg'])];
for ($i = 0; $i <= APPLICATION_MAX_POST_SPLIT; $i++) { for ($i = 0; $i <= APPLICATION_MAX_POST_SPLIT; $i++) {
$n = sprintf('msg%s', $i); $n = sprintf('msg%s', $i);
if (isset($post['userpost']['rt'][$n])) { if (isset($post['userpost']['rt'][$n])) {
$reTwists[] = $post['userpost']['rt'][$n]; $reTwists[] = Filter::string($post['userpost']['rt'][$n]);
} }
} }
$reTwist = [ $reTwist = [
'message' => Format::post(implode('', $reTwists)), 'message' => Format::post(implode('', $reTwists)),
'time' => Format::time($post['userpost']['rt']['time']), 'time' => Format::time(Filter::int($post['userpost']['rt']['time'])),
'userName' => $post['userpost']['rt']['n'], 'userName' => Filter::userName($post['userpost']['rt']['n']),
'reTwist' => $reTwist, 'reTwist' => $reTwist,
]; ];
} }
$posts[] = [ $posts[] = [
'message' => Format::post(implode('', $messages)), 'message' => Format::post(implode('', $messages)),
'time' => Format::time($post['userpost']['time']), 'time' => Format::time(Filter::int($post['userpost']['time'])),
'userName' => $post['userpost']['n'], 'userName' => Filter::userName($post['userpost']['n']),
'reTwist' => $reTwist, 'reTwist' => $reTwist,
]; ];
} }

12
src/application/controller/api/user/avatar.php

@ -27,14 +27,14 @@ if (isset($_SESSION['userName'])) {
foreach ($avatarVersions as $avatarVersion) { foreach ($avatarVersions as $avatarVersion) {
if (!$_modelAvatar->versionExists($userId, if (!$_modelAvatar->versionExists($userId,
$avatarVersion['p']['height'], Filter::int($avatarVersion['p']['height']),
$avatarVersion['p']['seq'])) { Filter::int($avatarVersion['p']['seq']))) {
$_modelAvatar->add( $userId, $_modelAvatar->add( $userId,
$avatarVersion['p']['height'], Filter::int($avatarVersion['p']['height']),
$avatarVersion['p']['seq'], Filter::int($avatarVersion['p']['seq']),
$avatarVersion['p']['time'], Filter::int($avatarVersion['p']['time']),
$avatarVersion['p']['v']); Filter::string($avatarVersion['p']['v']));
} }
} }
} }

36
src/application/controller/api/user/profile.php

@ -27,22 +27,22 @@ if (isset($_SESSION['userName'])) {
foreach ($userProfileVersions as $userProfileVersion) { foreach ($userProfileVersions as $userProfileVersion) {
if (!$_modelProfile->versionExists($userId, if (!$_modelProfile->versionExists($userId,
$userProfileVersion['p']['height'], Filter::int($userProfileVersion['p']['height']),
$userProfileVersion['p']['seq'])) { Filter::int($userProfileVersion['p']['seq']))) {
$profile = $userProfileVersion['p']['v']; $profile = $userProfileVersion['p']['v'];
$_modelProfile->add($userId, $_modelProfile->add($userId,
$userProfileVersion['p']['height'], Filter::int($userProfileVersion['p']['height']),
$userProfileVersion['p']['seq'], Filter::int($userProfileVersion['p']['seq']),
$userProfileVersion['p']['time'], Filter::int($userProfileVersion['p']['time']),
isset($profile['fullname']) ? $profile['fullname'] : '', isset($profile['fullname']) ? Filter::string($profile['fullname']) : '',
isset($profile['bio']) ? $profile['bio'] : '', isset($profile['bio']) ? Filter::string($profile['bio']) : '',
isset($profile['location']) ? $profile['location'] : '', isset($profile['location']) ? Filter::string($profile['location']) : '',
isset($profile['url']) ? $profile['url'] : '', isset($profile['url']) ? Filter::string($profile['url']) : '',
isset($profile['bitmessage']) ? $profile['bitmessage'] : '', isset($profile['bitmessage']) ? Filter::string($profile['bitmessage']) : '',
isset($profile['tox']) ? $profile['tox'] : ''); isset($profile['tox']) ? Filter::string($profile['tox']) : '');
} }
} }
} }
@ -52,12 +52,12 @@ if (isset($_SESSION['userName'])) {
$profile = [ $profile = [
'userName' => $userName, 'userName' => $userName,
'fullName' => $profileInfo['fullName'], 'fullName' => Filter::string($profileInfo['fullName']),
'location' => $profileInfo['location'], 'location' => Filter::string($profileInfo['location']),
'url' => $profileInfo['url'], 'url' => Filter::string($profileInfo['url']),
'bitMessage' => $profileInfo['bitMessage'], 'bitMessage' => Filter::string($profileInfo['bitMessage']),
'tox' => $profileInfo['tox'], 'tox' => Filter::string($profileInfo['tox']),
'bio' => nl2br($profileInfo['bio']), 'bio' => nl2br(Filter::string($profileInfo['bio'])),
]; ];
$response = [ $response = [

8
src/application/controller/register.php

@ -83,15 +83,7 @@ if (isset($_POST) && $_POST) {
require(PROJECT_DIR . '/application/view/welcome.phtml'); require(PROJECT_DIR . '/application/view/welcome.phtml');
exit; exit;
} else {
trigger_error($_twister->getError());
} }
} else {
trigger_error($_twister->getError());
} }
} }
} }

57
src/application/controller/settings/profile.php

@ -41,12 +41,12 @@ $errorBio = false;
if (isset($_POST) && !empty($_POST)) { if (isset($_POST) && !empty($_POST)) {
// Prepare request // Prepare request
$fullName = isset($_POST['fullName']) ? $_POST['fullName'] : ''; $fullName = isset($_POST['fullName']) ? Filter::string($_POST['fullName']) : '';
$location = isset($_POST['location']) ? $_POST['location'] : ''; $location = isset($_POST['location']) ? Filter::string($_POST['location']) : '';
$url = isset($_POST['url']) ? $_POST['url'] : ''; $url = isset($_POST['url']) ? Filter::string($_POST['url']) : '';
$bitMessage = isset($_POST['bitMessage']) ? $_POST['bitMessage'] : ''; $bitMessage = isset($_POST['bitMessage']) ? Filter::string($_POST['bitMessage']) : '';
$tox = isset($_POST['tox']) ? $_POST['tox'] : ''; $tox = isset($_POST['tox']) ? Filter::string($_POST['tox']) : '';
$bio = isset($_POST['bio']) ? $_POST['bio'] : ''; $bio = isset($_POST['bio']) ? Filter::string($_POST['bio']) : '';
// Get current block number // Get current block number
$blockId = $_modelBlock->getThisBlock(); $blockId = $_modelBlock->getThisBlock();
@ -94,7 +94,7 @@ if (isset($_POST) && !empty($_POST)) {
} }
// Update avatar cache // Update avatar cache
$_memcache->set('api.user.avatar.' . $_SESSION['userName'], $avatar, MEMCACHE_COMPRESS, MEMCACHE_DHT_AVATAR_TIMEOUT); $_memcache->replace('api.user.avatar.' . $_SESSION['userName'], $avatar, MEMCACHE_COMPRESS, MEMCACHE_DHT_AVATAR_TIMEOUT);
} }
// Get profile revision // Get profile revision
@ -164,14 +164,14 @@ if ($userAvatar = $_memcache->get('api.user.avatar.' . $_SESSION['userName'])) {
foreach ($avatarVersions as $avatarVersion) { foreach ($avatarVersions as $avatarVersion) {
if (!$_modelAvatar->versionExists($_SESSION['userId'], if (!$_modelAvatar->versionExists($_SESSION['userId'],
$avatarVersion['p']['height'], Filter::int($avatarVersion['p']['height']),
$avatarVersion['p']['seq'])) { Filter::int($avatarVersion['p']['seq']))) {
$_modelAvatar->add( $_SESSION['userId'], $_modelAvatar->add( $_SESSION['userId'],
$avatarVersion['p']['height'], Filter::int($avatarVersion['p']['height']),
$avatarVersion['p']['seq'], Filter::int($avatarVersion['p']['seq']),
$avatarVersion['p']['time'], Filter::int($avatarVersion['p']['time']),
$avatarVersion['p']['v']); Filter::string($avatarVersion['p']['v']));
} }
} }
@ -200,7 +200,7 @@ if ($userAvatar = $_memcache->get('api.user.avatar.' . $_SESSION['userName'])) {
$avatar = sprintf('data:image/jpeg;base64,%s', base64_encode(file_get_contents($filePath))); $avatar = sprintf('data:image/jpeg;base64,%s', base64_encode(file_get_contents($filePath)));
} }
// Get profile details // Get profile details from cache
if ($profile = $_memcache->get('api.user.profile.' . $_SESSION['userName'])) { if ($profile = $_memcache->get('api.user.profile.' . $_SESSION['userName'])) {
$fullName = $profile['fullName']; $fullName = $profile['fullName'];
@ -210,28 +210,32 @@ if ($profile = $_memcache->get('api.user.profile.' . $_SESSION['userName'])) {
$tox = $profile['tox']; $tox = $profile['tox'];
$bio = $profile['bio']; $bio = $profile['bio'];
// Get profile details from DHT
} else if ($userProfileVersions = $_twister->getDHT($_SESSION['userName'], 'profile', 's')) { } else if ($userProfileVersions = $_twister->getDHT($_SESSION['userName'], 'profile', 's')) {
// Add DHT version if not exists // Add DHT version if not exists
foreach ($userProfileVersions as $userProfileVersion) { foreach ($userProfileVersions as $userProfileVersion) {
if (!$_modelProfile->versionExists($_SESSION['userId'], if (!$_modelProfile->versionExists($_SESSION['userId'],
$userProfileVersion['p']['height'], Filter::int($userProfileVersion['p']['height']),
$userProfileVersion['p']['seq'])) { Filter::int($userProfileVersion['p']['seq']))) {
if (isset($userProfileVersion['p']['v'])) {
$profile = $userProfileVersion['p']['v']; $profile = $userProfileVersion['p']['v'];
$_modelProfile->add($_SESSION['userId'], $_modelProfile->add($_SESSION['userId'],
$userProfileVersion['p']['height'], Filter::int($userProfileVersion['p']['height']),
$userProfileVersion['p']['seq'], Filter::int($userProfileVersion['p']['seq']),
$userProfileVersion['p']['time'], Filter::int($userProfileVersion['p']['time']),
isset($profile['fullname']) ? $profile['fullname'] : '', isset($profile['fullname']) ? Filter::string($profile['fullname']) : '',
isset($profile['bio']) ? $profile['bio'] : '', isset($profile['bio']) ? Filter::string($profile['bio']) : '',
isset($profile['location']) ? $profile['location'] : '', isset($profile['location']) ? Filter::string($profile['location']) : '',
isset($profile['url']) ? $profile['url'] : '', isset($profile['url']) ? Filter::string($profile['url']) : '',
isset($profile['bitmessage']) ? $profile['bitmessage'] : '', isset($profile['bitmessage']) ? Filter::string($profile['bitmessage']) : '',
isset($profile['tox']) ? $profile['tox'] : ''); isset($profile['tox']) ? Filter::string($profile['tox']) : '');
}
} }
} }
@ -256,7 +260,6 @@ if ($profile = $_memcache->get('api.user.profile.' . $_SESSION['userName'])) {
$bio = $profile['bio']; $bio = $profile['bio'];
$_memcache->set('api.user.profile.' . $_SESSION['userName'], $profile, MEMCACHE_COMPRESS, MEMCACHE_DHT_PROFILE_TIMEOUT); $_memcache->set('api.user.profile.' . $_SESSION['userName'], $profile, MEMCACHE_COMPRESS, MEMCACHE_DHT_PROFILE_TIMEOUT);
} }
} }

19
src/system/helper/filter.php

@ -2,13 +2,28 @@
class Filter { class Filter {
public static function userName(string $userName) { public static function userName(mixed $userName) {
return preg_replace('/[^a-zA-Z0-9_]+/u', '', $userName); return preg_replace('/[^a-zA-Z0-9_]+/u', '', $userName);
} }
public static function userPrivateKey(string $userPrivateKey) { public static function userPrivateKey(mixed $userPrivateKey) {
return preg_replace('/[^a-zA-Z0-9_]+/u', '', $userPrivateKey); return preg_replace('/[^a-zA-Z0-9_]+/u', '', $userPrivateKey);
} }
public static function blockHash(mixed $blockHash) {
return preg_replace('/[^a-zA-Z0-9]+/u', '', $blockHash);
}
public static function string(mixed $string) {
return htmlentities($string, ENT_QUOTES, 'UTF-8');
}
public static function int(mixed $int) {
return (int) $int;
}
} }

5
tool/crawler/blockchain.php

@ -9,6 +9,7 @@ require(PROJECT_DIR . '/application/model/block.php');
require(PROJECT_DIR . '/system/curl.php'); require(PROJECT_DIR . '/system/curl.php');
require(PROJECT_DIR . '/system/twister.php'); require(PROJECT_DIR . '/system/twister.php');
require(PROJECT_DIR . '/system/helper/filter.php');
// Init libraries // Init libraries
$_twister = new Twister( $_twister = new Twister(
@ -51,6 +52,8 @@ while (true) {
exit; exit;
} }
$blockHash = Filter::blockHash($blockHash);
if (!$block = $_twister->getBlock($blockHash)) { if (!$block = $_twister->getBlock($blockHash)) {
trigger_error(sprintf('could not receive block info on %s (%s)', $nextBlock, $blockHash)); trigger_error(sprintf('could not receive block info on %s (%s)', $nextBlock, $blockHash));
@ -65,6 +68,8 @@ while (true) {
// Add users // Add users
foreach ($block['usernames'] as $userName) { foreach ($block['usernames'] as $userName) {
$userName = Filter::userName($userName);
if (!$_modelUser->addUser($blockId, $userName)) { if (!$_modelUser->addUser($blockId, $userName)) {
trigger_error(sprintf('could not add user %s in block %s)', $userName, $blockId)); trigger_error(sprintf('could not add user %s in block %s)', $userName, $blockId));
exit; exit;

Loading…
Cancel
Save