우선, 내 해석방법 보다 더 이해하기 쉽고 간단한 방법이 있어서 그분 글을 참조..!
문자열에 대해 이런 방식으로 접근해야 할 것 같다. 이런 접근이 더 좋은 것 같다.
te-ra.tistory.com/19?category=809225
기본적으로 프로그램에서 문자열을 받을때는 string값을 주소값에 저장하고 참고하게 되죠.
제일 밖에 ""구분은 문자열에 포함되는값이 아니라 그저 스트링값을 표현하는 구문/방식입니다
-> " ", ' ' 같은 건 코딩상에서 문자열을 표현하기 위한 형식(스트링값을 표현하는 구문)일 뿐 실제 내부 구조에서는 ""으로 문자열을 취급하지 않는 사실을 기반해서 생각하면 된다. 문자열 입력 시 123"은 가능하지만 str = "123"";은 안되는 것이 여기서 비롯.
문자열을 입력하면 그것이 꼭 따옴표로 감싸진 뒤 그제서야 문자열로 취급한다기보단, 따옴표는 코드 상에서 문자열을 구분할 때 쓰는 방법일 뿐 실제 내부 구조에서는 그러한 따옴표 방식으로 문자열이 취급되고 사용되지 않는 사실을 알아야 한다.
(ABC를 입력했을 때, 이걸 따옴표로 감싸서 "ABC"로 되어야 비로소 문자열로 취급되는 게 아니다. - 내가 어떤 문자열을 입력했는데, 그게 문자열로 취급되기 위해 내부에서 따옴표로 감싸지는 작업을 거쳐야 문자열로 취급되는 게 아니라는것 -
즉, ""가 문자열로 취급된다기보단 (=실제 내부구조에서 ""로 인해 문자열로 취급된다기보단), 그저 코드에서 문자열을 표현하기 위한 위한 약속이며 그 증거로 실제 내부 구조에서는 ""으로 문자열을 취급하지 않는다.)
아래는 좀 복잡한 내 해석..
--------------------------------------------------
문제를 못 풀었다 ㅜ..
다른 분들의 설명을 찾아봤는데, 내가 안될거라고 생각했던 부분이 정답이였다.
다른 분들은 나처럼 안될거라고 생각을 하긴 하신걸까..? 아마 다들 그냥 간과하고 계셨을 것 같다.
<?php
include "./config.php";
login_chk();
$db = dbconnect();
$_GET['id'] = strrev(addslashes($_GET['id']));
$_GET['pw'] = strrev(addslashes($_GET['pw']));
if(preg_match('/prob|_|\.|\(\)/i', $_GET[id])) exit("No Hack ~_~");
if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
$query = "select id from prob_zombie_assassin where id='{$_GET[id]}' and pw='{$_GET[pw]}'";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if($result['id']) solve("zombie_assassin");
highlight_file(__FILE__);
?>
일단 소스는 이렇다. 핵심은
$query = "select id from prob_zombie_assassin where id='{$_GET[id]}' and pw='{$_GET[pw]}'";
여긴데, $_GET['id']로 큰따옴표를 주게 되면, 난 당연히 $query를 감싸는 스트링이 큰따옴표이므로, 이에 영향을 줄 것이라고 처음에 생각했다. (다들 이런 생각은 안하신 것 같다)
$query = "select id from prob_zombie_assassin where id='"hello' and pw='{$_GET[pw]}'";
이렇게 - "hello를 입력하면 이렇게 되지 않을까.. - 라는 생각을 했다. $query 문자열이 끊기는 것.
그래서 이 방법은 아예 문제 풀이 선상에 두지도 않았었다. 하지만 이러한 방식으로 문제를 푸는 게 답이다. 그 내부작동과정을 다들 알고 쓰시는 것일까??... 우선 문제에서 "hello 를 입력하면 저렇게 되지는 않는다, addslashe 가 들어가고, 리버스가 들어가서
$query = "select id from prob_zombie_assassin where id='"\olleh' and pw='{$_GET[pw]}'";
정확힌 이렇게 들어간다. 이것 역시 위와 마찬가지로 다를 바는 없다. 역시나 큰따옴표가 쿼리스트링을 끝내지 않을까 하고 생각했다.
한참을 고민했다. 우리가 평소에는 아래처럼 저런 식에서 작은 따옴표를 변조해서 입력을 변조하니까말이다.
$query = "select id from prob_zombie_assassin where id='' or 1=1-- ' and pw='{$_GET[pw]}'";
우선 결론부터 말하면, 가장 바깥 큰 따옴표에 대한 시작 끝 처리는 입력값으로 변조할 수 없다. 그리고 안에 들어가는 따옴표에 대한 변조는 가능하다.
둘의 의미는 조금 다르기 때문인데, 바깥따옴표는 문자열 자체를 감싸는 기능이라면 내부따옴표는 문자 자체의 기능일 뿐이라는 것에서 착안된다.
만약 아래와 같은 식이 있다.
$query = "select id from prob_zombie_assassin where id='{$_GET[id]}'";
여기서 내가 $_GET[id]에 hello'를 주게 되면 이 문자열은 "hello'"가 되고 이게 문자열과 합쳐지면서
$query = "select id from prob_zombie_assassin where id='hello''";
이런 모습을 띄게 된다. 내가 입력한 hello' 에서 '는 문자 자체의 기능을 갖는 상태("hello'"이므로)로 문자열과 합쳐지는 것이다.
그리고 만약 hello"를 입력하게 된다면 이 문자열은 'hello"'이 되고, 이게 문자열과 합쳐지면서 " 가 문자 자체의 기능인 의미 그대로 합쳐지는 것이다.
$query = "select id from prob_zombie_assassin where id='hello"(여기서의 큰따옴표는 문자자체=\")'";
되게 어렵긴 한데,
이를 직접 눈으로 확인해 보는게 훨씬 빠르게 받아들여지긴 한다.
<?php
$g = 'good"man';
$s = "hello, id = '" . 'good "man' . "'";
echo $s;
--
hello, id = 'good "man'
문자 열 안의 다른 따옴표 역시 문자 자체로 들어가서 문자열 리터럴 전체를 감싸는 따옴표의 기능을 구현하진 못한다는거를 느낌.
' " ' = ' \" '
즉
" select ~ from ~ where id = '$_GET[id]' " -> 여기서의 id를 감싸는 작은따옴표도 큰따옴표 안에 들어가는, 애초에 문자 자체의 역할이므로,
id값으로 작은따옴표를 넣어줘도 작은따옴표 문자 자체의 기능을 하는 건 동일하므로 인젝션이 가능한것이고. ( 입력값 : ' or 1=1-- )
" select ~ from ~ where id = '$_GET[id]'" -> $_GET[id] 입력값에 " 가 포함된 문자 (이를테면 hello") 를 주더라도 전체 문자열을 끊어내는("select ~ from ~ where id = 'hello" | '" )역할을 할 순 없다는거.
결국엔 가장 바깥쪽 따옴표를 입력값으로 끊어낼 수 없다는 것이고, 안쪽에 존재하는 따옴표는 애초에 문자 자체의 기능이므로 입력값으로 얼마든지 끊어낼 수 있다.
-> 여러 문자열이 합쳐지는 과정에서, 가장 바깥쪽 따옴표와 일치하는 문자가 있으면 문자로 알아서 처리되는 것이고, 안쪽 따옴표와 일치하는 문자는 애초에 문자처리되므로 그대로 이용되는것.
가장바깥 따옴표 안쪽에 존재하는 따옴표(애초의 문자 자체의 기능인 따옴표)는 변조가 가능한데(내가 입력하는 따옴표도 결국 그 따옴표와 다른 따옴표로 감싸져서 이동하므로 문자 자체의 따옴표가 되기 때문), 가장바깥 따옴표의 변조(시작과 끝 변조같은)는 불가능(말했듯, 내가 입력하는 따옴표가 결국 다른 따옴표로 감싸져서 이동하므로 문자 자체의 따옴표가 되기 때문)
<?php
$g = 'good"man';
$s = "hello, id = ' ". '"hello"' ." ' ";
echo $s;
echo "\n";
$s = "hello, id = ' ". " ' or 1=1-- " ." ' ";
echo $s;
Output:
hello, id = ' "hello" '
hello, id = ' ' or 1=1-- '
-----
<?php
$s = "id = '" . ' "\ ' . " ' ";
echo $s;
echo "\n";
$s = "id = \" \' ";
echo $s;
Output :
id = ' "\ '
id = " \'
-----
굉장히 헷갈릴 수 있다 ㅜ.ㅜ 문자열은 알아갈수록 어려운 부분인 것 같다.
어쨌든 이를 기반을 문제를 풀어야 한다.
query : select id from prob_zombie_assassin where id='"\' and pw='or 1=1-- '
내가 id 입력값으로 "를 주었는데, 설명대로라면 "가 문자 자체의 역할을 해줘야 하므로 addslashe 기능말고도 문자열 합침 과정에서 자체적으로 \"가 또 들어가서 결과로 나와야 하는 것 아니냐 하고 생각할 수 있는데, 여기 출력값 역시 내가 담아낸 "가 문자 처리되어 자체적으로 \" 처리된 뒤 출력되는 것이다.
그렇지 않고서야
echo "<hr>query : <strong>{$query}</strong><hr><br>";
여기 echo가 큰따옴표로 감싸져있고, query에 큰따옴표값이 들어있는데, 어떻게 큰따옴표가 출력되겠는가.
+ 이게 너무 헷갈린다면 차라리 " 대신 NULL 을 입력해주는 방식을 채용해도 된다.
다른 참고
grini25.tistory.com/109#comment14401985
'[웹해킹] > [LOS]' 카테고리의 다른 글
[LOS] XAVIS (0) | 2020.12.27 |
---|---|
[LOS] NIGHTMARE (0) | 2020.12.25 |
[LOS] SUCCUBUS (0) | 2020.12.19 |
[LOS] ASSASSIN (0) | 2020.12.18 |
[LOS] GIANT (0) | 2020.12.17 |