freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

注入漏洞总结
Linux1234 2023-06-19 23:32:57 131695
所属地 江西省

学习注入也有一段时间了,虽然学的不多,但想着对注入漏洞做一些总结,于是写下这篇文章,有好的建议欢迎留言。

注入漏洞在十大Web安全漏洞之中,其主要原因是对用户的输入过滤不严,导致程序以危险的方式运行,注入漏洞应用最广泛,杀伤力也很大如最常见的sql注入,命令注入,还有代码注入、xss等。

SQL注入:最常见的Web漏洞之一,作用对象在数据库中,程序没有对用户输入数据的合法性进行验证和过滤,导致sql查询语句被恶意拼接,sql注入漏洞存在的条件:参数用户可控、参数可以动态拼接sql语句并带入数据库查询、参数过滤不严。

注入攻击:SQl注入根据注入效果可以分为:UNION联合注入、报错注入、布尔盲注、时间盲注、堆叠注入、二次注入等,按照提交方式可以分为:GET注入、POST注入、HTTP头注入,以及其他分类。

UNION联合注入:联合注入的前提条件是用户可控参数所在Sql语句为查询语句,且以页面存在回显,如:select * from users where id=”$id”;。此时可以通过更改参数id来实现对数据库的操作。考虑到前提是查询双方具有相同的列,可以使用order by 语句大致判断列数,也可以使用select 1,2,3,4等依次查看。UNION联合注入往往是最实用的,因为判断了回显位后就可以拼接语句union select version()等获取数据库信息,当然如果权限允许也可以在information_schema中查看全部数据库信息。在查询过程中可能会遇到查询结果有多个数据,但页面只显示一段,可以使用concat()、group_concat()等函数。

布尔盲注:与UNION联合注入不同,布尔盲注用于页面无回显信息,但不同的语句会有不同的效果,如:id=1,页面显示登入成功,但当输入id=0(前提是数据库中没有id=0)时,页面显示登入失败或什么都不显示,此时就可以用布尔盲注来判断语句的真假。如id=0’ or length(database())>4 --+ 可以判断数据库的名称的长度,有了长度后就可以逐字符判断,如:id=0’ or substring(database(),1,1)=’s’--+表示判断从数据库名第一个字符开始截取一个字符判断是否是字符s。也可以构造一些特殊语句如:id=0’ord(substring(database(),1,1))=65 --+ ord函数可以将字符转换成ascii码,就可以将65设为变量,使用字典爆破的方法逐一判断,也可以直接爆破数据库名和其他表名、字段名等等。

时间盲注:时间盲注用于当输入不同的语句后页面效果一样的情况,时间盲注多与if(),sleep()函数使用,if(1=1,sleep(1),1)表明如果1=1,Sql查询休眠1秒,否则返回1,可以通过页面响应时间判断语句的正确。其他语句的拼接与布尔盲注一样。

