CTF/Writeup

TenDollar CTF 2018 LinkedList - 1,2

JeonYoungSin 2018. 12. 1. 12:31

해당 문제는 동일한 소스코드에 버전 1,2로 두문제가 출제됬다.


두 문제모두 php 소스코드 오디팅을 통해 플래그가 나오는 조건을 맞춰주면 된다.


LinkedList - 1


index.php


<?php

@session_set_cookie_params(36000);

@session_start();


@require_once dirname(__FILE__)."/classes.php";

@require_once dirname(__FILE__)."/config.php";


if (@$_POST['name']) {

@$_SESSION['link'] = @array('name' => @htmlspecialchars(@$_POST['name']), 'time' => @time());

@die("<script type='text/javascript'>location.href='.';</script>");

}

if (!@$_SESSION['link']['name']) {

if (!@$_SESSION['link']['real_first?']) {

@$_SESSION['link']['real_first?'] = true;

@die("<script type='text/javascript'>location.href='.';</script>");

}

@die(@file_get_contents(@dirname(__FILE__).'/templates/set.html'));

}

if (!isset($_SESSION['link'][$_SESSION['link']['name']."_tail"])) {

@$_SESSION['link'][@$_SESSION['link']['name']."_tail"] = 0;

@die("<script type='text/javascript'>location.reload();</script>");

}

if (@$_SESSION['link']['name']) @$obj = new LinkList();

if (@$_GET['p'] == 'reset') {

unset($_SESSION['link']);

@die("<script type='text/javascript'>location.reload();</script>");

}

if (@$_SESSION['link'][@$_SESSION['link']['name']."_list"]) {

@$arr = @json_decode(@$_SESSION['link'][@$_SESSION['link']['name']."_list"]);

for(@$i=0;@$i<count(@$arr);@$i++){

@$obj->insert(@$arr[@$i], @$i);

}

}

if (@$_GET['p'] == 'raw') {

@header("Content-Type: text/plain");

@die(@$_SESSION['link'][@$_SESSION['link']['name']."_list"]);

}

if (@$_SESSION['link']['admin_only_list']) {

unset($_SESSION['link']);

die("<script type='text/javascript'>alert('GJ!!! The first flag is ".@addslashes(@$flag1)."');location.href='.';</script>");

admin:

if ($_POST['value'] && $_POST['key']) {

@$obj->insert(@$_GET['value'], @$_POST['key']);

@$arr[@$_POST['key']] = @$_GET['value'];

@$_SESSION['link'][@$_SESSION['link']['name']."_list"] = @json_encode(@$arr);

}

}

if (@$_SESSION['link'][@$_SESSION['link']['name']."_tail"] > 0xff) {

unset($_SESSION['link']);

@die("<script type='text/javascript'>alert('Realrudaganya?!?!? The second flag is ".@addslashes(@$flag2)."');location.href='.';</script>");

}

if (!@$_GET['p'] || $_GET['p'] == '') {

@$content = @file_get_contents(@dirname(__FILE__).'/templates/login.html');

@$content = @str_replace('$name', @$_SESSION['link']['name'], @$content);

if (@$_SESSION['link'][@$_SESSION['link']['name']."_list"] || @$data='') {

@$r = @$obj->readList();

@$data = '<pre>linked list: '.PHP_EOL;

for(@$i=0;@$i<count(@$r);@$i++){

@$data .= "No.".(@$i+1).": ".@$r[@$i].PHP_EOL;

}

@$data .= '</pre>';

}

@$content = str_replace('$content', @$data, @$content);

die(@$content);

}

if (@$_GET['p'] == 'insert' && isset($_GET['value'])) {

if (@$arr[100]) die("<script type='text/javascript'>alert('Too many linked-list! Get out!');location.href='.';</script>");

if (@$_SESSION['link'][@$_SESSION['link']['name']."_tail"] == 0) @$obj->insertFirst(@htmlspecialchars(@$_GET['value']));

else @$obj->insert(@$_GET['value'], @$_SESSION['link'][@$_SESSION['link']['name']."_tail"]);

@$_SESSION['link'][@$_SESSION['link']['name']."_tail"]++;

@$arr[@$_SESSION['link'][@$_SESSION['link']['name']."_tail"]-1] = @htmlspecialchars(@$_GET['value']);

@$_SESSION['link'][@$_SESSION['link']['name']."_list"] = @json_encode(@$arr);

die("<script type='text/javascript'>location.href='.';</script>");

}

