
5번문제에 들어가면 이렇게 Login과 Join으로 연결되는 버튼이 보인다.
먼저 Login페이지로 들어갔다.

ID를 admin 그리고 PW를 1234로 해서 입력결과 Wrong password라는 문구가 떴다.
즉 admin이라는 ID이미 존재하였다. 뭔가 이 비밀번호를 찾으면 풀릴 것으로 보인다.
다음은 아까 처음페이지에서 Join페이지로 들어가려 했지만 access denied 문구가 떴다.

소스코드를 보면 버튼이 눌리면 go라는 스크립트 함수를 실행하는데, go 함수는 페이지로 연결하지 않고 'Access Denied'라는 문구만 띄운다.
로그인페이지에서 인젝션 공격을 하기 보다 Join페이지를 우회해서 들어가는 것이 우선적인 추론이라고 생각하였다. Join페이지로 접근하지 못하는 이유는 자바스크립트 소스 때문이므로 url로 우회하면 접속이 가능하다고 생각했다.
https://webhacking.kr/challenge/web-05/mem/join.php로 접속하였다.
그 결과 역시 접속이 가능했다.
그러나 여전히 'access denied'문구가 떴다.
소스코드는 2번에 나누어서 살펴보자, 버프수트로 본 소스가 더 가독성이 좋았다.

이미지를 보면 소스코드가 난독화가 되어있음을 알 수 있다.
그렇다면 아 이걸 다 해석해야하나 라고 생각이 들 수 있지만, 크롬브라우저에서 콘솔창에 찾고자 하는 부분을 입력만 하면 알아서 해석해서 값을 돌려준다.
눈에 띄는 부분은 바로 eval함수이다.
eval 함수는 취약점이 많아 권장되지 않는 함수로 인자로 들어간 값을 실행하는 함수이다.
따라서 어떤 값을 실행하는지 크롬브라우저로 살펴보니

document.cookie라는 값이 나왔다.
그 다음 눈에 띄는 부분은 indexOf함수이다.
이 함수는 인자로 들어간 부분이 해당 문자열에 존재하면 그 위치를 반환하고, 인자가 없다면 -1을 반환한다.
어떤값이 문자열에 속해야 하는지 살펴보니

oldzombie라는 값이 나왔다.
따라서 우리는 oldzombie라는 쿠키name을 설정하고 value는 아무거다 만들고 페이지로 접속하면 이 throw되는 부분을 피할 수 있는 것이다.

눈에 띄는 부분은 역시 eval함수이다. 또 난독화된부분 + 'URL'을 실행한다.
따라서 어떤 값을 실행하는지 크롬브라우저로 살펴보니

document.URL이 나왔다.
그 다음 눈에 띄는 부분은 indexOf함수이다.
어떤 값이 문자열에 속해야 하는지 살펴보니

mode=1이 나왔다.
따라서 우리는 mode=1이라는 문구를 url에 삽입하고 페이지를 접속하면 이 throw되는 부분을 피할 수 있다.
만약 throw되는 모든 부분을 피한다면 어떤 글귀들을 보여준다. 이 글귀들을 위의 취약점을 뚫어서 보도록 하겠다.
첫번째 조건을 만족하도록 cookie의 name을 oldzombie로 value는 그냥 1로 설정한다.
두번째 조건을 만족하도록 url을 https://webhacking.kr/challenge/web-05/mem/join.php/mode=1로 고친다.
그 결과 아까 원했던 그 글귀들이 나타났다.

처음에 admin이라는 계정에 해당하는 비밀번호를 몰랐으나 여기서 admin이라는 계정으로 새로 가입을 해버리면 어떻게 될지 궁금했다.
그래서 id를 admin으로 pass를 1234로 해서 가입을 해보려 했으나

문구가 떴다.
여기서 좀 많은 고민을 했다. 앞으로 돌아가서 SQL 인젝션 공격을 해야하는 것인지 아니면 계정을 가입하는 과정에서 취약점이 있는지 고민했다.
일단 여러가지 추론 중에서 admin이라는 문구가 들어가도록 가입만 성공하면 될 것이라는 부분이 있었는데, admin1으로 가입한 결과 admin1과 admin을 다르게 인지하였다.
그러다가 결국 솔루션을 찾아보았는데 앞뒤로 공백문자를 붙이는 것이었다.
' admin '이런식으로 붙인다.
이것을 db단에서 insert 할때 과연 같은값으로 인지하는지가 의문이다.
' admin ' = 'admin' ?
웹서핑 결과 답은 그렇다였다.
https://techblog.woowahan.com/2559/
Postgre SQL과 SQLlite만이 저 공백을 다르게 판단하였다고 한다.
다른 db언어들은 'a '와 'a'를 비교함에 있어서 짧은쪽 'a'에 공백을 뒤에 이어붙여서 비교한다고 한다.
만약 CHAR(3)의 데이터 타입의 컬럼이 존재하는 경우, 'xyz'와 'a' 두 데이터는
'xyz', 'a__' 이렇게 저장된다.
즉 항상 정해놓은 데이터 타입의 크기를 맞추려고 공백을 추가하여 저장하는 것이다.
그렇다면 만약에 이 공백을 넣어서 가입을 시도한다면 어떻게 될까?
처음에 막힐 것이라고 생각하였다. 그 이유는 db단에서 쿼리를 보낼때 그 db단에서는 공백을 의도적으로 내가 만든 admin과 저장되어있던 admin을 이미 같은 값으로 인지하기 때문에 db단에서 이미 있는 값이다 라고 답이 올것이고 페이지에서 그것을 출력할 것이라고 생각하였다.
그러나 아니었다.
1. 아마도 이 문제는 처음 가입에 있어서는 php의 문자열 비교를 사용하여 "공백이 있는 admin"과 "admin"을 다른 값으로 인지하는 것 같다.
- 또한 회원 로그인에서는 db단에서의 쿼리문으로 이 둘을 같은값으로 생각하여 그냥 공백이 있는 admin으로 가입한 계정으로 접속해도 이를 admin으로 인지하는 것같다.

결론 SQL공부가 필요하다.