报错注入:报错注入可用于Sql语句执行错误后页面会显示错误信息的情况,报错注入的前提条件是后端脚本中有mysql_error等报错函数。常见的报错方法有extractvalue()函数、updatexml()函数、floor型报错、整数溢出报错、几何函数报错等。在Mysql5.1.5版本以上,可以使用XPATH报错(extractvalue函数、updatexml函数),这两个函数用与查询修改xml文档,extractvalue()函数的使用extractvalue(xml文档,文档路径),文档路径的格式是/xx/xx/xx,若格式错误,会显示错误路径。如:id=0’or (select extractvalue(1,concat(‘!’,database()))) --+会显示(!数据库名)路径错误。floor型注入一般要与rand函数、group by一起使用。group by用于给查询数据分组,分组依据为by后面的语句,先创建虚拟表,然后在查询数据时,从数据库中取出数据,看在虚拟表中是否有同样的记录, 如果有,就在相应字段加一,如果没有就直接插入新记录。rand函数用于生成随机数,rand(0)表明生成一个0-1的随机数,但rand()确实是随机数,rand(0)生成的是有规律的随机数,floor函数用于向下取整,所以floor(rand(0)*2)只返回0或1,且为011011011…。查询中如果使用rand()的话,该值会被计算多次,也就是在使用group by 的时候,floor(rand(0)*2)会被执行一次,如果虚拟表中不存在记录,把数据插入虚拟表中时会再被执行一次。分析语句:select count(*) group by floor(rand(0)*2),查询前会建立虚拟表,取第一条记录,执行floor(rand(0*)2),发现结果是0(第一次计算),查询虚拟表,发现0的键值不存在,就会往虚拟表插入新的数据,则floor(rand(0)2)会被再计算一遍,结果为1(第二次计算),插入虚拟表,这时第一条记录查询完毕,查询第二条记录,再次计算floor(rand(0)*2),发现结果为1(第三次计算),查询虚拟表,发现1的键值存在(上图),所以floor(rand(0)*2)不会被计算第二次,直接count(*)+1,第二条记录查询完毕,查询第三条记录,再次计算floor(rand(0)2),发现结果为0(第四次计算),查询虚拟表,发现0的键值不存在,则虚拟表尝试插入一条新的数据,在插入数据时floor(rand(0)2)被再次计算,结果为1(第五次计算),然而1这个主键已经存在于虚拟表中,而新计算的值也为1(应为主键键值必须唯一),所以插入时直接报错了,于是在注入时就可以构造语句0' or (select count(*)  from users group by concat(database(),floor(rand(0)*2)))--+爆出数据库信息。在版本号为5.5.47和5.7.17之间,Mysql有一些几何函数如geometrycollection(),multipoint(),polygon(),multipolygon(),linestring(),multilinestring(),这些函数对参数要求是形如(1 2,3 3,2 2 1)这样几何数据,如果不满足要求,则会报错,就可以构造语句:id = 1 and GeometryCollection((select from (select from(select database())a)b))获取数据库信息。根据官方文档说明,只有版本号大于5.5时整数溢出才会报错,在注入过程中不可能输入这么大的数,一般采用按位取反如:~0就表示最大整数值,~0+1就会产生报错信息。Sql语句执行成功的返回值为0,进行逻辑非运算后为1,这个值是可以参与运算的,我们就可以构造语句:id=0’or  (select(~0+!(select * from (select database())a))) --+,此方式只适用于Mysql版本号小于5.5.53。整数溢出报错的另一种方式是利用exp函数,exp函数返回e的指定次幂,利用语句:(select exp(~(select * from (select database())a))) --+同样可以完成整数溢出报错。

堆叠注入:在SQL语句中,;代表一个语句的结束,如果在注入过程中注入;+语句,就可以执行构造的语句,堆叠注入的危害巨大,用户可以构造任何合法语句,包括但不限与删除数据,但一般服务器都会限制一次只能执行一条SQl语句。

二次注入:二次注入一般用于可以注册信息的场景,其原理是后端代码对用户上传的参数做了过滤,但是未对从数据库传出的数据进行过滤。分析语句:$username=addslashes($_GET[‘username’]);insert into             users(‘username’,’password’) values $username,代码对username参数进行了过滤,也就是对‘进行了转义,如输入test’,实际SQL语句为test\‘,但如果从数据库中取出数据时未再次转义,就可以产生注入点。输入参数test’union select 1,2,version() --+,再从数据库中查询,语句变为:select * from user where username=’test’union select 1,2,version() --+’就可以获取数据库信息。

GET注入:提交数据的方式是 GET , 注入点的位置在 GET 参数部分,可以在url中看到参数名称,但url有长度限制,所以一般参数不能过长。

POST注入:使用 POST 方式提交数据,注入点位置在 POST 数据部分,多见于表单。

HTTP头注入:常见的HTTP头注入有COOKIE、HTTP_CLIENT_IP、HTTP_X_FORWARDED_FOR、HTTP_X_FORWARDED、HTTP_X_CLUSTER_CLIENT_IP、HTTP_FORWARDED_FOR、HTTP_FORWARDED、REMOTE_ADDR、User-agent、Referer。后端脚本从客户端发起的请求中获取cookie信息,并用于SQL语句中,如$_COOKIE函数。用burp suite抓包,修改cookie的值为1’union select 1,version(),3 --+,用于SQL语句中变为select * from user where id=’1’union select 1,version(),3 --+’,所以,从本质上来讲,Cookie注入与传统的SQL注入并无不同,两者都是针对数据库的注入,只是表现形式上略有不同罢了。HTTP_X_FORWARDED_FOR的注入也叫XFF注入,服务器端从HTTP_X_FORWARDED_FOR中获取参数(IP),并带入SQL语句中,可以通过burp suite抓包修改HTTP_X_FORWARDED_FOR头,构造目标SQL语句,其他的头注入也类似,关键在于后端脚本有无获取头信息并利用头信息的参数。

读写文件:SQL注入还可以通过读写文件来进行,但通常条件苛刻,要对目标主机的路径有所了解,否则就算写入了文件叶无法利用,同时也要有相应的权限来读写文件,否则就算能使用outfile、load_file(),也不能产生实质性效果。如果成功写入文件并且可以访问到,就可以写入webshell,并通过中国菜刀、webacoo等工具进行连接。

