Tech for online privacy

Pollute menti poll to evade detection

Released: Mentimeter Voting Bot

Tech for privacy

Mentimeter polls is a website that allows polling and receiving votes from an audience. It is a great evening time pass to play with my friends but is often abused as a channel for bullying. Recently I had experiences with people intentionally putting questions just to demean others and bully those who chose a certain poll option. A very light example: not knowing what does POTUS or LOTUS stand for and then being made fun of. This repository provides a way to sabotage such malicious attempts at singling out people for their lack of general knowledge. Undoing a vote is not allowed by Menti, so atleast the users of this repo can immediately pollute the results if they perceive a threat to their opinion privacy.

This bot needs the id of the menti poll which is shared by the poll creator before they open the poll publicly accessible. The bot automatically scrambles the votes by casting numerous fake votes on vote options selected randomly hence rendering the poll creator unable to identify or single out a poll participant for their opinions.

Why this is important?

In a very large group, if users just choose their details it becomes impossibly hard to identify them. But as we restrict the group, having even a little detail about a person’s preferences or taste or opinions, can single them out, hence leak their identity details.

I have used Menti as just an example, to show how polling in a restrictive group poses a privacy risk. For example, the poll creator can ask for the Date of Birth, Year of Birth, Parents name and easily reverse engineer participant’s online security passwords. With this bot, I am publishing one of the ways to randomize my polls if I suspect a privacy invasion.

Demo Video

Before I jump over to implementation details, enjoy my test setup’s recording:

Key Pointers

  1. Chrome Webdriver to automatically invoke chrome via Python scripts

  2. Change user agent randomly to evade “already polled” detection by Menti.

    
         from fake_useragent import UserAgent
         chrome_options = webdriver.ChromeOptions()
         chrome_options.add_argument("user-agent={}".format(UserAgent().random))
         browser = webdriver.Chrome(chrome_options=chrome_options)
         browser.get("https://www.menti.com")
     
  3. Automatically login to the poll:

    
         menti_code_inp = browser.find_element_by_xpath(
             '//input[@id="enter-vote-key"]'
         )
         menti_code_inp.send_keys(menti_code) # provided by poll creator
    
         default_login_btn = browser.find_element_by_xpath(
             '//button[@type="submit"]'
         )
         default_login_btn.click()
     
  4. Detect and Poll for a random vote option:

    
         def random_vote():
             vote_candidate = None
             # vote_id = 0
             attempts = 10
             # max 10 attempts to find a random voting option
             while vote_candidate == None and attempts > 0:
                 vote_id = random.randint(0, 6)  # usually 6 options are there
                 try:
                     vote_candidate = browser.find_element_by_xpath(
                         '//label[@data-testid="choice-' + str(vote_id) + '"]'
                     )
                     vote_candidate.click()
                 except:
                     vote_candidate = None
                     attempts -= 1
    
             submit_vote_btn = browser.find_element_by_xpath('//button[@type="submit"]')
             submit_vote_btn.click()
             if attempts >= 0:
                 print("Voted successfully to " + str(vote_id))
             else:
                 print("Voting failed")
             return attempts >= 0
     
  5. Cast parallel votes:

    
         def cast_single_random_vote():
             menti_bot = WebBot()
             menti_bot.login()
             return menti_bot.random_vote()
    
         def cast_parallel_votes(N=8):
             with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
                 # Start the load operations and mark each future with its URL
                 future_votes = [
                     executor.submit(cast_single_random_vote).result() for i in range(N)
                 ]
                 print(f"Performed {int(sum(future_votes))} fake menti votes")
                 return sum(future_votes)
     
  6. Unblocking chrome web driver - The only dependency I had was over ChromeWebDriver or selenium. Mac was often blocking it to execute saying the developer cannot be verified, for which I had to un-quarantine it like below:

    
         cd /usr/local/bin
         xattr -d com.apple.quarantine chromedriver
     

I felt it would be super awesome to have the following features - which would be a value add:

  • Add a custom vote option
  • Allow poll polluter for other polls

Demo Previews

For my demo, the source is hosted on GitHub repo: MentiVoterBot repo, quick sneak peek is below:

Menti Poll System
Menti Vote Randomizer

TECH
python webdriver chrome

Dialogue & Discussion