New Threads, New OSINT — An exploration of Poshmark
I was tossing around ideas for a blog about Poshmark, and my first inclination was to check Micah Hoffman’s WhatsMyName tool (also…
I was tossing around ideas for a blog about Poshmark. My first inclination was to check Micah Hoffman’s WhatsMyName tool (also available as Profiler in Recon-ng and as a Web Application). The tool had no support for Poshmark. I am a curious person, and I like to give back to the community. So, naturally, I thought about how I could automate the checks for the closet’s existence. Note: Closet is the term Poshmark uses for sellers and their available inventory.
Another note: 100% of these techniques are UNAUTHENTICATED. When doing the same analysis with a logged-in account, nothing changes.
Building the Automation
Initial Scenario
I use WhatsMyName quite frequently, so I am familiar with the general way that the application works. Sites are assembled in a JSON file that the Python script iterates over and does the checks for the sites, minding the HTTP code (200, 300, 404, etc.) and a string that is displayed in the response if an account exists or not. The script will then display on the screen whether it exists or not.
My downfall is that I was not intimately familiar with where to get the strings to verify the existence or conclude a lack of existence. To accomplish this, I copied the original WhatsMyName Python script (web_accounts_list_checker.py
). I read through the code to the point where I found where the script’s logic checks for the code and the string. The part of the code where this occurs is around line 209 and reads as:
# Analyze the responses against what they should becode_match = r.status_code == int(site[‘account_existence_code’])string_match = r.text.find(site[‘account_existence_string’]) >= 0
Finding Strings for Verification
I added another line to print the output of the variable r to see what is returned:
# Analyze the responses against what they should becode_match = r.status_code == int(site['account_existence_code'])string_match = r.text.find(site['account_existence_string']) >= 0print(r.text)
I searched around the site for accounts that did and did not exist (Hello Bob, Alice, and C_3PJoe). Once I determined which ones existed and did not, I reran the code. Here is the censored output of a valid user:
Here is the censored output of a non-existent user:
As we can see, a valid page says “<username> or <Real Name> is using Poshmark to sell items from their closet,” whereas we see “Page Not Found — Poshmark” if there is no user by that name. Now, to verify the HTTP codes.
Checking HTTP Codes
Next, we have to check the HTTP codes to input them into WhatsMyName. I found https://httpstatus.io/ as an easy website to do it in one single transaction for both accounts.
Instead of using my current browser for the user-agent string, I changed it to Firefox Desktop because I noticed that theheader
variable in the code for WhatsMyName is set to that user-agent string. At the bottom, we see that the valid account has an HTTP 200 code and, the non-existent account has a 404.
Now, we need to edit the web_accounts_list.json
file.
},{ "name" : "Poshmark", "check_uri" : "https://poshmark.com/closet/{account}", "account_existence_code" : "200", "account_existence_string" : " is using Poshmark to sell items from their closet.", "account_missing_string" : "Page not found - Poshmark", "account_missing_code" : "404", "known_accounts" : ["alice","bob"], "category" : "shopping", "valid" : true }
Now when we run the code, the script will check Poshmark.
I did some analysis using friends’ accounts that are both sellers and buyers. Even if a person is only a buyer, they are still listed as having a closet.
As of August 24, this is included in the WhatsMyName script, the Profiler module in Recon-ng, and the Web Application.
Further Poshmark OSINT
As I was probing around the Poshmark site to solve the problem from the previous section, I came across some other things of interest to an OSINT investigator.
Google Dorking
First, after we have positive confirmation of the username, if we use the Google Dork of site:poshmark.com <user name>
, we can see what they are mentioned in or have commented on. Below is a screenshot with all usernames and identifying information obscured. The black boxes are where the user name I searched for appear in the results.
While this is somewhat trivial, it can help us build a dossier on someone’s spending habits, fashion taste, and other things.
Harvesting other user info
Next, we will do the somewhat obvious. We will analyze the username (using tools like WhatsMyName, NameChk, and Sherlock). Furthermore, depending on what the user has on their profile, we may be able to ascertain the following:
Location
Last login time (derived from last comment or post)
School/College/University
Website
Clothing sizes (unless they are doing Poshmark as a business)
Possible pictures not shared elsewhere
Given these data vectors, we can extract information from the following:
Alumni Associations
People Search Engines (i.e. FamilyTreeNow, TruePeopleSearch, FastBackGroundCheck, and FastPeopleSearch) then move to public, voter, or property records
Web technologies and email addresses
Reverse image searches
General news in a specific area
Other social media platforms
This is a point where the possibilities are near-endless. This could be the goldmine we seek, especially if the person has little concept of OPSEC or privacy.
Shipping Labels
The final source of intelligence from Poshmark is their shipping labels. While I know some information is required to ensure delivery. The main part that I take issue with is the username. There is no reason for this to be on the labels. An adversary that sees this posted online or handles mail or packages could use the same techniques discussed above to stalk, harass, or harm a buyer solely using the label.
I frequently encourage people to avoid using the same username everywhere — just like with passwords. But, as with passwords, it often falls on deaf ears. There’s nothing wrong with populating the username across multiple websites; I discourage actually using the name on all sites for real accounts. From an OPSEC perspective, feel free to register the username then populate it with garbage data. Be on the lookout for a blog about that in the future.
Conclusion
In conclusion, this was a great learning experience. Furthermore, it proves that we can scrape intelligence out of almost any resource. There are definitely things that I would like to see changed with Poshmark, but for now, I will enjoy the ride and the source of OSINT.