If you are like me, lazy but able to get some crazy ideas sometime π then you might have wondered how to get your connected friends on Second Life without being forced to connect on their website.
I must admit that what I'm gonna explain is working only
because Linden Labs seems to have no clue about how security should be implemented correctly...The above sentence is only valid if you've not enabled the MFA on your account.
For example, if a bad actor gets hands on your
session
cookie, nothing will avoid that bad actor to impersonate your account without any time limit!This is due to the fact that till the
session
cookie is refreshed / actualized with the involvedwatch
command, it will never expire!! (while a forcedsession
cookie expiration / renewal would have been expected at some point...)I've been able to get connected under my own account after days of not having used their website!! π±
How so?! you might wonder... Simply by replacing the assigned
session
cookie by the one used in the magic command that will be explained later...
If you don't want to read the whole logic behind the idea, here is the magic command π
-
With internal names displayed:
$ watch -n5 "curl --silent -b session-token=[YOUR-SESSION-TOKEN-HERE] -A 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36' https://secondlife.com/my/loadWidgetContent.php?widget=widgetFriends | htmlq '#widgetFriendsOnlineContent' | grep -i -A2 'trigger online' | grep -i 'span' | grep -v '<br>' | sed -e 's/<span title=\"/(/' | sed -e 's/\">/) /' | sed -e 's|</span>||'"
-
Similar to what is displayed on website:
$ watch -n5 "curl --silent -b session-token=[YOUR-SESSION-TOKEN-HERE] -A 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36' https://secondlife.com/my/loadWidgetContent.php?widget=widgetFriends | htmlq '#widgetFriendsOnlineContent' | grep -i -A2 'trigger online' | grep -i 'span' | grep -v '<br>' | sed -e 's/<span title=\"/(/' | sed -e 's/\">/) /' | sed -e 's|</span>||' | sed -e 's/ Resident//'"
Replace
[YOUR-SESSION-TOKEN-HERE]
with the one assigned once you get connected.
Result:
The output is refreshed every 5 seconds.
I guess you understand that I've redacted all sensible information π
I've made a small project related to this work, you can find it here.
We all love cookies, don't you? π
In order to let the magic command getting access to your friends list, you'll need to get your current session
cookie once connected.
To do so, open the web console with the [F12]
key on your keyboard, go to the Application tab and select the Cookies section on the left:
Note the value of
session-token
in a safe place for later use in the magic command.
To ease the parsing of the HTML
content, a good friend of mine told me to give a try to htmlq. I you already know jQuery, you can think the same but for CLI
π
# Install 'cargo' first
$ sudo apt install cargo
# Then use 'cargo' to install 'htmlq'
$ cargo install htmlq
# Create required symlink
$ sudo ln -sfvn $(which htmlq) /usr/bin/htmlq
Here is where things gets a little tricky to find.
As the website structure is still pretty old and far from to be modern, I was expecting to find the friends list code in the server side HTML
source but surprisingly, nope π
They have used what they call, a widget written in PHP
but loaded on the client side within JS
code:
The logic here is the following:
- The
JS
code will load the widgetFriends widget using the loadWidgetContent.php loader written inPHP
- The server side generated content is then pushed on client side into the widgetFriendsBody
DIV
tag line 442 on the picture
So the code coming from server side that you can see on the picture above is then overloaded on client side to become:
Now the idea is to target the widgetFriendsOnlineContent DIV
tag with htmlq and parse the content with grep and sed to transform this:
Into this:
You can't see very well here but basically the output will be formated that way:
(Internal Name) Display Name
So... All of this to finally ends on:
$ watch -n5 "curl --silent -b session-token=[YOUR-SESSION-TOKEN-HERE] -A 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36' https://secondlife.com/my/loadWidgetContent.php?widget=widgetFriends | htmlq '#widgetFriendsOnlineContent' | grep -i -A2 'trigger online' | grep -i 'span' | grep -v '<br>' | sed -e 's/<span title=\"/(/' | sed -e 's/\">/) /' | sed -e 's|</span>||'"
Where:
watch -n5
- Refresh / Re-run the command every 5 seconds
curl --silent -b session-token=[YOUR-SESSION-TOKEN-HERE] -A 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36' https://secondlife.com/my/loadWidgetContent.php?widget=widgetFriends
- Connect on Second Life with your own
session
cookie - Hide the default
curl
User-Agent - and invoke the widgetFriends
PHP
widget
- Connect on Second Life with your own
htmlq '#widgetFriendsOnlineContent'
- Target the widgetFriendsOnlineContent
DIV
tag
- Target the widgetFriendsOnlineContent
grep -i -A2 'trigger online'
- Filter by online users only
grep -i 'span'
- Filter
SPAN
tags only
- Filter
grep -v '<br>'
- Remove extra
BR
tags captured from the firstgrep
invocation
- Remove extra
sed -e 's/<span title=\"/(/' | sed -e 's/\">/) /' | sed -e 's|</span>||'
- Convert
<span title="Internal Name">Display Name</span>
- To
(Internal Name) Display Name
- Convert
As you might have observed, the generated command does not parse the SPAN
tag that hold the username but instead, it parse the one that holds the internal name and display name of each users.
The main reason to that is because initially, every usernames in Second Life were supposed to be composed by Firstname
+ Lastname
from the randomly suggested names.
This restriction has been removed several years later to only ask for a single Nickname
+ Resident
added internally as Lastname
to kinda restore / keep using internally the old naming format Firstname
+ Lastname
.
It means that users created before the restriction being lifted will have their usernames composed that way:
SuggestedRandomFirstname
+SuggestedRandomLastname
While newer users will get their usernames composed that way:
SuggestedRandomNickname
+Resident
appended
Yes!
By adding another sed
invocation to remove the extra appended Resident
string from the output that way:
sed -e 's/ Resident//'
So the magic command becomes:
$ watch -n5 "curl --silent -b session-token=[YOUR-SESSION-TOKEN-HERE] -A 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36' https://secondlife.com/my/loadWidgetContent.php?widget=widgetFriends | htmlq '#widgetFriendsOnlineContent' | grep -i -A2 'trigger online' | grep -i 'span' | grep -v '<br>' | sed -e 's/<span title=\"/(/' | sed -e 's/\">/) /' | sed -e 's|</span>||' | sed -e 's/ Resident//'"
Unfortunately... Yes π’
Second Life recently announced that they have finally implemented MFA as additional protection of user accounts. Well done Second Life! π€
Follow instructions provided here if you are interested.
When the MFA is enabled, it will then ask for an additional TOTP to be authenticated. This might then break the way the magic command is working and then involve the need to simulate that MFA payload...
Based on the following research and work, I'll convert this magic command into a little bash
script with arguments.
I'll put the link here once created.
In the introduction I've mentioned that there is a risk in using this magic command because it directly use your session
cookie. If a bad actor can gets hands on it, it can simply impersonnate you and connect on your behalf.
- Take the value of
session-token=[YOUR-SESSION-TOKEN-HERE]
from the magic command - Open the browser and navigate to https://secondlife.com/my/account/login.php
- Open the web console and change the assigned
session
cookie value to the one stolen from step 1. - The bad actor is now connected on your behalf...
When you connect on Second Life, even if you still haven't given your username and password, a session
cookie is created with an automatically assigned session-token
. I guess that session-token
is then linked to your account when the connection has been successful and certainly revoked at some point if no connection has been made with it.
According to my limited knowledge in the Security domain (I know, I'm probably too much humble on that statement π ), here is what should be done to improve the security of their authentication process:
- the
session-token
should not be generated prior the authentication being successful but instead, should be generated only after the successful authentication. - the
session-token
should be automatically revoked at a certain time even if it's still valid, forcing the user to authenticate again once revoked.
The reason behind the automated token revocation is to limit the access of your account to the bad actor. For example, I've discovered this "lack of security knowledge" like two or three weeks ago, the last run of my magic command was probably 10 days ago and the used session-token
is still valid and I could even re-use it to get connected on the Second Life website under my own account...
This section will contains post observations and might not be very clean.
I've observed that the session-token
can be forced and rewritten while the sessionid
and the csrftoken
are genereted during the login.
The locale
value can be set to any ISO-639-1
2 or 4 letters country code. example: fr
, en-US
.
Made with β€οΈ of hacking by Jiab77.