渗透第2次作业
1. XSS基础
1.xss漏洞
XSS是一种常见的 Web 安全漏洞,攻击者通过注入恶意脚本到目标网站,使其他用户在浏览时执行这些脚本,从而窃取敏感信息或执行其他恶意操作
2.常见的编码
1.urlcode编码的规范:先转ASCLL码再转16进制 %数字
英文数字一般不编码,一般编码的是特殊字符
2.html实体编码:如果10进制的编码直接转ASCLL码如果16进制的编码再多转一个16进制编码然后输出的格式是 $#数字;
3.unicode编码:先转ASCLL码再转16进制 \u00数字
3.xss的基本功练习
补充:
1.html五元素
- 空元素(Void elements),如
<area>,<br>,<base>
等等 - 原始文本元素(Raw text elements),有
<script>
和<style>
- RCDATA元素(RCDATA elements),有
<textarea>
和<title>
- 外部元素(Foreign elements),例如MathML命名空间或者SVG命名空间的元素
- 基本元素(Normal elements),即除了以上4种元素以外的元素
2.页面的编码解析顺序
html->url->javascript(包含js中的unicode)
第一题
<body><a href="%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29">aaa</a>
</body>
URL 编码 "javascript:alert(1)"
由于这个是url编码,html的识别在url编码之前,不能对协议类型进行任何的编码操作,不然URL解析器会认为它无类型,所以它不解码,页面就不认识它
第二
<a href="javascript:%61%6c%65%72%74%28%32%29">
由于这里面有html编码,然后这个html编码先把自己的编码一解开,然后就有(javascript)然后页面就认识它,然后后面再把url编码解开就可以弹窗了
第三
<a href="javascript%3aalert(3)"></a>
URL 编码 ":"
由于这个解析出来是JavaScript:
,这个页面并不认识,所以无法弹窗
第四
<div><img src=x onerror=alert(4)></div>
HTML字符实体编码 < 和 >
这题涉及到了html的状态机制,由于解析器解析完
第五
<textarea><script>alert(5)</script></textarea>
HTML字符实体编码 < 和 >
可以解码<>,但是无法触发弹窗
第六
<textarea><script>alert(6)</script></textarea>
由于RCDATA只容纳文本和字符引用,所以这里面的<script>alert(6)</script
只会被当作文本,无法进行弹窗
第七
<button onclick="confirm('7');">Button</button>
HTML字符实体编码 " ' " (单引号)
confirm和alert一样都是可以触发弹窗,然后里面的'会被html提前解析成;
,可以正常弹窗
第八
<button onclick="confirm('8\u0027);">Button</button>
Unicode编码 " ' " (单引号)
里面的编码是js里的unicode编码,由于js严格区分大小写且不能对符号进行编码,\u0027解析出来是单引号就是符号,导致无法解析
第九
<script>alert(9);</script>
HTML字符实体编码 alert(9);
因为有<script>
,所以它是原始文本,然后原始文本元素只可以容纳文本,虽然这个html可以提前解析,但是原始文本也不认识它
第十
<script>\u0061\u006c\u0065\u0072\u0074(10);</script>
Unicode 编码 alert
js自带的unicode解码工具,可以解码
第十一
<script>\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0031\u0029</script>
Unicode 编码 alert(11)
由于js不能对符号解码,所以也解析不了()
第十二
<script>\u0061\u006c\u0065\u0072\u0074(\u0031\u0032)</script>
Unicode 编码 alert 和 12
纯js的语法问题,js的解析器默认把12解析成字符串了,所以要加两个‘’才能解析
第十五
<a href="javascript:%5c%75%30%30%36%31%5c%75%30%30=;%36%63%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34(15)">15</a>
这个可以先用html解析成JavaScript:%5c%75%30%36%31…然后发现后面又都是url解码然后解完又出现了unicode编码,然后js里面的unicode编码再解,可以弹窗
2.xss的种类
1.反射型xss
XSS的反射性漏洞:页面能解析js代码的功能被称之为XSS的反射性漏洞,也就是由于它对用户的输入没有做任何过滤,导致用户可以输入一些恶意的js代码,然后这些js代码通过输入进入到页面里面最终被页面解析
xss的反射性漏洞产生的原因:没有对用户的输入做特定的过滤,导致用户输入的恶意js代码输出到了页面中,被页面解析
防御xss反射型漏洞的一种手法:利用过滤函数把html标签的实体化,这样html标签被过滤后就不会被页面解析,只会被当作普通文字
xss放射型漏洞的小总结
1.反射型xss的存在位置 可能在搜索 input表单
2.可能会存在过滤 通过编码等方式尝试绕过
3.javascript伪协议 也可以触发xss
反射型xss的部分练习
第一
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");window.location.href="level2.php?keyword=test";
}
</script>
<title>欢迎来到level1</title>
</head>
<body>
<h1 align=center>欢迎来到level1</h1>
<?php
ini_set("display_errors", 0);
$str = $_GET["name"];
echo "<h2 align=center>欢迎用户".$str."</h2>";
?>
<center><img src=level1.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
</html>
在此题中发现注入内容会注入到h2标签内如需要弹窗只要让其触发alert即可
第二
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");window.location.href="level6.php?keyword=break it out!";
}
</script>
<title>欢迎来到level5</title>
</head>
<body>
<h1 align=center>欢迎来到level5</h1>
<?php
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("<script","<scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level5.php method=GET>
<input name=keyword value="'.$str3.'">
<input type=submit name=submit value=搜索 />
</form>
</center>';
?>
<center><img src=level5.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str3)."</h3>";
?>
</body>
</html>
在源码中,发现题目进行了简单替换:将<script
替换为<scr_ipt,on
替换为o_n
因此所有的on事件被过滤,<script>
标签被过滤
但发现<>并没有被过滤,因此我们需要将源码进行闭合即可
在input
输入框内输入
a"><a href="javascript:alert(1)">aaaaaaaaaaaa</a>"
即可题解
点击aaaaaaa即可弹窗
2.dom型xss
1.定义
控制js形成的xss 被叫做dom型xss
2.dom型xss与反射型 / 存储型 XSS 的区别:
传统 XSS(反射型 / 存储型)依赖服务器端处理用户输入并返回恶意代码,而 DOM 型 XSS 完全在客户端(浏览器)执行,无需服务器参与。
3.攻击路径:攻击者通过诱导用户访问包含恶意 URL 参数或本地存储的页面,触发浏览器 DOM 操作,直接在客户端注入恶意脚本。
第一题
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><h2 id="spaghet"></h2>
</body>
<script>spaghet.innerHTML = (new URL(location).searchParams.get('somebody') || "Somebody") + " Toucha Ma Spaghet!"
</script>
</html>
由于在Html5中指定不执行使用**.innerHTML**插入的
传参输入
<img src=1 onerror=alert(1337)>
即可弹窗
第二题
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head>
<body><h2 id="maname"></h2>
</body>
<script>let jeff = (new URL(location).searchParams.get('jeff') || "JEFFF")let ma = ""eval(`ma = "Ma name ${jeff}"`)setTimeout(_ => {maname.innerText = ma}, 1000)
</script>
</html>
由于script里面的eval是执行函数,可以直接让alert弹窗,然后看到my name前面有双引号,所以可以提前闭合双引号,但是后面原本又多了个双引号,因此就用//把多余的双引号注释掉
第三题
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head>
<body><div id="uganda"></div>
</body>
<script>let wey = (new URL(location).searchParams.get('wey') || "do you know da wey?");wey = wey.replace(/[<>]/g, '')uganda.innerHTML = `<input type="text" placeholder="${wey}" class="form-control">`
</script>
</html>
因为题目中规定不能用户交互,因此input里有一个非常特殊的属性:onfocus
聚焦与autofocus
自动聚焦
即在wey后面加入127.0.0.1/1.html?wey=a"autofocus οnfοcus="alert(1)
第四题
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head>
<body>
<form id="ricardo" method="GET"><input name="milos" type="text" class="form-control" placeholder="True" value="True">
</form>
</body>
<script>ricardo.action = (new URL(location).searchParams.get('ricardo') || '#')setTimeout(_ => {ricardo.submit()}, 2000)
</script>
</html>
form表单里面的action参数可以使用js的伪协议,由于form表单里面可以使用javascript:alert(1)意味着可以提交,然后ricardo又可以传给form的action,因此只需要在ricardo里面传参javascript:alert(1)就行(注意:一定要小写,js严格区分大小写)
第五题
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><h2 id="will"></h2>
</body>
<script>smith = (new URL(location).searchParams.get('markassbrownlee') || "Ah That's Hawt")smith = smith.replace(/[\(\`\)\\]/g, '')will.innerHTML = smith
</script>
</html>
由于这个replace把()‘’以及\ \全部过滤了,因此我们想到用编码的方式对()进行编码,但是后来发现js里面不能解码符号,所以这条方法就放弃了,然后只能用html编码的方式给它编码,但是发现html编码直接输入到导航栏格式不对,必须要转成urlencode,所以只需要把两个括号先转html再转url编码即可实现
DOM破坏
Dom破坏就是一种将HTML代码注入页面中以操纵DOM并最终更改页面上JavaScript行为技术,在无法直接XSS的情况下,我们就可以往DOM破坏这方向考虑了
DOM破坏的相关知识
<body><img id="x"><img name="y">
</body>
<script>console.log(x)console.log(y)console.log(document.x)console.log(document.y)console.log(window.x)console.log(window.y)
</script>
可以看在浏览器上的结果
发现只有document打印不出id(是undefind)其他皆可正常打印
1次覆盖
<body><img id="x"><img name="y">
</body>
<script>let div = document.createElement('div')//创建div标签div.innerHTML = '<img name="cookie">'//标签内容为<img name="cookie">document.body.appendChild(div)//将js创建的div标签插入到body中console.log(document.cookie)//请求document.cookie
</script>
由于我们自定义了一个div标签并在里面插入了img name= cookie,由于js,html默认优先自定义的cookie就会把系统自带document,cookie给覆盖掉(因为出现了dom破坏)
2次覆盖
<body><form name="body"><img id="appendChild"></form>
</body>
<script>console.log(body.appendChild)
</script>
发现覆盖成功,本来apendchild是一个函数(可以插入到body的一个功能函数),但是dom破坏直接将函数覆盖成一个img标签了
或者我们再试一下插入能否成功
<body><form name="body"><img id="appendChild"></form>
</body>
<script>let div =document.createElement('div')document.body.appendChild(div)
</script>
发现div插入不了,由此可以得出appendChild已经被覆盖成功,已经不是一个函数了
toString
我们可以通过以下代码来进行fuzz得到可以通过tostring 方法将其转换成字符串类型的标签
Object.getOwnPropertyNames(Window) //获取所有windows属性的name.filter(P =>P.match(/Element$/)) //从名字中过滤带Element后缀的名字.map(p => window[p]) // 拿出名字里面的值.filter(p => p && p.prototype && p.prototype.toString !== Object.prototype.toString) //就是想看是标签里面自定义的tostring方法还是祖先继承的tostring方法,然后我们只要那种标签自定义的tostring方法(因为只有自定义的tostring方法才能控制,才能写恶意代码)
我们通过以上步骤可以得到两个标签
- HTMLAreaElement ()area是空元素所以不行
- HTMLAnchorElement () 自带的tostring属性可以把href中的属性转换成字符串
ps:当你将a当作函数的参数时候,会自动调用a的tostring方法,而a的tostring是自身的方法,不是继承的,他可以打印href中的内容
dom破坏的案例
<body><h2 id="boomer">Ok, Boomer.</h2>
</body>
<script src="./js/dist/purify.min.js"></script>
<script>boomer.innerHTML = DOMPurify.sanitize(new URL(location).searchParams.get('boomer') || "Ok, Boomer")setTimeout(ok, 2000)
</script>
</html>
首先我们要从ok入手,因为boomer已经被DOMpurify保护着,无法绕过,因此可以定义一个a标签,然后a标签中就可以定义ok参数,这样就可以插入ok参数了,setTimeout这个语法与eval()一样存在相同的安全风险且允许你包含在定时器到期后编译和执行字符串而非函数,以及使用自带的tostring方法来打印href中的内容,因此我们就可以把alert类型可以弹窗的东西放入到href中,boomer=<a id=href = "javascript:alert(1)"但是发现DOM框架不让上传alert,因此我们只能去查询DOM中的白名单(tel cid)
3.存储型xss
1.存储型xss是最危险的跨站脚本攻击类型
2.什么是存储型xss
存储型XSS(跨站脚本攻击)是一种恶意脚本被永久存储在目标服务器上的攻击类型,当用户访问受感染页面时自动执行。
3.存储型XSS的特点
- 持久性:恶意脚本存储在服务器上(数据库、文件系统等)
- 自动传播:用户只需访问页面就会触发攻击
- 影响范围广:所有访问该页面的用户都会受到影响
- 危害严重:可窃取用户凭据、会话信息,传播恶意软件等