最近在做靶场漏洞复现的时候发现了一个由web虚拟机和db虚拟机一起跑起来的联动靶场环境,下载完镜像后总是报错,思前想后都没办法,于是只能自己来解决问题,虽然结果令人大失所望,但是过程还是挺让人有成就感的,就记录了一下。

#docker启服务

进入相对应的靶场环境文件夹下起靶场:

bin4xin@bin4xin's MacbookPro CVE-2020-9402 % docker-compose up -d
Creating network "cve-2020-9402_default" with the default driver
Creating cve-2020-9402_db_1 ... done
Creating cve-2020-9402_web_1 ... done
bin4xin@bin4xin's MacbookPro CVE-2020-9402 % docker-compose ps
       Name                      Command               State              Ports            
-------------------------------------------------------------------------------------------
cve-2020-9402_db_1    /entrypoint.sh                   Up      1521/tcp, 5500/tcp, 8080/tcp
cve-2020-9402_web_1   /docker-entrypoint.sh pyth ...   Up      0.0.0.0:8000->8000/tcp 

我们可以看到对应web服务的端口监听状态:0.0.0.0:8000->8000/tcp,所以我们直接访问试试看:

bin4xin@bin4xin's MacbookPro CVE-2020-9402 % curl localhost:8000
curl: (52) Empty reply from server
bin4xin@bin4xin's MacbookPro CVE-2020-9402 % docker-compose ps  
       Name                      Command               State              Ports            
-------------------------------------------------------------------------------------------
cve-2020-9402_db_1    /entrypoint.sh                   Up      1521/tcp, 5500/tcp, 8080/tcp
cve-2020-9402_web_1   /docker-entrypoint.sh pyth ...   Up      0.0.0.0:8000->8000/tcp 


bin4xin@bin4xin's MacbookPro CVE-2020-9402 % curl 127.0.0.1:8000/vuln
curl: (52) Empty reply from server
bin4xin@bin4xin's MacbookPro CVE-2020-9402 % docker-compose ps       
       Name                      Command               State              Ports            
-------------------------------------------------------------------------------------------
cve-2020-9402_db_1    /entrypoint.sh                   Up      1521/tcp, 5500/tcp, 8080/tcp
cve-2020-9402_web_1   /docker-entrypoint.sh pyth ...   Up      0.0.0.0:8000->8000/tcp 

在上面的bash终端代码我们可以看到,我们访问8000端口服务,都是返回Empty reply from server,我就很郁闷了,明明docker显示状态是Up状态,怎么访问时服务返回空呢。

#排错

#这是一个有脾气的容器

还是不甘心,看了一下本地的ip地址,再次访问看看:

bin4xin@bin4xin's MacbookPro shiro % ifconfig|grep inet                                                  
	inet 127.0.0.1 netmask 0xff000000 
	inet6 ::1 prefixlen 128 
	inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 
	inet6 fe80::aede:48ff:fe00:1122%en5 prefixlen 64 scopeid 0x7 
	inet6 fe80::146d:ed67:817a:e134%en0 prefixlen 64 secured scopeid 0x9 
	inet 114.97.221.67 netmask 0xfffffe00 broadcast 114.97.221.255
	inet6 fe80::24e6:3dff:fe1c:7c55%awdl0 prefixlen 64 scopeid 0x10 
	inet6 fe80::24e6:3dff:fe1c:7c55%llw0 prefixlen 64 scopeid 0x11 
	inet6 fe80::9a9a:9906:8f8d:5e0%utun0 prefixlen 64 scopeid 0x12 
	inet6 fe80::8ef2:d44b:f2b0:f37e%utun1 prefixlen 64 scopeid 0x13 

en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
	inet 114.97.221.67

bin4xin@bin4xin's MacbookPro shiro % curl http://114.97.221.67:8000/vuln
curl: (7) Failed to connect to 114.97.221.67 port 8000: Connection refused

bin4xin@bin4xin's MacbookPro shiro % docker-compose ps                  
       Name                      Command                 State                 Ports            
------------------------------------------------------------------------------------------------
cve-2020-9402_db_1    /entrypoint.sh                   Up           1521/tcp, 5500/tcp, 8080/tcp
cve-2020-9402_web_1   /docker-entrypoint.sh pyth ...   Restarting 

好家伙,这次直接web服务重启了,有脾气。没办法,直接把整个环境down掉重启。

#进容器

这次我想到的办法是直接进容器里面去看看服务到底发生了什么:

docker ps

a66976bc6d2b        cve-2020-9402_web      "/docker-entrypoint.…"   4 seconds ago       Up 3 seconds        0.0.0.0:8000->8000/tcp         cve-2020-9402_web_1
fc99758ce428        vulhub/oracle:12c-ee   "/entrypoint.sh"         5 seconds ago       Up 3 seconds        1521/tcp, 5500/tcp, 8080/tcp   cve-2020-9402_db_1