一些绕过方法:

大小写绕过:sql语句是不区分大小写的,一些老式的容器、waf等对大小写敏感,如union可以写成Union来绕过,现在基本没怎么老的版本,基本这种方法不可行。

双写绕过:有些waf是过滤危险字符,如把字符转换成空字符,这时就可以通过双写绕过,如uniunionon经过过滤之后变成union,但是好像除了靶场,基本没有会过滤危险字符的,一般都是直接拒绝访问。

编码绕过:可以通过对参数进行编码进行绕过,前提是后端代码有相应解码的功能。

注释绕过:一些waf没有对注释符进行判断,就可以通过注释来绕过,如:id=1 /*!union*/ /*!select*/,或者如union /*kuyed*/ select /*iuysv*/ 1。

宽字节绕过:当客户端与服务端的编码不一致时,有可能可以使用宽字节注入,比如php使用utf8,而mysql使用gbk编码,utf8使用一个字节表示英文,而gbk用两个字节,比如在‘/前面加上df就可以使df与/结合而绕过,通过url编码就变为%df。

Cookie绕过:一些程序员会通过$_REQUEST来获得参数,它会一次检测GET POST COOKIE是否有值,但有时程序只检测get或post的值,这时就可以通过cookie传参数来绕过。

使用其它函数:使用一些偏僻的waf不会检测的函数。

攻击防范:学习一种漏洞,除了学习如何利用,还要清楚的知道如何防范。

防范漏洞的第一个原则就是永远不能相信用户可控的数据,包括数据库中的数据,一些开发人员过于相信从数据库调出来的数据,始终要对数据进行严格的过滤,不要尝试“修复”数据,而应该拒绝有安全隐患的请求,因为人们总能想到绕过“修复”的方法。

参数化查询可以基本防范住sql注入漏洞,也叫预处理语句,传统的sql查询是使用字符串与用户参数动态拼接,PDO 语句可用的bind_param() 方法让你可以给预处理语句中出现的占位符绑定参数,并且接受基本的数据类型参数,基本杜绝了动态拼接恶意语句的可能,下面是一个代码示例。

1687149419_648fdb6b66b4cdb35798d.png!small?1687149419775

严谨的代码也是防范注入的一大方向,一些程序员在前期调试的时候会在代码中加入报错函数,但在上线后却忘记删除,或者一些程序员根本没有意识到要删除,这将会给不怀好意的用户提供很多信息,如代码路径、字段名称、数据库版本等。还有一些是只验证数据当下用途(例如,展示或计算),却不考虑数据最终存储位置的数据库表字段的验证需求,可能字符串长度超过了数据库中的限制。

除了尽可能的防范漏洞利用的可能,我们也要尽最大可能降低漏洞被利用后的危害。最小化当前执行业务的用户的权限,可以设置一个拥有写数据权限的用户,和另一个只有读数据权限的用户,这种角色区分可以确保在 SQL 注入攻击目标为只读用户时,攻击者无法写数据或操纵表数据,这种生物隔离区划可以延伸到进一步限制访问权限,这样就可以将 SQL 注入攻击的影响最小化。

XSS注入:XSS有自己的漏洞划分,但它其实也是注入漏洞的一种。

注入攻击:攻击者向web页面(input表单、URL、留言版等位置)插入恶意JavaScript代码,导致管理员/用户访问时触发,从而达到攻击者的目的,XSS攻击可以分为常见的四类,反射型、储存型、DOM型、基于页面型。XSS常见的绕过有大小写、双写、编码、事件绕过等

XSS常用的触发事件:

onclick:点击元素时触发

onerror:图片音频等加载错误时触发

onmouseover:鼠标移动到元素时触发

onmouseout:移出元素时触发

XSS常用的触发标签:

<scirpt>alert("xss");</script>

<img src=1 onmouseover="alert(1)">

<img src="x" onerror=alert(1)>

<a href=javascript:alert('xss')>test</a>

<a href="" onclick=alert('xss')>a</a>

<input onfocus="alert('xss');" autofocus>:自动触发

<iframe onload=alert("xss");></iframe>

<iframe src=javascript:alert('xss')></iframe>

<svg onload=alert(1)>

<details open ontoggle="alert('xss');">:自动触发

<select onfocus=alert(1) autofocus>:自动触发

<video><source onerror="alert(1)">

