Thứ Tư, 17 tháng 6, 2020

[NahamCon CTF 2020] Web Exploitation WriteUp !

Hello guys ! Long time no write !
Today , I come back to my blog with NahamCon CTF which is held about 1 week ago.
I had solved some web challenges and absorbed many things useful 👅
Let's start!



1.Agent 95


This is the warm-up challenge . The title said everything . 



After some minutes thinking about this notification , I realize that we must use the user-agent of windows 95 . Check it out!



Next step is :





And the flag comes up ! 




2.localghost









It's nothing here except a fat funny ghost 💀

Let's audit the source code for further information !




After some minutes seeking , I find out a JS file . Beautify it , I focus on those lines of code




Bring the string at atob function to the decode base64 page , we easily get the flag :D






3.Phphonebook



The point of this challenge is increased . So I think this not easy like previous challs 
Enter into it !





It seems that this challenge "talks" about LFI - Local File Inclusion .
Check this by input the value of file = phphonebook.php




I think I'm in the right direction :D .
Let's use some php protocol to read furthermore!


http://jh2i.com:50002/index.php/?file=php://filter/read=convert.base64-encode/resource=index.php

 Hmmmm ... Bingo ! I have the Base64 encoding form of source code. Decode and Audit it !

But the index.php source code not contain flag or any clue of it .
...

Let's check phphonebook.php indeed!


PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KICA8aGVhZD4KICAgIDxtZXRhIGNoYXJzZXQ9InV0Zi04Ij4KICAgIDx0aXRsZT5QaHBob25lYm9vazwvdGl0bGU+CiAgICA8bGluayBocmVmPSJtYWluLmNzcyIgcmVsPSJzdHlsZXNoZWV0Ij4KICA8L2hlYWQ+CgogIDxib2R5IGNsYXNzPSJiZyI+CiAgICA8aDEgaWQ9ImhlYWRlciI+IFdlbGNvbWUgdG8gdGhlIFBocGhvbmVib29rIDwvaDE+CgogICAgPGRpdiBpZD0iaW1fY29udGFpbmVyIj4KCiAgICAgIDxpbWcgc3JjPSJib29rLmpwZyIgd2lkdGg9IjUwJSIgaGVpZ2h0PSIzMCUiLz4KCiAgICAgIDxwIGNsYXNzPSJkZXNjIj4KICAgICAgVGhpcyBwaHBob25lYm9vayB3YXMgbWFkZSB0byBsb29rIHVwIGFsbCBzb3J0cyBvZiBudW1iZXJzISBIYXZlIGZ1bi4uLgogICAgICA8L3A+CgogICAgPC9kaXY+Cjxicj4KPGJyPgogICAgPGRpdj4KICAgICAgPGZvcm0gbWV0aG9kPSJQT1NUIiBhY3Rpb249IiMiPgogICAgICAgIDxsYWJlbCBpZD0iZm9ybV9sYWJlbCI+RW50ZXIgbnVtYmVyOiA8L2xhYmVsPgogICAgICAgIDxpbnB1dCB0eXBlPSJ0ZXh0IiBuYW1lPSJudW1iZXIiPgogICAgICAgIDxpbnB1dCB0eXBlPSJzdWJtaXQiIHZhbHVlPSJTdWJtaXQiPgogICAgICA8L2Zvcm0+CiAgICA8L2Rpdj4KCiAgICA8ZGl2IGlkPSJwaHBfY29udGFpbmVyIj4KICAgIDw/cGhwCiAgICAgIGV4dHJhY3QoJF9QT1NUKTsKCiAgICAJaWYgKGlzc2V0KCRlbWVyZ2VuY3kpKXsKICAgIAkJZWNobyhmaWxlX2dldF9jb250ZW50cygiL2ZsYWcudHh0IikpOwogICAgCX0KICAgID8+CiAgPC9kaXY+CiAgPC9icj4KICA8L2JyPgogIDwvYnI+CgoKPGRpdiBzdHlsZT0icG9zaXRpb246Zml4ZWQ7IGJvdHRvbToxJTsgbGVmdDoxJTsiPgo8YnI+PGJyPjxicj48YnI+CjxiPiBOT1QgQ0hBTExFTkdFIFJFTEFURUQ6PC9iPjxicj5USEFOSyBZT1UgdG8gSU5USUdSSVRJIGZvciBzdXBwb3J0aW5nIE5haGFtQ29uIGFuZCBOYWhhbUNvbiBDVEYhCjxwPgo8aW1nIHdpZHRoPTYwMHB4IHNyYz0iaHR0cHM6Ly9kMjR3dXE2bzk1MWkyZy5jbG91ZGZyb250Lm5ldC9pbWcvZXZlbnRzL2lkLzQ1Ny80NTc3NDgxMjEvYXNzZXRzL2Y3ZGEwZDcxOGViNzdjODNmNWNiNjIyMWEwNmEyZjQ1LmludGkucG5nIj4KPC9wPgo8L2Rpdj4KCiAgPC9ib2R5Pgo8L2h0bWw+



and here is that the thing I want . If we input $emergency variable via POST method to server , it may sends back a flag to us . Go on!



Congrat! Done! :D




4.Extraterrestrial



This challenger make me curious from the intro :D . I'm interested in space ,  aliens , time travel ,etc.. So let's check this !



It give us a form and no hint about what to do . So I try to fuzz some payloads in order to test whether the application return error . I try SQL , SSTI , Linux bash , plaintext, and stop at XSS . When I input into this form :
<script>alert("4rth4s")</script>
The web app respond



I thought this is XSS vulnerability . So I try many , many ways to input XSS payload into it .But it didn't work . However , I believed that this vulnerability relate to XSS . After 20 minutes , I decided to try injecy XXE payload ( XML eXternal entity) .


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE rss [
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=index.php"> 
]>
<rss version="2.0">