if (@$_GET['p'] == 'insert_first' && isset($_GET['value'])) {

@$obj->insertFirst(@htmlspecialchars(@$_GET['value']));

@$_SESSION['link'][@$_SESSION['link']['name']."_tail"]++;

@$arr[0] = @htmlspecialchars(@$_GET['value']);

@$_SESSION['link'][@$_SESSION['link']['name']."_list"] = @json_encode(@$arr);

@die("<script type='text/javascript'>location.href='.';</script>");

}

if ($_GET['p'] == 'delete' && isset($_GET['key'])) {

if (!@$arr[0]) @$arr[0] = '';

@$obj->deleteNode(@$_GET['key']);

unset($arr[@$_GET['key']]);

#@$_SESSION['link'][@$_SESSION['link']['name']."_tail"] = (int)@$_GET['key'] & 0x7fffffff;

#@$_SESSION['link'][@$_SESSION['link']['name']."_tail"]--;

@$_SESSION['link'][@$_SESSION['link']['name']."_list"] = json_encode(@$arr);

@die("<script type='text/javascript'>location.href='.';</script>");

}



classes.php


<?php

class ListNode {

public $data;

public $next;


function __construct($data){

$this->data = $data;

$this->next = NULL;

}


function readNode(){

return $this->data;

}

}


class LinkList {

private $firstNode;

private $lastNode;

private $count;


function __construct(){

$this->firstNode = NULL;

$this->lastNode = NULL;

$this->count = 0;

}


public function insertFirst($data){

$link = new ListNode($data);

$link->next = $this->firstNode;

$this->firstNode = &$link;


if ($this->lastNode == NULL) $this->lastNode = &$link;

$this->count++;

}



public function readList(){

$listData = array();

$current = $this->firstNode;


while($current != NULL){

array_push($listData, $current->readNode());

$current = $current->next;

}

$i = 0;

$return = array();

foreach($listData as $v){

$return[$i++] = $v;

}

return $return;

}


public function reverseList(){

if ($this->firstNode != NULL) {

if ($this->firstNode->next != NULL) {

$current = $this->firstNode;

$new = NULL;


while($current != NULL){

$temp = $current->next;

$current->next = $new;

$new = $current;

$current = $temp;

}

$this->firstNode = $new;

}

}

}


public function deleteNode($key){

$current = $this->firstNode;

$previous = $this->firstNode;


while($current->data != $key){

if ($current->next == NULL) return NULL;

else{

$previous = $current;

$current = $current->next;

}

}


if ($current == $this->firstNode) {

if ($this->count == 1) $this->lastNode = $this->firstNode;

$this->firstNode = $this->firstNode->next;

}else{

if ($this->lastNode == $current) $this->lastNode = $previous;

$previous->next = $current->next;

}

$this->count--;  

}


public function emptyList(){

$this->firstNode == NULL;

}


public function insert($NewItem,$key){

if ($key == 0) $this->insertFirst($NewItem);

else{

$link = new ListNode($NewItem);

$current = $this->firstNode;

$previous = $this->firstNode;


for($i=0;$i<$key;$i++){       

$previous = $current;

$current = $current->next;

}


$previous->next = $link;

$link->next = $current; 

$this->count++;

}

}

}



index.php를 보면 첫번째 플래그가 나오는 조건은 아래와 같다.

if (@$_SESSION['link']['admin_only_list']) {
unset($_SESSION['link']);
die("<script type='text/javascript'>alert('GJ!!! The first flag is ".@addslashes(@$flag1)."');location.href='.';</script>");
admin:
if ($_POST['value'] && $_POST['key']) {
@$obj->insert(@$_GET['value'], @$_POST['key']);
@$arr[@$_POST['key']] = @$_GET['value'];
@$_SESSION['link'][@$_SESSION['link']['name']."_list"] = @json_encode(@$arr);
}
}

@$_SESSION['link']['admin_only_list'] 요 값이 존재하면 플래그가 나오기 때문에 해당 값이 생성될 수 있는 조건을 확인해 보면 아래와 같다.

