Offsec is an Iranian computer security group which holds conferences or CTFs in the computer security area. In their recent challenge, they created a web challenge which is accessible through offsecmag Telegram channel. The challenge started on 16 Dec 2016 and here I will WRITE UP! 🙂
In this post, the write up of the challenge is presented.
The question was simply started with only one hyperlink.
Stage 1: Find the Start Point
The link points to https://offseclabs.ir/start_challenge.php. In the link, there is only some lines of texts:
So, It says Don’t be afraid of empty pages. We’ve started to test the common web attack interfaces:
- Web App Parameters: Which there is not any parameters in start_challenge.php (The body part of HTTP Request)
- Web Server Misconfiguration or Related Exploit: Which was sent in HTTP Header part. (Server is Apache/2.4.18 (Ubuntu) which there is not known vulnerability till the question period)
- Web App Parameters in Header: In which cookies are the main parameters.
None of the above were inside the start_challenge.php, but the page says that do not be afraid of empty pages. So we need to find an empty page! 🙂
We’ve tested some common pages including:
index.php was suspicious. There was no content on the answer page. Again we’ve checked the cookies. Voila! The first stage is done. There was a cookie which will guide us!
Stage 2: Getting deeper, to the source!
The cookie was:
Always_pay_attention_to_cookies = php%7E
The cookie had a url encoded value. php~ was the decoded one. We have reloaded the pages with several different (and vulnerable) content. There was no change in the answer. So we’ve tired up and tried another way.
As mentioned above the server is a Linux based server. ~ in *nix based systems has two main meaning:
- It is used for $HOME_DIR of the user.
- It is added to the end of files which are currently editing. For example if you are editing foo.bar text file, there will be foo.bar~ hidden file on the system too!
Voila! The second stage is done. We’ve tried start_page.php~ (which returned 404 – Not Found) and index.php~ (which returned the index.php source code!) 🙂
Stage 3: goto /admin!
The code is clear some how. It says you send two post parameters namely (__u and __p), the web application will use __u as user name and SHA-1(__p) as password.
There are two user types: guest and admin.
The password for guest is simple to guess. SHA-1(guest) = 35675e68f4b5af7b995d9205ad0fc43842f16450
But SHA-1(admin) <> 64ef3b1ee2815ab80b0741696c41f08925b4a703
So we searched web for cracking the hash. The hash could not be cracked through common services. In the start_challenge.php, it is said to keep tying which means may be SHA-1 calculated recursively.
We have collected a list of KEYs for the admin, including the hyper link, information from Domain, from the certificate and … We have applied SHA-1 over 1000 times on the KEY list, but no one cracked the password.
As the developer used === for comparing the results of SHA-1(__p) and ’64ef3b1ee2815ab80b0741696c41f08925b4a703′, PHP weak type vulnerability could not be applied. For more information about this vulnerability please refer to SANS Penetration Testing Website.
We’ve tested the /admin link with guest user. As we expected, the result should not be accessible by a simple guest user.
But there was a very interesting header in HTTP response from server.
The header may not control the content loaded from the domain. By default browser denies loading contents from different domains than the page’s domain. Some domains allow loading content from other domains for some usages such as loading content from CDNs. If the CDN does not check the domain correctly, it may load contents which the requester is not authorized. This vulnerability is named CORS (Cross Origin Resource Sharing). You may check detailed information from these links: Link 1 Link 2
Stage Three and Half: CORSing the admin!
In the index.php~ there is a link which is passed using __check_link GET parameter. We have created a web page for it and loaded a java script to send a request to the /admin and send back the response to us. We have passed the link to index.php and the page said that the admin will visit our link!
Voila! Admin visited our link and the content loaded for the admin, thus for us!
The content was the flag!
Because of our curiosity, we have checked some other headers. First the User Agent says that the UA is PhantomJS which is a famous headless web kit (or the admin who visited the /admin by our java script request).
The second interesting header was the IP of the admin (22.214.171.124) which is the same for offseclabs.ir, We’ve loaded the page with IP to check if offseclabs.ir is a vhost or not. It was a vhost and the returned content was:
As it is seen, it says lab-cors1-chall! Now we ensured that the CORS was the main challenge. Therefore the flag was:
Thanks OffSec for the interesting challenge.