
문제가 한번에 풀려서 당황했다. 내가 푼 다른 문제에서 고민했던 내용이 바로답이였다. 이 경우 이미지 파일임을 나타내는 Content type과 문서내 File signiture 를 수정하고 php 확장자 명을 붙여주면 바로 풀리게 된다.
그냥 바로 마지막 문제를 풀도록 하겠다.

마지막 문제는 업로드시 파일을 엄격하게 필터링한다고 나와있다. 하지만 파일 처리 방식에서 그것을 우회할 수 있다 했다. 아래는 어떤한 코드로 필터링하는지 나와있는 코드이다.
<?php
$target_dir = "avatars/";
$target_file = $target_dir . $_FILES["avatar"]["name"];
// temporary move
move_uploaded_file($_FILES["avatar"]["tmp_name"], $target_file);
if (checkViruses($target_file) && checkFileType($target_file)) {
echo "The file ". htmlspecialchars( $target_file). " has been uploaded.";
} else {
unlink($target_file);
echo "Sorry, there was an error uploading your file.";
http_response_code(403);
}
function checkViruses($fileName) {
// checking for viruses
...
}
function checkFileType($fileName) {
$imageFileType = strtolower(pathinfo($fileName,PATHINFO_EXTENSION));
if($imageFileType != "jpg" && $imageFileType != "png") {
echo "Sorry, only JPG & PNG files are allowed\n";
return false;
} else {
return true;
}
}
?>
간단히 해석해 보면 name의 변수는 post 방식으로 클라이언트에서 내용과 함께 받아오고 해당 파일을 서버의 임서 폴더에 올린다. 그후 필터링이 끝나면 서버로 올리게 되는 것이다. 여기서 주로 판별되는 요점은 jpg와 png 형식의 파일만 통과시킨다는 것이다. 문제에서 파일을 처리하는 과정에서 경쟁 특성을 이용하라 했으니 우선 함수들의 특성을 알아보겠다.
strtolower(pathinfo($fileName,PATHINFO_EXTENSION));
여기서 strtolower은 입력받은 문자를 다 소문자로 바꾸는 함수이기 때문에 패스하고
pathinfo 이 부분이 조사해보니 중요했다. pathinfo는 입력받은 파일의 확장자명을 따로 추출하여 인자를 전달하는 것으로 알려져 있다. 그렇다면 pathinfo에 대한 우회 기법을 찾아보면 더 수월하게 다음 단계로 진행될 것이다.
shell.php?\0.jpg 을 사용해서 올렸더니 0.jpg만 올라갔다.. \0은 null 문자로 뒤에 문자를 무시한다는 것인데 여기서는 필터링이 null 문자가 생기면 앞에 문자를 날려버리는 필터링을 가진 것으로 예상된다.
몇시간 째 이문제 붙잡고 풀어봤지만, 실패 하였다.
결국 답지를 보았는데 내가 생각한 방법과 완전히 다른 방법으로 진행하였다. 원리는 turbo Intruder를 이용하는 것인데 turbo Intruder라는 건 여러가지 요청을 한번에 여러개를 보내는 것을 의미한다.
burp suit에는 intruder도 있는데 intruder는 일반적으로 여러가지 페이로드를 한 페이지에 지속적으로 입력할때 사용되는 것이다.
그러면 turbo intrude는 왜 사용하는 것일까 코드를 보게되면 서버의 특정 경로에 파일이 우선 올라가서 검증하게 되는데 검증에 실패시 삭제가 바로 이뤄진다. 이 순간은 매우 짧은 순간이다. 그렇다면 만약 서버에 올라가는 짧은 시간동안 지속적으로 요청을 하게 되면 필터링 과정 중에 존재하는 파일을 가져올 수 있을 것이다.
이를 파이썬 코드로 작성해서 가져오는 것이다.
아래와 같은 코드로 말이다. your-post request에는 파일을 올리는 요청과 파일을 불러오는 요청코드를 각 1, 2번에 적어주고 실행하면 php 파일 실행이 가능하게 된다.
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint, concurrentConnections=10,)
request1 = '''<YOUR-POST-REQUEST>'''
request2 = '''<YOUR-GET-REQUEST>'''
# the 'gate' argument blocks the final byte of each request until openGate is invoked
engine.queue(request1, gate='race1')
for x in range(5):
engine.queue(request2, gate='race1')
# wait until every 'race1' tagged request is ready
# then send the final byte of each request
# (this method is non-blocking, just like queue)
engine.openGate('race1')
engine.complete(timeout=60)
def handleResponse(req, interesting):
table.add(req)
'Web > Web 보안' 카테고리의 다른 글
[File Download ] 공격방안 정리 (0) | 2022.06.04 |
---|---|
[File Upload ] 대응방안 정리 (0) | 2022.06.03 |
[File upload] 공격 기법 (0) | 2022.05.27 |
[CSRF] 공격 방법 및 대응 방안 (0) | 2022.05.23 |
XSS, CRSF (0) | 2022.05.12 |