if (@$_GET['p'] == 'insert' && isset($_GET['value'])) {
if (@$arr[100]) die("<script type='text/javascript'>alert('Too many linked-list! Get out!');location.href='.';</script>");
if (@$_SESSION['link'][@$_SESSION['link']['name']."_tail"] == 0) @$obj->insertFirst(@htmlspecialchars(@$_GET['value']));
else @$obj->insert(@$_GET['value'], @$_SESSION['link'][@$_SESSION['link']['name']."_tail"]);
@$_SESSION['link'][@$_SESSION['link']['name']."_tail"]++;
@$arr[@$_SESSION['link'][@$_SESSION['link']['name']."_tail"]-1] = @htmlspecialchars(@$_GET['value']);
@$_SESSION['link'][@$_SESSION['link']['name']."_list"] = @json_encode(@$arr);
die("<script type='text/javascript'>location.href='.';</script>");
}
if (@$_GET['p'] == 'insert_first' && isset($_GET['value'])) {
@$obj->insertFirst(@htmlspecialchars(@$_GET['value']));
@$_SESSION['link'][@$_SESSION['link']['name']."_tail"]++;
@$arr[0] = @htmlspecialchars(@$_GET['value']);
@$_SESSION['link'][@$_SESSION['link']['name']."_list"] = @json_encode(@$arr);
@die("<script type='text/javascript'>location.href='.';</script>");
}
if ($_GET['p'] == 'delete' && isset($_GET['key'])) {
if (!@$arr[0]) @$arr[0] = '';
@$obj->deleteNode(@$_GET['key']);
unset($arr[@$_GET['key']]);
#@$_SESSION['link'][@$_SESSION['link']['name']."_tail"] = (int)@$_GET['key'] & 0x7fffffff;
#@$_SESSION['link'][@$_SESSION['link']['name']."_tail"]--;
@$_SESSION['link'][@$_SESSION['link']['name']."_list"] = json_encode(@$arr);
@die("<script type='text/javascript'>location.href='.';</script>");
}

해당 코드는 리스트를 삽입,우선삽입,삭제할때인데 해당 기능 사용시 
@$_SESSION['link'][@$_SESSION['link']['name']."_list"] = json_encode(@$arr);
요 코드들을 통해 @$_SESSION['link']['admin_only_list'] 요 값을 세팅할 수 있다.

그럼 이제 @$_SESSION['link']['name'] 요 값을 admin_only로 어떻게 입력할 수 있는지 보면 되는데 해당 방법은 아래 코드를 통해 볼 수 있다.

if (@$_POST['name']) {
@$_SESSION['link'] = @array('name' => @htmlspecialchars(@$_POST['name']), 'time' => @time());
@die("<script type='text/javascript'>location.href='.';</script>");
}

그럼 이제 아래와 같이 name란에 admin_only를 넣고 접속한 뒤 insert,insert(priority), delete 중 아무 기능이나 사용해보면 아래와 같이 플래그가 나온다.







Flag = TDCTF{easy_7o_solve123}

LinkedList - 2


해당 문제는 1버전과 동일한 소스코드이며 두번째 플래그가 나오는 조건은 아래와 같다.


if (@$_SESSION['link'][@$_SESSION['link']['name']."_tail"] > 0xff) {

unset($_SESSION['link']);

@die("<script type='text/javascript'>alert('Realrudaganya?!?!? The second flag is ".@addslashes(@$flag2)."');location.href='.';</script>");

}


@$_SESSION['link'][@$_SESSION['link']['name']."_tail"] 값이 255보다 크면되기 때문에 해당 값을 어떠한 방식으로 증가시킬 수 있는지 보면 된다.


아래 코드를 보면 @$_SESSION['link'][@$_SESSION['link']['name']."_tail"] 값은 insert 혹은 priority insert 기능 사용시 1씩 증가하는데 insert와 같은 경우 리스트 길이가 100이면 더이상 증가가 안되기 때문에 priority insert 기능을 255번이상 사용해주면 플래그가 나오게 된다.


if (@$_GET['p'] == 'insert' && isset($_GET['value'])) {

if (@$arr[100]) die("<script type='text/javascript'>alert('Too many linked-list! Get out!');location.href='.';</script>");

if (@$_SESSION['link'][@$_SESSION['link']['name']."_tail"] == 0) @$obj->insertFirst(@htmlspecialchars(@$_GET['value']));

else @$obj->insert(@$_GET['value'], @$_SESSION['link'][@$_SESSION['link']['name']."_tail"]);

@$_SESSION['link'][@$_SESSION['link']['name']."_tail"]++;

@$arr[@$_SESSION['link'][@$_SESSION['link']['name']."_tail"]-1] = @htmlspecialchars(@$_GET['value']);

@$_SESSION['link'][@$_SESSION['link']['name']."_list"] = @json_encode(@$arr);

die("<script type='text/javascript'>location.href='.';</script>");

}

if (@$_GET['p'] == 'insert_first' && isset($_GET['value'])) {

@$obj->insertFirst(@htmlspecialchars(@$_GET['value']));

@$_SESSION['link'][@$_SESSION['link']['name']."_tail"]++;

@$arr[0] = @htmlspecialchars(@$_GET['value']);

@$_SESSION['link'][@$_SESSION['link']['name']."_list"] = @json_encode(@$arr);

@die("<script type='text/javascript'>location.href='.';</script>");

}



Flag = TDCTF{easy_t0_solve412}