我们可以通过docker ps来查看docker镜像cve-2020-9402_web对应的CONTAINER ID,通过这个id值进入容器;

bin4xin@bin4xin's MacbookPro CVE-2020-9402 % sudo docker exec -it a66976bc6d2b /bin/bash
root@a66976bc6d2b:/usr/src# 
root@a66976bc6d2b:/usr/src# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 06:44 ?        00:00:00 /bin/bash /docker-entrypoint.sh python manage.py runserver 0.0.0.0:8000
root         7     1  0 06:44 ?        00:00:00 bash /usr/local/bin/wait-for-it.sh -t 0 db:1521 -- echo oracle is up
root        56     0  0 06:45 pts/0    00:00:00 /bin/bash
root        73     7  0 06:45 ?        00:00:00 sleep 1
root        74    56  0 06:45 pts/0    00:00:00 ps -ef

看了一下,没什么大问题啊,服务该照常启动的都启动了,难道是db服务的问题?就在我疑惑的时候,果然:容器又重启了,我的shell直接掉了,查看一下状态,可不咋地,又restart了,心里苦阿。

bin4xin@bin4xin's MacbookPro CVE-2020-9402 % docker ps

CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS                         PORTS                          NAMES
a66976bc6d2b        cve-2020-9402_web      "/docker-entrypoint.…"   2 minutes ago       Restarting (1) 2 seconds ago

#日志排错:-)

排错之前看一下docker的打印日志指南

% docker logs --help

Usage:  docker logs [OPTIONS] CONTAINER

Fetch the logs of a container

Options:
      --details        Show extra details provided to logs
  -f, --follow         Follow log output
      --since string   Show logs since timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)
      --tail string    Number of lines to show from the end of the logs (default "all")
  -t, --timestamps     Show timestamps
      --until string   Show logs before a timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)

我们可以看到,f参数对应的是log查看的容器id,而我的需求是,对应查看某一个时间段之后的db虚拟机的日志,所以生成命令:docker logs --since 2020-09-11T14:50:00 -f b5731d06d3ea web的日志:

bin4xin@bin4xin's MacbookPro shiro % docker logs --since 2020-09-11T14:40:00  -f ae715c332e7e
+ cd /usr/src
+ wait-for-it.sh -t 0 db:1521 -- echo 'oracle is up'
wait-for-it.sh: waiting for db:1521 without a timeout
wait-for-it.sh: db:1521 is available after 60 seconds
oracle is up

我们可以看到没有任何报错;继续,看下面的报错:

+ python manage.py makemigrations
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/django/db/backends/base/base.py", line 220, in ensure_connection
    self.connect()
  File "/usr/local/lib/python3.6/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/db/backends/base/base.py", line 197, in connect
    self.connection = self.get_new_connection(conn_params)
  File "/usr/local/lib/python3.6/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/db/backends/oracle/base.py", line 232, in get_new_connection
    **conn_params,
cx_Oracle.DatabaseError: ORA-12505: TNS:listener does not currently know of SID given in connect descriptor


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "manage.py", line 21, in <module>
    main()
·中间部分省略
·中间部分省略
·中间部分省略
    **conn_params,
django.db.utils.DatabaseError: ORA-12505: TNS:listener does not currently know of SID given in connect descriptor

查看报错是db的报错,赶紧看看db虚拟机的日志情况docker logs --since 2020-09-11T14:40:00 -f b32b16e34b6c db:

ls: cannot access /u01/app/oracle/oradata/orcl: No such file or directory
No databases found in /u01/app/oracle/oradata/orcl. About to create a new database instance
Starting database listener

LSNRCTL for Linux: Version 12.1.0.2.0 - Production on 11-SEP-2020 06:54:05

Copyright (c) 1991, 2014, Oracle.  All rights reserved.

Starting /u01/app/oracle/product/12.1.0.2/dbhome_1/bin/tnslsnr: please wait...

TNSLSNR for Linux: Version 12.1.0.2.0 - Production
System parameter file is /u01/app/oracle/product/12.1.0.2/dbhome_1/network/admin/listener.ora
Log messages written to /u01/app/oracle/diag/tnslsnr/b32b16e34b6c/listener/alert/log.xml
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=b32b16e34b6c)(PORT=1521)))

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=b32b16e34b6c)(PORT=1521)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 12.1.0.2.0 - Production
Start Date                11-SEP-2020 06:54:05
Uptime                    0 days 0 hr. 0 min. 0 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /u01/app/oracle/product/12.1.0.2/dbhome_1/network/admin/listener.ora
Listener Log File         /u01/app/oracle/diag/tnslsnr/b32b16e34b6c/listener/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=b32b16e34b6c)(PORT=1521)))
The listener supports no services
The command completed successfully
Copying database files
1% complete
3% complete
11% complete
18% complete

数据库服务似乎已经启动起来了,但是数据库文件还在复制过程中:Copying database files,那就等待文件复制完成试试看是不是复制文件的行为。

