gitlabrat 1.2__tar.gz → 1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -183,7 +183,7 @@ cython_debug/
183
183
  # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
184
184
  # and can be added to the global gitignore or merged into this file. However, if you prefer,
185
185
  # you could uncomment the following to ignore the entire vscode folder
186
- # .vscode/
186
+ .vscode/
187
187
 
188
188
  # Ruff stuff:
189
189
  .ruff_cache/
gitlabrat-1.3/PKG-INFO ADDED
@@ -0,0 +1,59 @@
1
+ Metadata-Version: 2.4
2
+ Name: gitlabrat
3
+ Version: 1.3
4
+ Summary: LabRat: GitLab exploitation orchestrator
5
+ Project-URL: Homepage, https://github.com/JChamblee99/Labrat
6
+ Project-URL: Repository, https://github.com/JChamblee99/Labrat.git
7
+ Project-URL: Issues, https://github.com/JChamblee99/Labrt/issues
8
+ Author-email: John Chamblee <conway.py@proton.farm>
9
+ License: GPL-3.0
10
+ License-File: LICENSE
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Requires-Python: >=3.8
20
+ Requires-Dist: beautifulsoup4>=4.9.0
21
+ Requires-Dist: gitpython>=3.1.0
22
+ Requires-Dist: python-gitlab>=3.0.0
23
+ Requires-Dist: requests>=2.25.0
24
+ Description-Content-Type: text/markdown
25
+
26
+ <div align="center">
27
+
28
+ # Labrat
29
+
30
+ **Living rent-free in the walls of your GitLab.**
31
+
32
+ [![PyPI - Version](https://img.shields.io/pypi/v/gitlabrat)](https://pypi.org/project/gitlabrat/)
33
+ [![PyPI - Downloads](https://img.shields.io/pypi/dm/gitlabrat)](https://pypi.org/project/gitlabrat/)
34
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
35
+ [![GitHub last commit](https://img.shields.io/github/last-commit/JChamblee99/LabRat)](https://github.com/JChamblee99/LabRat/commits/main)
36
+
37
+ </div>
38
+
39
+ ---
40
+
41
+ ## Overview
42
+
43
+ Labrat automates workflows for gaining and maintaining access to GitLab instances and CI/CD pipelines.
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ pip install gitlabrat
49
+ ```
50
+
51
+ ## Quick Start
52
+
53
+ ```bash
54
+ # Authenticate to a GitLab instance
55
+ labrat auth -t https://gitlab.example.com -u username -p password
56
+
57
+ # List authenticated agents
58
+ labrat agents ls
59
+ ```
@@ -0,0 +1,34 @@
1
+ <div align="center">
2
+
3
+ # Labrat
4
+
5
+ **Living rent-free in the walls of your GitLab.**
6
+
7
+ [![PyPI - Version](https://img.shields.io/pypi/v/gitlabrat)](https://pypi.org/project/gitlabrat/)
8
+ [![PyPI - Downloads](https://img.shields.io/pypi/dm/gitlabrat)](https://pypi.org/project/gitlabrat/)
9
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
10
+ [![GitHub last commit](https://img.shields.io/github/last-commit/JChamblee99/LabRat)](https://github.com/JChamblee99/LabRat/commits/main)
11
+
12
+ </div>
13
+
14
+ ---
15
+
16
+ ## Overview
17
+
18
+ Labrat automates workflows for gaining and maintaining access to GitLab instances and CI/CD pipelines.
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ pip install gitlabrat
24
+ ```
25
+
26
+ ## Quick Start
27
+
28
+ ```bash
29
+ # Authenticate to a GitLab instance
30
+ labrat auth -t https://gitlab.example.com -u username -p password
31
+
32
+ # List authenticated agents
33
+ labrat agents ls
34
+ ```
@@ -21,7 +21,7 @@ def build_parser(parsers):
21
21
 
22
22
  def handle_list_args(args):
23
23
  # Prepare table
24
- headers = ["Host", "ID", "Username", "Name", "Authenticated", "Is Admin", "Is Bot", "Password", "Private Token"]
24
+ headers = ["Host", "ID", "Username", "Name", "Is Authenticated", "Is Admin", "Is Bot", "Password", "Private Token"]
25
25
  data = []
26
26
 
27
27
  for agent in args.controller.list(args.filter):
@@ -0,0 +1,55 @@
1
+ import datetime
2
+
3
+ import gitlab
4
+
5
+ from labrat.cli import common
6
+ from labrat.controllers.groups import Groups
7
+
8
+ def build_parser(parsers):
9
+ parser = parsers.add_parser("groups", help="Manage GitLab groups")
10
+ subparsers = parser.add_subparsers(dest="command", required=True)
11
+
12
+ list_parser = common.add_filtered_parser(subparsers, "list", handle_list_args, aliases=["ls"], help="List GitLab groups", filter_required=False)
13
+ list_parser.add_argument("-m", "--min-access-level", required=False, type=int, help="Minimum access level to filter groups", default=0)
14
+ list_parser.add_argument("-u", "--user", action="append", required=False, help="Filter agent performing action")
15
+
16
+ create_token_parser = common.add_filtered_parser(subparsers, "create_token", handle_create_token_args, help="Create an access token", filter_required=True)
17
+ create_token_parser.add_argument("-l", "--access-level", required=False, type=int, help="Access level for the access token", default=50)
18
+ create_token_parser.add_argument("-d", "--days", required=False, type=int, help="Number of days until the token expires", default=60)
19
+ create_token_parser.add_argument("-n", "--token-name", required=False, help="Name for the access token", default="project_bot")
20
+ create_token_parser.add_argument("-s", "--scopes", required=False, help="Comma-separated list of scopes for the access token", default="api,read_repository,write_repository")
21
+ create_token_parser.add_argument("-u", "--user", action="append", required=False, help="Filter agent performing action")
22
+
23
+
24
+ parser.set_defaults(controller=Groups())
25
+ return subparsers
26
+
27
+ def handle_list_args(args):
28
+ headers = ["Host", "ID", "Name", "Access Level", "Agents"]
29
+ data = []
30
+
31
+ for group in args.controller.list(args.filter, args.user):
32
+ # color each username by that agent's access level (higher -> brighter)
33
+ usernames = []
34
+ for agent in group.agents:
35
+ colored_username = common.color_access_level(agent.access_level, f"{agent.username} ({agent.access_level})")
36
+ usernames.append(colored_username)
37
+
38
+ # Add group information to data table
39
+ data.append([
40
+ group.host,
41
+ group.id,
42
+ group.name,
43
+ f"{group.access_level} ({gitlab.const.AccessLevel(group.access_level).name.lower()})",
44
+ ", ".join(usernames)
45
+ ])
46
+
47
+ common.print_table(headers, data)
48
+
49
+ def handle_create_token_args(args):
50
+ expiration = (datetime.datetime.now() + datetime.timedelta(days=args.days)).strftime("%Y-%m-%d")
51
+ for group, agent, err in args.controller.create_token(args.token_name, args.access_level, args.scopes.split(","), expiration, args.user, args.filter):
52
+ if err:
53
+ print(f"[!] Failed to create access token for {group.web_url}: {err}")
54
+ else:
55
+ print(f"[+] Successfully created access token for {group.web_url}: {agent.private_token}")
@@ -0,0 +1,81 @@
1
+ import copy
2
+
3
+ from labrat.core.agent import Agent
4
+ from labrat.core.config import Config
5
+ from labrat.core.utils import obj_filter
6
+
7
+ class Groups:
8
+ def __init__(self):
9
+ self.config = Config(authed_only=True)
10
+
11
+ def list(self, filter=None, agent_filter=None, min_level=0):
12
+ """List groups accessible by agents.
13
+
14
+ Keyword arguments:
15
+ - filter: Regex filter and field selection passed to `utils.obj_filter()` for group objects
16
+ - agent_filter: Regex filter and field selection passed to `utils.obj_filter()` for agent objects
17
+ - min_level: Minimum desired access level for agent to return a group
18
+ """
19
+
20
+ group_map = {}
21
+ for section, agent in self.config.filter(agent_filter):
22
+ groups = agent.gitlab.groups.list(all=True)
23
+ for group in groups:
24
+ access_level = self.get_group_access_level(agent, group)
25
+ if access_level < min_level:
26
+ continue
27
+
28
+ # Agent enrichment with shallow copy
29
+ agent_copy = copy.copy(agent)
30
+ agent_copy.access_level = access_level
31
+
32
+ # Group enrichment
33
+ group.host = agent.host
34
+
35
+ # Add group and agent to map
36
+ if group.web_url not in group_map:
37
+ group.agents = [agent_copy]
38
+ group.access_level = access_level
39
+ group_map[group.web_url] = group
40
+ else:
41
+ group_map[group.web_url].agents.append(agent_copy)
42
+ group_map[group.web_url].access_level = max(group_map[group.web_url].access_level, access_level)
43
+
44
+ return [group for group in group_map.values() if not filter or obj_filter(group, filter)]
45
+
46
+ def create_token(self, name, access_level, scopes, expires_at, agent_filter=None, filter=None):
47
+ """ Create Group Access Tokens.
48
+
49
+ Keyword arguments:
50
+ - name: Name of the access token.
51
+ - access_level: Access level of the created PAT.
52
+ - scopes: List of scopes for the created PAT. (e.g. `['read_repository', 'write_repository']`)
53
+ - expires_at: ISO format expiration date for the created PAT.
54
+ - agent_filter: Regex filter and field selection passed to `utils.obj_filter()` for agent objects.
55
+ - filter: Regex filter and field selection passed to `utils.obj_filter()` for group objects.
56
+ """
57
+
58
+ for group in self.list(filter=filter, agent_filter=agent_filter, min_level=50):
59
+ agent = group.agents[0]
60
+
61
+ try:
62
+ req = group.access_tokens.create({
63
+ 'name': name,
64
+ 'access_level': access_level,
65
+ 'scopes': scopes,
66
+ 'expires_at': expires_at
67
+ })
68
+
69
+ section = f"{req.user_id}_{group.id}@{agent.host}"
70
+ group_agent = Agent(agent.url, username=name, private_token=req.token, section=section)
71
+ self.config[section] = group_agent.to_dict()
72
+
73
+ yield group, group_agent, None
74
+ except Exception as e:
75
+ yield group, None, e
76
+
77
+ def get_group_access_level(self, agent, group):
78
+ try:
79
+ return group.members.get(agent.id).access_level
80
+ except Exception as e:
81
+ return 60 if agent.is_admin else 0
@@ -1,6 +1,6 @@
1
1
  # labrat/main.py
2
2
  import argparse
3
- from labrat.cli import agents, auth, projects, users
3
+ from labrat.cli import agents, auth, projects, groups, users
4
4
 
5
5
  def main():
6
6
  parser = argparse.ArgumentParser(
@@ -9,7 +9,7 @@ def main():
9
9
  )
10
10
  subparsers = parser.add_subparsers(dest="command", required=True)
11
11
 
12
- for command in [agents, auth, projects, users]:
12
+ for command in [agents, auth, projects, groups, users]:
13
13
  command.build_parser(subparsers)
14
14
 
15
15
  args = parser.parse_args()
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "gitlabrat"
7
- version = "1.2"
7
+ version = "1.3"
8
8
  description = "LabRat: GitLab exploitation orchestrator"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -13,7 +13,7 @@ authors = [
13
13
  ]
14
14
  license = {text = "GPL-3.0"}
15
15
  classifiers = [
16
- "Development Status :: 3 - Alpha",
16
+ "Development Status :: 4 - Beta",
17
17
  "Intended Audience :: Developers",
18
18
  "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
19
19
  "Programming Language :: Python :: 3",
@@ -30,9 +30,9 @@ dependencies = [
30
30
  ]
31
31
 
32
32
  [project.urls]
33
- Homepage = "https://github.com/JChamblee99/LabRat"
34
- Repository = "https://github.com/JChamblee99/LabRat.git"
35
- Issues = "https://github.com/JChamblee99/LabRat/issues"
33
+ Homepage = "https://github.com/JChamblee99/Labrat"
34
+ Repository = "https://github.com/JChamblee99/Labrat.git"
35
+ Issues = "https://github.com/JChamblee99/Labrt/issues"
36
36
 
37
37
  [project.scripts]
38
38
  labrat = "labrat.main:main"
gitlabrat-1.2/PKG-INFO DELETED
@@ -1,91 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: gitlabrat
3
- Version: 1.2
4
- Summary: LabRat: GitLab exploitation orchestrator
5
- Project-URL: Homepage, https://github.com/JChamblee99/LabRat
6
- Project-URL: Repository, https://github.com/JChamblee99/LabRat.git
7
- Project-URL: Issues, https://github.com/JChamblee99/LabRat/issues
8
- Author-email: John Chamblee <conway.py@proton.farm>
9
- License: GPL-3.0
10
- License-File: LICENSE
11
- Classifier: Development Status :: 3 - Alpha
12
- Classifier: Intended Audience :: Developers
13
- Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
14
- Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.8
16
- Classifier: Programming Language :: Python :: 3.9
17
- Classifier: Programming Language :: Python :: 3.10
18
- Classifier: Programming Language :: Python :: 3.11
19
- Requires-Python: >=3.8
20
- Requires-Dist: beautifulsoup4>=4.9.0
21
- Requires-Dist: gitpython>=3.1.0
22
- Requires-Dist: python-gitlab>=3.0.0
23
- Requires-Dist: requests>=2.25.0
24
- Description-Content-Type: text/markdown
25
-
26
- <div align="center">
27
-
28
- # LabRat
29
-
30
- **GitLab exploitation orchestrator.**
31
-
32
- [![PyPI - Version](https://img.shields.io/pypi/v/gitlabrat)](https://pypi.org/project/gitlabrat/)
33
- [![PyPI - Downloads](https://img.shields.io/pypi/dm/gitlabrat)](https://pypi.org/project/gitlabrat/)
34
- [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
35
- [![GitHub last commit](https://img.shields.io/github/last-commit/JChamblee99/LabRat)](https://github.com/JChamblee99/LabRat/commits/main)
36
-
37
- </div>
38
-
39
- ---
40
-
41
- ## Overview
42
-
43
- LabRat automates common GitLab exploitation workflows: credential spraying, token creation, project enumeration, repository cloning, and bulk updates.
44
-
45
- ## Features
46
-
47
- - **Authentication** — Spray credentials or combo lists across GitLab instances with optional LDAP support
48
- - **Agent management** — Track access tokens and push SSH keys across available agents
49
- - **Project operations** — Enumerate, clone, create access tokens, and perform procedural updates on repositories
50
- - **User enumeration** — List users with advanced filtering and create access tokens
51
-
52
- ## Installation
53
-
54
- ```bash
55
- pip install gitlabrat
56
- ```
57
-
58
- > Requires **Python 3.8+**
59
-
60
- ## Quick Start
61
-
62
- ```bash
63
- # Authenticate to a GitLab instance
64
- labrat auth -t https://gitlab.example.com -u username -p password
65
-
66
- # List authenticated agents
67
- labrat agents ls
68
- ```
69
-
70
- ## Usage
71
-
72
- ```
73
- labrat [-h] {agents,auth,projects,users} ...
74
- ```
75
-
76
- ## Dependencies
77
-
78
- | Package | Purpose |
79
- |---------|---------|
80
- | [python-gitlab](https://python-gitlab.readthedocs.io/) | GitLab API client |
81
- | [GitPython](https://gitpython.readthedocs.io/) | Git repository operations |
82
- | [BeautifulSoup4](https://www.crummy.com/software/BeautifulSoup/) | HTML parsing for session auth |
83
- | [Requests](https://docs.python-requests.org/) | HTTP session management |
84
-
85
- ## Disclaimer
86
-
87
- This tool is intended for **authorized security testing and research only**. The author assumes no liability for misuse. Always obtain proper authorization before testing against any system you do not own.
88
-
89
- ## License
90
-
91
- [GNU General Public License v3.0](LICENSE)
gitlabrat-1.2/README.md DELETED
@@ -1,66 +0,0 @@
1
- <div align="center">
2
-
3
- # LabRat
4
-
5
- **GitLab exploitation orchestrator.**
6
-
7
- [![PyPI - Version](https://img.shields.io/pypi/v/gitlabrat)](https://pypi.org/project/gitlabrat/)
8
- [![PyPI - Downloads](https://img.shields.io/pypi/dm/gitlabrat)](https://pypi.org/project/gitlabrat/)
9
- [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
10
- [![GitHub last commit](https://img.shields.io/github/last-commit/JChamblee99/LabRat)](https://github.com/JChamblee99/LabRat/commits/main)
11
-
12
- </div>
13
-
14
- ---
15
-
16
- ## Overview
17
-
18
- LabRat automates common GitLab exploitation workflows: credential spraying, token creation, project enumeration, repository cloning, and bulk updates.
19
-
20
- ## Features
21
-
22
- - **Authentication** — Spray credentials or combo lists across GitLab instances with optional LDAP support
23
- - **Agent management** — Track access tokens and push SSH keys across available agents
24
- - **Project operations** — Enumerate, clone, create access tokens, and perform procedural updates on repositories
25
- - **User enumeration** — List users with advanced filtering and create access tokens
26
-
27
- ## Installation
28
-
29
- ```bash
30
- pip install gitlabrat
31
- ```
32
-
33
- > Requires **Python 3.8+**
34
-
35
- ## Quick Start
36
-
37
- ```bash
38
- # Authenticate to a GitLab instance
39
- labrat auth -t https://gitlab.example.com -u username -p password
40
-
41
- # List authenticated agents
42
- labrat agents ls
43
- ```
44
-
45
- ## Usage
46
-
47
- ```
48
- labrat [-h] {agents,auth,projects,users} ...
49
- ```
50
-
51
- ## Dependencies
52
-
53
- | Package | Purpose |
54
- |---------|---------|
55
- | [python-gitlab](https://python-gitlab.readthedocs.io/) | GitLab API client |
56
- | [GitPython](https://gitpython.readthedocs.io/) | Git repository operations |
57
- | [BeautifulSoup4](https://www.crummy.com/software/BeautifulSoup/) | HTML parsing for session auth |
58
- | [Requests](https://docs.python-requests.org/) | HTTP session management |
59
-
60
- ## Disclaimer
61
-
62
- This tool is intended for **authorized security testing and research only**. The author assumes no liability for misuse. Always obtain proper authorization before testing against any system you do not own.
63
-
64
- ## License
65
-
66
- [GNU General Public License v3.0](LICENSE)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes