重新认识被人遗忘的HTTP头注入

前言

注入类漏洞经久不衰,多年保持在owasp Top 10的首位。今天就聊聊那些被人遗忘的http头注入。用简单的实际代码进行演示,让每个人更深刻的去认识该漏洞。

HOST注入

在以往http1.0中并没有host字段,但是在http1.1中增加了host字段,并且http协议在本质也是要建立tcp连接,而建立连接的同时必须知道对方的ip和端口,然后才能发送数据。既然已经建立了连接,那host字段到底起着什么样的的作用?

Host头域指定请求资源的Intenet主机和端口号,必须表示请求url的原始服务器或网关的是比如www.test.commail.test.com两个域名IP相同,由同一台服务器支持,服务器可以根据host域,分别提供不同的服务,在客户端看来是两个完全不同的站点。

Host头实验总结:在http 1.1中不能缺失host字段,如果缺失, 服务器返回400 bad request,http1.1中不能缺失host字段,但host字段可以是空值。

0×01 密码重置的中毒

相信大家忘记密码时,使用邮箱找回密码并不陌生。看上去貌似能可靠只能发送到你绑的邮箱去重置密码。并且使用你自己独特的密钥令牌才能重置成功。但是好多cms和实际场景为了获取网站的域名拼接秘钥令牌的方式将连接发送到你的邮箱。但是往往获取正确的域名并不是十分的不容易, 然而用一个固定的URI来作为域名会有各种麻烦。所以一般程序员会采用(java)request.getHeader(“Host”); (php)$_SERVER['HTTP_HOST']的方式来获取域名。

上面所述的两种获取域名的方法并不可靠。都可以人为的去控制。导致当域名和令牌拼接时,攻击者通过篡改hsot值生成钓鱼连接,当受害者点击时,受害者的秘钥令牌将会直接发送到攻击者的服务器上。使其受害者的密码被攻击者篡改。

文字看上去比较绕的话,我在本地用代码将此处的业务场景进行了复现。

public class FindPass extends HttpServlet{
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) { //此处真实场景的话,是根据输入的账号去查对应的邮箱。就不繁琐的构造了。 String email =request.getParameter("email"); //此处获取了host头中的host字段,此值可以被攻击者篡改 String Host =request.getHeader("Host");
int max=;
int min=;
Random random = new Random(); //生成随机的秘钥令牌 int randomNubmer = random.nextInt(max-min) + min;
String content= "用户您好:<br>现在给您发送邮件的XX银行系统,您的账户"+email+"申请找回密码!<br>" +
"只需在提交请求后的三天之内,通过点击下面的链接重置您的密码:<br>"+
"http://"+Host+"?id="+randomNubmer; //此处用Host拼接了秘钥名牌 try { //调用发信接口 SendEmail.send(email, content);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(email+Host);
}

}

提交找回密码表单,篡改其中的host头值。

当用户收到密码重置邮件后,发现是钓鱼者的网址,且秘钥令牌也已参数id的形式传给给攻击者,此时攻击者可以直接使用受害者的令牌进行密码重置。

0×02 XSS

有些网站会根据HTTP_HOST字段来进行加载css样式表。如果要为固定的话,当域名发生改变时,那么站内所有的css即将失效。而且修改的时候也将的十分头疼,因为每个页面都会引用大量的公共资源。如下是我重构的场景重现:

<?php
echo<<<EOT
测试host攻击<br>
cccccccc
<head>
<link rel="stylesheet" type="text/css" href="http://{$_SERVER['HTTP_HOST']}?id=111111" />
</head>
EOT;
echo $_SERVER["HTTP_HOST"];
?>
 

0×03 web缓存中毒

简单描述:

Web缓存服务器的应用模式主要是正向代理反向代理。正向代理(Proxy)模式是代理网络用户访问internet,客户端将本来要直接发送到internet上源服务器的连接请求发送给代理服务器处理。正向代理的目的是加速用户在使用浏览器访问Internet时的请求响应时间,并提高广域网线路的利用率。正向代理浏览器无需和该站点建立联系,只访问到Web缓存即可。通过正向代理,大大提高了后续用户的访问速度,使他们无需再穿越Internet,只要从本地Web缓存就可以获取所需要的信息,避免了带宽问题,同时可以大量减少重复请求在网络上的传输,从而降低网络流量,节省资费。

思路:

Apache接收到一个带有非法host header的请求,它会将此请求转发给在 httpd.conf 里定义的第一个虚拟主机。因此,Apache很有可能将带有任意host header的请求转发给应用。

场景:

一般的缓存服务器都会识别hsot,所以一般直接替换host字段会被拦截。。Varnish辨别第一个host Apache识别所有请求的host, Nginx则只是看最后一个请求。此时就可以通以下方式

GET / HTTP/1.1
Host: test.com
Host: exp.com

来绕过缓存服务器的检查。

0x04WordPressPHPMailer结合导致命令执行

漏洞描述:

独立研究人员Dawid Golunski发现该漏洞—远程攻击者利用该漏洞,可实现远程任意代码在web服务器上执行,并使web应用陷入威胁中。攻击者主要在常见的web表单如意见反悔表单、注册表单中 ,邮件密码重置表单等使用发送的组建时利用此漏洞。

POC展示:

主要是利用host注入恶意命令导致远任意代码执行
Host : target(any -froot@localhost -be ${run{${substr{}{}{$spool_directory}}usr${substr{}{}{$spool_directory}}bin${substr{}{}{$spool_directory}}touch${substr{}{}{$tod_log}}${substr{}{}{$spool_directory}}tmp${substr{}{}{$spool_directory}}manning.test}} null)

下面针对这个做个简要分析,网上很多文章已经对此作了详细分析,我在此就不做详细分析了。

if ( !isset( $from_email ) ) {

//此处会获取SERVER_NAME字段拼接到$from_email变量上且SERVER_NAME可被攻击者控制

        $sitename = strtolower( $_SERVER['SERVER_NAME'] );
if ( substr( $sitename, , ) == 'www.' ) {
$sitename = substr( $sitename, );
} $from_email = 'wordpress@' . $sitename;
} private function mailPassthru($to, $subject, $body, $header, $params)
{
//Check overloading of mail function to avoid double-encoding
if (ini_get('mbstring.func_overload') & ) {
$subject = $this->secureHeader($subject);
} else {
$subject = $this->encodeHeader($this->secureHeader($subject));
}
if (ini_get('safe_mode') || !($this->UseSendmailOptions)) {
$result = @mail($to, $subject, $body, $header);
} else { //最终$params参数被@mail调用后会触发CVE-2016-10033 phpmailer命令执行漏洞执行远程命令。 $result = @mail($to, $subject, $body, $header, $params);
}
return $result;
}

X-Forwarded-For注入:

大家有没有见过这样一种场景,当你对用户网站进行的爆破或者sql注入的时候,为了防止你影响服务器的正常工作,会限制你访问,当你再次访问时,会提示你的由于你的访问频过快或者您的请求有攻击行为,限制访问几个小时内不能登陆,并且重定向到一个错误友好提示页面。

由此可以发起联想?http是无状态连接,而且自己也清空了COOKIE信息,服务器是怎么还是自己的?

首先当你有攻击行为的时候,服务器一般会把恶意用户的ip存入数据库。当每次用户请求的时候(以java语言为例),服务器通过request.getRemoteAddr()这个方法来获取请求者的ip。于是想到这个ip我们自己到底能不能伪造?答案是否定的。因为经过测试request.getRemoteAddr并不会回从数据包的请求头去获取ip字段的Value。所以推测ip地址是ip包中的soure来的,当我们发送http请求时是否可以更新soure ip来绕过限制呢,这个可以有!,但是你将不会收到对方的响应,因为在正常的TCP/IP通信中,伪造数据包来源 IP会让发送出去的数据包返回到伪造的IP上,无法实现正常的通信。这样我们也就失去的绕过的意义。

request.getRemoteAddr方法我们没办法伪造,是不是我们就无法利用这个点了呢?

结合实际一般程序员是不会通过request.getRemoteAddr方法来获取ip的,这个方法虽然获取的ip比较准确,暂无办法绕过。但实际场景中往往服务器前面会有一个代理服务器和均衡负载服务器。当使用request.getRemoteAddr方法时,获取的只是代理服务器的ip并不能获取请求者的真实ip。这时候一些程序员为了实现获取真实ip会采取如下方法。

public static String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader("X-Real-IP"); if (ip == null || ip.length() == || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Forwarded-For");
}
if (ip == null || ip.length() == || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
if (ip != null) {
if (ip.indexOf(',') > ) {
ip = ip.split(",")[];
}
} else {
ip = "0.0.0.0";
}
return ip;
}
 

X-Forwarded-For通过这个字段我们可以控制绕过ip的限制,但是当我们去绕过ip限制的时候ip会带入数据库去查询,这点我们是不是可以尝试一下sql注入。

将数据包写入文件,通过 sqlmap.py  -r  “filePath”
 

通过sqlmap抛出的信息,可以看到存在sql注入的点是X-Forwarded-For字段,并且爆出了mysql的版本信息和脚本语言的信息。

User-Agent注入

User-Agent、Content-Type等只要是http包中存在的都可以进行篡改。在这再说下User-Agent的头注入和Content-Type的头注入,其他的就不详细赘述。基本原理大同小异。最后会进行总结。

一般使用user-Agent,有两种场景一是记录访问者的信息,如什么浏览器、操作系统版本等。二是获取客户的user-Agent,根据你提供的信息来给你推送不同的网页。如果你手机手机访问那么返回你的页面将是小型的web界面,还有各种浏览器的特性,推送相兼容的页面。此时已经进行的数据库的入库和查询操作,如果没对此做过滤那么漏洞就产生了。

Content-Type注入又一个远程命令执行

Content-Type看见这个字段相信大家都不陌生,瞬间就会想起一个很可怕的漏洞。S2-045的远程命令执行。当Jkarta解析文件上传请求包不当,当攻击者使用恶意的Content-Type,会导致上传发生异常。从而导致Str2框架对Content-Type的内容进行ongl的解析导致命令执行。这个漏洞虽然要涉及Jkarta插件,而arta插件ommons-fileupload和commons-io包,但是这是Str2的默认插件。也就是说基本所有开发使用到上传都会导入这两个依赖包。最重要的是这个漏洞不需要真正的上传只需进行模拟上传即可,甚至可以是GET请求。具体的详细代码就不跟大家分析了,要不估计还比我这篇文章还长。有兴趣的可以到我的博客或者网上搜索那些大佬的分析。

总结

归根结底,http头攻击漏洞的产生就是因为服务器使用了不受信任的http头字段对某个业务进行的操作。而http头都是我们可以恶意篡改的。具体产生什么漏洞,就看你把这个不受信任的字段,拿去做什么样的业务操作。在平常渗透的时候,可以思考程序员们会拿着这些参数去干什么,从而更有方向的去渗透。

2.HTTP头注入的更多相关文章

  1. PHPMYWIND4.6.6前台Refer头注入+后台另类getshell分析

    下载链接 https://share.weiyun.com/b060b59eaa564d729a9347a580b7e4f2 Refer头注入 全局过滤函数如下 function _RunMagicQ ...

  2. SQL注入篇二------利用burp盲注,post注入,http头注入,利用burpsuit找注入点,宽字节注入

    1.布尔盲注burpsuit的使用 先自己构造好注入语句,利用burpsuit抓包,设置变量,查出想要的信息. 比如----查数据库名的ascii码得到数据库构造好语句 http://123.206. ...

  3. 重新认识被人遗忘的HTTP头注入

    前言 注入类漏洞经久不衰,多年保持在owasp Top 10的首位.今天就聊聊那些被人遗忘的http头注入.用简单的实际代码进行演示,让每个人更深刻的去认识该漏洞. HOST注入 在以往http1.0 ...

  4. Sqli-LABS通关笔录-18-审计SQL注入2-HTTP头注入

     在此关卡我学习到了 1.只要跟数据库交互的多观察几遍.特别是对于http头这种类型的注入方式. 2. <?php //including the Mysql connect parameter ...

  5. host头注入

    看到有说这个题为出题而出题,其实我还是这么觉得, host出问题的话我觉得一般只有在审计代码,看到才知道有host注入 假设不提示host注入,就有难度了 常规的注入了

  6. sqlmap http头注入的一个技巧

    sqlmap.py -u "url" --host * --thread=1 --batch -v 1 --delay=0.7 --dbms mysql   --current-d ...

  7. 记录一次Oracle注入绕waf

    这个注入挺特殊的,是ip头注入.我们进行简单的探测: 首先正常发起一次请求,我们发现content-type是76 探测注入我习惯性的一个单引号: 一个单引号我发现长度还是76 我开始尝试单引号,双引 ...

  8. 跟bWAPP学WEB安全(PHP代码)--邮件头和LDAP注入

    背景 由于时间限制和这俩漏洞也不是特别常用,在这里就不搭建环境了,我们从注入原来和代码审计的角度来看看. 邮件头注入 注入原理: 这个地方首先要说一下邮件的结构,分为信封(MAIL FROM.RCPT ...

  9. SQL注入备忘录

    备忘录(一) 拿起小本本记下常考知识点. 常用连接词 and && %23%23 且 or || %7c%7c 或 xor 非 Access 数据库: 只能爆破表名.列名获取数据.无法 ...

随机推荐

  1. 第三篇、javascript整数和字符串

    一.整数 JavaScript中不区分整数值和浮点数值,JavaScript中所有数字均用浮点数值表示. 转换: parseInt(..)    将某值转换成数字,不成功则NaN parseFloat ...

  2. Android系统定制之SystemUI修改:下拉通知栏尺寸【转】

    本文转载自:https://blog.csdn.net/huil0925/article/details/67632358 最近项目需要修改下拉通知栏面板的宽度,完成后,写个Blog做个总结,也提供给 ...

  3. Linux iptables 从入门到放弃

    iptables表(iptables)和链(chains)    描述完iptables术语后,相信大家对iptables的表和链有了初步的了解.默认情况下,Iptables根据功能和表的定义划分包含 ...

  4. linux 新建分区 、格式化 并挂载的命令

    一.新建分区命令为 fdisk /dev/diskname fdisk命令为交互式命令 p:显示当前硬盘上的分区,包括没保存的改动 n:创建新分区 e:表示扩扩展分区 p:表示主分区 d:删除一个分区 ...

  5. javascript时间戳转换成指定格式的日期

    //时间戳转换成指定格式的日期DateTool.IntDatetimeTo = function(time, format){    var testDate = new Date(time);    ...

  6. Tomcat_总结_02_单机多实例

    一.tomcat下载及环境变量配置 1.tomcat下载 下载地址:tomcat官网 2.环境变量配置 只用配置一个CATALINA_HOME就可以了 二.CATALINA_HOME 与 CATALI ...

  7. Sqlite表结构读取工具,word批量转html,在线云剪贴板,文件批量提取工具;

    工欲善其事必先利其器,本周为您推荐工具排行 Sqlite表结构读取工具,word批量转html,在线云剪贴板,文件批量提取工具:     本周我们又要发干货了,准备好接受了吗? 为什么是干货,就是因为 ...

  8. [BZOJ1396&2865]识别子串

    bzoj1396 bzoj2865 dbzoj1396 dbzoj2865 题面 XX在进行字符串研究的时候,遇到了一个十分棘手的问题. 在这个问题中,给定一个字符串\(S\),与一个整数\(K\), ...

  9. VBScript 内置函数

    本页列出了所有内建的 VBScript 函数: Date/Time 函数 Conversion 函数 Format 函数 Math 函数 Array 函数 String 函数 其他函数 Date/Ti ...

  10. 【转】 Pro Android学习笔记(四八):ActionBar(1):Home图标区

    目录(?)[-] Home Icon 源代码 TextView的滚动 返回主activity或指定activity     ActionBar在Android 3.0 SDK中为平板引入,在4.0中也 ...