ISITDTU CTF 2018

[Web] Access Box
Bài này là một bài blackbox hoàn toàn, mặc dù có chút guessing nhưng ý tưởng cũng hay, chỉ có 1 vị trí đăng nhập và không nhiều chức năng có khả năng gây ra lỗi, bằng kinh nghiệm chơi ctf mình đoán lỗi nằm ở vị trí đăng nhập, sau khi fuzzing một hồi với một số payload thông dụng trong tham số username:

'or'1
guest'and'1'='1
...

Tới đây mình có thể xác định có thể có lỗi bảo mật xảy ra. Có thể là SQL Injection, XPath Injection, …
Sau một hồi thử kiểm tra với các logic về SQL Injection mình nhận ra hướng này có nhiều vấn đề phản logic do code hoặc không phải lỗi này.
Tiếp tục thử một số payload để kiểm tra logic XPath Injection, mình xác định 90% là hướng đi này chính xác.
Tới đây, mình chia ra làm 2 nhánh, nhánh thứ nhất là đi tìm kiếm database từ những file xml, sử dụng công cụ wfuzz với bộ payload sưu tầm, mình thấy được database http://35.190.131.105/accounts.xml, có lẽ đây là cách unintend mà nhiều đội làm ra.
Nhánh thứ 2 là tìm kiếm payload để leak được nhiều thông tin nhất có thể. XPath khác với SQL, do đó cách lấy toàn bộ schema là chuyện khó và có thể tốn nhiều thời gian, vì lười nên mình sẽ tìm một payload để tìm kiếm thông tin thay vì khai thác schema.
Payload:

username='and 1=0] | //*[contains(.,'tukhoatimkiem')] | //*['1'='0&password=lala

thay tukhoatimkiem bằng từng kí tự khác
bắt đầu tìm với những từ quen thuộc như admin, user, 4dmin, 4dm1n, ad1min, Adm1n…
mình thấy được 1 kết quả là Adm1n
Tuy nhiên không khả quan nếu cứ fuzzing bằng tay, mình dùng burp để blind từng cụm kí tự và thu được một số kết quả

Adm1n
Administrator
ColdTick
Ez_t0_gu3ss_PaSSw0rd
FromD2VNWithLove
guest

Không có captcha nên mình bruteforce cả username và password theo từ điển trên, thu được username=Adm1n&password=Ez_t0_gu3ss_PaSSw0rd
từ đó có được flag.

Advertisements

Bảo vệ: Shell (linux)

Nội dung này được bảo mật. Hãy nhập mật khẩu để xem tiếp:

CVE 2018-7475

Posted on February 25, 2018
============================================
CVE: CVE-2018-7475
============================================
Credit: 0xd0ff9
============================================
Dates: February 25, 2018
============================================
Vendor: https://www.icewarp.com/
============================================
Product: Ice Warp Mail Server
============================================
Versions Affected: 12.0.3
============================================
Risk / Severity Rating: Low
============================================
Vulnerability Description and Impact:
Description: Cross-site scripting (XSS) vulnerability for webdav/ticket/ URIs in IceWarp Mail.
Impact: context-dependent, such like force victim to change properties or make a open redirect to some malicious site.
For more information: https://www.youtube.com/watch?v=8_3Q80JrMm4&feature=youtu.be
============================================
Solution: Don’t output what user input, or sanitize it first.
============================================

Viettel matesctf round 5 (CoinMining)

When I start with this challenge, firstly I guess SSRF, exploit bot, javascript, exploit something with Cryptocurrency, bla bla…
But solution is SQL Injection.
Firstly, Guessing how it work, I guessed it use action to call function. In the javascript file, i find getDomain() function

Secondly, Guessing the arguments, I guessed this function “getDomain” have one argument and it is coin.

I think I guess very well.
After that, I guessed the query like:

select * from [table_name] where domainName="$_POST['domainName']" and coin="$_POST['coin']"

I guessed the character ‘,” is filtered or replaced, and I guessed the character \ didn’t replace or filter.
so I guessed my solution can be used character [\] to make [‘] be [\’] and escape query.

I used my payload to exploit:

action=doCheck&domainName=smallbox.ir\&coin=or if(substr((select anything from tablewhatyouwant limit 1),§1§,1)=0x§4c§,1,0)-- -
 

