SL-18165 Tighten up some command permissions

master
Andrey Kleshchev 2022-10-11 15:21:23 +03:00
parent 072844f744
commit 6f946b6b16
12 changed files with 267 additions and 36 deletions

View File

@ -41,7 +41,7 @@ class LLBuyCurrencyHTMLHandler :
{
public:
// requests will be throttled from a non-trusted browser
LLBuyCurrencyHTMLHandler() : LLCommandHandler( "buycurrencyhtml", UNTRUSTED_ALLOW ) {}
LLBuyCurrencyHTMLHandler() : LLCommandHandler( "buycurrencyhtml", UNTRUSTED_THROTTLE) {}
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
{

View File

@ -39,6 +39,7 @@
#define THROTTLE_PERIOD 5 // required seconds between throttled commands
static LLCommandDispatcherListener sCommandDispatcherListener;
const std::string LLCommandHandler::NAV_TYPE_CLICKED = "clicked";
//---------------------------------------------------------------------------
// Underlying registry for command handlers, not directly accessible.
@ -64,6 +65,9 @@ public:
bool trusted_browser);
private:
void notifySlurlBlocked();
void notifySlurlThrottled();
friend LLSD LLCommandDispatcher::enumerate();
std::map<std::string, LLCommandHandlerInfo> mMap;
};
@ -96,8 +100,6 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
const std::string& nav_type,
bool trusted_browser)
{
static bool slurl_blocked = false;
static bool slurl_throttled = false;
static F64 last_throttle_time = 0.0;
F64 cur_time = 0.0;
std::map<std::string, LLCommandHandlerInfo>::iterator it = mMap.find(cmd);
@ -115,44 +117,45 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
// block request from external browser, but report as
// "handled" because it was well formatted.
LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL;
if (! slurl_blocked)
{
if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT)
{
// Note: commands can arrive before we initialize everything we need for Notification.
LLNotificationsUtil::add("BlockedSLURL");
}
slurl_blocked = true;
}
notifySlurlBlocked();
return true;
case LLCommandHandler::UNTRUSTED_CLICK_ONLY:
if (nav_type == LLCommandHandler::NAV_TYPE_CLICKED
&& info.mHandler->canHandleUntrusted(params, query_map, web, nav_type))
{
break;
}
LL_WARNS_ONCE("SLURL") << "Blocked SLURL click-only command " << cmd << " from untrusted browser" << LL_ENDL;
notifySlurlBlocked();
return true;
case LLCommandHandler::UNTRUSTED_THROTTLE:
// if users actually click on a link, we don't need to throttle it
// (throttling mechanism is used to prevent an avalanche of clicks via
// javascript
if ( nav_type == "clicked" )
{
break;
}
//skip initial request from external browser before STATE_BROWSER_INIT
if (LLStartUp::getStartupState() == STATE_FIRST)
{
return true;
}
if (!info.mHandler->canHandleUntrusted(params, query_map, web, nav_type))
{
LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL;
notifySlurlBlocked();
return true;
}
// if users actually click on a link, we don't need to throttle it
// (throttling mechanism is used to prevent an avalanche of clicks via
// javascript
if (nav_type == LLCommandHandler::NAV_TYPE_CLICKED)
{
break;
}
cur_time = LLTimer::getElapsedSeconds();
if (cur_time < last_throttle_time + THROTTLE_PERIOD)
{
// block request from external browser if it happened
// within THROTTLE_PERIOD seconds of the last command
LL_WARNS_ONCE("SLURL") << "Throttled SLURL command from untrusted browser" << LL_ENDL;
if (! slurl_throttled)
{
if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT)
{
LLNotificationsUtil::add("ThrottledSLURL");
}
slurl_throttled = true;
}
notifySlurlThrottled();
return true;
}
last_throttle_time = cur_time;
@ -163,6 +166,34 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
return info.mHandler->handle(params, query_map, web);
}
void LLCommandHandlerRegistry::notifySlurlBlocked()
{
static bool slurl_blocked = false;
if (!slurl_blocked)
{
if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT)
{
// Note: commands can arrive before we initialize everything we need for Notification.
LLNotificationsUtil::add("BlockedSLURL");
}
slurl_blocked = true;
}
}
void LLCommandHandlerRegistry::notifySlurlThrottled()
{
static bool slurl_throttled = false;
if (!slurl_throttled)
{
if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT)
{
// Note: commands can arrive before we initialize everything we need for Notification.
LLNotificationsUtil::add("ThrottledSLURL");
}
slurl_throttled = true;
}
}
//---------------------------------------------------------------------------
// Automatic registration of commands, runs before main()
//---------------------------------------------------------------------------
@ -230,6 +261,7 @@ symbol_info symbols[] =
{
ent(LLCommandHandler::UNTRUSTED_ALLOW), // allow commands from untrusted browsers
ent(LLCommandHandler::UNTRUSTED_BLOCK), // ignore commands from untrusted browsers
ent(LLCommandHandler::UNTRUSTED_CLICK_ONLY), // allow untrusted, but only if clicked
ent(LLCommandHandler::UNTRUSTED_THROTTLE) // allow untrusted, but only a few per min.
};

