mirror of
https://github.com/Pennyw0rth/NetExec
synced 2026-06-06 16:34:30 +00:00
fix camelcase and logger import
This commit is contained in:
+122
-121
@@ -1,5 +1,4 @@
|
||||
import datetime
|
||||
import logging
|
||||
import struct
|
||||
import random
|
||||
from six import b
|
||||
@@ -7,224 +6,226 @@ from six import b
|
||||
from pyasn1.codec.der import decoder, encoder
|
||||
from pyasn1.type.univ import noValue
|
||||
|
||||
from impacket.krb5.asn1 import AP_REQ, AS_REP, TGS_REQ, Authenticator, TGS_REP, seq_set, seq_set_iter, PA_FOR_USER_ENC, \
|
||||
Ticket as TicketAsn1, EncTGSRepPart, PA_PAC_OPTIONS
|
||||
from impacket.krb5.asn1 import AP_REQ, AS_REP, TGS_REQ, Authenticator, TGS_REP, \
|
||||
seq_set, seq_set_iter, PA_FOR_USER_ENC, Ticket as TicketAsn1, EncTGSRepPart, \
|
||||
PA_PAC_OPTIONS
|
||||
from impacket.krb5.types import Principal, KerberosTime, Ticket
|
||||
from impacket.krb5.kerberosv5 import sendReceive, getKerberosTGT
|
||||
from impacket.krb5.ccache import CCache
|
||||
from impacket.krb5.crypto import Key, _enctype_table, _HMACMD5
|
||||
from impacket.krb5 import constants
|
||||
|
||||
def kerberos_login_with_S4U(domain, hostname, username, password, nthash, lmhash, aesKey, kdcHost, impersonate, spn, useCache, no_s4u2proxy = False):
|
||||
logger = logging.getLogger("nxc")
|
||||
TGT = None
|
||||
if useCache:
|
||||
domain, user, tgt, _ = CCache.parseFile(domain, username, f"cifs/{hostname}")
|
||||
if TGT is None:
|
||||
from nxc.logger import nxc_logger
|
||||
|
||||
def kerberos_login_with_S4U(domain, hostname, username, password, nthash, lmhash, aesKey, kdcHost, impersonate, spn, use_cache, no_s4u2proxy = False):
|
||||
my_tgt = None
|
||||
if use_cache:
|
||||
domain, _, tgt, _ = CCache.parseFile(domain, username, f"cifs/{hostname}")
|
||||
if my_tgt is None:
|
||||
raise
|
||||
TGT = tgt["KDC_REP"]
|
||||
my_tgt = tgt["KDC_REP"]
|
||||
cipher = tgt["cipher"]
|
||||
sessionKey = tgt["sessionKey"]
|
||||
if TGT is None:
|
||||
userName = Principal(username, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
|
||||
logger.debug("Getting TGT for user")
|
||||
tgt, cipher, _, sessionKey = getKerberosTGT(userName, password, domain,
|
||||
session_key = tgt["sessionKey"]
|
||||
if my_tgt is None:
|
||||
principal = Principal(username, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
|
||||
nxc_logger.debug("Getting TGT for user")
|
||||
tgt, cipher, _, session_key = getKerberosTGT(principal, password, domain,
|
||||
lmhash, nthash,
|
||||
aesKey,
|
||||
kdcHost)
|
||||
TGT = decoder.decode(tgt, asn1Spec=AS_REP())[0]
|
||||
decodedTGT=TGT
|
||||
my_tgt = decoder.decode(tgt, asn1Spec=AS_REP())[0]
|
||||
decoded_tgt=my_tgt
|
||||
# Extract the ticket from the TGT
|
||||
ticket = Ticket()
|
||||
ticket.from_asn1(decodedTGT["ticket"])
|
||||
ticket.from_asn1(decoded_tgt["ticket"])
|
||||
|
||||
apReq = AP_REQ()
|
||||
apReq["pvno"] = 5
|
||||
apReq["msg-type"] = int(constants.ApplicationTagNumbers.AP_REQ.value)
|
||||
ap_req = AP_REQ()
|
||||
ap_req["pvno"] = 5
|
||||
ap_req["msg-type"] = int(constants.ApplicationTagNumbers.AP_REQ.value)
|
||||
|
||||
opts = list()
|
||||
apReq["ap-options"] = constants.encodeFlags(opts)
|
||||
seq_set(apReq, "ticket", ticket.to_asn1)
|
||||
ap_req["ap-options"] = constants.encodeFlags(opts)
|
||||
seq_set(ap_req, "ticket", ticket.to_asn1)
|
||||
|
||||
authenticator = Authenticator()
|
||||
authenticator["authenticator-vno"] = 5
|
||||
authenticator["crealm"] = str(decodedTGT["crealm"])
|
||||
authenticator["crealm"] = str(decoded_tgt["crealm"])
|
||||
|
||||
clientName = Principal()
|
||||
clientName.from_asn1(decodedTGT, "crealm", "cname")
|
||||
client_name = Principal()
|
||||
client_name.from_asn1(decoded_tgt, "crealm", "cname")
|
||||
|
||||
seq_set(authenticator, "cname", clientName.components_to_asn1)
|
||||
seq_set(authenticator, "cname", client_name.components_to_asn1)
|
||||
|
||||
now = datetime.datetime.utcnow()
|
||||
authenticator["cusec"] = now.microsecond
|
||||
authenticator["ctime"] = KerberosTime.to_asn1(now)
|
||||
|
||||
encodedAuthenticator = encoder.encode(authenticator)
|
||||
encoded_authenticator = encoder.encode(authenticator)
|
||||
|
||||
# Key Usage 7
|
||||
# TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator (includes
|
||||
# TGS authenticator subkey), encrypted with the TGS session
|
||||
# key (Section 5.5.1)
|
||||
encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 7, encodedAuthenticator, None)
|
||||
encrypted_encoded_authenticator = cipher.encrypt(session_key, 7, encoded_authenticator, None)
|
||||
|
||||
apReq["authenticator"] = noValue
|
||||
apReq["authenticator"]["etype"] = cipher.enctype
|
||||
apReq["authenticator"]["cipher"] = encryptedEncodedAuthenticator
|
||||
ap_req["authenticator"] = noValue
|
||||
ap_req["authenticator"]["etype"] = cipher.enctype
|
||||
ap_req["authenticator"]["cipher"] = encrypted_encoded_authenticator
|
||||
|
||||
encodedApReq = encoder.encode(apReq)
|
||||
encoded_ap_req = encoder.encode(ap_req)
|
||||
|
||||
tgsReq = TGS_REQ()
|
||||
tgs_req = TGS_REQ()
|
||||
|
||||
tgsReq["pvno"] = 5
|
||||
tgsReq["msg-type"] = int(constants.ApplicationTagNumbers.TGS_REQ.value)
|
||||
tgs_req["pvno"] = 5
|
||||
tgs_req["msg-type"] = int(constants.ApplicationTagNumbers.TGS_REQ.value)
|
||||
|
||||
tgsReq["padata"] = noValue
|
||||
tgsReq["padata"][0] = noValue
|
||||
tgsReq["padata"][0]["padata-type"] = int(constants.PreAuthenticationDataTypes.PA_TGS_REQ.value)
|
||||
tgsReq["padata"][0]["padata-value"] = encodedApReq
|
||||
tgs_req["padata"] = noValue
|
||||
tgs_req["padata"][0] = noValue
|
||||
tgs_req["padata"][0]["padata-type"] = int(constants.PreAuthenticationDataTypes.PA_TGS_REQ.value)
|
||||
tgs_req["padata"][0]["padata-value"] = encoded_ap_req
|
||||
|
||||
# In the S4U2self KRB_TGS_REQ/KRB_TGS_REP protocol extension, a service
|
||||
# requests a service ticket to itself on behalf of a user. The user is
|
||||
# identified to the KDC by the user"s name and realm.
|
||||
clientName = Principal(impersonate, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
|
||||
# identified to the KDC by the user's name and realm.
|
||||
client_name = Principal(impersonate, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
|
||||
|
||||
S4UByteArray = struct.pack("<I", constants.PrincipalNameType.NT_PRINCIPAL.value)
|
||||
S4UByteArray += b(impersonate) + b(domain) + b"Kerberos"
|
||||
s4u_byte_array = struct.pack("<I", constants.PrincipalNameType.NT_PRINCIPAL.value)
|
||||
s4u_byte_array += b(impersonate) + b(domain) + b"Kerberos"
|
||||
|
||||
# Finally cksum is computed by calling the KERB_CHECKSUM_HMAC_MD5 hash
|
||||
# with the following three parameters: the session key of the TGT of
|
||||
# the service performing the S4U2Self request, the message type value
|
||||
# of 17, and the byte array S4UByteArray.
|
||||
checkSum = _HMACMD5.checksum(sessionKey, 17, S4UByteArray)
|
||||
# of 17, and the byte array s4u_byte_array.
|
||||
checksum = _HMACMD5.checksum(session_key, 17, s4u_byte_array)
|
||||
|
||||
paForUserEnc = PA_FOR_USER_ENC()
|
||||
seq_set(paForUserEnc, "userName", clientName.components_to_asn1)
|
||||
paForUserEnc["userRealm"] = domain
|
||||
paForUserEnc["cksum"] = noValue
|
||||
paForUserEnc["cksum"]["cksumtype"] = int(constants.ChecksumTypes.hmac_md5.value)
|
||||
paForUserEnc["cksum"]["checksum"] = checkSum
|
||||
paForUserEnc["auth-package"] = "Kerberos"
|
||||
pa_fo_user_enc = PA_FOR_USER_ENC()
|
||||
seq_set(pa_fo_user_enc, "userName", client_name.components_to_asn1)
|
||||
pa_fo_user_enc["userRealm"] = domain
|
||||
pa_fo_user_enc["cksum"] = noValue
|
||||
pa_fo_user_enc["cksum"]["cksumtype"] = int(constants.ChecksumTypes.hmac_md5.value)
|
||||
pa_fo_user_enc["cksum"]["checksum"] = checksum
|
||||
pa_fo_user_enc["auth-package"] = "Kerberos"
|
||||
|
||||
encodedPaForUserEnc = encoder.encode(paForUserEnc)
|
||||
encoded_pa_for_user_enc = encoder.encode(pa_fo_user_enc)
|
||||
|
||||
tgsReq["padata"][1] = noValue
|
||||
tgsReq["padata"][1]["padata-type"] = int(constants.PreAuthenticationDataTypes.PA_FOR_USER.value)
|
||||
tgsReq["padata"][1]["padata-value"] = encodedPaForUserEnc
|
||||
tgs_req["padata"][1] = noValue
|
||||
tgs_req["padata"][1]["padata-type"] = int(constants.PreAuthenticationDataTypes.PA_FOR_USER.value)
|
||||
tgs_req["padata"][1]["padata-value"] = encoded_pa_for_user_enc
|
||||
|
||||
reqBody = seq_set(tgsReq, "req-body")
|
||||
req_body = seq_set(tgs_req, "req-body")
|
||||
|
||||
opts = list()
|
||||
opts.append(constants.KDCOptions.forwardable.value)
|
||||
opts.append(constants.KDCOptions.renewable.value)
|
||||
opts.append(constants.KDCOptions.canonicalize.value)
|
||||
|
||||
reqBody["kdc-options"] = constants.encodeFlags(opts)
|
||||
req_body["kdc-options"] = constants.encodeFlags(opts)
|
||||
|
||||
serverName = Principal(username, type=constants.PrincipalNameType.NT_UNKNOWN.value)
|
||||
server_name = Principal(username, type=constants.PrincipalNameType.NT_UNKNOWN.value)
|
||||
|
||||
seq_set(reqBody, "sname", serverName.components_to_asn1)
|
||||
reqBody["realm"] = str(decodedTGT["crealm"])
|
||||
seq_set(req_body, "sname", server_name.components_to_asn1)
|
||||
req_body["realm"] = str(decoded_tgt["crealm"])
|
||||
|
||||
now = datetime.datetime.utcnow() + datetime.timedelta(days=1)
|
||||
|
||||
reqBody["till"] = KerberosTime.to_asn1(now)
|
||||
reqBody["nonce"] = random.getrandbits(31)
|
||||
seq_set_iter(reqBody, "etype",
|
||||
req_body["till"] = KerberosTime.to_asn1(now)
|
||||
req_body["nonce"] = random.getrandbits(31)
|
||||
seq_set_iter(req_body, "etype",
|
||||
(int(cipher.enctype), int(constants.EncryptionTypes.rc4_hmac.value)))
|
||||
|
||||
logger.info("Requesting S4U2self")
|
||||
message = encoder.encode(tgsReq)
|
||||
nxc_logger.info("Requesting S4U2self")
|
||||
message = encoder.encode(tgs_req)
|
||||
|
||||
r = sendReceive(message, domain, kdcHost)
|
||||
|
||||
tgs = decoder.decode(r, asn1Spec=TGS_REP())[0]
|
||||
|
||||
if no_s4u2proxy:
|
||||
cipherText = tgs["enc-part"]["cipher"]
|
||||
cipher_text = tgs["enc-part"]["cipher"]
|
||||
|
||||
# Key Usage 8
|
||||
# TGS-REP encrypted part (includes application session
|
||||
# key), encrypted with the TGS session key (Section 5.4.2)
|
||||
plainText = cipher.decrypt(sessionKey, 8, cipherText)
|
||||
plaintext = cipher.decrypt(session_key, 8, cipher_text)
|
||||
|
||||
encTGSRepPart = decoder.decode(plainText, asn1Spec=EncTGSRepPart())[0]
|
||||
enc_tgs_rep_part = decoder.decode(plaintext, asn1Spec=EncTGSRepPart())[0]
|
||||
|
||||
newSessionKey = Key(encTGSRepPart["key"]["keytype"], encTGSRepPart["key"]["keyvalue"].asOctets())
|
||||
new_session_key = Key(enc_tgs_rep_part["key"]["keytype"], enc_tgs_rep_part["key"]["keyvalue"].asOctets())
|
||||
|
||||
# Creating new cipher based on received keytype
|
||||
cipher = _enctype_table[encTGSRepPart["key"]["keytype"]]
|
||||
cipher = _enctype_table[enc_tgs_rep_part["key"]["keytype"]]
|
||||
|
||||
#return r, cipher, sessionKey, newSessionKey
|
||||
#return r, cipher, session_key, new_session_key
|
||||
tgs_formated = dict()
|
||||
tgs_formated["KDC_REP"] = r
|
||||
tgs_formated["cipher"] = cipher
|
||||
tgs_formated["sessionKey"] = newSessionKey
|
||||
tgs_formated["sessionKey"] = new_session_key
|
||||
return tgs_formated
|
||||
|
||||
################################################################################
|
||||
# Up until here was all the S4USelf stuff. Now let's start with S4U2Proxy
|
||||
# So here I have a ST for me.. I now want a ST for another service
|
||||
# Extract the ticket from the TGT
|
||||
ticketTGT = Ticket()
|
||||
ticketTGT.from_asn1(decodedTGT["ticket"])
|
||||
ticket_tgt = Ticket()
|
||||
ticket_tgt.from_asn1(decoded_tgt["ticket"])
|
||||
|
||||
# Get the service ticket
|
||||
ticket = Ticket()
|
||||
ticket.from_asn1(tgs["ticket"])
|
||||
|
||||
apReq = AP_REQ()
|
||||
apReq["pvno"] = 5
|
||||
apReq["msg-type"] = int(constants.ApplicationTagNumbers.AP_REQ.value)
|
||||
ap_req = AP_REQ()
|
||||
ap_req["pvno"] = 5
|
||||
ap_req["msg-type"] = int(constants.ApplicationTagNumbers.AP_REQ.value)
|
||||
|
||||
opts = list()
|
||||
apReq["ap-options"] = constants.encodeFlags(opts)
|
||||
seq_set(apReq, "ticket", ticketTGT.to_asn1)
|
||||
ap_req["ap-options"] = constants.encodeFlags(opts)
|
||||
seq_set(ap_req, "ticket", ticket_tgt.to_asn1)
|
||||
|
||||
authenticator = Authenticator()
|
||||
authenticator["authenticator-vno"] = 5
|
||||
authenticator["crealm"] = str(decodedTGT["crealm"])
|
||||
authenticator["crealm"] = str(decoded_tgt["crealm"])
|
||||
|
||||
clientName = Principal()
|
||||
clientName.from_asn1(decodedTGT, "crealm", "cname")
|
||||
client_name = Principal()
|
||||
client_name.from_asn1(decoded_tgt, "crealm", "cname")
|
||||
|
||||
seq_set(authenticator, "cname", clientName.components_to_asn1)
|
||||
seq_set(authenticator, "cname", client_name.components_to_asn1)
|
||||
|
||||
now = datetime.datetime.utcnow()
|
||||
authenticator["cusec"] = now.microsecond
|
||||
authenticator["ctime"] = KerberosTime.to_asn1(now)
|
||||
|
||||
encodedAuthenticator = encoder.encode(authenticator)
|
||||
encoded_authenticator = encoder.encode(authenticator)
|
||||
|
||||
# Key Usage 7
|
||||
# TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator (includes
|
||||
# TGS authenticator subkey), encrypted with the TGS session
|
||||
# key (Section 5.5.1)
|
||||
encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 7, encodedAuthenticator, None)
|
||||
encrypted_encoded_authenticator = cipher.encrypt(session_key, 7, encoded_authenticator, None)
|
||||
|
||||
apReq["authenticator"] = noValue
|
||||
apReq["authenticator"]["etype"] = cipher.enctype
|
||||
apReq["authenticator"]["cipher"] = encryptedEncodedAuthenticator
|
||||
ap_req["authenticator"] = noValue
|
||||
ap_req["authenticator"]["etype"] = cipher.enctype
|
||||
ap_req["authenticator"]["cipher"] = encrypted_encoded_authenticator
|
||||
|
||||
encodedApReq = encoder.encode(apReq)
|
||||
encoded_ap_req = encoder.encode(ap_req)
|
||||
|
||||
tgsReq = TGS_REQ()
|
||||
tgs_req = TGS_REQ()
|
||||
|
||||
tgsReq["pvno"] = 5
|
||||
tgsReq["msg-type"] = int(constants.ApplicationTagNumbers.TGS_REQ.value)
|
||||
tgsReq["padata"] = noValue
|
||||
tgsReq["padata"][0] = noValue
|
||||
tgsReq["padata"][0]["padata-type"] = int(constants.PreAuthenticationDataTypes.PA_TGS_REQ.value)
|
||||
tgsReq["padata"][0]["padata-value"] = encodedApReq
|
||||
tgs_req["pvno"] = 5
|
||||
tgs_req["msg-type"] = int(constants.ApplicationTagNumbers.TGS_REQ.value)
|
||||
tgs_req["padata"] = noValue
|
||||
tgs_req["padata"][0] = noValue
|
||||
tgs_req["padata"][0]["padata-type"] = int(constants.PreAuthenticationDataTypes.PA_TGS_REQ.value)
|
||||
tgs_req["padata"][0]["padata-value"] = encoded_ap_req
|
||||
|
||||
# Add resource-based constrained delegation support
|
||||
paPacOptions = PA_PAC_OPTIONS()
|
||||
paPacOptions["flags"] = constants.encodeFlags((constants.PAPacOptions.resource_based_constrained_delegation.value,))
|
||||
pa_pac_options = PA_PAC_OPTIONS()
|
||||
pa_pac_options["flags"] = constants.encodeFlags((constants.PAPacOptions.resource_based_constrained_delegation.value,))
|
||||
|
||||
tgsReq["padata"][1] = noValue
|
||||
tgsReq["padata"][1]["padata-type"] = constants.PreAuthenticationDataTypes.PA_PAC_OPTIONS.value
|
||||
tgsReq["padata"][1]["padata-value"] = encoder.encode(paPacOptions)
|
||||
tgs_req["padata"][1] = noValue
|
||||
tgs_req["padata"][1]["padata-type"] = constants.PreAuthenticationDataTypes.PA_PAC_OPTIONS.value
|
||||
tgs_req["padata"][1]["padata-value"] = encoder.encode(pa_pac_options)
|
||||
|
||||
reqBody = seq_set(tgsReq, "req-body")
|
||||
req_body = seq_set(tgs_req, "req-body")
|
||||
|
||||
opts = list()
|
||||
# This specified we"re doing S4U
|
||||
@@ -233,19 +234,19 @@ def kerberos_login_with_S4U(domain, hostname, username, password, nthash, lmhash
|
||||
opts.append(constants.KDCOptions.forwardable.value)
|
||||
opts.append(constants.KDCOptions.renewable.value)
|
||||
|
||||
reqBody["kdc-options"] = constants.encodeFlags(opts)
|
||||
req_body["kdc-options"] = constants.encodeFlags(opts)
|
||||
service2 = Principal(spn, type=constants.PrincipalNameType.NT_SRV_INST.value)
|
||||
seq_set(reqBody, "sname", service2.components_to_asn1)
|
||||
reqBody["realm"] = domain
|
||||
seq_set(req_body, "sname", service2.components_to_asn1)
|
||||
req_body["realm"] = domain
|
||||
|
||||
myTicket = ticket.to_asn1(TicketAsn1())
|
||||
seq_set_iter(reqBody, "additional-tickets", (myTicket,))
|
||||
my_ticket = ticket.to_asn1(TicketAsn1())
|
||||
seq_set_iter(req_body, "additional-tickets", (my_ticket,))
|
||||
|
||||
now = datetime.datetime.utcnow() + datetime.timedelta(days=1)
|
||||
|
||||
reqBody["till"] = KerberosTime.to_asn1(now)
|
||||
reqBody["nonce"] = random.getrandbits(31)
|
||||
seq_set_iter(reqBody, "etype",
|
||||
req_body["till"] = KerberosTime.to_asn1(now)
|
||||
req_body["nonce"] = random.getrandbits(31)
|
||||
seq_set_iter(req_body, "etype",
|
||||
(
|
||||
int(constants.EncryptionTypes.rc4_hmac.value),
|
||||
int(constants.EncryptionTypes.des3_cbc_sha1_kd.value),
|
||||
@@ -253,30 +254,30 @@ def kerberos_login_with_S4U(domain, hostname, username, password, nthash, lmhash
|
||||
int(cipher.enctype)
|
||||
)
|
||||
)
|
||||
message = encoder.encode(tgsReq)
|
||||
message = encoder.encode(tgs_req)
|
||||
|
||||
logger.info("Requesting S4U2Proxy")
|
||||
nxc_logger.info("Requesting S4U2Proxy")
|
||||
r = sendReceive(message, domain, kdcHost)
|
||||
|
||||
tgs = decoder.decode(r, asn1Spec=TGS_REP())[0]
|
||||
|
||||
cipherText = tgs["enc-part"]["cipher"]
|
||||
cipher_text = tgs["enc-part"]["cipher"]
|
||||
|
||||
# Key Usage 8
|
||||
# TGS-REP encrypted part (includes application session
|
||||
# key), encrypted with the TGS session key (Section 5.4.2)
|
||||
plainText = cipher.decrypt(sessionKey, 8, cipherText)
|
||||
plaintext = cipher.decrypt(session_key, 8, cipher_text)
|
||||
|
||||
encTGSRepPart = decoder.decode(plainText, asn1Spec=EncTGSRepPart())[0]
|
||||
enc_tgs_rep_part = decoder.decode(plaintext, asn1Spec=EncTGSRepPart())[0]
|
||||
|
||||
newSessionKey = Key(encTGSRepPart["key"]["keytype"], encTGSRepPart["key"]["keyvalue"].asOctets())
|
||||
new_session_key = Key(enc_tgs_rep_part["key"]["keytype"], enc_tgs_rep_part["key"]["keyvalue"].asOctets())
|
||||
|
||||
# Creating new cipher based on received keytype
|
||||
cipher = _enctype_table[encTGSRepPart["key"]["keytype"]]
|
||||
cipher = _enctype_table[enc_tgs_rep_part["key"]["keytype"]]
|
||||
|
||||
#return r, cipher, sessionKey, newSessionKey
|
||||
#return r, cipher, session_key, new_session_key
|
||||
tgs_formated = dict()
|
||||
tgs_formated["KDC_REP"] = r
|
||||
tgs_formated["cipher"] = cipher
|
||||
tgs_formated["sessionKey"] = newSessionKey
|
||||
tgs_formated["sessionKey"] = new_session_key
|
||||
return tgs_formated
|
||||
Reference in New Issue
Block a user