|
2019年夏天,我在一个甲方内网做渗透测试。目标是一个用了八年的OA系统,登录页面背后是IIS 6.0加ASP。随手丢了个单引号进用户名框,页面直接爆出ODBC错误,数据库是SQL Server 2000。那一刻我就知道,这系统八成要栽。 SQL注入本身不新鲜,但它和webshell之间那条路,很多人没走通过。大多数人拿到注入点,跑个sqlmap,dump出管理员密码,登进后台找上传点。这条路太绕,而且经常断——后台可能没有上传功能,或者上传被限制得死死的。真正直接的打法,是用注入点直接往服务器上写文件。 SQL Server有个经典手法:xp_cmdshell。这个扩展存储过程默认关闭,但如果当前数据库用户是sa权限,一条EXEC sp_configure 'xp_cmdshell',1;RECONFIGURE;就能打开。打开之后,等于拿到了一个命令行。我当时的操作是先用注入点确认权限,AND 1=(SELECT IS_SRVROLEMEMBER('sysadmin'))返回正常,说明是sa。然后开xp_cmdshell,直接echo一个ASP马到网站根目录。 但这里有个坑。网站根目录的物理路径怎么拿?很多人卡在这一步。SQL Server里可以用xp_dirtree或者直接查sys.databases里的文件路径,但最准的办法是看IIS的metabase.xml,或者用xp_cmdshell执行iisapp.vbs列出所有站点路径。我当时用了一条EXEC master..xp_cmdshell 'cscript C:\Inetpub\AdminScripts\adsutil.vbs enum w3svc',把IIS配置全列出来了,根目录一目了然。 写马的时候别用echo直接拼一句话,引号转义能把你逼疯。我的做法是本地生成一个Base64编码的ASP文件,然后用certutil -decode在目标机器上还原。命令大概长这样:EXEC xp_cmdshell 'certutil -decode c:\temp\a.txt c:\inetpub\wwwroot\shell.asp'。干净利落,不碰引号。 MySQL的路子不一样。MySQL没有xp_cmdshell,但如果有FILE权限且secure_file_priv为空,可以直接SELECT '' INTO OUTFILE 'C:/phpstudy/www/shell.php'。前提是你得知道绝对路径。phpMyAdmin的注入点经常能配合这个手法,但MySQL 5.7之后secure_file_priv默认限制得很死,成功率大不如前。 PostgreSQL更冷门一些。它可以用COPY ... TO PROGRAM执行系统命令,前提是数据库用户是超级用户。命令是COPY (SELECT '') TO PROGRAM 'echo > /var/www/html/shell.php'。这条在实战里遇到的概率低,但一旦碰上,比SQL Server还顺手,因为不需要开什么扩展。 说回2019年那个OA。我用xp_cmdshell写了马,路径是D:\oa\web\images\,一个看起来人畜无害的图片目录。马的名字叫logo.asp。连上去之后,whoami返回nt authority\system。整台机器就是我的了。后来复盘的时候发现,那个注入点其实在登录页的UserID参数上,开发压根没过滤,直接拼SQL。八年了,没人管过。 防御这事,参数化查询是唯一正解。别跟我提什么WAF、过滤关键字,绕过的姿势比防御的规则多。我见过用/*!50000union*/绕过注释过滤的,见过用%00截断的,见过把select写成se/**/lect的。只要SQL语句是拼出来的,就一定有办法。参数化查询从根上切断这条路,让注入数据永远只是数据,不会变成代码。 还有一个细节:数据库用户的权限。别用sa跑网站。给网站单独建一个用户,只给db_datareader和db_datawriter,xp_cmdshell、FILE、COPY TO PROGRAM这些全废掉。就算有注入,也写不了马,只能读数据。损失可控。 最后说个真事。去年帮一个朋友看他的站,发现/admin/upload.asp有个注入点,我随手测了一下,居然能xp_cmdshell。我问他这站谁做的,他说是某宝花三百块买的模板。我笑了笑,没说话。三百块的模板,配一个默认开xp_cmdshell的数据库,这就是很多小站的现状。 |