DVWA

Brute Force

LOW


函数解读:
1.mysqli_query(connection,query,resultmode):
作用:执行一条 MySQL 查询
语法:

1
2
3
4
5
connection 必需。规定要使用的 MySQL 连接
query 必需,规定查询字符串。
resultmode 可选。一个常量。可以是下列值中的任意一个:
MYSQLI_USE_RESULT(如果需要检索大量数据,请使用这个)
MYSQLI_STORE_RESULT(默认)

2.die(status):
作用:输出一条消息,并退出当前脚本
语法:

1
2
3
status 必需。规定在退出脚本之前需要输出的消息或状态号。状态号不会被写入输出
如果 status 是字符串,则该函数会在退出前输出字符串。
如果 status 是整数,这个值会被用作退出状态。退出状态的值在 0 至 254 之间。退出状态 255 由 PHP 保留,不会被使用。状态 0 用于成功地终止程序

3.is_object($var):
作用:用于检测变量是否是一个对象
语法:

1
2
$var:要检测的变量
如果指定变量为对象,则返回TRUE,否则返回FALSE

4.mysqli_num_rows(result):
作用:一共返回几行数据
5.mysqli_fetch_assoc(result):
作用:从结果集中取得一行作为关联数组;注意:本函数返回的字段名是区分大小写的
返回值:返回代表读取行的关联数组。如果结果集中没有更多的行则返回NULL
6.mysqli_error函数用于返回最近调用的函数的最后一个错误描述;
7.mysqli_connect_error函数用于返回上一次连接错误的错误描述
8.
$GLOBALS[“____mysqli_ston”]
和mysqli_connect(“localhost”,”用户名”,”密码”,”数据库名”)的作用相同,就是连接数据库。
源码解读:
先获取用户名和密码;接着将密码MD5加密;将用户名和密码带入查询语句后进行数据库查询,在查询过程中若检测的变量不是一个对象便使用die进行输出(这里用到了三目运算符进行选择);接下来使用mysqli_num_rows( $result )进行判断返回几行数据,当返回行数为1的时候便是正确;然后从该行数据中获取数据进行下一个判断。
当$avatar = $row[“avatar”]成功时变代表我们登入成功。可以看到此题并没有什么防御措施

Medium


函数介绍:
1.mysqli_real_escape_string(connection,escapestring)
转义在SQL语句中使用的字符串中的特殊字符;这个函数我们已经很熟悉了,在sqli-labs我们遇到了它和它的好兄弟addslashes();此时若是数据库使用gbk编码的时候我们便可以添加%df进行宽字节注入进行绕过。
2.trigger_error(errormsg,errortype):
作用:创建用户级别的错误消息。
trigger_error()函数能结合内置的错误处理器所关联,或者可以使用用户定义的函数作为新的错误处理程序(set_error_handler())
语法:

1
2
3
4
5
6
errormsg 必需。规定错误消息。最大长度 1024 字节。
errortype 可选。规定错误类型。可能的值:
E_USER_ERROR
E_USER_WARNING
E_USER_NOTICE(默认)
如果规定了错误的 errortype,则返回 FALSE。否则返回 TRUE

3.E_USER_ERROR :
E_USER_ERROR只能通过trigger_error($ msg,E_USER_ERROR)手动触发.
E_USER_ERROR是用户自定义错误类型,可以被设置为错误处理函数捕获退出运行
4.sleep(seconds):
作用:延迟执行当前脚本若干秒
语法:

1
2
3
4
seconds 必需。规定延迟执行脚本的秒数
如果指定秒数是负数,该函数将抛出一个错误
如果成功则返回0,如果错误则返回FALSE。
如果调用被信号中断,该函数返回一个非零值。在Windows平台上,该值将总是192,表示Windows API中的WAIT_IO_COMPLETION常量的值。在其他平台上,返回值将是剩余的延迟秒数

源码分析:
先获取我们的用户名当我们的用户名非空且是一个对象的时候,若是用户名里面包含危险字符便进行一个转义;防止SQL注入;若用户名不是一个对象,则使用trigger_error(errormsg,errortype)创建我们的错误消息;对
于我们的密码的输入也是采用这种方法,防止SQL注入;然后如果登入失败,则延迟两秒。这个等级比上个等级多了一个防御和延迟;但我们仍然可以使用bp爆破。

High


这个时候发现一个新的东西token
Token的引入:Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token便应运而生。
Token,即令牌,是服务器产生的,具有随机性和不可预测性,它主要有两个作用:
一:使用Token防表单重复提交步骤:
1.在服务器端生成一个唯一的随机标识号,同时在当前用户的Session域中保存这个Token;
2.将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端;
3.在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。


此时我分别登入两次,抓包拦截此时我们可以发现两次的token值不同;所以这里的Anti-CSRF token作用就是
防止我们重复提交进行爆破
二:用来作身份验证
使用基于 Token 的身份验证流程如下:
1.用户首次登录,将输入的账号和密码提交给服务器;
2.服务器对输入内容进行校验,若账号和密码匹配则验证通过,登录成功,并生成一个token值,将其保存到数据库,并返回给客户端;
3.客户端拿到返回的token值将其保存在本地(如cookie/localStorage),作为公共参数,以后每次请求服务器时都携带该token(放在响应头里),提交给服务器进行校验;
4.服务器接收到请求后,首先验证是否携带token,若携带则取出请求头里的token值与数据库存储的token进行匹配校验,若token值相同则登录成功,且当前正处于登录状态,此时正常返回数据,让app显示数据;若不存在或两个值不一致,则说明原来的登录已经失效,此时返回错误状态码,提示用户跳转至登录界面重新登录;
5.注意:用户每进行一次登录,登录成功后服务器都会更新一个token新值返回给客户端;

