Hi, I am vow. I participated IRIS CTF 2024 and played with Black Bauhinia.
I tried to make this write up as beginner friendly as possible so that everybody can follow and learn something.
Special thanks to harrier, hollow, TheHakkaman and th1k4n for solving the challenges with me.
OSINT is a new category added to IRIS CTF this year. So, what is OSINT?
Open-Source Intelligence (OSINT) is publicly available information appearing
in print or electronic form. This includes radio, television, newspapers, journals, the Internet, commercial databases, videos, graphics, and drawings.
To simply put, most of the time, OSINT CTF challenges require you to search and gather information from publicly available sources in order complete the challenge.
Some common OSINT challenges include:
So, how does one get better at OSINT?
Now, let's dive into the challenges.
Iris visited this cool shop a while back, but forgot where it was! What street is it on?
Hint! FYI: The flag is all lowercase and _ for spaces. Please remove all accent marks if there are any. Wrap your answer in irisctf{}
.
We are given an image, and are tasked to find the street name of where this image was captured.
This is a Geolocation OSINT challenge, and from the hint we can guess that the street name is likely to contain spaces and accent marks.
If we read the title carefully, Czech Where? is obviously a hint for where the image was taken, Czech Republic. However, there are lots of streets in Czech Republic so we need to narrow down our scope.
The image itself doesn't really provide us with any clues except for the N:20 address top of the door.
Fortunately, Google offers a very useful feature called "Search by Image" that can help us. Basically, you could upload an image, and Google will show webpages that have similar images (Remember to change the scale to the whole image!).
Looking at the results, the first returned image looks very similar to our image:
Visiting the webpage, we can see it is a travel blog of a Japanese person.
If we scroll down the blog, we would see our image, but let's focus on the text first. Perhaps it may give us some clues as to where the image was taken at?
If we copy and paste some text into DeepL Translator, we get the following translation:
夏旅☆チェコ 黄金小路@プラハ城①
次にやってきたのは黄金小路。
プラハ城内にある細い小道に昔ながらの家が並んでいる。
だいたいそこはお土産屋になっているのですが、ココもチケットに含まれているとはいえ、お金を払わなければ入れないんですね~。
昔の家々を見ることができるという意味では、タダでは入らせないってことなのかしら。
============================================================
Summer Trip☆Czech Republic Golden Alley at Prague Castle (1)
Next came Golden Alley.
This is a narrow alley inside Prague Castle lined with old-fashioned houses.
That's usually where the souvenir shops are, but even though this place is included in the ticket, you have to pay to get in!
I wonder if they don't let you enter for free in the sense that you can see the old houses.
Seems like it is mentioning a place called "Golden Alley", that is located in Czech Republic near Prague Castle. If we Google these keywords, we get this:
We now know that this image is likely to be taken in Czech Republic near Prague Castle, at a place called "The Golden Lane".
Now, we can proceed to search for this place using Google Maps Street View.
For those who don't know, Google Maps has something called "Street View" which provides interactive panoramas from positions along many streets in the world, which gives you the experience of "walking in a street" within your computer.
Typing "The Golden Lane" leads us to here:
Let's take a look using "Street View" (Just drag the "Orange Person" at the bottom right, and place it on the blue lines that appear!)
Looking around the streets, we see this building:
If we compare the 2 images, we can see that there are many similarites:
At this point, we are quite confident that this is the building we are looking for.
Now, we just have to check the street name, modify it so it matches our flag format, and we would have our first flag!
irisctf{zlata_ulicka_u_daliborky}
Google Image Search is very useful for finding similar images on the web. Other good options include:
For geolocation challenges, Google Street View is often the go-to solution.
Language Barrier? DeepL and Google Translate are here to help.
Iris and her assistant are away on vacation. She left an audio message explaining how to get in touch with her assistant. See what you can learn about the assistant.
Transcript: Hello, you’ve reached Iris Stein, head of the HR department! I’m currently away on vacation, please contact my assistant Michel. You can reach out to him at michelangelocorning0490@gmail.com. Have a good day and take care.
This time, our goal is to learn more about the assistant of Iris Stein. Reading the transcript, we can learn a few facts:
Given that we have an email address, why not try sending a message to it?
Note: It is highly recommended to use a non-personal email address, for safety and privacy reasons.
After sending an email to Michel, we received this reply:
Dear,
Thank you for the email, I'm currently away on vacation to celebrate New Years! If you would like a quicker response, feel free to reach out to my social media. I mostly talk about birds on it.
Have a great start to the year, and take care!
From this reply, we learn something new, which is that Michel has his own social media account and mostly talk about birds on it. Let's try searching for it.
Hmm, it seems like searching for "Michelangelo Corning" or "Michelangelo Corning Social Media" or "Michelangelo Corning [Insert Popular Social Media Platform Name Here]" did not provide any relevant information.
Maybe trying a different search engine might yield better results?
There are many search engines in the world besides Google, here are a few other examples:
Let's try using DuckDuckGo, repeating the same keywords and we get this:
Let's check out this Instagram account:
Several important details stand out here:
This is probably the social media we are searching for, let's take a look at the posts! But, Instagram requires you to have an account in order to access the platform.
Nowadays, many websites require you to register an account to access their tools or platform, but sometimes we prefer not to sign up with our personal email accounts, either to avoid spam or for privacy reasons.
A solution to this problem would be to use a "Disposable Email".
Disposable emails are temporary email addresses which are deleted after a certain time period, and most can only receive emails. They take very little time to create and are easily disposable, which is good if you want to access online materials without releasing your contact information. A good recommendation would be TempMail.
For some larger platforms, they may have checks that prevent email addresses with unusual email domains from signing up. In that case, your only option would be to use your personal email, or to create a new email address with a commonly known email doamin like Gmail.
After creating an account, we can take a look at Michel's posts. If we take a closer look at the images, descriptions and comments, we would find something interesting:
The flag is located in the description of this post!
irisctf{pub1ic_4cc0unt5_4r3_51tt1ng_duck5}
When searching for information, don't just read the descriptions, sometimes go through the comments! They might provide additional information.
People tend to use their real names for their personal email address, as it is easier for others to identify them and feels more professional.
There are many search engines in the world, each might yield different search results.
Disposable emails are handy, use them if you don't want to give out your personal information.
============================================================
Usually when creating social media accounts for OSINT challenges, challenge authors most of the time won't use real people's faces. Therefore, these profile images are mostly like AI generated.
There is a website called ThisPersonDoesNotExist, which generates random human faces using AI. Since AI is not perfect, this explains why the profile pictures sometimes look a bit uncanny. (Their stares sometimes haunt me lol)
Security questions can be solved by reconnaissance. The weakest link in security could be the people around you.
For this challenge, we are given a link to a website where we have to fill in some personal information related to Iris Stein. Here are the questions:
Reading the description, the second sentences hints that for this challenge, we are going to have to look at other people's social media accounts or websites in order to gain more information about Iris Stein.
Since we already have Michel's Instagram account, let's take a look at who Michel is following:
We see that Michel is following Iris Stein, how about let's take a look at Iris Stein's Instagram account?
Taking look at Iris Stein's followers, it seems she is mainly following other companies' social media accounts (with the exception of Michel), so it is unlikely we can find any more useful information here.
Again, let's go through Iris' posts and see what we can find!
Reading the posts, we can learn a few facts:
But the more useful information for this task would be:
Remember the description? "The weakest link in security could be the people around you." Maybe we can find more information in her mother's social media account.
After completing the exercise (or checking the answers), you should know what to look for. Using different search engines, an interesting result popped up when I searched the key words using DuckDuckGo, and upon clicking the result, we arrive here:
Let's do a check:
This does seem like the account we should be looking for.
Taking a deeper look, we see that there is a section called "Life Events":
And it seems like it has Elaina and Iris' birthdays! Let's take a look at Iris' birthday:
At this point, we know Iris' birth date, which allows us to determine Iris' age. We also got an image and a hint to where Iris was born.
Google Image Search is here to save the day!
Using the image of the hospital room for a reverse search gives us the following queries:
It is easy to see that the first query is exactly the same as our image. Therefore, we can conclude that Iris was born in Lenox Hill Hospital.
We now have two pieces of information to fill in the form, but we are still missing the last piece of the puzzle - "What company does Iris work for?"
Not much more information can be found within the social media accounts and posts, so let's go back to the drawing board. Since it is asking something related to work, we can try searching in one of the biggest business networking platforms - LinkedIn.
After signing up an account for LinkedIn and searching for "Iris Stein", we are met with an overwhelming amount of results:
How can we find the correct account? We have some clues in hand:
Looking back at LinkedIn, there does exist an account that looks very similar to the images above:
In fact, this account has the exact image as the first image above, just with different color grading and without the heart emojis. We can also see that this Iris Stein in LinkedIn is also a HR of a company.
At this point we can pretty much confirm that this LinkedIn account belongs to the same Iris Stein we are searching for, and we can conclude that Iris Stein works for Mountain Peak Hiring Agency.
Now, we just have to submit the answers and get our flag!
irisctf{s0c1al_m3d1a_1s_an_1nf3cti0n}
Some people may have more than one social media account, keep searching at different platforms.
Don't just focus on the person you are searching, pay some attention to the people close them.
Recently, Iris's company had a breach. Her password's hash has been exposed. This challenge is focused on understanding Iris as a person.
Hash: $2b$04$DkQOnBXHNLw2cnsmSEdM0uyN3NHLUb9I5IIUF3akpLwoy7dlhgyEC
The flag format is irisctf{plaintextPassword}
Hints:
============================================================
The write up author used Python, a programming language, to solve this challenge. This write up will assume that the reader has basic knowledge in using Python.
If you want to learn Python from scratch, I would recommend these 2 sites:
But most importantly, try coding something yourself. Experience is the best teacher. 😀
Before attempting this challenge, we need to understand what is a "Hash".
A hash function is any function that can be used to map data of arbitrary size to fixed-size values. The values returned by a hash function are called hashes. Hashing is mainly used for data validation purposes.
Hash functions are commonly used as an effective cryptographic tool because of the following properties:
In short, hashing is a secure data validation method. It is not meant to be decrypted (most of the time).
That is the very basic idea of hashing. So our goal is to find a password that matches the hash, which would then be our flag. But first, we need to know what type of hash function is used for this hash, as there are many types of hash functions.
Throwing the hash into Hash Analyzer, we learn that the hash is made with a hash function called bcrypt.
So the main question remains: How do we find the password?
Based on the hints, we can have a rough idea of how the password looks like:
Since this is an OSINT challenge (not a cypto challenge), we can guess that the password should be composed of words and numbers that were mentioned, or related to the theme of the posts.
Let's start off with numbers. It is very common to add numbers to password as it would make the password more secure, however most people would use numbers that have special meaning to them, perhaps the date of an anniversary, a birthday, etc.
If we recall the post where we found Iris' mother's name, there is something important written there:
It seems that Iris mother's birthday is important to Iris, and it is common knowledge that dates are represented using numbers. Checking back the Facebook page:
We see that Elaina Stein was born in 9th April, 1965, however when we click into the life event, we can see that Elaina was in fact born in 8th April, 1965.
The correct date should be 8th April, 1965.
We will remember this for now.
Now, here comes the big question: What should the 3 words in the password be?
Unfortunately, there is no method to directly determine the words, therefore our only way is to brute force the password using a custom password list, which will be generated using Python.
The first step would be to get a list of potential keywords that might be in the password. Usually the keywords would be something of importance like locations, food, items, etc, and usually not words like pronouns, adjectives, etc.
Here is my wordlist consisting of words that I think are important to Iris.
Below is a slight explaination for why I chose each word:
Elaina - Her mother's name, said her birthday was important
Stein - Same as above
Mom - Same as above
Michel - Iris' assistant (Away on Vacation)
Czech - Where she got the lamp (Czech Where?)
Prague - Same as above
Amsterdam - Mentioned in post
Swarovski - Said she love Swarovski sculptures
Sculptures - Same as above
Swans/Swan - Said that they were adorable
Portofino - Said it is a destination that she will always remember
Italy - Portofino is in Italy, also appeared in hashtag
Netherland - Appeared in hashtag
Berlin - Appeared in hashtag
Mimosas - Said it was one of her favourite drinks
Tiramisu - Had a whole post talking about Tiramisu
Milan - A place she tried Tiramisu
Conte - Same as above
Ugolino - Same as above
Starbucks - Same as above
Lenox - Iris' birth place (Personal Breach)
Hill - Same as above
Food - Iris seems to like food and beverages?
Travel - Profile description, said she likes to travel
Traveling - Same as above
Europe - Posts are mainly about places in Europe
Note that my code and wordlist may not be very optimized, therefore the run time of my Python code may be slightly long.
Please also note that since my wordlist may be different from yours, my code may or may not work for your wordlist.
It is highly not recommended to use every word from all the Instagram post.
Still, here is a wordlist that contains all words from Iris' Instagram (contains duplicates).
Now that we have our wordlist, let's do some data processing. The first goal would be to split every word into it's own unique string, remove all unnesscary newline or space characters, and put all the words into a list:
We now have a list of words, but we want a list with all words starting with capital letters only (All words have proper capitalization). Again, we can accomplish this with a little bit of Python:
One neat trick to remove the repeated strings is to first convert the list into a set, then convert it back to a list. (This works because Python sets do not allow duplicates, so it removes them.)
Now here comes the fun part, we are going to use a built-in Python module called "itertools" to help us generate different password combinations. Itertools is very useful when you need to generate permutations and combinations with elements, it is also much faster and memory efficient when compared to using loops.
Our goal would be to select 3 words in order to form a password, and the 3 words can be in any order without repeats.
{A,B,C}, {B,A,C}, {C,A,B}, {A,C,B}, {B,C,A}, {C,B,A}
Now, let's implement this idea in Python, and using our wordlist as our set of elements:
Now, we have a list containing all permutations of our word list!
But wait, we remember that we still have a number (date) to consider.
Recall that Iris’ mother was born in 8th April, 1965, so our date list should look something like this:
This leaves us with 60 different dates (we will be using this), which is good enough, however we know that there are some dates that won't be in the password (such as "8084", "04808").
If you would like to further reduce the number of possible dates, we can modify our code into this:
Which leaves us with just 24 possible combinations.
Now, we have a list of words and a list of dates, we just need to join them together, save it to a text file, and we would have our password list!
Now that we have our password list, it's time for the last step: Finding which password is the correct one.
There are two ways to do this, one is to use a password cracking tool called "Hashcat" (probably the fastest method), the other is to use the "bcrypt" module in Python. Note that you have to install the module using pip.
Prepare two textfiles, one would be your password list, and the other would be your hash list.
In this case the hash.txt should only contain:
$2b$04$DkQOnBXHNLw2cnsmSEdM0uyN3NHLUb9I5IIUF3akpLwoy7dlhgyEC
Now, once you have installed hashcat, you can execute the following command (Linux):
$ hashcat -m 3200 -a 0 password.txt hash.txt
The arguments -m
and -a
means the hashing function and attack method respectively.
-m 3200
is bcrypt hash function, and -a 0
is called "Dictionary attack" (basically means going through all the passwords in a text file to see which passwords match).
Once hashcat finds the password, the output would look like this:
$2b$04$DkQOnBXHNLw2cnsmSEdM0uyN3NHLUb9I5IIUF3akpLwoy7dlhgyEC:REDACTED_FOR_NOW
The "bcrypt" module has a function called checkpw()
, which checks whether a password is equal to a hash and returns a boolean value.
We can then brute force the password with the following code:
Before showing the flag, let's see some statistics for password generation and hash cracking time:
Using my wordlist (27 words, all starting with capital letters and 60 possible date combinations), we get 1053000 different password combinations.
(Roughly 1.0 million combinations)
It took:
If the wordlist can have words that are completely lowercase (56 words, 60 possible date combinations), we would get 8929440 combinations.
(Roughly 8.9 million combinations!)
If we include every single unique word from Iris' Instagram posts, all starting with capital letters, the same 60 date combinations, we would get 749216160 combinations.
(Roughly 749.2 million combinations!!)
Now add lowercase words to the mix, and we have a grand total of 6032649600 combinations.
(Roughly 6.0 billion combinations!!!)
============================================================
As we can see, if we did not choose our wordlist for our password generation wisely, we would have waited for quite a long time (It would take about a month for the last case 💀).
Now, here is the final code and the flag!
irisctf{PortofinoItalyTiramisu0481965}
People tend to use words that are important to them for their passwords, as it is much easier to memorize.
Data preprocessing is very important.
============================================================
And that's it! I hope you learned something from this write up!