<audio src=x onerror=alert("xss");>

<textarea onfocus=alert("xss"); autofocus>:自动触发

一些绕过:

data:后接自定义流,data:text/html;base64, YWxlcnQoMSk=

大小写绕过:<SCript>alert();</SCript>

双写绕过:<scripScriptt> <imimgg src=>

空格绕过:有些时候会过滤空格,可以用换行符、制表符(TAB)、/来绕过

拼接绕过:要利用到eval,用于拼接字符串,<img src=1 onerror=”a=aler,b=t(),eval(a+b)”>

注释、优先级绕过: <scri<!--test-->pt>alert("hello world!")</scri<!--test-->pt>,<title><img src=</title>><img src=x onerror="alert(``xss``);">

编码绕过:unicode编码、base64编码、url编码、hex编码、八进制等

<img src=1 onerror=&#108,&#101,&#114,&#116,&#40,&#34,&#120,&#115,&#115,&#34,&#41,&#59>

<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=">

攻击防范:和sql注入一样,要对用户的参数进行严格过滤

一些比较简单的过滤有限制内容长度,还有比如php内置的函数htmlspecialchars()会把html预定义字符编码成html实体,如果把全部的字符都编码,该函数可以防止很大一部分的攻击。

在纯前端渲染中,浏览器先加载一个静态HTML,此HTML中不包含任何跟业务相关的数据。然后浏览器执行HTML中的JavaScript,JavaScript 通过 Ajax 加载业务数据,调用 DOM API 更新到页面上。在纯前端渲染中,我们会明确的告诉浏览器:下面要设置的内容是文本(.innerText),还是属性(.setAttribute),还是样式(.style)等等,浏览器就不会被轻易的被欺骗,执行预期外的代码了。

设置httponly也是防范XSS漏洞带来的危害的一种有效措施,禁止 JavaScript 读取某些敏感 Cookie,就算攻击者完成 XSS 注入后也无法窃取cookie。

命令注入漏洞(PHP):命令注入也是常见漏洞,Web有执行操作系统命令的业务,该漏洞的条件和sql注入相似,执行命令的函数的参数用户可控、后端对数据过滤不严格。

注入攻击:system、exec、shell_exec、passthru、popen、proc_popen等函数,如果函数中的参数用户可控,且过滤不严格,就有可能导致执行恶意命令,造成命令执行漏洞。

常见绕过:

Windows命令拼接符,$,$$,|,||

1687149480_648fdba8673913adcf50d.png!small?1687149480890

Linux拼接符

‘&’的作用是使命令在后台运行

()用于组合命令

;表示一个命令的结束,可以执行多条无关联的命令

命令执行的通配符?、*、[]

1687149495_648fdbb7860dac822f0aa.png!small?1687149496233