and got the flag in the table flag: matesctf: matesctf: fl4g_NT_h3r3_
but I guessed it is not the truly flag.

The real flag is in bingo table: matesctf{sql_f!l73r_i$_n0&_s@’f’_’3’n0ugh!}

Whitehat GrandPrix 2017 ( Web200: 10K )

Mấy ngày nay gặp bao nhiêu là chuyện, từ thọt game tới, fail đồ án, rồi “hack in the bus”…bla, bla, nay mới có thời gian chém gió tự kỉ. Cuộc sống này thật đáng buồn 😥
Trở về chủ đề chính, nay mình sẽ write up bài 10K trong Whitehat GrandPrix 2017 vừa qua 😦 .
Decription:
“`Flipping
Link: 10k.grandprix.whitehatvn.com
Backup: bak.10k.grandprix.whitehatvn.com“`

Tiếp cận:

Sau khi recon xong thì có một cái comment nhỏ trong admin.php cho mình password:

<!-- password:testtttt --!>

Thứ nhất, mình thấy một form upload, hình như là chỉ upload được ảnh thì phải.

Sau khi upload lên một file chuẩn theo đề thì nó sẽ hiện ra cái dòng này:


File name : /var/www/html/web03/images/7826d385de85848b6f9ce7bb301c8c56

File size : 71313 Bytes

MIME type : image/png

Image size : 846 x 547

còn nếu upload 1 file hình bị lỗi thì sẽ fail.
Từ đây, mình rút ra 1 kết luận rằng: “Cái này nó sài tools check ảnh chắc luôn”.
Sau khi google thì:
https://superuser.com/questions/275502/how-to-get-information-about-an-image-picture-from-the-linux-command-line
Với cái output như vậy, nó có thể là exiv2.
Mặt khác, nhìn những thông tin requests thì nó có 2 biến là action và param và nhảy lộn xộn như zuka vậy (trên GET và dưới POST) và không ngoại lệ với cả function upload.

Thứ 2: Mình thấy một trang admin, và có vẻ không có gì hot lắm ngoài cái cookie “data”. Và mình đoán, nó có thể sẽ là step2

Vector:

Từ đó, suy ra, mình có 3 khả năng tấn công:

  1. Sẽ có injection gì đó chỗ command sử dụng exiv2
  2. Sẽ có 1 CVE nào đó của exiv2
  3. Sẽ có thể fuzz được gì ở cái action và param

Case1: Tên file hầu như không gửi lên và file được gửi dạng base64, sau khi fuzzing với trình của mình thì fail toàn tập

Case2: Search hoài mình chỉ thấy 1 cái CVE-2017-6353 là có khả năng bị RCE nhưng khá là khó khai thác, với lại nó cũng cũ lắm rồi 😦

Case3: Fuzzing một hồi thì tự nhiên mình có cái này:

Có mùi XXE, exploit một hồi thì mình thấy nhiều payload entity không chạy được, nhớ lại cái này “SimpleXMLElemen” hình như rất giống cái object. Có thể code sẽ là:


$zuka = new $_REQUESTS['action']($_REQUESTS['param']);

echo $zuka;

Sau khi tìm một hồi list object php thì có cái này hay nè: “SplFileObject”, và đúng là nó hay thật.

OK mình có thể đọc được bất kì file nào, và chắc chắn file cần đọc sẽ là “admin.php” chứ còn gì nữa.

đọc coi:

<?php
include('config.php');
include('classes.php');

#ini_set('display_errors',1);
#error_reporting(E_ALL | E_STRICT);
$handler = new Session();
session_start();
if (isset($_SESSION['auth'])&&(isset($_COOKIE['settings'])) && ($_COOKIE['settings'] == true)) {
echo 'Welcome, TESTER!

';
$cnt = 0 ;
$files = scandir($config['root'].'/images');
$cnt = count($files);
echo 'Total images uploaded: '.$cnt.'

';
//echo 'Link uploaded:

';
//$file = fopen("link.txt", "r") or die("Unable to open file!");
//$link = fread($file,filesize("link.txt"));
//echo "</br>".$link."</br>";
//fclose($file);
#echo "</br>".$_COOKIE['settings']."</br>";
echo "<b>Admin puts S3cr333t here ...</b>";
if ($_COOKIE['settings']) {
$settings = decrypt(base64_decode($_COOKIE['settings']));
#$settings = implode('|',$settings) ;
#echo "Cookie".$settings."</br>";
if(strpos($settings,'S3cr333t') !== false){
echo ' Secret link: '.$config['secret'].'

';
}
}
echo '<a href="logout.php">Log out </a>';
exit();
}

