BLOG - Images architectures

pull/1/head
Swissky 2020-04-11 15:18:52 +02:00
parent 1169fa1c79
commit 7fefdefe13
39 changed files with 18 additions and 18 deletions

View File

@ -5,7 +5,7 @@ title: UYBHYS - Sea Monster Attack & Defense CTF
Last week-end I teamed up with members from [Aperikube](https://www.aperikube.fr) for an Attack/Defense CTF which took place in Brest - France. In this "small" blog post I will write about this experience, the challenges and our methodology :) Last week-end I teamed up with members from [Aperikube](https://www.aperikube.fr) for an Attack/Defense CTF which took place in Brest - France. In this "small" blog post I will write about this experience, the challenges and our methodology :)
![Banner]({{ site.baseurl }}/images/SeaMonsterBanner.png "Banner"){: .center-image } ![Banner]({{ site.baseurl }}/images/SeaMonster/SeaMonsterBanner.png "Banner"){: .center-image }
<!--more--> <!--more-->
@ -23,7 +23,7 @@ All teams had the same virtual machines to secure and attack.
These machines host some services such as Web Servers, RDP etc... We had access to the source code of the binaries and the URL alive.unlock.ctf displayed the status of all teams services. In the following picture you can clearly see Team08 and Team10 didn't patch their RDP. These machines host some services such as Web Servers, RDP etc... We had access to the source code of the binaries and the URL alive.unlock.ctf displayed the status of all teams services. In the following picture you can clearly see Team08 and Team10 didn't patch their RDP.
![Alive]({{ site.baseurl }}/images/SeaMonsterAlive.png "Alive services"){: .center-image } ![Alive]({{ site.baseurl }}/images/SeaMonster/SeaMonsterAlive.png "Alive services"){: .center-image }
In the first 30 minutes we could access our machines and secure them without losing any points, then the scoreboard will update every 20 seconds to decrease your point if a service is down, you also loose point when a team is stealing one of your flag. Based on what we had we mapped the services linked to a flag and 2 columns to check if they were patched and/or exploited. In the first 30 minutes we could access our machines and secure them without losing any points, then the scoreboard will update every 20 seconds to decrease your point if a service is down, you also loose point when a team is stealing one of your flag. Based on what we had we mapped the services linked to a flag and 2 columns to check if they were patched and/or exploited.
@ -68,13 +68,13 @@ TEAM15-RAYMOL
I wasn't paying attention when the organizers told us the account was not `user` as stated in the PDF but in fact `Administrator`. Missing this information, made me try to exploit the machine in order to get an NT AUTORITY SYSTEM shell, I went to the easy path `Eternal Blue`. I wasn't paying attention when the organizers told us the account was not `user` as stated in the PDF but in fact `Administrator`. Missing this information, made me try to exploit the machine in order to get an NT AUTORITY SYSTEM shell, I went to the easy path `Eternal Blue`.
![Windows Eternal Blue]({{ site.baseurl }}/images/SeaMonsterWin.png "Windows Eternal Blue"){: .center-image } ![Windows Eternal Blue]({{ site.baseurl }}/images/SeaMonster/SeaMonsterWin.png "Windows Eternal Blue"){: .center-image }
### RDP - 3389 ### RDP - 3389
However the SMB service was not forwarded by the firewall and we couldn't exploit the service, it seems the intended way was to use `Bluekeep` as the RDP was checked by the bot and the team lose some points until we opened a Port Forward rule. However the SMB service was not forwarded by the firewall and we couldn't exploit the service, it seems the intended way was to use `Bluekeep` as the RDP was checked by the bot and the team lose some points until we opened a Port Forward rule.
![Firewall]({{ site.baseurl }}/images/SeaMonsterFirewall.png "Firewall services"){: .center-image } ![Firewall]({{ site.baseurl }}/images/SeaMonster/SeaMonsterFirewall.png "Firewall services"){: .center-image }
## plc.unlock.ctf ## plc.unlock.ctf
@ -83,9 +83,9 @@ However the SMB service was not forwarded by the firewall and we couldn't exploi
This machine was an easy win, we used [plcscan](https://github.com/meeas/plcscan) to scan the Modbus service on port 502, the PLC description contained the flag. This machine was an easy win, we used [plcscan](https://github.com/meeas/plcscan) to scan the Modbus service on port 502, the PLC description contained the flag.
![Modbus]({{ site.baseurl }}/images/SeaMonsterModbusScan.png "Modbus services"){: .center-image } ![Modbus]({{ site.baseurl }}/images/SeaMonster/SeaMonsterModbusScan.png "Modbus services"){: .center-image }
![PLC]({{ site.baseurl }}/images/SeaMonsterPLC.png "PLC description"){: .center-image } ![PLC]({{ site.baseurl }}/images/SeaMonster/SeaMonsterPLC.png "PLC description"){: .center-image }
{% highlight sql %} {% highlight sql %}
team02.ctf:502 Modbus/TCP team02.ctf:502 Modbus/TCP
@ -118,7 +118,7 @@ It appears we could read the file `file:///etc/bind/zones/unlock.ctf.db`, so we
for i in `seq 1 15`; do echo "Team"$i; curl -s http://team0$i.ctf:8080/index.php?ip=file%3A%2F%2F%2Fetc%2Fbind%2Fzones%2Funlock.ctf.db | grep UYB; done for i in `seq 1 15`; do echo "Team"$i; curl -s http://team0$i.ctf:8080/index.php?ip=file%3A%2F%2F%2Fetc%2Fbind%2Fzones%2Funlock.ctf.db | grep UYB; done
{% endhighlight %} {% endhighlight %}
![Bind]({{ site.baseurl }}/images/SeaMonsterWWWssrfpath.png "Bind"){: .center-image } ![Bind]({{ site.baseurl }}/images/SeaMonster/SeaMonsterWWWssrfpath.png "Bind"){: .center-image }
We made the mistake to assume a simple filter like `$ip[0] == "1"` would be enough to stop any exploitation on our machine, however we missed the critical point. Another service was available on port 6666, which would display the content of the file using a specificly crafted URL. We saw the exploit in our logs and replayed the URL on the other team to get more flags. We made the mistake to assume a simple filter like `$ip[0] == "1"` would be enough to stop any exploitation on our machine, however we missed the critical point. Another service was available on port 6666, which would display the content of the file using a specificly crafted URL. We saw the exploit in our logs and replayed the URL on the other team to get more flags.
@ -140,26 +140,26 @@ Team4 UYB{41c0136228d5a7db614f89431}
Our patch might have been the worst of all patch history, we made a copy a the current index page with `curl` and then replaced the nostromo service with a `python -m SimpleHTTPServer 3232`. Dirty but efficient ! Our patch might have been the worst of all patch history, we made a copy a the current index page with `curl` and then replaced the nostromo service with a `python -m SimpleHTTPServer 3232`. Dirty but efficient !
![Trade]({{ site.baseurl }}/images/SeaMonsterTrade.jpg "Trade"){: .center-image } ![Trade]({{ site.baseurl }}/images/SeaMonster/SeaMonsterTrade.jpg "Trade"){: .center-image }
### Custom website - Port 80 ### Custom website - Port 80
First part of the exploitation was to create an account to access the website and find the SQL injection. The exploitation doesn't need to be logged in, the flag was stored as a plaintext password for the administrator. `SQLmap` and simple `for` loop were enough to exploit the vulnerability and dump the users table. First part of the exploitation was to create an account to access the website and find the SQL injection. The exploitation doesn't need to be logged in, the flag was stored as a plaintext password for the administrator. `SQLmap` and simple `for` loop were enough to exploit the vulnerability and dump the users table.
![SQL]({{ site.baseurl }}/images/SeaMonsterSQL.png "SQL"){: .center-image } ![SQL]({{ site.baseurl }}/images/SeaMonster/SeaMonsterSQL.png "SQL"){: .center-image }
The website contains multiple vulnerabilities, once logged as admin we can access the upload page, even though the HTML upload part was commented. The website contains multiple vulnerabilities, once logged as admin we can access the upload page, even though the HTML upload part was commented.
![UPLOAD]({{ site.baseurl }}/images/SeaMonsterWWWuploadcode.png "upload"){: .center-image } ![UPLOAD]({{ site.baseurl }}/images/SeaMonster/SeaMonsterWWWuploadcode.png "upload"){: .center-image }
The PHP backend is doing some checks but it is not enough to prevent the upload of a PHP file in the images directory, we used a payload from [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Upload%20Insecure%20Files/Picture%20Metadata/PHP_exif_system.jpg) and then executed our commands with `http://team12.ctf/images_import/PHP_exif_system.php?c=whoami`. Unfortunately the CTF ended when we got our command exec... (otherwise we might have been able to exploit EternalBlue against the Windows machine and grab the flag located in C:\flag). The PHP backend is doing some checks but it is not enough to prevent the upload of a PHP file in the images directory, we used a payload from [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Upload%20Insecure%20Files/Picture%20Metadata/PHP_exif_system.jpg) and then executed our commands with `http://team12.ctf/images_import/PHP_exif_system.php?c=whoami`. Unfortunately the CTF ended when we got our command exec... (otherwise we might have been able to exploit EternalBlue against the Windows machine and grab the flag located in C:\flag).
Even if you had patched these vulnerabilities in the website, there were two backup folders `site.bak` and `site_save` to remove. Even if you had patched these vulnerabilities in the website, there were two backup folders `site.bak` and `site_save` to remove.
![Backup]({{ site.baseurl }}/images/SeaMonsterWWWtree.png "Backup"){: .center-image } ![Backup]({{ site.baseurl }}/images/SeaMonster/SeaMonsterWWWtree.png "Backup"){: .center-image }
## Final Thought ## Final Thought
The CTF was great, the infrastructure worked flawlessly and the challenge difficulty was balanced enough to let the team understand, patch and exploit them during the 5 hours timeframe. We finished 1st but I would like to thank all the teams for their fair-play and the organisers for the event. Also thank you to the different sponsors ;) The CTF was great, the infrastructure worked flawlessly and the challenge difficulty was balanced enough to let the team understand, patch and exploit them during the 5 hours timeframe. We finished 1st but I would like to thank all the teams for their fair-play and the organisers for the event. Also thank you to the different sponsors ;)
![Scoreboard]({{ site.baseurl }}/images/SeaMonsterScoreboard.jpg "Scoreboard"){: .center-image } ![Scoreboard]({{ site.baseurl }}/images/SeaMonster/SeaMonsterScoreboard.jpg "Scoreboard"){: .center-image }

