web

web复现之攻防世界fakebook和Cat

Posted by 1nhann on 2021-01-09
Page views

最近学的知识有点杂,这次还是围绕两道web题,稍微记录点东西


两道题是 fakebook还有Cat


知识点概要

fakebook

简单概述一下,用到的知识点

  • sql注入

    绕过union select

    爆表名、字段名、数据库名、各个字段的内容

  • php curl

    curl 的 file:// 协议用法

  • php反序列化

  • html中 iframe

    iframe 的 src 有两种,一是url,二是Data URI

  • 御剑扫描

Cat

简单概述一下用到的知识点

  • gbk编码问题

    gbk编码,如果第一个字节大于等于0x80那么这个字节和它后面的一个字节将被看做同一个字符的编码

  • php curl POST上传文件

    能用在url中的,就是 @+文件名

  • 数据库文件格式

    这题中用到 sqlite3为后缀得到文件存储数据库数据

具体wp

fakebook

拿到手,先玩一玩,注册,登录……

然后发现在view.php 有个注入点,那就注入试试看

order by 4 没问题

order by 5 报错

一开始看,拦截 了 select,但是实际上,是拦截了 union select 这个整体

union select 可以用 union++select 或者union/**/select来绕过

爆出数据库名 :fakebook

爆出表名:users

爆出所有字段:

group_concat(column_name),3,4 from information_schema.columns where table_name='users'

dirsearch一下

看看robots.txt

看看user.php.bak

有一个get方法,里面直接curl了$this->blog

想到也许可以ssrf,即用file协议读服务器上的文件

随便join看看

报错了

这里有个方法,估计就是用来判断blog是否满足正则

分析一波

blog不能以file://开头了,那就得另想办法

随便注册一个

点开看看

看看the contents of his/her blog

发现有个iframe

好奇如果blog是www.baidu.com会怎么样

即使是正常的url也没怎么样

再看看,发现这个src有点奇怪

查了一下,src=后的参数,可以有两种,一是 url ,二是DATA URI

Data URI的格式这样:

src="data:<MIME Type>;base64,<content>"

做个试验,写个js代码到iframe里面看看

现在就打开浏览器,访问str.php,预期是看到弹窗

果然可以

如果我写入一个图片行吗

试了试看,确实行

那么就看懂了,这个iframe用的是Data URI,打印出来的内容用base64编码解码后,直接写在HTML中

但是正如图片中看到的,当base64,后面是空的的时候,什么也没有。

再注一下,确定一波信息

发现几个要点

  • php unserialize
  • 回显的位置是2
  • view.php所在位置是 /var/www/html/

再看一眼所有字段

no,username,passwd,data,USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS

看看每个字段有没有什么异端

看看no字段

看看username字段

看看passwd字段

密码看来是md5过的

看看data字段

发现有点东西——两个对象的序列化,和user.php对比,可以发现

序列对应的对象,正好是这个UserInfo的实例

因此推测,unserialize的内容就可能取自这里,即data字段

看看USER字段

报错了

剩下两个也都报错

在页面下方,仔细看看,在contents of his/her blog部分,还有一个报错

可以猜测,每次select ,先从data中取一个序列,序列生成一个对象,对象调用了getBlogContents()方法,然后成为了contents的内容

正常情况下,no如果是存在的,那么一个no就对应了一个data,一个username,一个ageunserialize的内容,猜测取自data,所以data大概率是在1或者3或者4的位置被select

复制过来试试看,看看底下有没有报错,就能确定哪个是data

'O:8:"UserInfo":3:{s:4:"name";s:5:"hello";s:3:"age";i:0;s:4:"blog";s:7:"a.a.abc";}'

3的位置报错

试试4的位置

对了,就是4的位置,selectdata

现在,就要借助getBlogContents函数,来读取服务器中的文件了

用到file协议file:///var/www/html/index.php

'O:8:"UserInfo":3:{s:4:"name";s:5:"hello";s:3:"age";i:0;s:4:"blog";s:30:"file:///var/www/html/index.php";}'

看看index.php

看看db.php

好像也没什么用

flag到底在哪里呢?

使用御剑,用php的字典来扫

谁也没有想到,竟然有一个flag.php文件,所以直接读

http://220.249.52.134:40925/view.php?no=0 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:5:"hello";s:3:"age";i:0;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'#

Cat

看到题目,猜测是用到ping了,输入个127.0.0.1,确实ping 通了

而且看到是php开发的

再试试看,发现www.baidu.com 不能ping通,但是对应的ip 可以

再继续尝试输入各种字符,初步猜测,url参数中只能有 [a-z0-9A-Z/.-],否则就报错URL Invalid

试试看,这个网站处理宽字节会有什么问题吗

%80

取得了重大进展,报错了

复制下来,放到一个html中,好好看看报错的信息

其中有一些要点

分析一波:

在view.py中看到ping函数,接收的是POST,可见当前页面是把url当做post的数据再传到127.0.0.1/api/ping中,且post中数据的名称也叫url

对于传入的url,先会 escape ,如果有 \\、\、"、$、' 中的一个,都会被加个 \\

最后得到的新 url 会被gbk 编码

而 如果 url 最后不满足这样的形式:

就会报错 Invalid URL

查一查看,有没有数据库的信息

是有的,这个数据库的数据放在/opt/api/database.sqlite3

还可以可以看到

报错信息竟然尝试把post进去的内容打印出来!!

受此启发,我想到能不能把服务器上的文件当做post的内容来传入,引起报错,然后看到文件内容?

这时候,思考一下,php向127.0.0.1/api/ping 发出POST 请求的方式有哪些

  1. curl
  2. file_get_contents
  3. fopen
  4. fsockopen

而其中,能够POST文件的,有curl、file_get_contents,但是,能仅仅通过控制url来控制传递的文件的,就只有 curl 了!!

也就是说,如果服务器的php用的culr来搞事情,那么攻破这题就很简单了,可以通过curl将database.sqlite3的内容作为POST的参数,传入python,然后通过报错信息,不就能看到文件其中的内容了吗~~~

如果是用的curl,可以想象,php中差不多这样写的:

1
2
3
4
5
6
7
$ch = init_curl();
curl_setopt($ch,CURLOPT_URL,"127.0.0.1/api/ping");
curl_setopt($ch,CURLOPT_POST,true);
$post_data=array('url'=>$_GET['url']);
curl_setopt($ch,CURLOPT_POSTFIELDS,$post_data);
curl_exec($ch);
............

复习一下php 的 curl怎么POST上传文件

post data 中 /etc/passwd是个字符串,但是 @/etc/passwd 是个文件

/opt/api/database.sqlite3是个二进制文件,我猜,里面可能会有flag的信息吧

我们看一看

果然,报错了,看来二进制数据作为post_data 传到了 python

复制下来到HTML中,打开浏览器看

搜索一下flag、ctf 这样的关键字,最后找到了flag

WHCTF{yoooo_Such_A_G00D_@}

总结

还差得远,学就完事儿了