Ejemplo n.º 1
0
def enumerate_tokens(cookie: str):
    """Given a Slack login cookie string, enumerate all logged-in Slacks and
    return a list of tokens.

    cookie need only be the d= portion of the cookie."""

    rv = []

    try:
        cookies = http.cookies.SimpleCookie(cookie)
        if 'd' not in cookies:
            # Make a guess that we got passed only the value after `d=`.
            cookies = http.cookies.SimpleCookie()
            cookies['d'] = cookie
        cookies = dict(
            d=urllib.parse.quote(urllib.parse.unquote(cookies['d'].value)))
        sess = requests.Session()
        # a 'real' cookie jar was too annoying to figure out and seemed of dubious benefit anyway
        sess.headers['cookie'] = f"d={cookies['d']}"
        utils.set_user_agent(sess.headers)
        # This Slack exists, but no one has access to it.
        # So, Slack helpfully lists all your logged-in teams.
        r = sess.get("https://emojifs-wasteland.slack.com")
        r.raise_for_status()
        ALREADY_SIGNED_IN_TEAM_REGEX = r"(https://[a-zA-Z0-9\-]+\.slack\.com)"
        QUOTED_ALREADY_SIGNED_IN_TEAM_REGEX = r""url":"(https:\\/\\/[a-zA-Z0-9\-]+\.slack\.com)"
        SLACK_API_TOKEN_REGEX = r"\"api_token\":\"(xox[a-zA-Z]-[a-zA-Z0-9-]+)\""
        teams = (set(re.findall(ALREADY_SIGNED_IN_TEAM_REGEX, r.text))
                 | set(
                     t.replace('\\', '') for t in re.findall(
                         QUOTED_ALREADY_SIGNED_IN_TEAM_REGEX, r.text)) -
                 set(['https://status.slack.com', 'https://api.slack.com']))
        for team in teams:
            try:
                r = sess.get(team + "/customize/emoji")
                r.raise_for_status()
                parsed = re.findall(SLACK_API_TOKEN_REGEX, r.text)
                logger.debug('👀 Found %s tokens from %s', len(parsed), team)
                rv.extend(parsed)
            except Exception:
                logger.error(
                    "😖 Something went wrong when scraping token from %s",
                    team,
                    exc_info=1)
                # then continue
        return rv
    except Exception:
        logger.error("😖 Something went wrong when scraping login cookies",
                     exc_info=True)
    finally:
        return rv
Ejemplo n.º 2
0
    def __init__(self, token: str):
        self._retry_after = {
        }  # URL -> time.time() after which it's ok to retry
        self._write_buffers = {}  # path (not name!) -> BytesIO

        # emoji metadata for 100 guilds + 1 guild membership list
        self._emojis_cache = cachetools.TTLCache(maxsize=100, ttl=600)
        self._membership_cache = cachetools.TTLCache(maxsize=1, ttl=600)

        self._session = requests.Session()
        utils.set_user_agent(self._session.headers)
        self._session.headers['Authorization'] = token

        r = self._request('GET', 'users/@me')
        self._my_user = r.json()
        logger.info('👍 Successfully authenticated to Discord as %s',
                    self._user_string(self._my_user))
Ejemplo n.º 3
0
    def __init__(self, token: str, *, real_sizes: bool = True, name: str = ''):
        """Given an authentication token (xox.-....), construct a Slack instance."""

        # TODO: real_sizes=False is a big speedup on common tasks like `ls -l`, but, if you lie
        # about sizes you break reads and such, presumably unless you set direct_io (which disables
        # kernel buffer cache and probably introduces some other performance penalty for other
        # usages, although probably they're less bad/annoying).
        assert (real_sizes)

        self.name = name  # the identifying part before .slack.com
        self._token = token
        self._real_sizes = real_sizes
        self._base_url = f"https://{name}.slack.com/api/" if name else 'https://api.slack.com/api/'
        self._retry_after = {
        }  # URL -> time.time() after which it's ok to retry
        self._write_buffers = {}  # path (not name!) -> BytesIO
        self.__cached_metadata = cachetools.TTLCache(
            maxsize=1, ttl=600)  # for _get_all_emoji()

        self._session = requests.Session()
        utils.set_user_agent(self._session.headers)
        self._session.headers['Authorization'] = f"Bearer {token}"

        # Our token should be usable for a single Slack.
        # To see if we have an admin token, first, we need our user ID.
        r = self._request('GET', self._url('auth.test'))
        j = r.json()
        self._user_id = j['user_id']
        self._base_url = j['url'] + 'api/'
        if not self.name:
            m = re.match(r'https://([^.]+)\.slack\.com/', j['url'])
            if m:
                self.name = m[1]
        r = self._request('GET',
                          self._url('users.info'),
                          params={'user': self._user_id})
        j = r.json()
        self._user_json = j['user']
        # TODO: we thought we cared about is_admin, but of course is_admin is sufficient but not
        # necessary to upload emoji.
        self._is_admin = (j['user']['is_admin'] or j['user']['is_owner']
                          or j['user']['is_primary_owner'])
        logger.info('👍 Successfully authenticated to %s as user %s', self.name,
                    j['user']['name'])