View File

@ -5,7 +5,7 @@ title: HIP19 Writeup - Meet Your Doctor 1,2,3
Last wednesday I was in the Hack In Paris event for the 3rd time. As always there were some great conferences and challenges, and a new competition called "Hacker Jeopardy" which was very fun! During the Wargame I focused my time on Web challenges based on the `graphql` technology which was new to me, you will find below my writeups for the `Meet Your Doctor` challenges. Last wednesday I was in the Hack In Paris event for the 3rd time. As always there were some great conferences and challenges, and a new competition called "Hacker Jeopardy" which was very fun! During the Wargame I focused my time on Web challenges based on the `graphql` technology which was new to me, you will find below my writeups for the `Meet Your Doctor` challenges.
![HIP Wargame 2019]({{ site.baseurl }}/images/hip19_wargame.png "HIP Wargame 2019"){: .center-image } ![HIP Wargame 2019]({{ site.baseurl }}/images/HIP19/hip19_wargame.png "HIP Wargame 2019"){: .center-image }
<!--more--> <!--more-->
@ -41,7 +41,7 @@ type Mutation {
A simple query `{Doctors{id email password}}` was enough to extract all doctors' email and password. The flag was the password of the Admin doctor : `Now-_Let$|GetSeri0us` A simple query `{Doctors{id email password}}` was enough to extract all doctors' email and password. The flag was the password of the Admin doctor : `Now-_Let$|GetSeri0us`
![GraphQL UI]({{ site.baseurl }}/images/doctors1graphql.png "GraphQL UI") ![GraphQL UI]({{ site.baseurl }}/images/HIP19/doctors1graphql.png "GraphQL UI")
## Meet your doctor 2 - 200 pts ## Meet your doctor 2 - 200 pts
@ -59,7 +59,7 @@ fragment+FullType+on+__Type+{++kind++name++description++fields(includeDeprecated
It is strongly recommended to use `Firefox` to view the server response as it parses JSON an displays it nicely. It is strongly recommended to use `Firefox` to view the server response as it parses JSON an displays it nicely.
![Doctors schema]({{ site.baseurl }}/images/doctors2_schema.png "Doctors schema") ![Doctors schema]({{ site.baseurl }}/images/HIP19/doctors2_schema.png "Doctors schema")
Using GraphQLmap, we got the following structure. Using GraphQLmap, we got the following structure.
@ -101,7 +101,7 @@ Token
In this case `Doctors` have an `options` parameter which accepts JSON. It allows us to specify items linked to the doctors' structure and project their data into the GraphQL response. I saw the following picture in a blog post, it helped me a lot to understand the structure of the query. In this case `Doctors` have an `options` parameter which accepts JSON. It allows us to specify items linked to the doctors' structure and project their data into the GraphQL response. I saw the following picture in a blog post, it helped me a lot to understand the structure of the query.
![GraphMap]({{ site.baseurl }}/images/graphmap.png "GraphMap") ![GraphMap]({{ site.baseurl }}/images/HIP19/graphmap.png "GraphMap")
We can query `{doctors(options: "{\"patients.ssn\" :1}"){firstName lastName id patients{ssn}}}`, don't forget to escape the `"` inside the `options`. We can query `{doctors(options: "{\"patients.ssn\" :1}"){firstName lastName id patients{ssn}}}`, don't forget to escape the `"` inside the `options`.
@ -172,7 +172,7 @@ The injection worked, now we can re-use the payload from the challenge #2 and ex
Obviously we scripted the data extraction in Python, the script below will get the last flag : `4f537c0a-7da6-4acc-81e1-8c33c02ef3b`. Obviously we scripted the data extraction in Python, the script below will get the last flag : `4f537c0a-7da6-4acc-81e1-8c33c02ef3b`.
![NOSQL]({{ site.baseurl }}/images/doctors3_nosql.png "NOSQL") ![NOSQL]({{ site.baseurl }}/images/HIP19/doctors3_nosql.png "NOSQL")
At that time we were checking if the content of `r.json()['data']['doctors']` was not empty, in order to abstract the data extraction we now take a check input from the user in order to compare the output. At that time we were checking if the content of `r.json()['data']['doctors']` was not empty, in order to abstract the data extraction we now take a check input from the user in order to compare the output.

File diff suppressed because one or more lines are too long

View File

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View File

Before

Width:  |  Height:  |  Size: 179 KiB

After

Width:  |  Height:  |  Size: 179 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

Before

Width:  |  Height:  |  Size: 271 KiB

After

Width:  |  Height:  |  Size: 271 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 132 KiB

View File

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 105 KiB

View File

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

View File

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 83 KiB

View File

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

View File

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB

View File

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 96 KiB

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Before

Width:  |  Height:  |  Size: 216 KiB

After

Width:  |  Height:  |  Size: 216 KiB

View File

Before

Width:  |  Height:  |  Size: 220 KiB

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 954 KiB