$settings = array();
if (isset($_POST['password'])) {
if (md5($_POST['password']) === $config['password']) {
$_SESSION['auth'] = 1;
$settings = array(
'name' => $_POST['password'],
'sweeting' => ('nahnah ' . escapeshellarg("Hello {$_POST['password']}!")),
);
setcookie('settings', base64_encode(encrypt(serialize($settings))));
header('Location: admin.php');
} else {
echo '
<h1>Access denied</h1>
';
}
exit();
}
?>
<html>
<body>
<b>Enter password:</b>
<form action="admin.php" method="POST">
<input type="text" name="password">
<input type="submit" name="submit" value="GO">
</form>
<a href="logout.php">Log out</a>
<!-- password:testtttt --!>
</body>
</html>

Với kinh nghiệm của một người mù crypto như mình, thì chắc chắn cái này sẽ là một trò crypto (bit flipping).

setcookie('settings', base64_encode(encrypt(serialize($settings))));

Sau khi đọc hết source, thì mình vẫn prefer tìm file config.php hơn là làm crypto, và thế là mình đã đi vào limbo khá lâu. <- noob
Quyết định quăng source vào group dù rất sợ bị chửi 😥 , và sau 5 phút một trùm crypto đã last hit. Thật là ấm ức nếu không giải ra bài này.
Mục đích là chỉ cần chữ "S3cr333t" nằm trong plain text là được, chắc chắn là bit flipping rồi.
Sau khi đọc định nghĩa về Bit Flipping, mình tìm thấy một công thức xor:
enc[2] = chr(ord($enc[2]) ^ ord("8") ^ ord ("S"));
Với "8" là plaintext ban đầu, "S" là kí tự muốn thay thế, "enc[2]" là cipher
Sẽ biến "8" thành "S".
Triển khai xem thử:

<?php
define('MY_AES_KEY', "caigicungduochetluon");
function aes($data, $encrypt) {
    $aes = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
    $iv = "zukano1ahihilalalala";
    mcrypt_generic_init($aes, MY_AES_KEY, $iv);
    return $encrypt ? mcrypt_generic($aes,$data) : mdecrypt_generic($aes,$data);
}

define('MY_MAC_LEN', 40);

function encrypt($data) {
    return aes($data, true);
}

function decrypt($data) {
    $data = rtrim(aes($data, false), "\0");
    return $data;
}
$v = "a:2:{s:4:\"name\";s:8:\"testtttt\";s:8:\"sweeting\";s:25:\"nahnah 'Hello testtttt!'\";}";
echo "
<h1>before</h1>
$v";
$b = array();
$enc = array();
$enc = @encrypt($v);
$enc[2] =  chr(ord($enc[2]) ^ ord("8") ^ ord ("S"));
$enc[3] =  chr(ord($enc[3]) ^ ord(":") ^ ord ("3"));
$enc[4] =  chr(ord($enc[4]) ^ ord("\"") ^ ord ("c"));
$enc[5] =  chr(ord($enc[5]) ^ ord("t") ^ ord ("r"));
$enc[6] =  chr(ord($enc[6]) ^ ord("e") ^ ord ("3"));
$enc[7] =  chr(ord($enc[7]) ^ ord("s") ^ ord ("3"));
$enc[8] =  chr(ord($enc[8]) ^ ord("t") ^ ord ("3"));
$enc[9] =  chr(ord($enc[9]) ^ ord("t") ^ ord ("t"));

$b = @decrypt($enc);
echo "
<h1>After</h1>
$b";

if(strpos($b,"S3cr333t")!==false)
{
	echo "
<h1>Solved</h1>
";
	echo "pl: ".base64_encode($enc);
}
?>


Ơ được nè

Vậy là công thức đúng rồi, lấy enc của server về xor thôi.