View File

@ -65,9 +65,12 @@ public:
{
UNTRUSTED_ALLOW, // allow commands from untrusted browsers
UNTRUSTED_BLOCK, // ignore commands from untrusted browsers
UNTRUSTED_CLICK_ONLY, // allow untrusted, but only if clicked
UNTRUSTED_THROTTLE // allow untrusted, but only a few per min.
};
static const std::string NAV_TYPE_CLICKED;
LLCommandHandler(const char* command, EUntrustedAccess untrusted_access);
// Automatically registers object to get called when
// command is executed. All commands can be processed
@ -76,6 +79,13 @@ public:
virtual ~LLCommandHandler();
virtual bool canHandleUntrusted(
const LLSD& params,
const LLSD& query_map,
LLMediaCtrl* web,
const std::string& nav_type)
{ return true; }
virtual bool handle(const LLSD& params,
const LLSD& query_map,
LLMediaCtrl* web) = 0;

View File

@ -45,7 +45,7 @@ class LLSearchHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_THROTTLE) { }
LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_CLICK_ONLY) { }
bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
{
if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableSearch"))

View File

@ -123,7 +123,7 @@ class LLWorldMapHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_THROTTLE ) { }
LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_CLICK_ONLY ) { }
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)
@ -160,7 +160,7 @@ class LLMapTrackAvatarHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
LLMapTrackAvatarHandler() : LLCommandHandler("maptrackavatar", UNTRUSTED_THROTTLE)
LLMapTrackAvatarHandler() : LLCommandHandler("maptrackavatar", UNTRUSTED_CLICK_ONLY)
{
}

View File