100% complete
Look at the log file "/u01/app/oracle/cfgtoollogs/dbca/orcl/orcl.log" for further details.

LSNRCTL for Linux: Version 12.1.0.2.0 - Production on 11-SEP-2020 07:00:33

Copyright (c) 1991, 2014, Oracle.  All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=b32b16e34b6c)(PORT=1521)))
The command completed successfully
Database has been created in /u01/app/oracle/oradata/orcl
SYS and SYSTEM passwords are set to [oracle]
Setting HTTP port to 8080

PL/SQL procedure successfully completed.

Please login to http://<ip_address>:8080/em to use enterprise manager
User: sys; Password oracle; Sysdba: true
Fixing permissions...
Running init scripts...
Init scripts in /oracle.init.d/: Ignoring /oracle.init.d/*

Done with scripts we are ready to go

难道是因为db的原因导致web服务报错,而且恰好报错是oracle数据库的错,而又恰好我们看日志时是存在这样的情况的。返回去在看web虚拟机的日志,果然:db虚拟机数据库文件拷贝完成后,这边web虚拟机重启后启动服务就没有报错了,服务跑在8000端口。

+ cd /usr/src
+ wait-for-it.sh -t 0 db:1521 -- echo 'oracle is up'
wait-for-it.sh: waiting for db:1521 without a timeout
wait-for-it.sh: db:1521 is available after 0 seconds
oracle is up
+ python manage.py makemigrations
Migrations for 'vuln':
  vuln/migrations/0001_initial.py
    - Create model Names
    - Create model Collection
    - Create model Collection2
+ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, vuln
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying sessions.0001_initial... OK
  Applying vuln.0001_initial... OK
+ python manage.py loaddata collection.json
Installed 8 object(s) from 1 fixture(s)
+ python manage.py shell -c 'from django.contrib.auth.models import User; User.objects.create_superuser('\''admin'\'', '\''[email protected]'\'', '\''admin'\'') if not User.objects.filter(username='\''admin'\'').exists() else 0'
+ exec python manage.py runserver 0.0.0.0:8000

#令人失望的结果

exec python manage.py runserver 0.0.0.0:8000看到这个日志打印出来,觉得好像确实没有什么问题了,再来查看一下docker的状态。

bin4xin@bin4xin's MacbookPro CVE-2020-9402 % docker-compose ps
       Name                      Command               State              Ports            
-------------------------------------------------------------------------------------------
cve-2020-9402_db_1    /entrypoint.sh                   Up      1521/tcp, 5500/tcp, 8080/tcp
cve-2020-9402_web_1   /docker-entrypoint.sh pyth ...   Up      0.0.0.0:8000->8000/tcp    

看一眼docker的情况,都是up状态。访问一下8000端口终于也可以访问到web服务了,不再是Empty reply from server了。

bin4xin@bin4xin's MacbookPro CVE-2020-9402 % curl localhost:8000
<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <title>Page not found at /</title>
  <meta name="robots" content="NONE,NOARCHIVE">
  <style type="text/css">
    html * { padding:0; margin:0; }
    body * { padding:10px 20px; }
    body * * { padding:0; }
    body { font:small sans-serif; background:#eee; color:#000; }
    body>div { border-bottom:1px solid #ddd; }
    h1 { font-weight:normal; margin-bottom:.4em; }
    h1 span { font-size:60%; color:#666; font-weight:normal; }
    table { border:none; border-collapse: collapse; width:100%; }
    td, th { vertical-align:top; padding:2px 3px; }
    th { width:12em; text-align:right; color:#666; padding-right:.5em; }
    #info { background:#f6f6f6; }
    #info ol { margin: 0.5em 4em; }
    #info ol li { font-family: monospace; }
    #summary { background: #ffc; }
    #explanation { background:#eee; border-bottom: 0px none; }
  </style>

web访问日志:

Watching for file changes with StatReloader
Not Found: /
[11/Sep/2020 07:01:23] "GET / HTTP/1.1" 404 2137

Not Found: /
[11/Sep/2020 07:06:47] "GET / HTTP/1.1" 404 2141
---
Parameter: q (GET)
    Type: boolean-based blind
    Title: Oracle boolean-based blind - Parameter replace
    Payload: q=(SELECT (CASE WHEN (6457=6457) THEN 6457 ELSE CAST(1 AS INT)/(SELECT 0 FROM DUAL) END) FROM DUAL)

    Type: time-based blind
    Title: Oracle time-based blind - Parameter replace (DBMS_PIPE.RECEIVE_MESSAGE)
    Payload: q=(SELECT (CASE WHEN (6135=6135) THEN DBMS_PIPE.RECEIVE_MESSAGE(CHR(83)||CHR(74)||CHR(88)||CHR(115),5) ELSE 6135 END) FROM DUAL)
---
[15:22:11] [INFO] the back-end DBMS is Oracle
back-end DBMS: Oracle