Flaskmetal Alchemist ( Medium)
So we have a flaskmetal in the description.
First we downloaded file and started doing source code analysis. There’s 4 python scripts btw. But wait let’s check the requirements.txt
requirements.txt
has the version of the library download when we use pip3 install -r requirements.txt
Do you remember from the code that we have the option to control the value of order_by
‘s value.
Frustrating thing here was finding a way to cause a time delay as SQLite
doesn’t have a built-in sleep function like sleep()
in MySQL or waitfor delay
in MSSQL.
So, the PoC takes advantage of the function randomblob()
that will generate a random byte string with a length specified as an integer parameter. We generate 200000000
bytes which will cause a time delay of approximately 4 seconds in case the condition returns true, and 10000
bytes in case it returns false, which won’t cause any time delays.
We forgot to say about this website. There’s really nothing tho. Only Atomic numbers,symbols and names.
Let’s submit the reqeusts.
Response is 200 OK. If we now try to set order
to the true payload like CASE WHEN 1=1 THEN atomic_number ELSE name END
, we can see that the first element returned is Lithium. When we then invert the condition to something false like 1=2
we get Actinium, meaning our condition is actually evaluated by the server. Now we can use this condition to get the flag. We could try and parse the whole HTML response to look at what metals were returned. But since the response is always the same for a true condition, and always the same for a false condition, we can just save a hash like md5 of both responses and compare them when we get a response. Then we know what hash corresponds to what type of response, without having to deal with parsing HTML. I made a simple web()
function to test if a certain condition is true or false. Then we can use this function to get the flag.
We can look a bit to see how we could exfiltrate the data with a boolean injection in SQLite. On PayloadsAllTheThings on Github I found a simple way of doing it with a subquery like this:
(SELECT substr(flag,{index},1) FROM flag) = '{character}'
Where for each index of the flag, we try all possible characters and compare them. We keep going for all indexes until we have the whole string. We can do this in python:
EXtravagant (Easy)
Hello I am back again. Let’s start talking right now since I’m really tired.
So this is the challenge. It’s about XML parsing service. I am happy because they added something about XXEi. Let’s visit the URL of the challenge.
So everything’s useless but our important thing is that we can upload XML file and read files. That’s Trial and View XML. You can clearly see it.
Let’s send request to the /upload endpoint.
It says upload sucessful which is 200 OK. But wait we can do that without burp suite lmao. Why am I using burp suite.
So let’s submit.
Alright we can see it’s /etc/passwd file. But in challenge description we could see that flag is stored in /var/www
Let’s re-write the following file:
So what I did? I changed to /var/www/flag.txt instead of /etc/passwd because we don’t need /etc/passwd anymore and now we need flag.
So let’s upload the file:
Alright it was succesful. Now let’s read the file:
And yeah pretty nice challenge with XXEi ( XML External Entity Injection). Pretty easy. Take a care and see you!
Personnel Lookup (Easy)
Hello guys I am back to posting another NahamCon CTF challenge. It’s about Web again so let’s start talking.
So we have a python file there. Let’s download it and open in our visual studio code. But first let’s access to the website.
Hm interesting this is like some lookup for users. Let’s check that python file. Obviously we need to do source code analysis.
It seems like this code runs upon sending a request to the endpoint /
either using GET or POST method. So, let’s try to submit a request to see how the web app responds.
So I typed my name as a rootjkqsta and sent request. Response was 200 OK but if you scroll down, you will se Sorry! No results were found. So what does this means? It means that it’s using re.findall()
method to search for matches in the name we submit in our request. Notice that the name
parameter’s value is embedded into the pattern the regex uses to filter out the results. Let’s inject * and see what response are we gonna get.
Response is 500 Internal server error. The pattern was [A-Z][a-z]*?*[a-z]*?
. Given that the injected *
is placed after ?
mark, it’s normal to get the error we got in the response. But if we can inject into a regex, then we have the chance of telling the findall()
method to return all the results at once including the flag. Using .*
It returned a lot of results, but there’s no flag only some users. But didn’t you know that setting
value is a flag that modifies the standard behavior of the pattern. They all start with a capital letter, but our flag starts with a small letter. In order to get the flag, we need to tell the pattern to ignore the case of the characters in the users
string. Note that re.I
means ignore case, but since the code only accepts numerical values, we need to give re.I
as 2
.
Change setting from 0 to 2 and name from * to .* and send request.
And that is it. flag is here. RCE was really easy lol
DeafCon ( Hard)
Hello guys I am back to posting writeup but now about this tournament NahamCon CTF 2022. It was pretty fun. So let’s start talking.
Alright so I entered my name and my email. And it lead us to the PDF file. And It’s something about ticket. In PDF it is possible to inject server-side XSS and escalate it to the SSRF. I tried injecting XSS but it didn’t worked nor can you escalate it to the SSRF. But however many people thought it was about email bypasses when they tried to inject XSS. No It’s not, you will always get 400 response code. Many of them tried CLRF Injection and etc. So I was in that position too. But let’s think PDF generator and email parser might be vulnerable to SSTI.
So basically SSTI could lead us to the RCE. So It is a unicode normalization.
I was trying a lot of filter bypasses, It’s a blackbox approach after all so you never know what can work on the backend side.
So I noticed that some special characters are getting parsed and normalized when generated by the PDF generator.
By reading about some filter bypasses, I stumbled upon a Unicode normalization filter bypass. So that should work and bypass the parenthesis. Special characters are normalized after the PDF generation.
So I injected the final SSTI payload with the Unicode normalized parenthesis and I got RCE.
SSTI Weaponization without spacebars
Another problem is that RFC-5322 does not accept spacebars in the email regex. We can do to get around this web shell, then pass any command we want to execute into it and get the flag.
So let’s list a files and there’s flag.txt let’s cat it.
And yeah we got RCE and flag is here. This nahamcon challenge was awesome it was rated as a hard one. But for me it is easy one lmao. Hope you enjoyed and hope you learned something, take a care and see you!
Jurassic Park
This is the challenge. You can see It’s about portfolio. Let’s access to the given URL.
You can click nothing at all. But let’s remember some web basics 101. What is the first directory that we should check? Obviously it is robots.txt. Let’s check it.
Okay there’s /ingen/ let’s check it.
And lead us to the index of /ingen and there’s flag.txt. This directory traversal is fun.
And that is it. Flag is here. Hope you enjoyed.
Two For One
So you can see description, it’s not useful. And there’s no source code analysis hm okay.
So I accessed to the given URL. And It is login page and there’s a 2FA OTP. Well I have google authenticator so yeah, it won’t be problem.
So I created my account there. However I had some errors with this challenge I changed many accounts because message was always saying error and error…
So when you create a account you will get this QR. Honestly scan it with google authenticator.
As you can see I had errors so I had to switch accounts like I said. So in response we have this otpauth, but this secret is our secret actually of our account. We need admin’s secret. You might start thinking like me for XSS, stealing cookies lol.
So when I logined in to my account. I saw this. Let’s create new secret.
Alright I typed flag as a name and our value will be <script>alert(1)</script> I typed this as a value because I want to see is it gonna be executed as a JavaScript code. If It gets executed then we can confirm XSS.
Nope It is not executed. Let’s intercept this request in burp suite.
So It takes OTP one time pass. And secret id will return value obviously.
First you will need to got the settings and change 2FA OTP to the -2 and scroll down to the feedback. So I typed this payload. But I started my http.server and ngrok with our 8000 port to see are we gonna get anything after sending the feedback. If we get connection that means we can inject some JavaScript or we can create link a to JavaScript. So let’s see it.
As you can see it was executed. And change in the settings 2FA OTP to the -3 btw. And under that we can see option Reset 2FA. Let’s intercept that in our burp suite. Btw when you click it will give you some QR code.
Alright I sent request and this is what we got as a response. So It didn’t took any parameters, we have our cookie but our response is otpauth again, so this is the URL we’ll be stealing from the admin using that blind XSS vulnerability we discovered in the feedback submission form.
This will be our JavaScript code. So here in this code we have a XMLHttpRequest which is set up here and we will make a POST request to the 2FA we intercepted that in our burp suite, just scroll up. We got a credentials set as a true. And we are gonna exfil train the response so we will get a response in base64 decode, we will create a new request and we will send back to the our ngrok server. Btw don’t forget to update your URL in this code. And update your ngrok address as well. So basically in feedback remove that exploit.js and add 2fa_exfil.js and then submit it.
So it made a request basically we got a response in our ngrok and our http.server, response is 200 OK which is good, but take a look at the http.server just look that flag which is base64 encoded secret. So let’s decode it.
So as you can see we got a new secret. Add that secret to the google authenticator as a Fort Knox. That means that we have admin OTP, let’s use it with the XSS vuln to reset the password and achieve full account takeover.
So this is our new code for new password. Basically we will be able to reset admin’s password. You can take a look at view page source and password,password2,otp will be our parameters also make sure we have in JSON format we have set as JSON stringify. So why did I put password and password2 as a admin? So this will automatically update admin’s password to admin password. And we need to set OTP quickly before new OTP re-generates. Don’t forget to update your ngrok address and port! So remove 2fa.js and change it to the reset_password.js then submit it. And update OTP before sending feedback like I said once. So I had errors again for no reason. So since this is the last part let me explain this in the text. After you submit new feedback you will get something in your http.server. You should get a flag and it will be base64 encoded again. So you will need to decode it. And when you decode it, response should be success not fail. So this means that OTP is valid and we reset the password. Just logout and put admin as a username and admin as a password and put OTP and when you log to the admin’s account click on secret and enter OTP code again and that is it, you will get a flag. This challenge was interesting not gonna lie.
Hacker Ts ( Hard)
Okay description is about Hacker T-shirts. So let’s access to the given URL.
This looks like an CMD Injection lol but it’s not. If we type any command like rootjkqsta example it will write on t-shirt ‘rootjkqsta’ and that is it.
But look in the corner something named as a admin hm.
Alright you can’t access to admin. It says forbidden and there’s localhost:5000. Maybe we can trick the system that we are that location.
So let’s type simple JavaScript code for XSS.
So we didn’t got a alert. Let’s try with document.write
So I put 133 and it gave us 133 on the t-shirt. Let’s do research on google.
Okay I found hacktricks page. Here’s the link https://book.hacktricks.xyz/pentesting-web/xss-cross-site-scripting/server-side-xss-dynamic-pdf
Let’s paste that first one that we coppied.
It does works. We have a tmp directory, pathname, hostname, protocol..
Let’s try this one with <iframe>
This is the <iframe> of the window.location. We just put <iframe> of the same page into the page.
Let’s try to add /admin
We got a error and it is telling us that there’s a problem generating PNG and wkhtmltoimage is being used. The reason why did we got error was because it was appended to the admin which we didn’t append to the window.href.location and it is not valid. But what about having our <iframe> source to be /admin?
Now our message is blocked access to file. It is not possible to access to the admin page. But what if we try to put there http://localhost:5000/admin
And we got a another error. Now we got a parse error. But let’s try with ngrok. First let’s set up our http.server and now let’s use ngrok.
So I loaded script from source and typed my ngrok address and was using exploit.js. And when we submit that we won’t get anything but let’s look what we got in our http.server
So we got this exploit.js file, let’s write that exploit.js so it might be get executed.
So we will be using same payload script src= bc server will load this JavaScript and then it’s gonna start executing. But what is it gonna execute? It is gonna creat new XMLHttpRequest and It’s gonna request to the localhost to the admin page and once this page is onload we will get response text and then base64 encode and it will create new HttpRequest and make request to our ngrok server with the result of the previous response and finally send it. And this last line it will send this request to the top xhr.open, it’s gonna wait for onload, once the page is loaded it’s gonna send another HttpRequest to our local server and with flag obviously. So let’s submit it.
And we got a base64 encoded flag. So decode it in burp suite if you want. And that is it. our JavaScript exploit is executed and yeah there’s a CORS.
Poller (Hard)
So challenge description is useless again lol and there’s no source code analysis again lol. Let’s access to the given URL.
So it is login page again. First I signed up and then logined to my account.
It’s some questions lol. Like flash cards lmao. First I was thinking is this challenge gonna be about SSTI again or SQLi or about CSRF.
Let’s view page source.
Hm look down there. You can see there’s a github link, interesting right? Let’s check that github link.
Oh yeah It’s about Django, if you didn’t know what is Django, well now you will, basically Django is python framework but high level framework like Laravel framework but Laravel is PHP framework and It’s like really “secured” when It’s not and Django is not secured either.
So after some research I found this right one secret key, there were fake one secret key btw. So we need to craft our exploit. Here’s the solution since I’m really tired.
Start nc -lvnp 444 in your VPS and change above cookie to sessionid. And that is it you will get RCE. And flag is yours.
README.md
I think y’all will enjoy reading this NahamCon CTF 2022 writeup that I posted. I wasted whole night to post for you guys. Take a care, have a good night and see you. Also If you are stucked somewhere you can contact me on my twitter: @rootjkqsta and peace out.