如cat /etc/passwd可以替换成cat /*tc/pa??wd,通配符也可以配合使用

Linux中未定义的变量为null,可以通过未定义的变量来绕过

如:cat$a /etc$a/passwd$a、cat /et$ac/pass$bwd等,但是经过测试,好像$a,$b这种有英文的在命令字母中间并不起作用,但是$1等可以绕过

1687149525_648fdbd57b0a1526a9d53.png!small?16871495258141687149510_648fdbc6b5e7b1c18a09a.png!small?1687149511095

‘命令’(反引号)、$(命令)也是命令执行的一种方式,它将结果保存到一个变量中,如echo $(pwd)

1687149544_648fdbe85426790114bc1.png!small?1687149544676

1687149549_648fdbedb3197638c3fdd.png!small?1687149550152

插入单双引号反斜杠绕过

1687149597_648fdc1d0b4735aff202f.png!small?16871495974661687149559_648fdbf703730518a9bc2.png!small?1687149559864

变量组合

1687149604_648fdc24ad59a150e9db5.png!small?1687149605123

关键字被过滤的话,可以试着替换关键字,如cat可以替换成more、vi、vim、head等等

还可以考虑将代码分段写入文件中,再通过调用文件来执行命令,这种方法可以用于限制长度的情况

1687149630_648fdc3eb23f3ab1c8832.png!small?16871496313441687149614_648fdc2ec8f871b751213.png!small?1687149615379

还可以利用编码绕过,如base64编码,16进制编码,8进制编码等

1687149638_648fdc465b812a58430df.png!small?1687149638750

攻击防范:

对数据的合法性进行校验():比如IP地址,直接校验IP地址的格式看,如果是url域名,则从url域名中获取IP地址后,在进行IP格式校验,若获取失败或者校验失败,则认为数据非法。

使用白名单,限制参数的内容也是很有效的方法

给web服务器系统及使用的中间件及时打上安全补丁,同时将应用程序的权限降到最低

代码注入(PHP):php代码注入包含很多内容,文件包含、内置函数、动态函数、正则表达式等,代码注入的危害是巨大的,用户通过拼接参数影响php代码的执行,使服务器等处于危险之中。

注入攻击:

代码注入最显眼的就是文件包含了,其影响函数有include(),include_once(),require()等,include和require区别主要是,include在包含的过程中如果出现错误,会抛出一个警告,程序继续运行;而require函数出现错误的时候,会直接报错并退出程序的执行,如果不可信输入被允许来决定传输给这些函数的路径参数,它就可能影响被包含的文件,应该注意的是,被包含的文件不一定是一个真正的 PHP 文件,任何能够携带文字数据的被包含文件都有可能,文件包含也可以包含远程文件,高版本php默认关闭该功能。

Windows下一些默认隐私文件

1687149649_648fdc51863f9403b552a.png!small?1687149649927

Linux下的一些文件

1687149654_648fdc5662d05109cf607.png!small?1687149654848

本地文件中的session文件包含用户可以控制服务器中session文件的内容,除了可以查看内容还可以执行恶意代码,如

用户可以控制ctfs变量的值,如传入<?php phpinfo(); ?>,再通过文件包含漏洞访问到该文件,前提是要了解session文件的路径,就可以执行上述代码

文件包含的一些绕过:

1687149663_648fdc5fc6ebb8a15c6e1.png!small?1687149664215

本地文件包含中有这种后缀限制的可以通过00截断绕过,但是有php版本限制,同时也可以利用路径长度限制截断,也就是大量的././././之后的内容会被丢弃,点号也有长度限制,如果是远程文件包含,可以在url结尾加?#空格等字符过滤掉不需要的后缀

1687149670_648fdc663ba4d926cdc77.png!small?1687149670550

http(s)协议:也就是远程文件包含,需要allow_url_fopen和allow_url_include都开启

file协议:用于访问本地文件,php 涉及到文件以及协议的地方默认使用 file 协议,如果没有写出协议名或者协议不存在,都会被当成 file 协议来解析

ftp协议:跟http协议一样,只是换了个协议名,同样需要allow_url_fopen和allow_url_include都开启

zip协议:压缩流,可以访问压缩文件中的子文件,格式为zip://[压缩包绝对路径]#[压缩包内的子文件名],压缩包内的子文件名后缀可以更改,如换成图片的后缀名

data协议:使用方法data://text/plain;base64,xxxx(base64编码后的数据),需要allow_url_fopen和allow_url_include都开启

php协议:常见的有php://input,php://filter,filter可以对打开的数据流进行筛选和过滤,常用于查看源码,格式为php://filter/过滤器|过滤器/resource=待过滤的数据流,如base64编码过滤器为read=convert.base64-encode,php://input 可以访问请求的原始数据,配合文件包含漏洞可以将post请求体中的内容当做文件内容执行,从而实现任意代码执行,需要注意的是,当enctype=multipart/form-data时,php:/input将会无效,需要allow_url_include开启

php的一些函数把参数当做php代码执行的,eval(),assert(),preg_replace()等。eval函数可以将字符串当作代码来执行,assert与eval用法一样,正则函数preg_replace()中的e修饰符可以将截取的字符串作为代码来执行

1687149697_648fdc81a946d411b533e.png!small?1687149698051

call_user_func()函数把第一个参数作为回调函数

1687149703_648fdc8789c5ec031104e.png!small?1687149703930

意思是$fun是一个函数,$para作为函数的参数,如果用户参数可控,则可以实现远程代码执行

php支持动态变量、函数,如$$a,$a($b),可以动态拼接变量

攻击防范:

对于代码注入,最主要的还是少使用危险函数,如果要使用,一定要严格过滤用户参数,还有preg_replace放弃使用/e修饰符

对于文件包含,除了要严格限制外来参数外,如/,.,..等字符,还有的防范措施是限制文件包含的路径,从源头将文件包含限制在一个相对安全的路径。

严格管控权限范围,或对服务器中的重要信息文件、隐私文件加密,就算有文件包含漏洞,攻击者也获取不到有用的信息。

尽量避免使用一些常见的路径名称。

# 漏洞 # web安全 # 网络安全技术
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 Linux1234 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
Linux1234 LV.1
这家伙太懒了,还未填写个人描述!
  • 1 文章数
  • 0 关注者