<channel>
  <title>W3Schools Home Page</title>
  <link>https://www.w3schools.com</link>
  <description>Free web building tutorials</description>
  <item>
    <title>&xxe;</title>
    <link>https://www.w3schools.com/xml/xml_rss.asp</link>
    <description>New RSS tutorial on W3Schools</description>
  </item>
  <item>
    <title>XML Tutorial</title>
    <link>https://www.w3schools.com/xml</link>
    <description>New XML tutorial on W3Schools</description>
  </item>
</channel>

</rss>
I had use this payload  to bypass RootMe challenge about XXE ( I had WU about this in my blog)

Fortunately , It works!



I have the base64 source code of index.php
decode this , I absorb nothing! the flag not in source code 
So, I think my goal is read the file flag.txt
I change the payload
php://filter/read=convert.base64-encode/resource=index.php

 to


file:///flag.txt

and submit ...
The flag comes up !!!






5.Rejected movie sequels

From the title , we can guess this challenge related to SQLi .


We have a form allow any input . Review the source code , I figure out this stuff



the green line of code means : If we set True value to $debug variable , we will see sql_query which is inputed . Check this!





okay , it's true . I realize that my sql query is filtered ,the "space" character is stripped out . My next goal is to force the web page return some sql errors and bypass this filter . hmm .

After few minutes testing and fuzzing , I figure out that the double quote (") make web app return error about sql , and this backend database is likely mysql . 



So , let's bypass the filter . after googling , I think the simple way to bypass this filter is /**/ character . I build a simple payload to figure out the quantity of column in this database
"/**/order/**/by/**/3#
 It returns error ...
Change the guessing column to 2 , still error . Go on and I have the result


  
Just 1 columns in this table of database . Let's figure the name of database :


"/**/union/**/select/**/database()#




We have "rejected_sequel" is the name of this database

Next steps is simple . Find tables_name , columns name , extract data . Let's see those pictures below:



We can see the table named "flag"
Find the column 





the only column named "flag" too . Finally , extract data with the query
"union/**/select/**/*/**/from/**/flag#
Here comes the result


6.official business



There is no hint at the intro of this challenge in my vision .
I try SQLi ,XSS ,XXE,SSTI ,etc.. but nothing appear except authentication errors .
After few hours , I suddenly check robots.txt file and encounter  the source code of this challenge . Lucky !
Audit the source code , I am attracted by those lines :


@app.route("/login", methods=["POST"])
def login():

    user = request.form.get("user", "")
    password = request.form.get("password", "")

    if (
        user != "hacker"
        or hashlib.sha512(bytes(password, "ascii")).digest()
        != b"hackshackshackshackshackshackshackshackshackshackshackshackshack"
    ):
        return abort(403)
    return do_login(user, password, True)
 And I spend 2 hours to find a way which can bypass this condition . I realize that impossble and change the direction .


def load_cookie():

    cookie = {}
    auth = request.cookies.get("auth")
    if auth:

        try:
            cookie = json.loads(binascii.unhexlify(auth).decode("utf8"))
            digest = cookie.pop("digest")

            if (
                digest
                != hashlib.sha512(
                    app.secret_key + bytes(json.dumps(cookie, sort_keys=True), "ascii")
                ).hexdigest()
            ):
                return False, {}
        except:
            pass

    return True, cookie
These blue lines of source code "tell" that we can bypass this authentication via cookie . And our bussiness is to make a payload or script which can force the server send us the bypass cookie . Follow the flow of code , I realize that  how matter the [try:except] block return , the if condition always return True and give us the cookie .

When the cookie is submitted to server , It would be   


json.loads(binascii.unhexlify(auth).decode("utf8"))
So I build a payload :



Next step is subbmit the auth cookie with the value






Reload the page and we get 


7.Flag Jokes




This challenge is all about JWT and how to exploit it .
Prequesite : Basic knowledge about JWT/JWKs/JWS , RSA256 , keypem 

First of all , the webpage give me a login form which allow anyone except admin to login :D
OKay ! Our quest is to login as admin via cookie . The cookie given to us is exactly JWT .


                      
Let's decode it via JWT.io!



Check the header field , in "jku" parameter ,we can see a link to .json file . Enter into it!



This is a JWKs ( Json Web Key set) which is a set of keys which contains the public keys used to verify any JSON Web Token (JWT) issued by the authorization server and signed using the RS256 signing algorithm

We must beware of JKU parameter . It's not a simple place to storage a link . the server will check this value and take data from the link it contains, to compare with signature .

I'm not an expert of this type of challenge , so I spend my time googling and reading some articles about that . After this time , I realize that out goal is to tamper the data of JWT token : change user to admin , and MUST build a new value of JKU parameter

the First goal , tamper data , change user to admin. We can change directly at the website above or some tool .



Next step , more complexible, change the value of JKU parameter . the current value is a link , so we must have a link that direct to json file with OUR JWKs . The aim is authentication , JWKs must be matched with the Signature . Our goal is to completely make a new authentication chain, remove anything related to current admin ! :D 

Thanks to google . I find a place which can generate a new JWKs for my need . 


Generate !


Cool! So my new "kid" parameter value is "4rth4s" (optional) . Remember to change at JWT .

Next step , find a place to storage this Jwks . I find It ,too . And Finally , we want the new key pairs (PUBLIC key and PRIVATE key) which is converted from this JWks  . This stuffs have a "relationship" to each orther. I use 
to convert my Jwks to the new public key and private key - which can make my Signature verified 

Now I have the completely new decoded token .The server will check the validation of JWS , ensure It matched with Json File we provided .



So , let's submit it :D !


Congrat! 

Done!

Happy Hacking!







Phổ Biến