Zip Password functionality works wrong - python

I have a paradoxon, that I just cannot explain.
In short: I built a python script that is supposed to crack a zipped file, which is password protected.
This is what I've done:
(1) zip the text file:
zip --password bla zip3.zip myZip So the passphrase is "bla".
(2) Then I use the following Python Script:
import zipfile
import itertools
from itertools import *
import string
import time
That's the basic function, that is supposed to check, if a given password works or not:
def crack(File, pwd):
try:
File.extractall(pwd=str.encode(pwd))
print("\n---- SUCCESS! {0} ----".format(pwd))
except:
print("{0} did not work.".format(pwd))
pass
Here I specify, which characters I want to use for trying:
myLetters = string.ascii_letters
Here I specify, which zip-file I want to crack:
File = zipfile.ZipFile("PATH/TO/MY/zip3.zip", 'r')
Here I specify, how long the password-phrase is:
pwd_len = 3
here I specify, how many possible combinations of the charactes exist:
all_poss = (len(myLetters)**pwd_len)
Here is the procedure for concrete password cracking:
count = 0
start_time = time.time()
for i in range(0,pwd_len+1):
for j in map(''.join, itertools.product(myLetters, repeat=i)):
crack(File, j)
count += 1
print(round((count/all_poss)*100, 1), end='\r')
res_time = time.time() - start_time
print("\n--- {} ---".format(round(res_time,2)))
I use a nested loop, to try every password. If it works, I should get the Success-message. Else I should only see the "doesn't work message".
However...
If I type in my terminal: python3 pwdCracker.py >> out I get a long text file, which contains many many "does not work messages", BUT I also get a whole bunch of "Success-messages", although only ONE ("bla") should be correct.
Here is a little extract:
wN did not work.
---- SUCCESS! wO ----
wO did not work.
wP did not work.`
So apparently "wO" is working.. But why?? I set the password to "bla"! I really can open the file with "wO"... why can that happen??
Hope you can help!

The default zip encryption is known to be weak, and I think you are seeing hash collisions 1,2.
Most encryption methods (including those used in zip files) need a fixed length key, and so the password is hashed to give that key. The hash function used in zip is crc32 (specified here, although it details a different attack) which was designed for error checking rather than cryptographic hashing. Therefore it will be vulnerable to this type of attack.

The old zip format contains a check byte to quickly verify if your password is right or wrong. This check byte is verified against the last byte of the decrypted 'decryption header'.
Since the check byte is, well, only one byte, false positives happen quite frequently (1/256). What bruteforce crackers usually do in these cases is to check against multiple files from the same archive (hence using multiple check bytes).
From PkWare's APPNOTE.TXT:
After the header is decrypted, the last 1 or 2 bytes in Buffer SHOULD
be the high-order word/byte of the CRC for the file being decrypted,
stored in Intel low-byte/high-byte order. Versions of PKZIP prior to
2.0 used a 2 byte CRC check; a 1 byte CRC check is used on versions after 2.0.
This can be used to test if the password supplied is correct or not.
So what you are seeing is just that, false positives.

Related

How can I crack a werkzeug generate_password_hash() hash with hascat?

I created a SHA256 hash of the password 123456 with this.
from werkzeug.security import generate_password_hash
print(generate_password_hash('123456', "sha256"))
And the output is:
sha256$xq5IdqcV$226e9165e4d2c014939ac591b27418d0e9a668b774a64a3e89b41caab0bee724
I tried searching for the mode to use to crack within hashcat. But I wasn't able to find it. Every mode I tried, gave me a token length exception or Separator unmatched. I thought maybe the format of the hash that should be specified is different.
My final goal is to find the correct mode to crack this hash with hashcat; or any other tool to crack these types of hashes(hashes generated with werkzeug generate_password_hash() function)
First off:
SHA256 cannot be "cracked" as in "hacked", by a shortcut or anything, but you can bruteforce SHA256 Hashes.
That means you just try out as many passwords as possible, and look if it matches with the target hash.
To your question: You can crack SHA256 with hashcat in numerous ways, most of the time you want to use a wordlist, a list of passwords it should search through. You can download a lot of them online.
You have to craft your command by following the docs.
hashcat -m 1710 -a 0 {yourHash} {yourList}
-m stands for Mode, 1710 is SHA256
-a Is the attack mode, you can see the different attack modes in the docs above, 0 is Straight
YourHash and Your(Password)List should be self explanatory.

Hashing Password in .py file

how i said in the title, i want the password to be hashed when is saved. Its possible with this?
def __OnClickSaveLoginButton(self):
id = self.idEditLine.GetText()
pwd = self.pwdEditLine.GetText()
if (len(id) == 0 or len(pwd) == 0):
self.PopupNotifyMessage("ID and Password required",self.SetIDEditLineFocus)
return
file_object = open("account.cfg", "w")
file_object.write(id+"\n"+pwd)
self.PopupNotifyMessage("Saved.",self.SetIDEditLineFocus)
file_object.close()
You'll want to use the python hashlib. An example could look something like this:
import hashlib
def valid_password(userid, password):
user = get_user(userid)
pw_hash = hashlib.sha256(password).hexdigest()
if user.hash == pw_hash:
return True
return False
Also I recommend reviewing some password storage best practices noted in this SO
Edit: I used sh256 in this example, but that is more useful as a message digest. A better use would be hashlib.pbkdf2_hmac or another key derivation function. There is a good write up here.
If you're going to hash passwords in Python, as nudies mentioned, hashlib.pbkdf2_hmac is correct.
If you want to save the result in Base64, that's a reasonable option, as it turns it into a character string.
Just remember you also have to store the salt and the number of iterations; choose as high a number of iterations as your CPU can stand.
DO NOT request more bytes of output than the native hash function can support; for instance, PBKDF2-HMAC-SHA-512 caps out at 64 bytes for password hashing; the others less.
I have a fully working example at my github repository, including test vectors for all the normal SHA variants, of which the core piece is
import argparse,hashlib,base64,timeit
BinaryOutput = hashlib.pbkdf2_hmac('sha512',args.password, args.salt, args.iterations, args.outputBytes)
BinaryOutput.encode('base64')

Python with etc/Shadow

so I'm writing this program that needs to check the password hash in etc/shadow and compare it to the password the user entered. I tried encrypting the password with hashlib.sha512, but the result was not the same. I think it's salted some how, but I don't know if it uses a universal salt or how I can get the salt each time.
tldr; I need a way for a user to enter a password, then have the program hash it and check it against the etc/shadow. Any ideas?
Try this https://pypi.python.org/pypi/pam . First link in google by python pam.
Look at distribution package manager for python-pam if exists. Else install with pip or easy_install.
Small example:
>>> import pam
>>> pam.authenticate('fred', 'fredspassword')
False
>>> import crypt
>>> line = 'bob:$1$qda8YAO9$rBiov9uVJlH1/97cbcyEt.:15965:0:99999:7:::'
>>> encript = line.split(':')[1]
>>> encript
--> '$1$qda8YAO9$rBiov9uVJlH1/97cbcyEt.'
>>> i = encript.rfind('$')
>>> salt = encript[:i]
>>> salt
--> '$1$qda8YAO9'
>>> crypt.crypt('bob_password',salt)
--> '$1$qda8YAO9$rBiov9uVJlH1/97cbcyEt.'
>>> encript
--> '$1$qda8YAO9$rBiov9uVJlH1/97cbcyEt.'
The passwd field is not just a SHA-512 hash of the password.*
This is explained in the crypt manpage. The format is $id$salt$hash, where id specifies the hash method (1 for MD5, 2a for Blowfish, 5 for SHA-256, 6 for SHA-512), salt specifies the salt to use with that algorithm, and hash specifies what the result should be.
As the manpage implies, you can actually pass the whole $id$salt$ to the crypt function in place of the salt, and it will automatically use the appropriate algorithm. This wouldn't be too hard to do via, say, ctypes.
At any rate, what you're doing is almost certainly a bad idea. You'll need to run as root in order to have access to /etc/shadow, and you'll need to simulate more than just password verification if you actually want to verify that the user can log in, and of course you'll need to handle secure input and make sure you don't end up saving the password in plaintext somewhere and so on. It's a lot simpler and safer to just let PAM do the work for you.
* I believe that in theory, it can be—if it doesn't start with a $ it's interpreted as some legacy format… presumably meaning it's interpreted as POSIX crypt using the DES algorithm.

Simple programming language with a md5/sha1 hash command?

I'm looking to create a simple brute-force password-cracker which will hash an input from stdin and compare the result to an existing hash (for my securities class).
I've never done any actual programming involving hashes, though, since it's mostly been conceptual/mathematical parts so far. Is there a (relatively) easy-to-learn language which has a simple hash command? A friend of mine recommended Python but I'm not sure if there's anything else out there I could pick up within a day or two. I know a bit of C, but hashing seems relatively complicated and needs additional libraries.
Also, any syntax help with an actual hash command would be appreciated. The program itself needs to be able to support odd hash methods, like hashing a value twice or using a set salt that doesn't change, and be able to take input from stdin (for use with programs like johntheripper).
Assuming that you're only being asked to use the hash functions, and not to implement the hash yourself, Python's hashlib module has routines for md5 and sha1:
[Updated for Python 3, in which hashlib wants bytes, not strings:]
>>> import hashlib
>>> s = 'something to hash'
>>> sb = s.encode("utf8")
>>> hashlib.md5(sb)
<md5 HASH object # 0x7f36f5ce3440>
>>> hashlib.md5(sb).hexdigest()
'6f4815fdf1f1fd3f36ac295bf39d26b4'
>>> hashlib.sha1(sb).hexdigest()
'72668bc961b0a78bfa1633f6141bcea69ca37468'
[Legacy Python 2 version:]
>>> import hashlib
>>> s = 'something to hash'
>>> hashlib.md5(s)
<md5 HASH object # 0xb7714ca0>
>>> hashlib.md5(s).hexdigest()
'6f4815fdf1f1fd3f36ac295bf39d26b4'
>>> hashlib.sha1(s).hexdigest()
'72668bc961b0a78bfa1633f6141bcea69ca37468'
I think python is a fine choice for something like this. It has the hashlib module to start with, and if you need more power, the PyCrypto toolkit is easy to use and supports plenty of cryptographic primitives, including hashing. If you already know some C, then maybe just using that with the openssl libraries will be easier for you to pick up. In any case, it is usually worth the investment to learn a crypto library for your preferred language (especially for a crypto class), because eventually you will want to use something that you won't want to code by hand and be confident that it is implemented correctly.
As for syntax with an actual hash command, here is an example in python with PyCrypto for getting a SHA256 hash (using python 3.2):
import Crypto.Hash.SHA256
to_hash = "hello, how are you?"
sha256 = Crypto.Hash.SHA256.new()
sha256.update(to_hash.encode())
dgst = sha256.hexdigest()
print(dgst)
produces the output
5c1940d2a11cd8b1e256ea4183ba22cddfa7cc0d00610a159bd7f5886d01067a
The hashlib library in python contains the following :
'md5', 'new', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512'
for details check:
http://docs.python.org/release/3.1.3/library/hashlib.html
>>> import hashlib
>>> m = hashlib.md5()
>>> m.update(b"Nobody inspects")
>>> m.update(b" the spammish repetition")
>>> m.digest()
b'\xbbd\x9c\x83\xdd\x1e\xa5\xc9\xd9\xde\xc9\xa1\x8d\xf0\xff\xe9'
>>> m.digest_size
16
>>> m.block_size
64
This small python program suits best for these type of small jobs
hash.py
import hashlib
import sys
try:
hash_name = sys.argv[1]
except IndexError:
print 'Specify the hash name as the first argument.'
else:
try:
data = sys.argv[2]
except IndexError:
print 'Please enter the data to be hashed'
sys.exit()
h = hashlib.new(hash_name)
h.update(data)
print h.hexdigest()
Output
$ python hash.py sha1 password1
e38ad214943daad1d64c102faec29de4afe9da3d
$ python hash.py sha256 password1
0b14d501a594442a01c6859541bcb3e8164d183d32937b851835442f69d5c94e
$ python hash.py md5 password1
7c6a180b36896a0a8c02787eeafb0e4c
No programming language worth its salt can be learned in a few days. You may be able to get the syntax figured out, but not much beyond that. I like this article: http://norvig.com/21-days.html
There is probably not a best programming language for this. I can recommend C#, as it has simple cryptography classes in System.Security.Cryptography.
To find the MD5 hash of a byte array, you can use something like this:
byte[] hash = System.Security.Cryptography.MD5.Create().ComputeHash(myByteArray);
To use SHA1, just replace MD5 with SHA1.
If you want to get the hash of an ASCII string, you can get a byte array like so:
byte[] myByteArray = System.Text.Encoding.ASCII.GetBytes(myString);
An example function for converting a string to a hash:
// At the top of the file:
// using System.Security.Cryptography;
// using System.Text;
byte[] GetHash(string message)
{
return MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(message));
}

Code to verify updates from the Google Safe Browsing API

In order to verify the data coming from the Google Safe Browsing API, you can calculate a Message Authentication Code (MAC) for each update. The instructions to do this (from Google) are:
The MAC is computed from an MD5 Digest
over the following information:
client_key|separator|table
data|separator|client_key. The
separator is the string:coolgoog: -
that is a colon followed by "coolgoog"
followed by a colon. The resulting
128-bit MD5 digest is websafe base-64
encoded.
There's also example data to check against:
client key: "8eirwN1kTwCzgWA2HxTaRQ=="
response:
[goog-black-hash 1.180 update][mac=dRalfTU+bXwUhlk0NCGJtQ==]
+8070465bdf3b9c6ad6a89c32e8162ef1
+86fa593a025714f89d6bc8c9c5a191ac
+bbbd7247731cbb7ec1b3a5814ed4bc9d
*Note that there are tabs at the end of each line.
I'm unable to get a match. Please either point out where I'm going wrong, or just write the couple of lines of Python code necessary to do this!
FWIW, I expected to be able to do something like this:
>>> s = "+8070465bdf3b9c6ad6a89c32e8162ef1\t\n+86fa593a025714f89d6bc8c9c5a191ac\t\n+bbbd7247731cbb7ec1b3a5814ed4bc9d\t"
>>> c = "8eirwN1kTwCzgWA2HxTaRQ=="
>>> hashlib.md5("%s%s%s%s%s" % (c, ":coolgoog:", s, ":coolgoog:", c)).digest().encode("base64")
'qfb50mxpHrS82yTofPkcEg==\n'
But as you can see, 'qfb50mxpHrS82yTofPkcEg==\n' != 'dRalfTU+bXwUhlk0NCGJtQ=='.
Anders' answer gives the necessary information, but isn't that clear: the client key needs to be decoded before it is combined. (The example above is also missing a newline at the end of the final table data).
So the working code is:
>>> s = "+8070465bdf3b9c6ad6a89c32e8162ef1\t\n+86fa593a025714f89d6bc8c9c5a191ac\t\n+bbbd7247731cbb7ec1b3a5814ed4bc9d\t\n"
>>> c = "8eirwN1kTwCzgWA2HxTaRQ==".decode('base64')
>>> hashlib.md5("%s%s%s%s%s" % (c, ":coolgoog:", s, ":coolgoog:", c)).digest().encode("base64")
'dRalfTU+bXwUhlk0NCGJtQ==\n'
c="8eirwN1kTwCzgWA2HxTaRQ==".decode('base64')

Categories

Resources