mirror of
https://github.com/bellingcat/octosuite.git
synced 2026-06-08 03:18:35 +03:00
v3.1.0
This commit is contained in:
37
README.md
37
README.md
@@ -56,6 +56,43 @@ A framework for gathering open-source intelligence on GitHub users, repositories
|
||||
- [x] All the above can be used with command-line arguments (PyPI Package only)
|
||||
- [x] ...And more
|
||||
|
||||
**Used the following implementation from [Somdev Sangwan](https://github.com/s0md3v)'s [Zen](https://github.com/s0md3v/zen) to get an email from a username**
|
||||
```python
|
||||
def findReposFromUsername(username):
|
||||
response = get('https://api.github.com/users/%s/repos?per_page=100&sort=pushed' % username, auth=HTTPBasicAuth(uname, '')).text
|
||||
repos = re.findall(r'"full_name":"%s/(.*?)",.*?"fork":(.*?),' % username, response)
|
||||
nonForkedRepos = []
|
||||
for repo in repos:
|
||||
if repo[1] == 'false':
|
||||
nonForkedRepos.append(repo[0])
|
||||
return nonForkedRepos
|
||||
|
||||
def findEmailFromContributor(username, repo, contributor):
|
||||
response = get('https://github.com/%s/%s/commits?author=%s' % (username, repo, contributor), auth=HTTPBasicAuth(uname, '')).text
|
||||
latestCommit = re.search(r'href="/%s/%s/commit/(.*?)"' % (username, repo), response)
|
||||
if latestCommit:
|
||||
latestCommit = latestCommit.group(1)
|
||||
else:
|
||||
latestCommit = 'dummy'
|
||||
commitDetails = get('https://github.com/%s/%s/commit/%s.patch' % (username, repo, latestCommit), auth=HTTPBasicAuth(uname, '')).text
|
||||
email = re.search(r'<(.*)>', commitDetails)
|
||||
if email:
|
||||
email = email.group(1)
|
||||
if breach:
|
||||
jsonOutput[contributor] = {}
|
||||
jsonOutput[contributor]['email'] = email
|
||||
else:
|
||||
jsonOutput[contributor] = email
|
||||
return email
|
||||
|
||||
def findEmailFromUsername(username):
|
||||
repos = findReposFromUsername(username)
|
||||
for repo in repos:
|
||||
email = findEmailFromContributor(username, repo, username)
|
||||
if email:
|
||||
print (username + ' : ' + email)
|
||||
break
|
||||
```
|
||||
## Note
|
||||
> Octosuite automatically logs network and user activity of each session, the logs are saved by date and time in the .logs folder
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ from octosuite.config import red, white, green, reset, Tree
|
||||
|
||||
# banner.py
|
||||
# This file holds the program's banner and version tag
|
||||
version_tag = "3.0.4"
|
||||
version_tag = "3.1.0"
|
||||
|
||||
|
||||
def banner():
|
||||
|
||||
@@ -124,7 +124,7 @@ def usage():
|
||||
|
||||
def create_parser():
|
||||
parser = argparse.ArgumentParser(description='OCTOSUITE: Advanced GitHub osint framework — by Richard Mwewa | https://about.me/rly0nheart', usage=usage())
|
||||
parser.add_argument('-m', '--method', help='method', choices=['user_profile', 'user_repos', 'user_gists', 'user_orgs', 'user_events',
|
||||
parser.add_argument('-m', '--method', help='method', choices=['user_email', 'user_profile', 'user_repos', 'user_gists', 'user_orgs', 'user_events',
|
||||
'user_subscriptions', 'user_following', 'user_followers', 'user_follows',
|
||||
'org_profile', 'org_repos', 'org_events', 'org_member',
|
||||
'repo_profile', 'repo_contributors', 'repo_stargazers', 'repo_forks',
|
||||
|
||||
@@ -67,6 +67,7 @@ def user_command():
|
||||
user_cmd_table = Table(show_header=True, header_style=header_title)
|
||||
user_cmd_table.add_column("Command", style="dim")
|
||||
user_cmd_table.add_column("Description")
|
||||
user_cmd_table.add_row("email", "Return a target's email")
|
||||
user_cmd_table.add_row("profile", "Get a target's profile info")
|
||||
user_cmd_table.add_row("gists", "Return a users's gists")
|
||||
user_cmd_table.add_row("org", "Return organizations that a target belongs to/owns")
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#!usr/bin/python
|
||||
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
@@ -9,6 +10,7 @@ import requests
|
||||
import platform
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
from requests.auth import HTTPBasicAuth
|
||||
from octosuite.banner import version_tag, banner
|
||||
from octosuite.config import Tree, Text, Table, Prompt, Confirm, xprint, create_parser, args, red, white, green, yellow, header_title, reset
|
||||
from octosuite.message_prefixes import ERROR, WARNING, PROMPT, POSITIVE, NEGATIVE, INFO # wondering why I name all the variables instead of just using the * wildcard?, because it's the pythonic way lol
|
||||
@@ -29,7 +31,7 @@ if os.name == "nt":
|
||||
try:
|
||||
from pyreadline3 import Readline
|
||||
except ImportError:
|
||||
subprocess.run(['pip3', 'install', 'pyreadline3'])
|
||||
subprocess.run(['pip3', 'install', 'pyreadline3'], shell=False)
|
||||
readline = Readline()
|
||||
else:
|
||||
import readline
|
||||
@@ -199,7 +201,7 @@ An advanced and lightning fast framework for gathering open-source intelligence
|
||||
|
||||
|
||||
Whats new in v{version_tag}?
|
||||
[{green}FIXED{reset}] Merged pull request from #9: bad indentation leading to reference before assignment error #9
|
||||
[{green}IMPROVED{reset}] Added a subcommand to the 'user' commands, that will be used to get a user's email (user:email)
|
||||
|
||||
Read the wiki: https://github.com/bellingcat/octosuite/wiki
|
||||
GitHub REST API documentation: https://docs.github.com/rest
|
||||
@@ -207,6 +209,25 @@ GitHub REST API documentation: https://docs.github.com/rest
|
||||
xprint(about_text)
|
||||
|
||||
|
||||
def get_email_from_contributor(username, repo, contributor):
|
||||
json_output = {}
|
||||
response = requests.get(f"https://github.com/{username}/{repo}/commits?author={contributor}",
|
||||
auth=HTTPBasicAuth(username, '')).text
|
||||
latest_commit = re.search(rf'href="/{username}/{repo}/commit/(.*?)"', response)
|
||||
if latest_commit:
|
||||
latest_commit = latest_commit.group(1)
|
||||
else:
|
||||
latest_commit = 'dummy'
|
||||
commit_details = requests.get(f"https://github.com/{username}/{repo}/commit/{latest_commit}.patch",
|
||||
auth=HTTPBasicAuth(username, '')).text
|
||||
email = re.search(r'<(.*)>', commit_details)
|
||||
if email:
|
||||
email = email.group(1)
|
||||
json_output[contributor] = {}
|
||||
json_output[contributor] = email
|
||||
return email
|
||||
|
||||
|
||||
class Octosuite:
|
||||
def __init__(self):
|
||||
# API endpoint
|
||||
@@ -243,6 +264,7 @@ class Octosuite:
|
||||
("repo:issues", self.repo_issues),
|
||||
("repo:releases", self.repo_releases),
|
||||
("user", user),
|
||||
("user:email", self.get_user_email),
|
||||
("user:repos", self.user_repos),
|
||||
("user:gists", self.user_gists),
|
||||
("user:orgs", self.user_orgs),
|
||||
@@ -271,6 +293,7 @@ class Octosuite:
|
||||
|
||||
# Arguments map will be used to run Octosuite with argparse
|
||||
self.argument_map = [("user_profile", self.user_profile),
|
||||
("user_email", self.get_user_email),
|
||||
("user_repos", self.user_repos),
|
||||
("user_gists", self.user_gists),
|
||||
("user_orgs", self.user_orgs),
|
||||
@@ -510,6 +533,28 @@ class Octosuite:
|
||||
'About.me': 'https://about.me/rly0nheart',
|
||||
'Buy Me A Coffee': 'https://buymeacoffee.com/189381184'}
|
||||
|
||||
def get_repos_from_username(self, username):
|
||||
response = requests.get(f"{self.endpoint}/users/{username}/repos?per_page=100&sort=pushed",
|
||||
auth=HTTPBasicAuth(username, '')).text
|
||||
repositories = re.findall(rf'"full_name":"{username}/(.*?)",.*?"fork":(.*?),', response)
|
||||
unforked_repos = []
|
||||
for repository in repositories:
|
||||
if repository[1] == 'false':
|
||||
unforked_repos.append(repository[0])
|
||||
return unforked_repos
|
||||
|
||||
def get_user_email(self):
|
||||
if args.username:
|
||||
username = args.username
|
||||
else:
|
||||
username = Prompt.ask(f"{white}@{green}Username{reset}")
|
||||
repos = self.get_repos_from_username(username)
|
||||
for repo in repos:
|
||||
email = get_email_from_contributor(username, repo, username)
|
||||
if email:
|
||||
xprint(f"{username}: {email}")
|
||||
break
|
||||
|
||||
# Fetching organization info
|
||||
def org_profile(self):
|
||||
if args.organization:
|
||||
|
||||
Reference in New Issue
Block a user