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 have REALLY no clue about how security should be implemented correctly...
The above sentence is valid whatever you have enabled or not the MFA on your account.
For example, if a bad actor gets hands on your
sessioncookie, nothing will avoid that bad actor to impersonate your account without any time limit!This is due to the fact that till the
sessioncookie is refreshed / actualized with the involvedwatchcommand, it will never expire!! (while a forcedsessioncookie 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
sessioncookie by the one used in the magic command that will be explained later...
After having done some additional analysis, the way the authentication system has been implemented in Second Life is even worst than I thought...
I'll document all my findings in another gist and add a link pointing to it in this gist when published.
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-tokenin 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/htmlqHere 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
JScode 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
DIVtag 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
sessioncookie - Hide the default
curlUser-Agent - and invoke the widgetFriends
PHPwidget
- Connect on Second Life with your own
htmlq '#widgetFriendsOnlineContent'- Target the widgetFriendsOnlineContent
DIVtag
- Target the widgetFriendsOnlineContent
grep -i -A2 'trigger online'- Filter by online users only
grep -i 'span'- Filter
SPANtags only
- Filter
grep -v '<br>'- Remove extra
BRtags captured from the firstgrepinvocation
- 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+Residentappended
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
sessioncookie 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-tokenshould not be generated prior the authentication being successful but instead, should be generated only after the successful authentication. - the
session-tokenshould 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.