@ -52,7 +52,32 @@ class LLGroupHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
LLGroupHandler() : LLCommandHandler("group", UNTRUSTED_THROTTLE) { }
LLGroupHandler() : LLCommandHandler("group", UNTRUSTED_CLICK_ONLY) { }
virtual bool canHandleUntrusted(
const LLSD& params,
const LLSD& query_map,
LLMediaCtrl* web,
const std::string& nav_type)
{
if (params.size() < 1)
{
return true; // don't block, will fail later
}
if (nav_type == NAV_TYPE_CLICKED)
{
return true;
}
const std::string verb = params[0].asString();
if (verb == "create")
{
return false;
}
return true;
}
bool handle(const LLSD& tokens, const LLSD& query_map,
LLMediaCtrl* web)
{

View File

@ -1663,7 +1663,7 @@ void LLPanelEditWearable::initPreviousAlphaTextureEntry(LLAvatarAppearanceDefine
class LLMetricSystemHandler : public LLCommandHandler
{
public:
LLMetricSystemHandler() : LLCommandHandler("metricsystem", UNTRUSTED_THROTTLE) { }
LLMetricSystemHandler() : LLCommandHandler("metricsystem", UNTRUSTED_CLICK_ONLY) { }
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
{

View File

@ -484,6 +484,30 @@ public:
// requires trusted browser to trigger
LLAgentHandler() : LLCommandHandler("agent", UNTRUSTED_THROTTLE) { }
virtual bool canHandleUntrusted(
const LLSD& params,
const LLSD& query_map,
LLMediaCtrl* web,
const std::string& nav_type)
{
if (params.size() < 2)
{
return true; // don't block, will fail later
}
if (nav_type == NAV_TYPE_CLICKED)
{
return true;
}
const std::string verb = params[1].asString();
if (verb == "about" || verb == "inspect" || verb == "reportAbuse")
{
return true;
}
return false;
}
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)
{

View File

@ -81,6 +81,30 @@ public:
std::set<LLUUID> mClassifiedIds;
std::string mRequestVerb;
virtual bool canHandleUntrusted(
const LLSD& params,
const LLSD& query_map,
LLMediaCtrl* web,
const std::string& nav_type)
{
if (params.size() < 1)
{
return true; // don't block, will fail later
}
if (nav_type == NAV_TYPE_CLICKED)
{
return true;
}
const std::string verb = params[0].asString();
if (verb == "create")
{
return false;
}
return true;
}
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
{

View File

@ -63,6 +63,30 @@ public:
// requires trusted browser to trigger
LLPickHandler() : LLCommandHandler("pick", UNTRUSTED_THROTTLE) { }
virtual bool canHandleUntrusted(
const LLSD& params,
const LLSD& query_map,
LLMediaCtrl* web,
const std::string& nav_type)
{
if (params.size() < 1)
{
return true; // don't block, will fail later
}
if (nav_type == NAV_TYPE_CLICKED)
{
return true;
}
const std::string verb = params[0].asString();
if (verb == "create")
{
return false;
}
return true;
}
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)
{

View File

@ -173,11 +173,103 @@
class LLFloaterOpenHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
// requires trusted browser to trigger or an explicit click
LLFloaterOpenHandler() : LLCommandHandler("openfloater", UNTRUSTED_THROTTLE) { }
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)
virtual bool canHandleUntrusted(
const LLSD& params,
const LLSD& query_map,
LLMediaCtrl* web,
const std::string& nav_type)
{
if (params.size() != 1)
{
return true; // will fail silently
}
std::string fl_name = params[0].asString();
if (nav_type == NAV_TYPE_CLICKED)
{
const std::list<std::string> blacklist_clicked = {
"camera_presets",
"delete_pref_preset",
"forget_username",
"god_tools",
"group_picker",
"hud",
"incoming_call",
"linkreplace",
"message_critical", // Modal!!! Login specific.
"message_tos", // Modal!!! Login specific.
"save_pref_preset",
"save_camera_preset",
"region_restarting",
"outfit_snapshot",
"upload_anim_bvh",
"upload_anim_anim",
"upload_image",
"upload_model",
"upload_script",
"upload_sound"
};
return std::find(blacklist_clicked.begin(), blacklist_clicked.end(), fl_name) == blacklist_clicked.end();
}
else
{
const std::list<std::string> blacklist_untrusted = {
"360capture",
"block_timers",
"add_payment_method",
"appearance",
"associate_listing",
"avatar_picker",
"camera",
"camera_presets",
"classified",
"add_landmark",
"delete_pref_preset",
"env_fixed_environmentent_water",
"env_fixed_environmentent_sky",
"env_edit_extdaycycle",
"font_test",
"forget_username",
"god_tools",
"group_picker",
"hud",
"incoming_call",
"linkreplace",
"mem_leaking",
"marketplace_validation",
"message_critical", // Modal!!! Login specific. If this is in use elsewhere, better to create a non modal variant
"message_tos", // Modal!!! Login specific.
"mute_object_by_name",
"publish_classified",
"save_pref_preset",
"save_camera_preset",
"region_restarting",
"script_debug",
"script_debug_output",
"sell_land",
"outfit_snapshot",
"upload_anim_bvh",
"upload_anim_anim",
"upload_image",
"upload_model",
"upload_script",
"upload_sound"
};
return std::find(blacklist_untrusted.begin(), blacklist_untrusted.end(), fl_name) == blacklist_untrusted.end();
}
return true;
}
bool handle(
const LLSD& params,
const LLSD& query_map,
LLMediaCtrl* web) override
{
if (params.size() != 1)
{

View File

@ -232,7 +232,7 @@ class LLInventoryHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_THROTTLE) { }
LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_CLICK_ONLY) { }
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)