This commit is contained in:
Richard Mwewa
2023-01-25 14:11:25 +02:00
parent 646ea3cb51
commit 85cadefd50
6 changed files with 88 additions and 5 deletions

View File

@@ -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

View File

@@ -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():

View File

@@ -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',

View File

@@ -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")

View File

@@ -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:

View File

@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as file:
setuptools.setup(
name="octosuite",
version="3.0.4",
version="3.1.0",
author="Richard Mwewa",
author_email="rly0nheart@duck.com",
packages=["octosuite"],