wh
Flag: WH{10k$_10k$_10k$}

SVATTT2017 – Mình có lỗi với team

WEB300-1: Bài mình Focus nhất, tâm huyết của lần thi này và kết quả là thất bại.
Flow: Try hard theo con đường CSRF nhưng thất bại.

WEB300-2:
Tuy không phải là một bài mà mình focus nhất, nhưng nếu team thua thì mình cảm thấy có lỗi nhất là bài này.
B1. Làm quen, tìm hiểu:
Thứ đầu tiên đập vào mắt chắc chắn sẽ là “index.php?page=login”, từ cái này mà bất kì ai chơi web cũng sẽ nghĩ tới “file inclusion” để get source và từ đây mình có full bộ source.
Ngoài ra không có gì đặc biệt (robots, git, .idea, .db) khi fuzzing.
B2. Đọc source:
Sau khi đọc đi đọc lại mấy lần, mình rút ra được một số lưu ý:
1. file này /tmp/log/log_request_web300.txt ghi log lại và thêm cái function include($_GET[‘page’].”.php”)
2. Hàm Forget password sử dụng hơi kì cục.
3. Thường xuyên sử dụng hàm sprintf
4. Thêm 2 cái hàm đáng nghi là dns_get_record và mail.
5. XSS chỗ username
6. Có 1 vài chỗ public comment và khả năng là không khai thác được gì.
7. Sử dụng database mysql.

B3. Vấn đề xảy ra:
Ở những notes trên B2, mình đã sắp sếp theo thứ tự tiềm năng để khai thác, và mình dự định sẽ đi theo thứ tự đó.
1. Ở đây, hình như là không có filter gì hết cho việc include 1 file, và nếu thành công ở case này, mình sẽ có được shell bằng cách gieo shell vào log và include cái log lên. Nhưng mình đã try hard thất bại vì không thể bypass được cái .php đằng sau.
2. Đây là case thứ 2 mà mình cảm thấy nó là exploit đẹp nhất. Từ cái flow của tính năng này, mình có thể lấy hết được username, password, email nhưng phải bruteforce. Thứ nhất, cái “username enumeration” sẽ giúp mình đoán username, thứ 2 “weak password”+”unauthen password update” có thể giúp mình lấy được password của bất kì user nào, hơn nữa mình cũng nghĩ cái hàm này openssl_random_pseudo_bytes có thực là an toàn không, thứ 3 email sẽ in ra nếu tồn tại username. Tuy nhiên mình đã thực sự sụp đổ khi phát hiện ra rằng trong code không hề tồn tại đoạn kiểm tra username có phải admin hay không.
3. sprintf, mình luôn mơ là format string sẽ xảy ra nhưng thực sự tối hôm trước mình đã ngủ đủ giấc.
4,5. Tuy là đặc biệt nhưng khai thác rồi mình cũng có được gì đâu.
6. Có vẻ như escape rất kĩ đến nỗi không thêm bất kì đoạn code nào để firewall và theo quan điểm của mình, sẽ không thể là 1 bug truyền thống như thế đối với 1 bài 300 điểm. Tuy nhiên, mình đã sai và vấn đề chính là nó.

B4. Khai thác:
Nếu đã confirm là case số 6 thì khả nghi nhất sẽ là hàm forget password ( vì thường những bài CTF sẽ không có hàm này ).
Vulnerable Code:

       
$update_result = mysqli_query($link, sprintf("update users set password='%s', resetinfo='%s' where username='%s'", $passwordnew,$details, $username)); 

Đoạn này không escape trước khi update và mà dữ liệu thì lấy trong database, do đó nếu ta có thể import được câu sqli vào database rồi thực thi đoạn này thì sẽ có SQLi.
Mình sửa lại code cho dễ debug:

$res = sprintf("update users set password='%s' where username='%s'",$passwordnew, $username);
echo $res;
$update_result = mysqli_query($link,$res);

Khi mình forget username: lala’and’1’=’1

Từ đây, mọi chuyện sẽ chỉ còn là blind theo quy trình:
1. Tạo 1 account có username chứa câu query
2. Forget password username trên
3. Login vào username với password cũ, nếu login được -> query sai, ngược lại -> query đúng.

Server tắt rồi, mình cũng nên dừng ở đây.