因为每次生成的token值不同,所以我们无法像上面一样无脑的爆破;需要换一种





还有另外一种利用bp宏去爆破:https://blog.csdn.net/qq_41617034/article/details/106605187

Impossible

以下的防御措施十分的严格,来学习一下它的防御姿势


Command Injection

Command Injection命令注入:
命令注入攻击,是指由于Web应用程序对用户提交的数据过滤不严格,导致黑客可以通过构造特殊命令字符串的方式,将数据提交至Web应用程序中,并利用该方式执行外部程序或系统命令实施攻击,非法获取数据或者网络资源等。在命令注入的漏洞中,最为常见的是PHP的命令注入。PHP命令注入攻击存在的主要原因是Web应用程序员在应用PHP语言中一些具有命令执行功能的函数时,对用户提交的数据内容没有进行严格的过滤就带入函数中执行而造成的。例如,当黑客提交的数据内容为向网站目录写入PHP文件时,就可以通过该命令注入攻击漏洞写入一个PHP后门文件,进而实施下一步渗透攻击。(在编写程序的时候,当碰到要执行系统命令来获取一些信息时,就要调用外部命令的函数,比如php中的exec()、system()等,如果这些函数的参数是由用户所提供的,那么恶意用户就可能通过构造命令拼接来执行额外系统命令。)
我的理解就是:应用有时需要调用执行系统命令的函数,当服务器没有严格过滤用户提供的参数时,就可能导致用户提交恶意代码被服务器执行,从而造成命令执行漏洞。

在此之前我们先来了解几个函数:
1.system(string $command, int &$result_code = null):
作用:system函数是php函数通过调用外部程序命令来实现与系统命令函数交互达到执行系统函数的目的,本函数执行 command 参数所指定的命令,并且输出执行结果。
语法:

1
2
3
4
command
要执行的命令。
result_code
如果提供 result_code 参数,则外部命令执行后的返回状态将会被设置到此变量中。



2.passthru(string $command, int &$result_code = null):
作用:执行外部程序并且显示原始输出
语法:

1
2
3
4
command
要执行的命令。
result_code
如果提供 result_code 参数, Unix 命令的返回状态会被记录到此参数。



exec()函数也是命令执行函数。作用与system差不多,只不过exec函数可以执行,但是不回显结果要,回显结果的话要在该函数前面加上echo
3.eval(phpcode):
作用:可将括号里面的字符串转换为代码执行,字符串必须是合法的php代码并且用分号结束,这样才能执行代码命令。
语法:

1
phpcode 必需。规定要计算的 PHP 代码。



4.assert():assert()函数是一个断言函数,在php里面判断一个表达式是否成立,返回真或假。如果直接将PHP代码传入也会被执行


接下来学习一下常用的DOS连接符:
&&:只有前面的命令执行成功才执行后面的命令
||:只有当前面的命令执行失败才执行后面的命令
&:无论怎样总执行后面的命令
|:将前面命令执行的输出作为后面命令执行的输入
系统命令整理:(感谢学长提供的资源)
windows下:https://www.shuzhiduo.com/A/Vx5MBqZLdN/
linux下:https://www.cnblogs.com/54chensongxia/p/12510758.html

LOW


stristr(string,search,before_search):
作用:函数搜索字符串在另一字符串中的第一次出现。
语法:
string:必需。规定被搜索的字符串。
search :必需。规定要搜索的字符串。如果该参数是数字,则搜索匹配该数字对应的 ASCII 值的字符。
before_search :可选。默认值为 “false” 的布尔值。如果设置为 “true”,它将返回 search 参数第一次出现之前的字符串部分。
php_uname() 返回了运行 PHP 的操作系统的描述。
参数:
‘a’:此为默认。’s’:操作系统名称。’n’:主机名。’r’:版本名称。’v’:版本信息。’m’:机器类型。
源码解读:
以POST的方式提交变量;然后通过stristr()和php_uname()来判断我们的操作系统;接着通过shell_
exec()输出我们的变量;这题可以使用命令注入就是在shell_exec()这个函数上面;该函数和system()差不多
都可以执行外部命令并且输出。
执行了一下查看某个文件的内容,发现成功执行了;这个漏洞真的太可怕了

Medium


这个只是增加了一个过滤方式,过滤了一种DOS连接符,我们仍然可以换种DOS连接符继续进行命令注入

High


过滤虽然多,但仍是百密一疏,|还是可以用

Impossible

学习一下源码吧

防御解读:
这里检查了token防止了CSRF;然后使删掉我们提交数据中的反斜杠;接着将我们输入的数据分成4个数组,每一组都是从”.”断开;接下来分别验证每一组数组里面的元素是否是数字。这样我们的命令就没有办法逃过过滤。
token防止了CSRF原理:
https://www.freebuf.com/articles/neopoints/271171.html